Don't call us, we'll call you In part 1 of this series, we learned how to use millis() for timing. But in order to make that work, we had to call millis() every time through the loop to see if it was time to do something. It is kind of a waste to be calling millis() more than once a millisecond, only to find out that the time hasn't changed. Wouldn't it be nice if we only had to check once per millisecond?

Timers and timer interrupts let us do exactly that. We can set up a timer to interrupt us once per millisecond. The timer will actually call us to let us know it is time to check the clock! Arduino Timers The Arduino Uno has 3 timers: Timer0, Timer1 and Timer2. Timer0 is already set up to generate a millisecond interrupt to update the millisecond counter reported by millis(). Since that is what we are looking for, we'll get Timer0 to generate an interrupt for us too! Frequency and Counts Timers are simple counters that count at some frequency derived from the 16MHz system clock. You can configure the clock divisor to alter the frequency and various different counting modes. You can also configure them to generate interrupts when the timer reaches a specific count. Timer0 is an 8-bit that counts from 0 to 255 and generates an interrupt whenever it overflows. It uses a clock divisor of 64 by default to give us an interrupt rate of 976.5625 Hz (close enough to a 1KHz for our purposes). We won't mess with the freqency of Timer0, because that would break millis()! Comparison Registers Arduino timers have a number of configuration registers. These can be read or written to using special symbols defined in the Arduino IDE. For comprehensive description of all these registers and their functions, see the links in "For further reading" below. We'll set up a up a comparison register for Timer 0 (this register is known as OCR0A) to generate another interrupt somewhere in the middle of that count. On every tick, the timer counter is compared with the comparison register and when they are equal an interrupt will be generated. The code below will generate a 'TIMER0_COMPA' interrupt whenever the counter value passes 0xAF.

Download: Copy Code Download: file // Timer0 is already used for millis() - we'll just interrupt somewhere // in the middle and call the "Compare A" function below OCR0A = 0xAF; TIMSK0 |= _BV(OCIE0A); // Timer0 is already used for millis() - we'll just interrupt somewhere // in the middle and call the "Compare A" function below OCR0A = 0xAF; TIMSK0 |= _BV(OCIE0A);

Then we'll define an interrupt handler for the timer interrupt vector known as "TIMER0_COMPA_vect". In this interrupt handler we'll do all the stuff we used to do in the loop.

Download: Copy Code Download: file // Interrupt is called once a millisecond, SIGNAL(TIMER0_COMPA_vect) { unsigned long currentMillis = millis(); sweeper1.Update(currentMillis); //if(digitalRead(2) == HIGH) { sweeper2.Update(currentMillis); led1.Update(currentMillis); } led2.Update(currentMillis); led3.Update(currentMillis); } // Interrupt is called once a millisecond, SIGNAL(TIMER0_COMPA_vect) { unsigned long currentMillis = millis(); sweeper1.Update(currentMillis); //if(digitalRead(2) == HIGH) { sweeper2.Update(currentMillis); led1.Update(currentMillis); } led2.Update(currentMillis); led3.Update(currentMillis); }

Which leaves us with a completely empty loop.

You can do anything you want in your loop now. You can even be decadent and use a delay()! The flashers and sweepers won't care. They will still get called once per millisecond regardless! For further reading: This is just a simple example of what timers can do. For more in-depth information on the different types of timers and ways to configure them, check out the "Libraries and Links" page. The Source Code: Here's the whole code, including the flashers and sweepers: