Go Down

Topic: When does millis() increment? (Read 749 times) previous topic - next topic

ArduinoTom

When going from one count to the next, when does millis() increment?  For example, if it's been 1025.4 ms since the Arduino fired up, would millis() return 1025 or 1026? 

retrolefty


When going from one count to the next, when does millis() increment?  For example, if it's been 1025.4 ms since the Arduino fired up, would millis() return 1025 or 1026?   


It's being counted as a result of a timer interrupt, so it will return 1025 until the next interrupt increments it to 1026. It's a simple count not a measurement.

Lefty

Nick Gammon

The interrupt fires every 1.024 mS, so millis() increments that often. Because of the slight discrepancy (the 0.024 part) the interrupt will increment the millis figure by 2 from time to time (think of it as a leap year).

That's on a Uno or similar running at 16 MHz.

Nick Gammon

One of my sketches on this page uses Timer 2 to generate interrupts exactly every 1 mS (rather than 1.024 mS) which you might find useful if you want an exact count (at least, within the error of the onboard crystal or resonator).

Krupski


When going from one count to the next, when does millis() increment?  For example, if it's been 1025.4 ms since the Arduino fired up, would millis() return 1025 or 1026?   


In your example, millis() would return 1025 since is has not yet been flipped to 1026 yet.

Imagine you are the Arduino and you have a mechanical counter in your hand. Every second, you press the button.

If the counter currently has "1025" in it and the next second has not arrived yet (i.e. you have not pressed the button again) and I look at your counter, I will see 1025.
Gentlemen may prefer Blondes, but Real Men prefer Redheads!

tack


The interrupt fires every 1.024 mS, so millis() increments that often. Because of the slight discrepancy (the 0.024 part) the interrupt will increment the millis figure by 2 from time to time (think of it as a leap year).

That's on a Uno or similar running at 16 MHz.

Ahh, that's interesting information. Thanks Nick.

I know I've got a little timer bug in one of my early sketches. I totally suspect it is because I've done something like 'if millis()-lastmillis==1000 when it needs to be >=1000 but haven't got round to fixing it yet. Every now and then the led stops flashing and stays on. Millis() jumping 2, so the interval goes from 999 to 1001 would explain that.

ArduinoTom

Thanks all. Great info.  Two questions about micros() then:

1. Does using micros() in a sketch cause the processor to work extra hard (slow down) trying to increment a counter so frequently, or is that happening anyway?

2.  When micros() rolls over back to zero after 70 minutes or so, am I right to think this math still works:

If (nowMicros -thenMicros > 1000) {do something};


PaulS

Quote
1. Does using micros() in a sketch cause the processor to work extra hard (slow down) trying to increment a counter so frequently, or is that happening anyway?

Think about that. The clock is going to tick, whether you look at it, or not.

Quote
2.  When micros() rolls over back to zero after 70 minutes or so, am I right to think this math still works:

As long as the interval (1000 in this case) is less than the rollover time, yes.

michinyon

The number of microseconds  actually gets incremented by 4,   after every 4 microseconds.   Or something like that.
So if you expect it to exactly hit a specific value,  you might be disappointed.

Nick Gammon

#9
Feb 10, 2013, 09:09 pm Last Edit: Feb 10, 2013, 10:12 pm by Nick Gammon Reason: 1
Quote
Does using micros() in a sketch cause the processor to work extra hard (slow down) trying to increment a counter so frequently, or is that happening anyway?


It's doing it anyway. Every 1.024 mS an interrupt occurs (when the timer overflows) and this is when the number used by millis() is calculated. Basically the interrupt adds one to the counter, and sometimes adds another one to allow for the fact that the timer interval is slightly longer than 1 mS.

To calculate micros, the micros() function interrogates the timer hardware to find exactly how far it is between the last millis "tick" and now. It then adds that to the value used by millis() Timer 0 overflow count to get a higher-resolution result.

As michinyon said, because of the timer prescaler, this will always be a multiple of 4 (microseconds) because the timer has a prescaler of 64 (64 * 62.5 nS = 4 uS).

This calculation is reasonably quick (it has to get data from the timer register) however it would take longer than millis() because of the add, and there is a multiply in the code as well, which looks to me like it is being done by a couple of adds, so that is fairly fast.

It's interesting to note that, because of the fact that micros() uses the millis() figure as part of its calculation, that micros() must skip every now and then (every 41 mS or so) by a whole millisecond (1000 uS).

(Edit) That last statement was wrong. micros() uses a different figure (simply the Timer 0 overflow count) to get the return value, and thus it is not affected by the "jumping" or inaccuracy that affects millis().

Go Up