Go Down

### Topic: Reset millis (Read 6175 times)previous topic - next topic

#### pauldreed

#15
##### Jul 19, 2011, 09:07 pm
Thanks Rob, I get it now!

#### robtillaart

#16
##### Jul 19, 2011, 10:52 pm

Advice, spend a few hours/evenings at the reference and tutorial section of Arduino.cc just to read code there. It should give you an impression how things work and can be done. Time spend in these sections is well spent!

Succes,
Rob
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

#### Utopia

#17
##### Jul 20, 2011, 03:30 am

I am using millis() to perform some time-based calculations, and want to be able to reset millis automatically every 24hrs back to 0.
I am using a long integrer to count millis, and was thinging along the lines of;
If millis() >= 86400000
set timer0_overflow_count to 0
Would this sort of approach work, or is there a better approach?

If all you need is a personal time that never goes over 86400000, then you can do that with the modulo operator (%) instead of working with the Arduino internals:

Code: [Select]
`unsigned long myMilliseconds = ( millis() % 86400000UL );`

myMilliseconds will always run from 0 to 86399999, inclusive. Don't forget that this is from the program starting, not midnite (unless you start the program at exactly midnight). Also, the millisecond count resets after about 50 days so you'll only be able to track it that long.

#### Cylindric

#18
##### Jul 20, 2011, 01:40 pm
Code: [Select]
`unsigned long myMilliseconds = ( millis() % 86400000UL );`

myMilliseconds will always run from 0 to 86399999, inclusive. Don't forget that this is from the program starting, not midnite (unless you start the program at exactly midnight). Also, the millisecond count resets after about 50 days so you'll only be able to track it that long.
Wait, won't that just do the same as millis()?  That'll overflow the same way...

Quote from: Reference
Returns the number of milliseconds since the Arduino board began running the current program. This number will overflow (go back to zero), after approximately 50 days.

#### robtillaart

#19
##### Jul 20, 2011, 03:47 pm
Quote
Wait, won't that just do the same as millis()?  That'll overflow the same way...

Yep, as its value is derived from millis() it has to follow wherever millis() goes even in an overflow  ....
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

#### Cylindric

#20
##### Jul 20, 2011, 03:50 pm
My point is, aren't these identical?  The result of millis() will overflow back round to zero anyway, so why mess about with the whole modulo thing?

Code: [Select]
`myMilliseconds = ( millis() % 86400000UL);myMilliseconds = millis();`

#### PaulS

#21
##### Jul 20, 2011, 04:21 pm
Quote
My point is, aren't these identical?

Think about the values returned my millis() and stored in myMillis (using the modulo operator) after 1 second of running, 1 minute, 1 hour, 1 day, 1 week, and 1 month.

They will be the same up to the 1 week mark. After 1 week, the myMillis value will be millis() minus 1 week. After 2 weeks, the myMillis value will be millis() - two weeks.

Once millis() overflows, after about 7 weeks, the values match again for another week.
The art of getting good answers lies in asking good questions.

#### Cylindric

#22
##### Jul 20, 2011, 04:25 pm
Silly me.  86,400,000 is such a big number for my little head

Wouldn't the numbers match after a day though?  86400000 milliseconds = 1 day.

#### PaulS

#23
##### Jul 20, 2011, 04:51 pm
I read the 86,400,000 value and the request to reset the millis timer after a week, and assumed that whoever came up with the number could operate a calculator. But, yes, the value represents one day, not one week, so everywhere I said week, substitute day (or use the correct value...).
The art of getting good answers lies in asking good questions.

#### Cylindric

#24
##### Jul 20, 2011, 04:57 pm
Hah, I did the same, but assumed something about the overflow value.  Silly big numbers!  One.  Two.  Many.  Lots.  What more do we need?

#### Utopia

#25
##### Jul 20, 2011, 08:38 pm

Wouldn't the numbers match after a day though?  86400000 milliseconds = 1 day.

That's the idea - the original poster wanted a timing pulse that reset every day to zero - the modulo (%) was one way to provide it. And since the maximum value millis() can 'hold' is 4,294,967,295 that still gives room for almost 50 rollovers before the original value rolls over

#### pauldreed

#26
##### Jul 20, 2011, 09:28 pm
I have never used or even seen the modulo (%) used anywhere before, but it's an ingenious way of achieving this result, and one which I would have never considered.
Assuming that the counter is started at midnight, (to gather a full day's data), what would happen if after 49 days and millis overflows and returns back to zero, say at midday when myMilliseconds = 43200000 ?
Will myMilliseconds continue on to  43200001, 2, 3 ect.
Or, will it return back to zero (and start the 24 hour counter from midday instead of midnight, throwing the 24hr period out of sync).

#### robtillaart

#27
##### Jul 21, 2011, 12:20 am

Quote
Will myMilliseconds continue on to  43200001, 2, 3 ect.

As MyMilliseconds as it was previous defined just follows millis it will jump to 0   as 0 % 864000000UL  = 0.

It will happen after 49 days, 17 hours, 2 minutes, 47 seconds and 295millis. So between tea time and dinner, not the most easy time.

Fortunetely we know it will happen exactly after 61367295 millis after midnight (assumption no drift).
So we can use that number as a correction factor every time you see that millis has been wrapped to zero again.

Code: [Select]
`// assumption it is called at least once per 7 weeks :)unsigned long MyMIllis(){  static unsigned int wraps = 0;  static unsigned long MM = 0;  if (MM > millis() ) wraps++;   // millis() has been wrapped  MM = (millis() + 61367295 * wraps ) % 86400000UL;  return MM;}`

wraps is a unsigned int -> allows you to wrap 65535 times (* 49 days...) >>  8000+ years
if wraps is a byte it would be sufficient for 30+ years or so.

by adding an offset in the main formula you can even start your sketches at some predefined time. e.g. 08:00 AM => startTime =  (8 * 3600000UL)
Code: [Select]
`  MM = (startTime + millis() + 61367295 * wraps ) % 86400000UL;`

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

#### pauldreed

#28
##### Jul 21, 2011, 01:04 am
Rob, you've just fried my brain!
I'm going to have a large whisky, some paracetamol, and go to bed.

start;
whisky+paracetamol+sleep=x;
x=clear_brain;
if clear_brain = x;
then start again tomorrow!!;

(Please don't correct my logic, I know it's wrong, but goto start;)

#### robtillaart

#29
##### Jul 21, 2011, 01:36 am
Quote
Rob, you've just fried my brain!

Think I join the whiskey...

Tip for tomorrow: draw a timeline and write the values under and above, and let millis() overflow on paper ...

millis():
----------------------------------------------------------------------------
MyMillis():
----------------------------------------------------------------------------
wraps:
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Go Up