Go Down

Topic: What is exact value for millis() rollover? (Read 3802 times) previous topic - next topic

gpvillamil

I am in the process of writing code to deal with the millis() rollover on the Arduino.

Since I don't want to wait 50 days -

Does the Arduino clock rollover to 0 after millis() reaches 2,147,483,647 (maximum value of a *signed* long, 24.8 days), or 4,294,967,294 (maximum value of an *unsigned* long, 50 days)?

While the documentation implies that the latter is the case, it seems strange, since there would not be any variable type that would catch it - assigning var = millis() when millis > 2,147,483,647 would cause var to overflow.

Can anyone confirm the rollover value for the millis() function, or better still, show some working examples of millis() based timers that compensate for rollover?

mellis

Looking at the code again, I think the clock will overflow every 33 million milliseconds or so or about 9.3 hours.  I'd better update the documentation, since this is obviously significantly shorter than 50 days.  The mistake was that the count overflows not at 4 billion milliseconds, but at 4 billion of the largest intermediate value in the computation of milliseconds.  Sorry about that.  But I imagine it won't be so bad to write code to handle the overflow.  Let us know if you have any trouble.

gpvillamil

Thank you for the info!

My current scheme is to maintain my own timer, based on millis() modulo <timerLimit>, where <timerLimit> is a number under the rollover threshold. I would then use the self-maintained timer to calculate intervals between events, with a prior check that, if a previous event appears to happen *after* the current timer (ie a rollover has occurred), then <timerLimit> is subtracted from the previous event. I would also track the number of rollovers that have occurred.

I am working on a project where very slow changes must be accurately measured...

natable

I am working on a project that must accurately keep time over weeks & months.  Therefore, the millis() rollover is important.  A colleague helped modify the wiring.c & .h files to include a function that directly returns the timer0_overflow_count.  Similar to gpvillamil's schema, the bitwise AND isolates only the long portion (timer0_overflow_count & 0xFFFF).  Therefore, the overflow is known and can be trapped.

Using this, I ran a simple program for over 9 hours and captured:
Quote
ticks millis
h:m:s ms
0:0:1 1000
0:0:2 2000
  ...
9:32:38 34358000
9:32:39 34359000
9:32:40 261
9:32:41 1261


Therefore, it would appear that the millis() overflow occurs at 34,359,739ms or 9h, 32m, 39s, and 739ms.  I'll be working on rollover trap based on millis() so that the code is compatible w/ Arduino 6...

Till then, I've done the following code modifications, but I would instead recommend making your own header:
wiring.c
Code: [Select]
unsigned long ticks()
{
     // timer 0 increments every 8 cycles, and overflows when it reaches 256.
     return timer0_overflow_count;
}


wiring.h
Code: [Select]
unsigned long ticks(void);

impoze

hi,

so how would i make my timer continue on past the overflow?

must i store the timer when it overflows and restart the timer?

and what would i do to handle the overflow?

thanks,

mellis

BTW, if you don't want to modify wiring.c or wiring.h, you should be able to add this line to the top of your sketch and then access timer0_overflow_count as a normal variable:

Code: [Select]

extern volatile unsigned long timer0_overflow_count;

Go Up