if ( (long int) (millis() - T) >= 0 ) {
// millis() has passed T
} else {
// millis() has not passed T yet
}
But it don't seem to work in some cases. let's say millis() and T are 3-bit unsigned (just to make the numbers smaller).
When millis() == 5, I set T = millis() + 6 (thus T == 3)
When millis() == 6, millis() - T == 3 . Casting it to a signed 3-bit also gives 3.
In this case, millis() has not passed T yet but the code above will indicate that it has passed T.
KE7GKP:
You have two different questions there. Which one are you asking about?
simply comparing millis() to some target number will tell you whether you are past the time you set.
rollover is a second-order effect that has almost nothing to do with #1 millis() will rollover every 50 days. Are you REALLY measuring something that takes that long? If so, then I would strongly suggest using a Real Time Clock (RTC) module.
My main problem is how does one tell if millis() is past a certain time?
The second subproblem is, http://www.arduino.cc/playground/Code/TimingRollover seems to work, but fails in some cases. If it can be fixed, then I can use it as a solution to my problem.
To clarify: I'm looking for something like TimedAction, except that instead of something like
suppose millis() runs from 0...1000 and rolls over.
When millis() == 900, I want to trigger a single event to happen in 2000ms, i.e. let target = 900+2000, which is 100 after rolling over
I can't just compare millis() with 100 and decide whether millis() has "passed" 100.
I think you are looking at it slightly skewed.
set up these variables
unsigned long currentMillis;
unsigned long previousMillis;
unsigned long elapsedMillis;
unsigned long duration;
millis() returns an unsigned long value (0 to (2^32-1) )
It takes 49+ days before that 2^32-1 rolls over over back to 0.
But even if it does it will not matter as long as all your math is done using subtraction and you always subtract the earlier time from the later time.
example:
currentMillis = millis(); // capture the current time
elapsedMillis = currentMillis - previousMillis;
if (elapsedMillis >=duration){
previousMillis = currentMillis; // reset for the next cycle
// time has passed, do something
your_code_to_do_something;
}
using this approach, if previousMillis was a time before the rollover, and currentMilllis is after the rollover, the elapsedMillis is still correct:
previousMillis = 0xFFFFFF9C
currentMillis = 0x00000010
elapsedMillis = 0x00000074
and if duration = 0x100
then elapsedMillis is not >= duration, and you keep going.
SilentMusic:
But I provided an example in which it doesn't work; can you point out what is wrong with my example then?
Your example is wrong.
When millis() == 5, I set T = millis() + 6 (thus T == 3)
if millis() is equal to 5, then millis() + 6 is going to equal 11, not 3.
Thus millis() - T will not be greater than or equal to 0 until millis() returns 11. If that's not working as you would expect it to, then how do you expect it to work?
f millis() is equal to 5, then millis() + 6 is going to equal 11, not 3
You can't represent 11 decimal in three bits.
There are 10 kinds of people, those who know binary, and those who don't.
Ah, I see. I originally missed that. A contrived example in the name of simplification. Ok then, that is where he went wrong right there.
In which case, your original thinking was correct AWOL, the delay has to be less than half the rollover period, or half the max value the datatype can contain. If it is greater than that, it'll not only rollover, but potentially roll right past all the unsigned values that would get cast to negative signed values (any values with the msb set) and muck up the compare.