Millis overflow

millis takes 49+_days to rollover (and so what if it does?) = 2^32mS * 1sec/1000mS * 1min/60sec * 1hr/60min * 1day/24 hrs
micros takes some number of hours to rollover = 2^32mS * 1sec/1000000uS * 1min/60sec * 1hr/60min * 1day/24 hrs

if all your time calculations are done as:
if ((later_time - earlier_time ) >=duration ) {action}
then the rollover does generally not come into play.

THanks so much

but i have another question is there a way to use miilis to calculate hrs of the day without problems

By "calculate hrs of the day" do you mean tell the time?

Sure:

currentMillis = millis();
if ( (currentMillis - previousMillis) >= 1000){
previousMillis = previousMillis + 1000;
seconds = seconds +1;
if (seconds == 60){
seconds = 0;
minutes = minutes +1;
if(minutes == 60){
minutes = 0;
hours = hours +1;
if (hours == 24){
hours = 0;
} // end hrs check
} // end minutes check
} // end seconds check
} // end time check

aabdelrahman_12:
but i have another question is there a way to use miilis to calculate hrs of the day without problems

No, millis() tells you how long the sketch has been running, it does not tell you what the real-world time is. If you had an external source that you can get real world time from, for example a network interface or real time clock, then you could use millis() to extrapolate from that. However it doesn't directly tell you what the time is.

I don't know how to thank you @crossroad

@ peter thanks .i know and my idea is based on set-up the current time using serial communication when my arduino start working

You could use the abs function which returns the +ve differance between the two numbers.

Eg

a=27;
b=30;

abs(a-b) and abs(b-a) will both give 3.

Mark

millis() returns an unsigned long.

Whenever you subtract an older time from a newer one, you get the correct unsigned result. No matter if there was an overflow.
You never need abs() for such calculations.

For ease of understanding think in bytes ( 0.. 255 ), instead of unsigned longs.
Example: If your old time was at 250 and now you're at 5 , you calculate (5 - 250) and interpret the result as an unsigned byte, the result is 11.
abs() might just make it worse (if you are in the wrong data types for intermediate values).
abs() of an unsigned value should not do any harm, but if you think it might help, you should rethink :wink:

CrossRoads:
if all your time calculations are done as:
if ((later_time - earlier_time ) >=duration ) {action}

then the rollover does generally not come into play.

Thanks

(No harm in resurrecting this, I guess)

Are there instances where the rollover does come into play?

Nick_Pyner:

CrossRoads:
if all your time calculations are done as:
if ((later_time - earlier_time ) >=duration ) {action}

then the rollover does generally not come into play.

Thanks

(No harm in resurrecting this, I guess)

Are there instances where the rollover does come into play?

When duration is >= the rollover period. (Or if you use signed comparison, >= 1/2 the rollover period).

I found this link, it avoids the problem of rollover.

The quick answer to “How do you reset millis()” is: You Don’t! And here’s why: if you did, it would potentially break most libraries and functions that rely on it. Generally the reason people want to reset it, is that they are concerned about rollover. Instead of focusing on resetting millis(), here is how to use it correctly.
Avoiding rollover and checking how much time as passed is done in a single line:
if ((unsigned long)(millis() - waitUntil) >= interval)
That single line of code is all that is really needed, to avoid rollover! Pretty simple, huh? So let’s go into more detail about how this works and what each of those variables do.

if ((unsigned long)(millis() - waitUntil) >= interval)

Better I think to capture the time

currentTime = millis();

currentTime = micros();

and then use that in your calculations.
This allows the same currentTime value to be used several times in blink without delay sketches:

void loop():
currentTime - micros();
elapsedTime1 = currentTime - previousTime1;
elapsedTime2 = currentTime - previousTime2;
elapsedTime3 = currentTime - previousTime3;
if (elapsedTime1 >= duration1){ 
   previousTIme1 = previousTime1 + duration1 // set up for next time interval
   // event 1 action(s)
   }
if (elapsedTime2 >= duration2){ 
   previousTIme2 = previousTime2 + duration2 // set up for next time interval
   // event 2 action(s)
   }
if (elapsedTime3 >= duration3){ 
   previousTIme3 = previousTime3 + duration3 // set up for next time interval
   // event 3 action(s)
   }
} // end loop
[//code]

if ((unsigned long)(millis() - waitUntil) >= interval)

The name waitUntil is poorly chosen. It implies that the variable holds the time at which the interval ends. In this case it holds the time at which the interval starts, and this is the best way IMO to deal with intervals while avoiding rollover issues.

Casting the return value from millis() to an unsigned long is redundant since it is already an unsigned long.

CrossRoads:
if all your time calculations are done as:
if ((later_time - earlier_time ) >=duration ) {action}
then the rollover does generally not come into play.

Should later_time and earlier_time be set as signed or unsigned variables?

Only 3 years late to the millis() party...

donovanpl123:
Should later_time and earlier_time be set as signed or unsigned variables?

unsigned longs

If you read this quote with attention, you will find the very best answer for your torments.
Understand the data_types.
Thank you Michael_X

michael_x:
millis() returns an unsigned long.

Whenever you subtract an older time from a newer one, you get the correct unsigned result. No matter if there was an overflow.
You never need abs() for such calculations.

For ease of understanding think in bytes ( 0.. 255 ), instead of unsigned longs.
Example: If your old time was at 250 and now you're at 5 , you calculate (5 - 250) and interpret the result as an unsigned byte, the result is 11.
abs() might just make it worse (if you are in the wrong data types for intermediate values).
abs() of an unsigned value should not do any harm, but if you think it might help, you should rethink :wink:

when it exceeds millis, the variables are initialized, since the variables are greater than millis.

// while loop

while (int((millis() - start)) < timeout) {

if (millis() < start){ start = 0xffffffff - timeout - start; }

//accions

}

// or
//condition if

if (millis() < start){ start = 0xffffffff - timeout - start; }

if (millis() - start > timeout){

//accions

{

why not using unsigned long long?
it is proved to be at least 64 bits or 8 bytes so it can store 2^64 -1 numbers or 18446744073709551615 miliseconds, also Arduino compiler accept it and I tried with UNO R3, it worked.
this is 584942417.35 years!!!

Why would you? millis() returns a unsigned long. Which works fine for forever as long as the interval you want to time is smaller then 49 days. Only requirement is you check it like:

if(millis() - lastMillis >= interval){
//and NOT like
if(millis() >= lastMillis + interval){