Questions about millis()

The reference guide states that the millis() function can run for about 9 hours before rolling-over to zero.

I was wondering what the exact value is that it rolls-over after? If I knew this then I could still work out the elapsed time after it had rolled-over ... assuming I'd checked it before it rolled over the first time. By keeping a count of the number of roll-overs I could have my own VERY long elapsed time function.

This got me to thinking about the roll-over value/time and I am now not sure how the 9 hours is calculated. The reference guide tells me that millis() provides a value of data type unsigned long. Then it tells me that an unsigned long (32 bits) ranges from 0 to 4,294,967,295 (2^32 - 1). By my calculation this should roll-over after 1193 hours (~50 days), assuming the full 32 bits are used.
4,294,967,295 / 1000 = 4,294,967 seconds
4,294,967 /60 = 71582 minutes
71582 / 60 = 1193 hours

This is a long way from 9 hours .... can someone clarify this for me please?

Secondly, is it possible to clear, or reset the millis() counter back to zero via software?

Thanks in advance ... Matt

Check out:

http://blog.faludi.com/2007/12/18/arduino-millis-rollover-handling/

Linked from:

http://www.arduino.cc/playground/Main/GeneralCodeLibrary

The millis function doesn't actually count milliseconds. It uses an internal counter based on the number of times that timer0 overflows. Timer0 ticks every 8 clock cycles. It's 8 bits wide so it overflows every 256 ticks. So each increment of the internal counter represents 2048 clock cycles. The counter is an unsigned long. At 16Mhz, that's 550 seconds, which is about 9 hours.

You can easily detect an overflow by comparing two consecutive times: if the second is less than the first then an overflow has occurred. The problem is that you don't know how many, and if you wait long enough even that method won't work.

What you could do is to edit the overflow interrupt handler to use TWO variables, an overflow counter and an overflow-overflow counter. Then do some fancy (but careful) math to get the number of milliseconds.

Resetting the counter is easy: set timer0_overflow_count to 0.

Thanks for the feedback !

timmaah, your reply looks like it may nail the solution I'm after. I hadn't spotted that, thanks for pointing it out.

ckiick, thanks for the info on how the millis() function works. The name seems misleading to me. timmaahs' solution should deal with the overflow issue, all I have to work out is some algorithm to give me a millisecond conversion (or as near accuracy as I can hope for).

I'm new here but this already strikes me as a very friendly and helpful place.

Many thanks ..... Matt

sorry but i have a question regarding the tick for timer0. how do u know that it ticks once every 8 clock cycles? i cant seem to find it in the manual

For how to set the timer scaler see section 15.11.2 of the ATMega168 data sheet. There's a link from the hardware page on this site.

There are some comments for the millis() function that tell how it works in the wiring.c file.

To see where it is set, look in the wiring.c file. Search for the register name TCCR0 or TCCR0B.

Hmm.... it seems to be set to 64 now, instead of 8. That means the timer ticks once for every 64 clock cycles. Wonder when that happened. That means the counter won't overflow as much, but delayMicroseconds won't be as accurate.

HTH,

Check out:
http://blog.faludi.com/2007/12/18/arduino-millis-rollover-handling/

From that link:

You want to blink an LED only on Christmas during leap years? Totally possible now.

Made me chuckle :slight_smile:

Mike

i want to use the timer0 overflow vector interrupt but i m unable do so because it is already in use by millis() function...
is there any way to stop the millis() function from operating...??