Arduino Timer Interrupts




Timer interrupts allow you to perform a task at very specifically timed intervals regardless of what else is going on in your code.  In this instructable I’ll explain how to setup and execute an interrupt in Clear Timer on Compare Match or CTC Mode.  Jump straight to step 2 if you are looking for sample code.

Normally when you write an Arduino sketch the Arduino performs all the commands encapsulated in the loop() {} function in the order that they are written, however, it’s difficult to time events in the loop().  Some commands take longer than others to execute, some depend on conditional statements (if, while…) and some Arduino library functions (like digitalWrite or analogRead) are made up of many commands.  Arduino timer interrupts allow you to momentarily pause the normal sequence of events taking place in the loop() function at precisely timed intervals, while you execute a separate set of commands.  Once these commands are done the Arduino picks up again where it was in the loop().

Arduino Timer Interrupts




Interrupts are useful for:

Measuring an incoming signal at equally spaced intervals (constant sampling frequency)
Calculating the time between two events
Sending out a signal of a specific frequency
Periodically checking for incoming serial data
much more…

There are a few ways to do interrupts, for now I’ll focus on the type that I find the most useful/flexible, called Clear Timer on Compare Match or CTC Mode.  Additionally, in this instructable I’ll be writing specifically about the timers to the Arduino Uno (and any other Arduino with ATMEL 328/168… Lilypad, Duemilanove, Diecimila, Nano…).  The main ideas presented here apply to the Mega and older boards as well, but the setup is a little different and the table below is specific to ATMEL 328/168.

Step 1: Prescalers and the Compare Match Register

The Uno has three timers called timer0, timer1, and timer2.  Each of the timers has a counter that is incremented on each tick of the timer’s clock.  CTC timer interrupts are triggered when the counter reaches a specified value, stored in the compare match register.  Once a timer counter reaches this value it will clear (reset to zero) on the next tick of the timer’s clock, then it will continue to count up to the compare match value again.  By choosing the compare match value and setting the speed at which the timer increments the counter, you can control the frequency of timer interrupts.

The first parameter I’ll discuss is the speed at which the timer increments the counter.  The Arduino clock runs at 16MHz, this is the fastest speed that the timers can increment their counters.  At 16MHz each tick of the counter represents 1/16,000,000 of a second (~63ns), so a counter will take 10/16,000,000 seconds to reach a value of 9 (counters are 0 indexed), and 100/16,000,000 seconds to reach a value of 99.

In many situations, you will find that setting the counter speed to 16MHz is too fast.  Timer0 and timer2 are 8 bit timers, meaning they can store a maximum counter value of 255.  Timer1 is a 16 bit timer, meaning it can store a maximum counter value of 65535.  Once a counter reaches its maximum, it will tick back to zero (this is called overflow).  This means at 16MHz, even if we set the compare match register to the max counter value, interrupts will occur every 256/16,000,000 seconds (~16us) for the 8 bit counters, and every 65,536/16,000,000 (~4 ms) seconds for the 16 bit counter.  Clearly, this is not very useful if you only want to interrupt once a second.

Instead you can control the speed of the timer counter incrementation by using something called a prescaler.  A prescaler dictates the speed of your timer according the the following equation:

(timer speed (Hz)) = (Arduino clock speed (16MHz)) / prescaler

So a 1 prescaler will increment the counter at 16MHz, an 8 prescaler will increment it at 2MHz, a 64 prescaler = 250kHz, and so on.  As indicated in the tables above, the prescaler can equal 1, 8, 64, 256, and 1024.  (I’ll explain the meaning of CS12, CS11, and CS10 in the next step.)

Now you can calculate the interrupt frequency with the following equation:

interrupt frequency (Hz) = (Arduino clock speed 16,000,000Hz) / (prescaler * (compare match register + 1))
the +1 is in there because the compare match register is zero indexed

rearranging the equation above, you can solve for the compare match register value that will give your desired interrupt frequency:

compare match register = [ 16,000,000Hz/ (prescaler * desired interrupt frequency) ] – 1
remember that when you use timers 0 and 2 this number must be less than 256, and less than 65536 for timer1

so if you wanted an interrupt every second (frequency of 1Hz):
compare match register = [16,000,000 / (prescaler * 1) ] -1
with a prescaler of 1024 you get:
compare match register = [16,000,000 / (1024 * 1) ] -1
= 15,624
since 256 < 15,624 < 65,536, you must use timer1 for this interrupt.

Step 2: Structuring Timer Interrupts

Timer setup code is done inside the setup(){} function in an Arduino sketch.

The code involved for setting up timer interrupts is a little daunting to look at, but it’s actually not that hard.  I pretty much just copy the same main chunk of code and change the prescaler and compare match register to set the correct interrupt frequency.

Arduino Timer Interrupts Schematic

The main structure of the interrupt setup looks like this:

Notice how the value of OCR#A (the compare match value) changes for each of these timer setups.  As explained in the last step, this was calculated according to the following equation:

compare match register = [ 16,000,000Hz/ (prescaler * desired interrupt frequency) ] – 1
remember that when you use timers 0 and 2 this number must be less than 256, and less than 65536 for timer1

Also notice how the setups between the three timers differ slightly in the line which turns on CTC mode:
TCCR0A |= (1 << WGM01);//for timer0
TCCR1B |= (1 << WGM12);//for timer1
TCCR2A |= (1 << WGM21);//for timer2
This follows directly from the datasheet of the ATMEL 328/168.

Finally, notice how the setup for the prescalers follows the tables in the last step (the table for timer 0 is repeated above),
TCCR0B |= (1 << CS22);  // Set CS#2 bit for 64 prescaler for timer 2
TCCR2B |= (1 << CS11);  // Set CS#1 bit for 8 prescaler for timer 1
TCCR1B |= (1 << CS02) | (1 << CS00);  // Set CS#2 and CS#0 bits for 1024 prescaler for timer 0

Notice in the last step that there are different prescaling options for the different timers.  For example, timer2 does not have the option of 1024 prescaler.

Major Components in Project

Arduino

For more detail: Arduino Timer Interrupts




This Post / Project can also be found using search terms:

  • arduino timer interrupt
Clip to Evernote

Leave a Comment

(Spamcheck Enabled)

Read previous post:
Quiz Game Show Buzzer using Arduino
Quiz Game Show Buzzer using Arduino

A good friend of mine who's a teacher was doing quizzes in her class making students compete to answer questions......

Close
Scroll to top