How to detect if millis() has passed a certain time T

I'm trying to detect whether millis() has "passed" a certain time T and I found this:
http://www.arduino.cc/playground/Code/TimingRollover

It says that I can do this

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).

  1. When millis() == 5, I set T = millis() + 6 (thus T == 3)
  2. 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.

How does one fix this?

KE7GKP:
You have two different questions there. Which one are you asking about?

  1. simply comparing millis() to some target number will tell you whether you are past the time you set.
  2. 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

if (millis() - previous >= interval) {
    previous = millis();
    execute();
}

I want to just keep a 32-bit timestamp and track if millis() has passed this time. I can't just do:

target = millis() + interval

...

if (millis() >= target) {
    execute();
}

Because

  1. suppose millis() runs from 0...1000 and rolls over.
  2. 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.

But I provided an example in which it doesn't work; can you point out what is wrong with my example then?

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.

I think problems only arise if the delay exceeds half the roll-over period.
Have to put my thinking-cap on.

I think problems only arise if the delay exceeds half the roll-over period.
Have to put my thinking-cap on.

Exactly. And, if the desire is to have the Arduino only do something every 25 days or so, a RTC is a much better solution.

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.

  1. 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.

AWOL:

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.