millis overflow

after the millis() overflow and return to be 0, does it start running again until it overflowing again ?

Yes.
It's value is incremented and incremented. While it is being increment it might rollover.

The millis() returns a variable of 32-bits. That is a variable with bit 0 up to bit 31. When it does a rollover, the bit 32 should become '1'. But that bit does not exist.

Yep. It doesn't "stop" at all when it wraps around. 0xFFFFFFF + 1 = 0, 0 + 1 = 1, etc...

yes, every 49 + days

49.71026962962962962962962962963 days x 24 hrs /per day x 60 min/per hour x 60 secs / per min * 1000 mS / per second=232 = 4294967296

The limitation is due to the largest number the uC can handle is 232.

so if I’m planning to do something like that :

	  unsigned long currentMillis = millis();
	  unsigned long previousMillis = 0;
	  unsigned long interval = 1000;

	  if ((unsigned long)(currentMillis - previousMillis) >= interval) {
		  SomeFunction()
		  previousMillis = currentMillis;
	  }

I sould also add that ? : (for when it rollover ?)

	  else{
                  if(currentMillis < previousMillis){
		          previousMillis = 0;
                  }
	  }

Read this:

If you mean a counter to count the roll-overs that could be tricky.

LarryD:
Read this:
Gammon Forum : Electronics : Microprocessors : millis() overflow ... a bad thing?

I read that just now, so just correct me if I’m wrong
what I wrote above will work…
but that will work better :

unsigned long startTime = millis ();
unsigned long interval = 60000;

if (millis () - startTime >= interval)
  {
  // do something
  }

The code you have in your last reply is what you want to stick with.
Normally you would have the following in order to repeat things.

if (millis () - startTime >= interval)
{
startTime = startTime + interval
// do something
}

If you have a hour or so look at this thread:

LarryD:
The code you have in your last reply is what you want to stick with.
Normally you would have the following in order to repeat things.

if (millis () - startTime >= interval)
{
startTime = startTime + interval
// do something
}

tnx :slight_smile:
but the code from my last reply was quote from what you let me to read...

LarryD:
If you have a hour or so look at this thread:
http://forum.arduino.cc/index.php?topic=223286.0

ty I will look at it tomorow

This has a test sketch that explains how the rollover will not be a problem : http://playground.arduino.cc/Code/TimingRollover#arithmetic

LarryD:
The code you have in your last reply is what you want to stick with.
Normally you would have the following in order to repeat things.

if (millis () - startTime >= interval)
{
startTime = startTime + interval
// do something
}

@LarryD - I'm not convinced that works, although I understand why you are doing it.

Let's say you want something to happen every 20 mS, and it is now 10 mS before rollover:

Time now: 2^32 - 10 = 4294967286 (0xFFFFFFF6)

Add 20:

2^32 + 10 = 4294967306 (0x10000000A)

That truncates to 4 bytes:

0x0000000A (10 in decimal)

Now our test is:

if (millis () - startTime >= interval)

That is:

if (4294967286 - 10 >= 20)

That is:

if (4294967276 > 20)

It immediately passes that test (not 20 mS later).


(edit) After further discussion below it appears that I am wrong about this. Since we are adding to startTime (which is in the past), and after adding our interval, we should either be at the current time, or a millisecond or so earlier than it. Thus, startTime will not wrap around before actual time does, and the problem goes away.

   startTime = startTime + interval

The flaw in this is the exact reason we recommend subtracting to work out when time has passed, and not adding. So you have merely transferred the flaw from the "if" to the calculation for when to do whatever-it-is next.

So how to fix this? The reason for doing the add in the first place is to stop "creep", which is when you notice that it is time to take action a millisecond or so later. And if you don't allow for it, the actions creep forwards slightly. I should point out that this normally doesn't matter, eg. flashing an LED or turning on a pump for the fish. But if it does matter, what can we do?

Problem area:

if (millis () - startTime >= interval)

If interval is 60000 and we get delayed doing something then we might find that millis () - startTime is 60001 or maybe 60002.

So we can use that information, can't we? Have two variables. One is the desired interval (60000) and the other is the "working" interval.

So we could update the working interval like this:

const unsigned long INTERVAL = 60000;
unsigned long workingInterval = INTERVAL;

...
unsigned long timeNow = millis ();
if (timeNow - startTime >= workingInterval)
  {
  unsigned long adjustment = (timeNow - startTime) - INTERVAL;  // might be 0, 1, 2 or something
  workingInterval = INTERVAL - adjustment;  // eg. 60000, 59999, 59998 etc.

  //  now do whatever
  }

Effectively this reduces the time when we next act by the amount of time we were late this time around.

@Nick

if (millis () - startTime >= interval)

That is:

if (4294967286 - 10 >= 60000)

Must be missing something here, if your premise is "Let's say you want something to happen every 20 mS"
then this would be:
if (4294967286 - 10 >= 6000 20)

So you are saying millis() is 4294967286 at which time the if statement is true.
startTime would then increment to 4294967286 +20 = A
next iteration could still be
if (4294967286 - 10 >= 20) which is true again right away
etc. etc. until millis() overflows to zero.

WOW :astonished:
Not good!
Thank you, "Eyes Wide Open"

LarryD:
@Nick

if (millis () - startTime >= interval)

That is:

if (4294967286 - 10 >= 60000)




Must be missing something here, if your premise is "Let's say you want something to happen every 20 mS"
then this would be:
if (4294967286 - 10 >= ~~6000~~ 20)

Oh yeah, I had 60000 on the brain. I amended my earlier post. But still:

if (4294967286 - 10 >= 20)

Clearly it will immediately pass the test. And again, and again. So if you are feeding fish or chooks or something, every 49 days they will get a lot of food!

Clearly it will immediately pass the test. And again, and again. So if you are feeding fish or chooks or something, every 49 days they will get a lot of food!

Or if you are writing code for a heart stimulator.

2014-10-06_0-22-19.jpg

So must also add:
startTime = timeNow;
after line
workingInterval = INTERVAL - adjustment;
?

unsigned long timeNow = millis ();
if (timeNow - startTime >= workingInterval)
  {
  unsigned long adjustment = (timeNow - startTime) - INTERVAL;  // might be 0, 1, 2 or something
  workingInterval = INTERVAL - adjustment;  // eg. 60000, 59999, 59998 etc.
  startTime = timeNow;
  //  now do whatever
  }

Good point. Untested code, but yes, you clearly have to do that. :slight_smile: