asherflynt:
So this issue came up on my other project thread and I would like a good answer if I can find one. I started out with code that would fail when millis() resets automatically at about 50 days. I have added the code (first if statement) below. I believe this will correct the issue.
I know delay() would work but not for me as this is not the only thing I want to do in my loop.
I am open to suggestions on better ways to do this a couple users on my project thread were going back and forth so I wanted to make this it's own thread.
the 50day overflow can catch you if your code is something like this:
unsigned long timeout=0;
void loop(){
if(millis()>timeout) {
// do some action
timeout = millis() +1000; // do the action in one second
}
}
Now that code looks pretty bullet proof doesn't it?
but,
if (millis() + 1000 ) causes a rollover, the action will trigger every loop, as long as (millis()+1000) causes a rollover and millis() has not rolled over, timeout will always be less than millis().
So, you have to code for this condition, either reset the millisecond counter, or set your own rollover flag.
bool rollover=false;
unsigned long timeout=0, timeout1=0;
void loop(){
unsigned long timenow = millis();
if(timenow<timeout1) rollover = false; // reset rollover flag
if((timenow>timeout)&&(!rollover)){
do something
timeout = timenow + 1000;
timeout1 = timenow; // check for rollover
rollover = (timeout<timenow);
}
other important code
}
Now this code looks even better, but there is another gotya here !
if timeout is set to a large value and millis() rolls, because 'other important code' took a while to complete, the timeout would not trigger for 50 days!
So, you need to code for this possibility: timeout is some big value and millis() has slipped by to roll.
bool rollover=false;
unsigned long timeout=0, timeout1=0;
void loop(){
unsigned long timenow = millis();
if(timenow<timeout1) {// millis rolled!
if(!rollover) timeout=timenow; // cant be timenow-1 because timenow could be 0
// catch the timeout on the next loop!
timeout1 = timenow; // clear the millis rollover check.
rollover = false; // reset rollover flag
}
if((timenow>=timeout)&&(!rollover)){
do something
timeout = timenow + 1000;
timeout1 = timenow; // check for rollover
rollover = (timeout<timenow);
}
other important code
}
So this is what I think needs to be done to handle Millis() rollovers for timeout coding.
Chuck.