Millis()

Hi,

Is there a way to restart the millis() counter to zero using code?
I've googled and looked on the boards but couldn't find anything.

FlavoFraz:
Is there a way to restart the millis() counter to zero using code?

declare somewhere:

extern volatile unsigned long timer0_millis;
// reset
timer0_millis = 0;

Why bother?

extern volatile unsigned long timer0_millis;
// reset
timer0_millis = 0;

Are you certain that code is bug free?

That avoids a lot of extra coding just to handle overflow conditions.

What extra code? Please post an example.

It's not bug-free - gcc will emit 4x sts instructions to achieve the 32 bit write and an interrupt can happen between any of them. He needs to surround the zeroing with cli(), sei() calls to make it safe.

So, what you're saying is, you can have extra code to reset the clock (based on some criteria) to avoid overflow, or you can have code to handle the overflow?

It's been explained many times before by more experience software types then me, that if you always perform a subtraction when testing between present millis value and previously saved millis values that overflow will not be a problem ever, as the overflow bit handles the critical test at overflow time. You may be able to search for the better explanation, but the consensus has always been that the 55 day overflow 'problem' is not the problem if only a subtraction is used in comparing time values.

Lefty

It's not bug-free - gcc will emit 4x sts instructions ... surround the zeroing with cli(), sei()

That takes care of one problem. What about the next one?

I think this version of the "BlinkNoDelay" kind of test will work even if the end of the interval causes an overflow.

const unsigned long interval = 999;  

void loop()
{
  static unsigned long previousMillis = millis();
  unsigned long currentMillis = millis();  // Need it to be stable
  static boolean overflowed = false;

  // If our interval has wrapped (every 49+ days) make sure currentMillis overflows first
  if ( (((previousMillis + interval) < previousMillis) && 
    (currentMillis < previousMillis) && 
    (currentMillis >= (previousMillis + interval)) ) 
    ||
    ( ((previousMillis + interval) > previousMillis) && 
    (currentMillis >= (previousMillis + interval))))

  {
    previousMillis = currentMillis

      // Do the 'once per interval' stuff
  }

  // More efficient version
  if ( (overflowed && 
    (currentMillis < previousMillis) && 
    (currentMillis >= (previousMillis + interval)) ) 
    ||
    ( !overflowed && 
    (currentMillis >= (previousMillis + interval))))
  {
    previousMillis = currentMillis;
    overflowed = (previousMillis + interval) < previousMillis;   // The interval wraps

      // Do the 'once per interval' stuff
  }

}

If you have a way of handling millis() or micros() overflow without extra code, please post an example.

I have. On several occasions. Start with this...
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1260223964/1

I think this version of the "BlinkNoDelay" kind of test will work even if the end of the interval causes an overflow.

And is considerably more complicated than necessary.

I don't understand. Maybe a concrete example would help.

Your problem description is incomplete. You did not state the resolution or range of your timer. I'm going to assume a resolution of one full day; range of an unsigned long; no rounding. With a range of 0xFFFFFFFF / 365.24 = 11,759,301.5 years I don't think we need to worry about a rollover.

unsigned long PreviousMilliseonds;

static unsigned long OneDayInMilliseconds = 24ul * 60ul * 60ul * 1000ul;

unsigned long ElapsedDays;

void setup( void )
{
}

void loop( void )
{
  unsigned long CurrentMilliseconds;

  CurrentMilliseconds = millis();

  if ( CurrentMilliseconds - PreviousMilliseonds >= OneDayInMilliseconds )
  {
    ++ElapsedDays;
    PreviousMilliseonds = CurrentMilliseconds;
  }
}

We can assume unsigned long...

"unsigned long" is a data-type not a resolution. "Seconds" ... "nearest year" ... "full day" ... those are resolutions when measuring time.

You want a "crude" timer with a millisecond accuracy and a range greater than 50 days? And you consider that a "concrete" example?

Oh well. Who am I to judge...

long long ElapsedMilliseconds;

unsigned long PreviousMilliseonds;

void setup( void )
{
}

void loop( void )
{
  unsigned long CurrentMilliseconds;

  CurrentMilliseconds = millis();

  if ( CurrentMilliseconds - PreviousMilliseonds >= 1 )
  {
    ++ElapsedMilliseconds;
    PreviousMilliseonds = CurrentMilliseconds;
  }
}

The range is (0xFFFFFFFF / (24 * 60 * 60 * 1000)) * 0x80000000 = 1.06751991 × 10^11 days or 292,279,025 years.

What else can I do for you?

Oh, before I wander off I need to mention ... The problem you're describing has nothing to do with the millis rollover. It's a limitation of the data-type you've chosen. The only way to overcome the problem is to choose the correct (larger) data-type.

KE7GKP:
Then you are confirming that there is no way of handling the overflow

I just gave you a solution.

You must set up your own counter

Exactly.

I guess that is why I have not found an actual solution yet

I just gave you a solution.

Perhaps people here only do casual experiments with Arduino and never run up against the real-world cases of overflow

You believe your example is "real world"?

What you could do for me is explain why your notion of overflow is several orders of magnitude different than Arduinos?

64 bit variable storing milliseconds. The math is in the previous post.

KE7GKP:
The built-in Arduino functions millis() and micros() use unsigned long

Yup.

That is the longest integer data type available in Arduino-land

Nope.

Correct me if I am wrong here, but there appears to be no larger data-type available

I already have...

KE7GKP:
Please provide the reference to "long long" in Arduino?

I can't. The data-type is not listed in the Arduino reference. I'm sure you can find the reference you seek with a few Google queries.

you are saying that Arduino is incapable of continuous operation and must be regularly reset ... but that takes us back full-circle ... I allow the possibility that there actually is a solution

I agree. We have come full circle. I've given you a complete simple reliable solution and you are still not convinced that it works. I can only conclude that you lied. That you do not allow the possibility that a solution exists. Which means I am now wasting my time.

If you do reach the point that you will allow for the possibility that a solution exists I am willing to help with any problems you encounter.