SOLVED - - - Stopwatch / blink without delay problem

Hello all,

I am using a IR photo photodiode / Receiver pair to light up leds connected to a TLC5940. Everything works fine with that, but I want there to be a delay after the sensor stops receiving data before the leds turn off. I cannot actually use " delay(500);" because the sensor will not be able to take in information during that delay.
I have looked intensely at the Arduino Stopwatch example to help solve my problem, Arduino Playground - Stopwatch, but what they are reading is digital... my readings from the IR sensor are analog. What I need specifically to happen in the code is this....

  • IR sensor is ALWAYS taking in readings and being compared to a threshold found in the setup to see if something is over the sensor...(FIGURED THIS OUT ALREADY)
  • IF the sensor detects motion the lights turn on, if not the lights stay off.... (FIGURED THIS OUT ALREADY)
  • IF the sensor does NOT detect motion JUST AFTER it has previously detected motion, a timer starts and the lights stay on until the timer reaches an arbitrary value.. ( .5 seconds ) .. ( HAVE NOT FIGURED THIS OUT YET)

Here is the code that works perfectly to perform the first 2 functions above...

#include "Tlc5940.h"

int Threshold;

  void setup()
    {
      Tlc.init();
      Threshold = analogRead(A0);
    }

  void loop()
    {
      int NewThreshold = (Threshold - 7);
      int ReceiverVal = analogRead(A0);
      int Value;
      
        if(ReceiverVal < NewThreshold)
           {
             Value = 2000;
           }
        else if(ReceiverVal > NewThreshold)
           {
             Value = 0;
           }
             for(int i=0; i<16; i++)
               {
                  Tlc.set(i,Value);
               }
                Tlc.update();
               
    }

Any suggestions??

I believe you may be looking for the millis() function to detect how long it has passed since you last used the same functions.

Yes sorry I am aware of how to actually measure time.. where I need guidance is how to tell the arduino " When the sensor stops sensing something above it AFTER it has been sensing something, start the timer"

So.. the problem I have is putting this into an if statement... if (( Receiver > Threshold )&&(Receiver WAS JUST PREVIOUSLY < Threshold)).. start the timer... ??? Not sure how to code this part.. especially because it is an analog value, not digital, as the stopwatch example uses.
Thanks

Just keep restarting the timer anytime reciever is less than threshold:

if(Receiver < Threshold){
  startTime = millis();
  digitalWrite(ledPin, HIGH);
}
if(millis()-startTime > 500){
  digitalWrite(ledPin, LOW);
}
if(Receiver < Threshold){
  startTime = millis();
  digitalWrite(ledPin, HIGH);
}
if(millis()-startTime > 500){
  digitalWrite(ledPin, LOW);
}

This just turns the led on for .5 seconds when the sensor first detects movement. I need the led to be on WHILE the sensor detects something and for an ADDITIONAL .5 seconds after it is done detecting.

Example:

My hand could be over the sensor for

1 second
3 seconds
100 seconds... but the led should be on for

1.5 seconds
3.5 seconds
100.5 seconds

It needs to check that if the sensor is NOT sensing anything and It JUST GOT DONE sensing something, the timer begins and tells the led to stay on for .5 more seconds. I don't know how to ask..

" (is nothing being sensed? AND was something just being sensed?) "

This just turns the led on for .5 seconds when the sensor first detects movement.

No. Remember these statements are being repeatedly called in loop(). So long as the first if statement remains true (hand in detector) startTime keeps getting updated and light remains on. The second if statement is always false. Once the first if statement is no longer true (you move your hand away from detector) stopTime stops being updated and if .5 sec goes by without the first if re-triggering the second if goes true and light turns off. It is doing exactly what you want.

Still confused..

if(Receiver < Threshold){             //   if hand is detected
  startTime = millis();                          //   start timer
  digitalWrite(ledPin, HIGH);                //    turn led on
}
if(millis()-startTime > 500){                 //    if it has been .5 seconds since hand was detected
  digitalWrite(ledPin, LOW);                //     turn led off
}

That is what it looks like to me... is this code supposed to be mixed into my code or just inserted as is?

Here's how I would comment

if(Receiver < Threshold){             //   is hand detected?
  startTime = millis();                          //   the current time as hand is detected
  digitalWrite(ledPin, HIGH);                //    make sure led is on
}
if(millis()-startTime > 500){                 //    has it been .5 sec since hand was LAST detected?
  digitalWrite(ledPin, LOW);                //     turn led off
}

Maybe "startTime" isn't the best name for the variable. Here it is dropped into your code, so you can try it

#include "Tlc5940.h"

int Threshold;
int ledPin = 13; //pin # driving LED
unsigned long detectTime; //time of last detection

  void setup()
    {
      Tlc.init();
      Threshold = analogRead(A0);
      pinMode(ledPin, OUTPUT);  //set mode for LED
    }

  void loop()
    {
      int NewThreshold = (Threshold - 7);
      int ReceiverVal = analogRead(A0);
      int Value;
      
        if(ReceiverVal < NewThreshold)
           {
             Value = 2000;
             detectTime = millis();
             digitalWrite(ledPin, HIGH);
           }
        else if(ReceiverVal > NewThreshold)  //this can just be an else statement, don't need else if
           {
             Value = 0;
           }
        if(millis()-detectTime > 500)   //turn off LED after .5 sec since last detection
          {
             digitalWrite(ledPin, LOW);
          }
        for(int i=0; i<16; i++)
           {
              Tlc.set(i,Value);
           }
        Tlc.update();
               
    }

EDIT: I declared detectTime in the wrong scope in my original posting. It should be global so it is remembered each time through loop().
EDIT AGAIN: looking closer at your original post. I guess the Tlc is the lights you want to turn on and off. I did it for the onboard LED. I'm sure you can modify it so the Tlc lights have the .5 sec delay.

Ok so I tried that and it still works the exact same, no delay =(

here it is

#include "Tlc5940.h"

int Threshold;
unsigned long DetectTime;

  void setup()
    {
      Tlc.init();
      Threshold = analogRead(A0);
    }

  void loop()
    {
      int NewThreshold = (Threshold - 7);
      int ReceiverVal = analogRead(A0);
      int Value;
      
      if(ReceiverVal < NewThreshold)
           {
             Value = 1000;
             DetectTime = millis();
           }
           
      else if(ReceiverVal >= NewThreshold)
           {
             Value = 0;
           }
      if((millis() - DetectTime) > 2000)
          {
            Value = 0;
          }  
      
             for(int i=0; i<16; i++)
               {
                  Tlc.set(i,Value);
               }
                  Tlc.update();
                  
    }

remove your "else if" section. Then it should work.

After deleting that section, the lights illuminate immediately after the program starts and stay lit forever. no good

Hmmm? Could you post the code you have loaded? I just tested the algorithm on my arduino and it works fine.

#include "Tlc5940.h"

int Threshold;
unsigned long DetectTime;

  void setup()
    {
      Tlc.init();
      Threshold = analogRead(A0);
    }

  void loop()
    {
      int NewThreshold = (Threshold - 7);
      int ReceiverVal = analogRead(A0);
      int Value;
      
      if(ReceiverVal < NewThreshold)
           {
             Value = 1000;
             DetectTime = millis();
           }
      if((millis() - DetectTime) > 2000)
          {
            Value = 0;
          }  
      
             for(int i=0; i<16; i++)
               {
                  Tlc.set(i,Value);
               }
                  Tlc.update();
                  
    }

The code looks good to me. Check that your hardware is still working. Is your photodiode trigger still aligned with the receiver and / or the photodiode still emitting?

HA! got it. The problem I had is updating the TLCs outside of the if statements. I needed to update them at the end of each if statement. Thanks so much TedCook!!!

Sweet! Glad you got it working. Does it makes sense to you now how it works?

I don't think it should matter if you switch the lights in the if statements or not. I would still be suspicious of flaky hardware.

It does make sense! But now I have a new problem. With this running, my range for the IR sensor has gone from about 8 inches down to 2. WTF. It also has problems now with the lights in the room. Whereas without this delay stuff there was never a problem. I've created a new topic under Leds and multiplexing