Pages: 1 [2] 3   Go Down
Author Topic: Reset millis  (Read 2456 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Full Member
***
Karma: 0
Posts: 128
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks Rob, I get it now!
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13705
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


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
Logged

Rob Tillaart

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

Victoria, BC, Canada
Offline Offline
Full Member
***
Karma: 0
Posts: 222
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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.



Logged

London
Offline Offline
Full Member
***
Karma: 0
Posts: 168
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
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.
Logged

Current Projects: Rodentometer - Hamster Endurance Moni

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13705
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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  ....
Logged

Rob Tillaart

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

London
Offline Offline
Full Member
***
Karma: 0
Posts: 168
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
myMilliseconds = ( millis() % 86400000UL);
myMilliseconds = millis();
Logged

Current Projects: Rodentometer - Hamster Endurance Moni

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 613
Posts: 49270
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

London
Offline Offline
Full Member
***
Karma: 0
Posts: 168
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Silly me.  86,400,000 is such a big number for my little head smiley

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

Current Projects: Rodentometer - Hamster Endurance Moni

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 613
Posts: 49270
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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...).
Logged

London
Offline Offline
Full Member
***
Karma: 0
Posts: 168
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hah, I did the same, but assumed something about the overflow value.  Silly big numbers!  One.  Two.  Many.  Lots.  What more do we need?
Logged

Current Projects: Rodentometer - Hamster Endurance Moni

Victoria, BC, Canada
Offline Offline
Full Member
***
Karma: 0
Posts: 222
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 128
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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).
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13705
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


 
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:
// 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:
  MM = (startTime + millis() + 61367295 * wraps ) % 86400000UL;


Logged

Rob Tillaart

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

Offline Offline
Full Member
***
Karma: 0
Posts: 128
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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;)
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13705
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
Logged

Rob Tillaart

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

Pages: 1 [2] 3   Go Up
Jump to: