Reset millis

Rob, the code takes some understanding (by a learner!!), but I'm working my way through it.
I'm stuck with;
for(int i=0; i< 10; i++)
What does this do??

See reference page - http://www.arduino.cc/en/Reference/For -

robtillaart:
See reference page - http://www.arduino.cc/en/Reference/For -

But i does not appear to be used anywhere?
int i=0; //On first run sets the value of i as 0
i< 10; //checks to see if i is less than 10
i++ //adds one to the value of i

Does it run through 10 times and then execute the next piece of code? i.e. a delay of 10 cycles?

  for(int i=0; i< 10; i++)
  { 
    delay(10);
    Serial.println(MyMillis());
  }

you almost got it, the above code does execute the block between { and } 10 times

you can use the i in side the block too

example:

  for(int i=0; i< 10; i++)
  { 
    delay(i);
    Serial.println(MyMillis());
  }

here the i causes different (increasing) delay's

for has a few special tricks:

endless loop

for ( ; ; ) 
{
  ...
}

executes the block forever

int i=0;
for (i=0 ; i<10 ;i++ ) 
{
  ...
}
for (  ; i>0 ;i-- ) 
{
  ...
}

two for loops, the int i is declared outside the for loops so it can be reused, the first loop counts to 10 and the second loop counts back to 0.
This is possible as the second for does not (re)initialize the var i.

Thanks Rob, I get it now!

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

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

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.

[quote author=David Pankhurst link=topic=66962.msg492289#msg492289 date=1311125432]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.
[/quote]Wait, won't that just do the same as millis()? That'll overflow the same way...

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.

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

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?

myMilliseconds = ( millis() % 86400000UL);
myMilliseconds = millis();

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.

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

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

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

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

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

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

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.

// 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)

  MM = (startTime + millis() + 61367295 * wraps ) % 86400000UL;

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

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:

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

Because 4294967296 % 86400000 = 61367296 (4294967296 is the equivalent of the rollover 0)), then the next day at midnight you're not be at zero, but 61,367,296. You'd have to take that into account from now on, perhaps by subtracting this value before taking the modulo. However, unless you really plan to run something for 50 days, this likely won't be an issue.