URM37 ultrasonic sensor: dimming LED, almost working but need some guidance

Hi all,

I'm new to the forum and programming in general, so actually I'm trying to get my first piece of functional code working.

I want to make a PWM dimmer for an LED using a ultrasonic range sensor. At the moment I have a functional sketch, but there are some things I can't rely work out just yet. So I need some guidance.

I've seen a few posts concerning this idea already, but since everyone is using different hardware and code, it seemed more sensible to start a new topic for this specific question.

The sensor I'm using is the URM37 V3.2 from DFrobot.

The sketch is based on the library by Miles Burton.
http://milesburton.com/index.php/URM37_Ultrasonic_Distance_Measurement_Library

Right now the LED is 'off' (PWM=0) when the URM gives a value under 30 cm (the values are converted to cm's), it has full brightness (255) above 115cm and inbetween the LED is dimmable according to the distance above the sensor. (brightness=(sensorvalue-30)*3).
This all works fine.

The problem is that right now you have to keep your hand in place in order to keep the LED at the desired brightness. I would like to be able to sort of 'lock' the brightness so that when you remove your hand (after leaving it in the same place for a few seconds for example) the LED keeps burning at the same brightness level, until you interfere with your hand again.

How do i go at this? Any ideas? Has anyone done this already?

Thanks all!

Here's the code:

//URM37 led dimmer; interface distance between 30cm and 115 cm
// URM 1 - ARDUINO VCC
// URM 2 - ARDUINO GND
// URM 8 - ARDUINO 3
// URM 9 - ARDUINO 2
// LED+ - ARDUINO 9 (PWM)
// LEDgnd - ARDUINO GND


#include "URMSerial.h" 


// The measurement we're taking
#define DISTANCE 1 
#define TEMPERATURE 2
#define ERROR 3
#define NOTREADY 4 


int LED = 9;
URMSerial urm; 

void setup() { 
Serial.begin(9600); // Sets the baud rate to 9600
urm.begin(2,3,9600); // RX Pin, TX Pin, Baud Rate 
pinMode(LED, OUTPUT);
}


void loop()
{
  // Request a distance reading from the URM37 
urm.requestMeasurement(DISTANCE); // You may call this as many times as you like. It will only send once 

// Avoid fetching the distance until we're sure the reading is ready
if(urm.hasReading()) 
{ 
int value; // This value will be populated
switch(urm.getMeasurement(value)) // Find out the type of request
{
  case DISTANCE: // Double check the reading we recieve is of DISTANCE type
  Serial.println(value); // Fetch the distance in centimeters from the URM37 

if ((value < 30) && (value >= 0)) // if distance is less than 30cm LED brightness is 0 (PWM number between 0 and 255)
{
  analogWrite(LED, 0); 

}

if((value >= 30) && (value <= 115)) // if distance is between 30cm and 115 cm brightness is determined by value
{
  int light; // this value will be populated by formula based on sensor value
  light = (value-30)*3;
  analogWrite(LED,light);
}

if(value > 115) // distance is greater than 115cm brightness is 255
{
  analogWrite(LED,255);
}



delay(200); 
break; 
} 
}}

How are you supposed to tell that you've taken you hand away, or that the range hasn't suddenly gone to > 115cm?
Do you need to look for gradual vs. sudden changes?

This is also what I was struggeling with. I don't have a solution just yet, that's why I was asking.
actually i hope it is possible at all like this....

void loop()
{
  // Request a distance reading from the URM37 
urm.requestMeasurement(DISTANCE); // You may call this as many times as you like. It will only send once 

// Avoid fetching the distance until we're sure the reading is ready
if(urm.hasReading())

What if doesn't "hasReading"?
Wait 1/5th of a second and ask for another?
You're not doing anything else, why not just loop on "! hasReading()" ?

Why bother with a switch for a single 'case', unless you like typing?

(When you're posting code, can you please remember to use the # (code) icon on the editor's toolbar?)

How about if you make the system so that if your hand is detected between say 80cm and 115cm that it turns the led off. Anything less and it adjusts the brightness and if you take your hand away it just keeps it at that brightness.

I was thinking the following, this LED is eventually becoming a floorlamp so; when there is no hand to interfere the distance jumps up to 2.4m (ceiling height)

what i see when I'm interfering with the sensor in the serial monitor is the string of values, as soon if you pull your hand away it jumps up immediatly.

So what i would like to do is have the code check if value > 150: if so jump back up again to the beginning of the loop, and do a new measurement. (brightness at beginning = 0)
If not the brightness is adjusted, if brightness is adjusted, the brightness should be saved.

then when you pull your hand away, and the value jumps up over 150, the brightness saved should be kept.

so much for the theory at least, would this work? how would i go at it including this in a code?

Ok so it's sloppy code... but it seems to work.. and i wanted to share..

//URM37 led dimmer; interface distance between 30cm and 115 cm
// URM 1 - ARDUINO VCC
// URM 2 - ARDUINO GND
// URM 8 - ARDUINO 3
// URM 9 - ARDUINO 2
// LED+ - ARDUINO 9 (PWM)
// LEDgnd - ARDUINO GND


#include "URMSerial.h" 


// The measurement we're taking
#define DISTANCE 1 
#define TEMPERATURE 2
#define ERROR 3
#define NOTREADY 4 


int LED = 9;
URMSerial urm; 

void setup() { 
Serial.begin(9600); // Sets the baud rate to 9600
urm.begin(2,3,9600); // RX Pin, TX Pin, Baud Rate 
pinMode(LED, OUTPUT);
}


void loop()
{
  // Request a distance reading from the URM37 
urm.requestMeasurement(DISTANCE); // You may call this as many times as you like. It will only send once 

// Avoid fetching the distance until we're sure the reading is ready
if(urm.hasReading()) 
{ 
int value; // This value will be populated
int light = 0;
switch(urm.getMeasurement(value)) // Find out the type of request
{
  case DISTANCE: // Double check the reading we recieve is of DISTANCE type
  Serial.println(value); // Fetch the distance in centimeters from the URM37 
  
 if(value> 150)
  {
  break;}
  

if ((value < 30) && (value >= 0)) // if distance is less than 30cm LED brightness is 0 (PWM number between 0 and 255)
{
 light = 0;
}

if((value >= 30) && (value <= 115)) // if distance is between 30cm and 115 cm brightness is determined by value
{
  light = (value-30)*3; 
}

if ((value > 115) && (value <=150)) // distance is greater than 115cm brightness is 255
{
  light= 255;
 }
  
  analogWrite(LED,light);




delay(200); 
break; 
} 
}}

there are still a few mistakes probably and it probably isn't the most efficient way of doing things.. so it will take some time to clean it up.. but I'm happy to continue to the next step of the project