Go Down

MattCook

Jan 18, 2008, 02:25 pmLast Edit: Jan 18, 2008, 02:28 pm by MattCook Reason: 1
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?

timmaah

#1
Jan 18, 2008, 03:57 pm
Check out:

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

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

ckiick

#2
Jan 18, 2008, 05:12 pm
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.

MattCook

#3
Jan 18, 2008, 07:23 pm
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

axileon

#4
Jan 22, 2008, 03:51 pm
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

ckiick

#5
Jan 24, 2008, 03:49 am
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,

BigMike

#6
Mar 17, 2008, 03:30 pm
Quote
Check out:
http://blog.faludi.com/2007/12/18/arduino-millis-rollover-handling/

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