3

I want to know how much time has elapsed since a certain event, and I do not want to use any external timers. It seems logical to reset an internal timer whenever the event occurs (using an interrupt). Unfortunately, as far as I can tell, millis() and micros() cannot be manually reset. Obviously, I could save a time stamp whenever the event occurs; however, I want to avoid overflow problems (micros() will overflow every ~71 minutes, and millis() will overflow every ~50 days).

Is there a way to manually reset these built-in counters? If not, how can I manage the overflow?

rebatoma
5593 gold badges12 silver badges22 bronze badges
asked Apr 11, 2016 at 16:42

3 Answers 3

6

millis() and micros() overflow periodically. However, this is not a problem: as long as you compare durations instead of timestamps you can forget about the overflows.

The liked answer also gives the trick for resetting millis(). Can be handy for testing purposes, but you do not need this to handle the millis() rollover problem. Notice that there is no clean way to reset micros(): it relies on a static variable, i.e. a variable private to the file defining it.

answered Apr 11, 2016 at 17:28
5

Overflow is never really an issue if you always calculate time difference. (Unless the time difference is more that 50 days.)

unsigned long previousTime = millis();
... wait for some event to happen ...
unsigned long elapsedTime = millis() - previousTime;

Even if previousTime was before the overflow, and millis() is after the overflow (so essentially millis()<previousTime), elapsedTime will still be the correct value.

This is because the calculation itself will also overflow. Since millis()<previousTime, the result would be negative, but the type of the variable is unsigned, so it wraps around. I hope that makes sense.

Just don't ever do something like if( millis() > (previousTime+1000) )

If you still want to reset millis, you can use the following:

extern volatile unsigned long timer0_millis;
unsigned long new_value = 0;
void setup(){
 //Setup stuff
}
void loop(){
 //Do stuff
 //--------
 //Change Millis
 setMillis(new_value);
}
void setMillis(unsigned long new_millis){
 uint8_t oldSREG = SREG;
 cli();
 timer0_millis = new_millis;
 SREG = oldSREG;
}
answered Apr 11, 2016 at 17:29
1
  • I haven't tried the SetMillis() example yet, but this would be perfect to test the rollover. I don't see using it in normal circumstances, but to test my rollover code, this would be great, as I don't see having my Arduino set and run for 50 days and get to the part where it rolls over! Commented Jun 12, 2018 at 1:51
0

It seems logical to reset an internal timer whenever the event occurs (using an interrupt).

No it doesn't. You don't reset your clock to 00:00 when you put a cake in the oven do you?

What you do is note the time. Then periodically you subtract the start time from the current time, giving you the elapsed time. When time is up, you remove the cake from the oven.


Think about it for a minute. What if you wanted to time two events? Setting millis back to zero would hardly work then, would it? Setting it to zero for the second event would corrupt your timing for the first event.

However noting the time each one starts, and comparing the time now to the start time, will work for any number of events.


For more details see my post about millis() overflow ... a bad thing?

answered Apr 11, 2016 at 22:04

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.