read sensor while dimming LED's (individually)

Hi,

I am trying to make a led dim depending on the distance of a person to a Sharp distance sensor. This works fine, however, when the LED is dimming (using PWM) it seems as if the program can not be bothered to read the input from distance sensor.

So the question is: can I get input from a sensor while dimming a LED? And as a next step; can I dim/undim multiple leds individually at the same time?

This is the code I am running now, based on a program found elsewhere on the forum:

// a Sharp distance sensor on analog pin 2 makes a light (un)dim on a certain treshhold 

int sharpIR = 2;
int avgFactor =10;

int value = 0;                            // variable to keep the actual value 
int lightPin = 10;                        // light connected to digital pin 9

boolean lightOn = false;

void setup(void){

  Serial.begin(9600);
}


void loop()
{

  int val = getDist();
  Serial.println(val);
  delay(100);

  //fade in
  if ((val>200)&&(lightOn == false)){
    for(value = 0 ; value <= 255; value+=1) // fade in (from min to max) 
    { 
      analogWrite(lightPin, value);           // sets the value (range from 0 to 255) 
      delay(30);                            // waits for 30 milli seconds to see the dimming effect 
    }
    lightOn = true;
  }
  //fade out
  else if((val<100)&&(lightOn == true)){
    for(value = 255; value >=0; value-=1) // fade out (from max to min) 
    { 
      analogWrite(lightPin, value);           // sets the value (range from 0 to 255) 
      delay(30);                            // waits for 30 milli seconds to see the dimming effect 
    }
    lightOn = false;
  }
}


int getDist()
{
  int runningTotal=0;
  for (int i=0; i < avgFactor; i++)
  {
    int distRead = analogRead(sharpIR);
    runningTotal += distRead;
  }
  int distAvg = (runningTotal / avgFactor);
  return distAvg;
}

I’d appriciate any advice,

thanks,

Jaap

Your fade up/fade down takes over seven and a half seconds (0.03 * 255) , during which time, you're not reading the distance.
You only read the distance at the start of "loop ()"
Is this what you intended?

Hi AWOL,

thanks for your reply. Indeed, I am fading up/down slowly, and indeed the problem is that I can not read the distance during this fading. Therefore I was wondering if there is a way that I can fade in/out slowly, and still read the distance at the same time. That is the most important thing right now.

Even better, I'd like to control the fading of multiple LED's at the same time individuall. Just as an example: say I have 2 LED's, LED1 fades in (slowly) when you are 1 meter from the sensor, while LED2 starts to fade in (slowly) when you are 70cm from the sensor. At a distance of 60cm LED1 stops fading.

Maybe there is an easy solution for this which I am not seeing, my programming skills are quite basic so any halp is appreciated!

I'm not familiar with the Sharp sensor and from the looks of it "getDist" should be fairly fast, so I don't see why you couldn't use something like the "map () " function to return a PWM value:

analogWrite (lightPin, map (getDist(), minRange, maxRange, 0, 255));

where minRange and maxRange are the values you expect to get back from getDist for the sort of ranges you talked about. (you may have to transpose them in the call to "map" depending upon how you want the LEDs to behave).
Or you could call getDist () just once, and pass the value like this:

range = getDist ();
analogWrite (lightPin, map (range, minRange, maxRange, 0, 255));
analogWrite (lightPin1, map (range, minRange1, maxRange1, 0, 255));

and play with the values to get what you want.

Would this do the same thing ?

It would sample much faster without having to do a full fading sequence between samples, and if the distance changed mid-fade, it would respond accordingly.

int fade = 0;

void loop()
{
int distance = getDist();
Serial.println(distance);
// dont know what the delay(100) was for

if (distance > 200) fade = (fade < 255) ? fade+1 : 255;
if (distance < 100) fade = (fade > 0) ? fade-1 : 0;
analogWrite(lightPin, fade);
delay(30);
}

Thanks for your suggestions! I will give it a go and let you know how it turns out. Probably I'd have to filter the input from the distance sensor a bit more to make sure that the LED's fade in a decent way.

Do you guys have any ideas about my second question; whether it is possible to have a 'programmed' PWM fade (of say 5 seconds from 0 to 255) and doing other stuff during the fading, for example initiating another PWM fade?

thanks!

A fairly simple way of doing it would be to note the value of "millis()" each time through "loop" and every 19milliseconds decrement or increment the value you're writing to the analogWrite.

19mS * 255 = 4.8 seconds.

Using a delay(19) instead of delay(30) would take 5 seconds to go from 0-255. if you used an array (ie fade[x]) and processed each fade during the loop you should have no problems controlling multiple led's. You might have to lower the delay value a tiny bit to allow for the extra time spent actually processing within loop

Ray,

thanks, your solution works very well. Here is the complete code, hope others can benefit from this as well:

// a Sharp distance sensor on analog pin 2 makes a light (un)dim on a certain treshhold 

int sharpIR = 2;                          // Sharp distance sensor on analog pin 2
int lightPin = 10;                        // light connected to digital pin 9

int avgFactor = 10;                       // factor for filtering signal
int fade = 0;

void setup(void){
}


void loop()
{
  int distance = getDist();
   
  if (distance > 200)  fade = (fade < 255) ? fade+1 : 255; //ternary conditional, syntax: var variable = (otherVar == 1) ? valueIfTrue : valueIfFalse;
  if (distance < 100)  fade = (fade > 0)   ? fade-1 : 0;
  analogWrite(lightPin, fade);
  delay(30);
}


int getDist()
{
  int runningTotal=0;
  for (int i=0; i < avgFactor; i++)
  {
    int distRead = analogRead(sharpIR);
    runningTotal += distRead;
  }
  int distAvg = (runningTotal / avgFactor);
  return distAvg;
}

AWOL, PWM’ing using the millis() stuff works great as well, here is the code I am using now, just to dim one LED:

int ledGrid1 = 11;                          // ledGrid connected to digital pin 11

boolean ledGrid1On = false;


int value = 0;
unsigned long time;
unsigned long prevTime = 0;

void setup()                    
{
  Serial.begin(19200);
}

void loop()                    
{
 time = millis();

  if (time == (prevTime + 19)){
    if ((value <= 255)&&(ledGrid1On == false)){
      value+=5;
      analogWrite(ledGrid1, value);           // sets the value (range from 0 to 255)
      prevTime = time;
    } else{
      ledGrid1On = true;
    }
  }

//EDIT: time and prevTime are 'unsigned long’s, not 'float’s

"millis" returns a value of type "unsigned long", not "float" - you're probably making the compiled code more complex and longer than it needs to be.

You may not need your ledGrid1On variable, it doesn’t seem like you ever set it to false again once it’s been set to true.

Another thing you can do in your loop is to return early if conditions aren’t met rather than nesting if statements

void loop()
{
time = millis();

if (time < prevTime + 19) return;

if ((value <= 255)&&(ledGrid1On == false)){
value+=5;
analogWrite(ledGrid1, value);
prevTime = time;
} else{
ledGrid1On = true;
}

It can make your code more readable when you get to your third or fourth nested level. On the downside if you add code later and forget you’re returning early it’ll never get run, but usually in those situations you should probably have things broken out into functions anyway.

Also, this line,

if ((value <= 255)

may cause you some head-scratching later, because you’re just about to add five to “value”.

:wink:

Hehe, I am learning here! Wow :wink: Thanks,

J