I should know how to do this, but I am obviously missing the concept here…
I want a sensor to echo every second. If the threshold is met, I want a counter to increase, and an LED to light up every 1/2 second that the counter is tripped. Such as if the sensor has been tripped 5 times in a day - the LED will blink 5 times, wait 2 seconds and flash again 5 times. Bascially just a visual indicator that the sensor has been tripped and how many times it was tripped.
My problem is the code concept. There has to be a loop for the sensor to keep sensing, so I was thinking - oh ok, put a loop within that loop - but the delay in the second loop would actually delay the main loop - such as…
int LED = 13;
int TRIP_COUNTER = 0;
int TRIPPED = 0;
void setup()
{
pinMode(LED,OUTPUT);
}//end setup
void loop()
{
//Sensor stuff here - which will set TRIPPED to 1 if something is detected. it is too long and boring to put on the forum.
//TRIP_COUNTER is also increased by 1 (++) if something is detected.
delay(1000);
//Inner loop to handle LEDs
void loop()
{
//if system was ever tripped, it should be greater than 0 and the LEDS should blink indicating how many times it has been tripped.
if(TRIPPED >= 1)
{
int i = 0; //to be used in the while loop below as a counter.
//this should blink the LED as many times as the system has been tripped.
WHILE(i < TRIP_COUNTER)
{
digitalWrite(LED, HIGH); // LED ON
delay(500);
digitalWrite(led, LOW); // LED OFF
delay(500);
i++;
}//end while loop
}//end if
}//end inner loop
}//end main loop
Any suggestions? I think that it would INCREASE the time between sensing by how many times the led blinks. Is there a way around this? I know I have to have a loop on the sensor, just not sure how to have two things going on at once like this without interfering with each other.
Any help or suggestion would be greatly appreciated
Read about the Arduino function millis().
http://arduino.cc/en/Reference/Millis#.Ux5Q3YWmWVI
Your code would be an offshoot of this snippet.
if(millis() - priorTime > timeout1){
//do some task(s)
digitalWrite(ledPin, HIGH);
//store the last time task was done
priorTime = millis();
}
This way you can keep delays in the inner loop from taking too much time from your outer, “sensing” loop. Be aware the millis() function will overflow every so often (go from max # to zero) and you should have additional code to detect “rollover” if that’s a potential problem in your usage.
This number will overflow (go back to zero), after approximately 50 days.
I am sorry if I seem clueless here, but how can a function that counts how long a program started help me light an led within a sensing type loop and not increase the overall time of that loop?
I guess I should be asking, how does one do two things at once, without interfering with with each other? Would creating a function with a global that is updated and fed to the function each loop of the sensing loop accomplish this, or is an arduino not really intended to be multi tasking like this?
techtony:
I am sorry if I seem clueless here, but how can a function that counts how long a program started help me light an led within a sensing type loop and not increase the overall time of that loop?
Strictly speaking, even using interrupts (the elegant solution) will add some 10's of usec ... but if your 1000 msec loop becomes 40 usec longer ... do you really care ? I suspect not so let me illustrate one possible (easy) way. Yes it will add some 10's of usec but even that can either be negated if needed (your sensor code doesn't need 1000 msec to execute it's non-delay portions does it?).
You have “sensor” code that you want to run every 1000 msec, polling the sensor for a “tick”, processing some data when there is one. You wish to count these ticks and flash an LED for each tick every so many secs/mins/hours. Have I got the basic idea correct ? See if the following does that. It’s not exactly as you specified but it’s a small change to make it so. No doubt it could be done more efficiently but I wanted to illustrate the use of time comparisons vs other methods (state machine, interrupts and, ugh, delays). As it sits it’s incomplete and I’d have more questions to ask to finish it (should the “ticks” be reset, bleed off, ??) but shows what I was trying to say.
//put includes here
//define constants used
const int LEDpin = 5; //pin for LED output
const unsigned long pollTime = 1000; //loop time msecs
const unsigned long onTime = 200; //LED on time msecs
const unsigned long offTime = 300; //LED off time msecs
const unsigned long fiveMins = 300000; //period btw visual (LED) updates
//define variables used
boolean LEDstate = false; //on or off state of LED
int numTicks = 0; //accumulated number of ticks from sensor
int numFlashs = 0; //number of LED flashes so far this visual update
unsigned long sensorTime = 0; //last time sensor was read msecs
unsigned long updateTime = 0; //last time of visual update msecs
unsigned long priorTime = 0; //last time LED was turned on/off msecs
void setup(){
pinMode(LEDpin, OUTPUT);
digitalWrite(LEDpin, LOW);
//put other stuff here as needed
}
void loop(){
//start sensor polling loop to continually count ticks
//sensor code runs < min(onTime, offTime) msec
if(millis() - sensorTime > pollTime){
//put sensor code here
//it will run once every pollTime msecs
}
//now flash LED in a time efficient fashion
if(numTicks > 0){
//so flash the LED on/off = numTicks
if(millis() - updateTime > fiveMins){
//it's been long enough btw visual updates
if(numFlashs < numTicks){
if(!LEDstate && (millis() - priorTime > offTime)){
//LED is off for longer than it's off time so turn it on
LEDstate = !LEDstate; //flip state
digitalWrite(LEDpin, LEDstate);
priorTime = millis();
}
if(LEDstate && (millis() - priorTime > onTime)){
//LED is on for longer than it's on time so turn it off
LEDstate = !LEDstate; //flip state
digitalWrite(LEDpin, LEDstate);
priorTime = millis();
numFlashs++; //increment count of LED on/off flashes
}
}
else{
//all done flashing LED for this period
//reset variables for next visual update period
updateTime = millis();
numFlashs = 0;
}
}
}
} //end of loop()
I’ve not had a chance to test it but it’s simple enough that it should work (famous last words before foot enters mouth). Hopefully the names and comments explain the operation but ask questions where they are less than clear.
Looking at the above code I see one thing that might not be clear. In this part …
void loop(){
//start sensor polling loop to continually count ticks
//sensor code runs < min(onTime, offTime) msec
if(millis() - sensorTime > pollTime){
//put sensor code here
//it will run once every pollTime msecs
}
//now flash LED in a time efficient fashion
… the sensor code needs to save the time when it ran. To make it clear I should have written …
void loop(){
//start sensor polling loop to continually count ticks
//sensor code runs < min(onTime, offTime) msec
if(millis() - sensorTime > pollTime){
//put sensor code here
//it will run once every pollTime msecs
sensorTime = millis();
}
//now flash LED in a time efficient fashion
So if not foot-in-mouth, them toes are pretty close. :oops: :mrgreen:
Well it is interesting I did not come back to the forums until just now. I looked first at the arduino reference site, which of course has no real world example of millis (thus my utter confusion earlier)… I started looking through other peoples examples and they were so undocumented with poor commenting, that I gave up. Then I stumbled on arduinoplaygrounds example using millis and I came back here to say eureka. I then read your posts… must say it makes so much more sense now! THANK YOU THANK YOU!
To answer your questions…
-
No the sensor is an hc-sr501 pir sensor, so not critical that it is a one second delay, I used it as a reference point only. It could be a 4 second delay if I wanted.
-
You have the idea down, yes. This is a simple project to on get me up to speed with the arduino and sensors in a real world application where you could potentially have 4 sensors running and processing that data all at the same time. I am just starting out with one sensor… beginning to realize that hardware programming is very different than I had expected.
-
As for whether the sensor tick should be reset or bleed off, I do not understand what you mean really.the digital pin 13 goes HIGH when motion is detected and then it goes back to LOW when nothing moves. So I guess that would be considered reset?
I really do appreciate the advise, I will hook it up again, rewrite the code let you know how it goes tomorrow.
techtony:
3. As for whether the sensor tick should be reset or bleed off, I do not understand what you mean really.the digital pin 13 goes HIGH when motion is detected and then it goes back to LOW when nothing moves. So I guess that would be considered reset?
What the code does is accumulate "ticks", or trips, the above being 1 tick/trip. Let it run long enough and I wonder if that number has any meaning. Do you want to know how many trips per day ... per week ... per year ? Should the accumulated number be reset to 0 ? If so, when ... how often ? Or should it "bleed", like an air leak in your tire ... so many trips lost per hour ... or per day ... or ... but never letting the accumulated number to be < 0. It all depends on how you want to interpret the accumulated trip count.
In any case I hope you can see how the above beats using delays in some circumstances. Using delay() is fine, if the MCU has nothing else to do. Use delay() only for short delays.
FWIW if the motion sensor does the above, and you might have more than 1 sensor, then when polling (reading the sensor output line once per loop) the time it takes to do a loop() is important. Too long and a pulse might be missed. Too short and you might double count a single pulse. A better way is to use an external interrupt and a function called, in general, an ‘interrupt service routine’, ISR. But one step at a time.
http://arduino.cc/en/Reference/AttachIn … x_s3YWmWVI