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?
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?
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
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.
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).
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?
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.
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.
Thanks all. Great info. Two questions about micros() then:
-
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?
-
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};
- 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.
- 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.
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.
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().
Nick,
I was looking at using your timer sketch to generate an accurate 1 mS interrupt on timer 2. I was wondering if this could be used like millis() in the blink without delay sketch? Is there some timer code that would keep track of the number of interrupts from timer 2 to then accumulate the count of milliseconds like the millis command does?
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).
const byte OUTPUT_PIN = 3; // Timer 2 "B" output: OC2B
const byte n = 224; // for example, 1.111 kHz
void setup()
{
pinMode (OUTPUT_PIN, OUTPUT);
TCCR2A = bit (WGM20) | bit (WGM21) | bit (COM2B1); // fast PWM, clear OC2A on compare
TCCR2B = bit (WGM22) | bit (CS22); // fast PWM, prescaler of 64
OCR2A = n; // from table
OCR2B = ((n + 1) / 2) - 1; // 50% duty cycle
} // end of setup
void loop() { }
This is the example code form Nick's forum. I want to follow this type of structure without writing anything to a pin. I just want to keep count of the number of times the OCR2A = 249 (period of 1 mS) and use that count to make a currentMillis and previousMillis value then essentially run a blink without delay sketch.
Sdlyons:
This is the example code form Nick's forum. I want to follow this type of structure without writing anything to a pin. I just want to keep count of the number of times the OCR2A = 249 (period of 1 mS) and use that count to make a currentMillis and previousMillis value then essentially run a blink without delay sketch.
something like this maybe (adapted from Nicks webpage:Gammon Forum : Electronics : Microprocessors : Timers and counters)
(UNTESTED!)
volatile unsigned long T2_ms_count = 0;
ISR (TIMER2_COMPA_vect)
{
++T2_ms_count;
}
void setup()
{
// Timer 2 - gives us our 1 ms counting interval
// 16 MHz clock (62.5 ns per tick) - prescaled by 128
// counter increments every 8 µs.
// So we count 125 of them, giving exactly 1000 µs (1 ms)
OCR2A = 124; // ((1ms) x ((16MHz)/(128 prescaler)))-1
// initialize counter
TCNT2 = 0;
// enable compare interrupt
TIMSK2 |= (1 << OCIE2A);
TCCR2A = bit (WGM21) ; // CTC mode
TCCR2B = bit (CS20) | bit (CS22) ; // prescaler of 128. start Timer 2
} // end of setup
void loop() { }
Thank you Sherzaad! The program works, but Arduino does not seem to be fast enough to use it as a millis operation in the variation of blink without delay that I am executing. I am trying to make a very accurate delay, but it seems like I need to do too many things too quickly to use timers. The only commands that I can use that are somewhat accurate are delay, delayMicrosecond, millis, and _delay_us(). I would like to find a more accurate method, but I am having a hard time because my on time and off time for the blink without delay program are programmable with a keypad. The user enters the number of milliseconds for each and after each output goes high I need to add a microsecond delay that increments by a user define number (typically 1uS, but could be anything) of microseconds each time the output goes high.