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().

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.

<p>Hi,</p><p>Your project and explanations helped me a lot starting with my project. Thanks!</p><p>I'm using Arduino uno timer 0 and 2 to output 2 distinct (in sync) MIDI Clock signal and it works like charm. I can change BPM with a knob going from 30 to 250.</p><p>I'm struggling on my next step which is introducing an offset (-200ms / +200ms) between the 2 signals using an analogRead on a knob.</p><p>Would you know how to induce such an offset for a Serial output?</p><p>Timr0 and Timer2 doesnt have much room to change start point and end point and the induced delay would only be a few milliseconds maybe.</p><p>Well if this message finds you and you wish to reply, I'm all ears opened.</p><p>Thanks again,</p><p>Stef</p>
<p>Wonderful, I worked with PICs but I see the AVR work slighly different</p>
<p>Hi, great tutorial, thanks heaps.</p><p>What libraries do I need to include, I'm getting compiler errors saying it doesn't know the names of the timing registers.</p>
<p>Hi Amanda,</p><p>I found these article very informative. I'm designing a card reader and i have included these timer interrupts in my programs.I have several confusions to use these timer interrupts on Arduino Leonardo.I have attached pins on pin 3 and pin 2 for D0 and D1 from my Mifare card reader.My card is a Mifare (32bits) type, so when i batch these card,i'm getting the extra bit of 33,so i decided to use timer interrupts just to execute exact 32 bits,but still i'm getting these extra bit.Please help me..Im lost!!</p>
<p>In an Arduino code for pulse sensor 256 prescalar is activated by TCCR2b=0x06 . Why is it so ? Why is it not 0x04 as per the table for Timer0. Is it possible to make an interrupt of 100 Hz using Timer 2. (ocr2a &lt;256, 1024 prescalar is not present). Could you help me with this. I am just a beginner.</p>
<p>How could I make an interrupt of 100Hz with timer 2. Could you share the table for timer2 similar to the one for Timer0 .</p>
<p>Just wondering if it would not be easier and more accurate to generate an interupt when a switch change is registered and use millis() to determine the time since the last switch change? Sampling every 1ms using the method above may miss a switch change?? </p>
<p>I am no expert but to my knowledge the problem with switch state interrupts is that they bounce and your can't denounce a switch using software on an interrupt routine as its already been triggered (as in the interrupt routine is already done before you have a chance to de-bounce.). The other way is to use a hardware based button debounce switch which just uses a capacitor. This will solve the problem. However unless your project is huge, polling a switch every x cycles doesn't really make any difference to any project.</p>
<p>I had the problem with a motor encoder, just put a 10k Ohms resistor to Vcc and a 1&micro;F capacitor to GND around your interrupt pin, this will be ok !!<br>Pin interrupt would be more efficient because you'll never miss a change, and above that, you'll not waste time with useless interruption =)</p>
<p>While I don't think sampling every 1ms may miss a switch change (think about it, 1000 times a second???) I too would like to know if the more efficient way would be to make an interrupt for the switch change. I have a project that would use something similar and I'm trying to determine the most efficient course of action.</p>
<p>If the Arduino is executing some code within an interrupt does the counter continue to count up so that the next interrupt is correctly timed? </p>
<p>thank for Example interrupts that working.</p><p>!!But void loop() has not work</p><p>my increase program</p><p>void setup(){</p><p> //set pins as outputs</p><p> pinMode(7, OUTPUT); //my led</p><p> pinMode(8, OUTPUT);</p><p> pinMode(9, OUTPUT);</p><p> pinMode(13, OUTPUT);</p><p>cli();//stop interrupts</p><p>same example</p><p>sei();//allow interrupts</p><p>}</p><p>void loop(){</p><p> digitalWrite(7, HIGH); // turn the LED on (HIGH is the voltage level)</p><p> delay(100); // wait for a second</p><p> digitalWrite(7, LOW); // turn the LED off by making the voltage LOW</p><p> delay(100); // wait for a second</p><p> //do other things here</p><p>}</p>
<p>I made a python script that walks you through setting up the code for timer interrupts.<br>https://gist.github.com/cltnschlosser/e747efae07a76e117e02</p>
<p>Could this be used for a 2 player reflex timer game? Trying to push your players button on multiples of 5 seconds and getting a point when you do.</p>
<p>Good job, I want to import 200khz frequency, it's about 5us, but I only have 13.6us with every OCRnA that I used to change from 0 to 80. I'm using 2560. How can I do that?</p><p>Thanks</p>
<p>Thank you... Very nice tutorial!</p>
<p>Hei, very usefull application, but i&acute;ve one cuestion, how can i call de interrup for timer 1 inside the loop??Thanks!</p>
<p>I could be wrong. You may want to check</p><p>http://arduino.cc/en/Reference/AttachInterrupt</p>
You don't call interrupts like normal functions. An interrupt service routine (ISR) is &quot;called&quot; or better yet &quot;triggered&quot; at the specified frequency that you determined when you set up the interrupt.
Hello... The code is very useful, however, be aware that the sketch you posted doesn't seem to ever get into the main loop!
<p>I'm kind of a noob about all this, but unless I'm mistaken the point of interupts is that you don't NEED a main loop. The main loop just runs forever and everything is done when interupts happen. It is an extremely efficient way to code....</p>
<p>can we generate square wave with varying pulse width with this interrupt ?</p>
yes it's possible, but probably easier to just use the analogWrite command
<p>sir please send program for generating 15000 sample valuesin 10 sec using timer interrupt values adc values from accelometer sensor</p>
<p>This is really annoying to read. Annoying as crap. If you're going to ask something say it in a way that somebody can freaking understand. Spend more than 30 seconds typing some crap if you want anybody to spend more than 30 seconds helping you.</p>
<p>sir please send program for generating 15000 sample values using timer interrupt values adc values from accelometer sensor</p>
<p>i am confused about something in the code, the line</p><p>// turn on CTC mode </p><p> TCCR0A |= (1 &lt;&lt; WGM01);</p><p>shouldnt it be TCCR0A |= (1&lt;&lt;WGM02); or am i understanding this wrong, i am a beginner at arduino so its still very confusing to me. </p>
<p>Thank you for this tutorial, I'm struggling with a project and this helped me stumble at least to the right direction. </p>
<p>cool, glad to hear it!</p>
I read many doc about arduino timer and counter but this one most helpful.......thank you for making it.... :)
<p>65,536/15,624 = 4.19457245264</p><p>So the greatest interval we can get from such timer is a little more than 4 sec. or 0.25hz?</p><p>I am new to CPL and C++. What does if (toggle1){ } stand for? toggle1 compared to what?</p><p>Thanks.</p>
<p>Toggle1 was declared as &quot;boolean&quot; which means it can have values of 1 ( meaning TRUE ) or 0 ( meaning FALSE ). These values are used for &quot;logical&quot; operations, such as in an if statement like you noted. Normally ( doing an if statement ), if you're comparing variable x to some defined number A, for example A = 5, the expression x &gt; A gives you a boolean value 1 ( meaning TRUE ), if x is 6 or higher. So, declaring a if expression &quot;if(toggle1){}&quot; is a kind of funny way of saying if toggle 1 is true (1) you're gonna do it. So now, remembering that we defined toggle1 as 0 at first, the first time we encounter if(toggle1){}, it's not gonna get executed since toggle1 is 0. Instead, since we have declared the &quot;else&quot; part, that's the way we're gonna take. At the end of the &quot;else&quot; statement, there's the line toggle1 = 1, which means that the next time we have to choose between the if and else-statements if(toggle1){} is gonna be TRUE, and since that statement ends with toggle1 = 0, we end up switching between these two expression until the very end.</p>
Hello Amanda!! I've been reading your post! but. What if I what to use pines to get frequencies from A0 to A5 ? I have been reading your guitar tuner post. I would like to to something similar but, reading the 6 strings signals. <br> <br>What could you recommend to me? :D <br> <br>greetings and congratulations for your excellent posts
it's a little tricky to read from all the analog inputs. you will definitely not be able to get ~38kHz, probably more like 7kHz (or less), is that ok? The arduino is just not fast enough for this type of thing.
hi everyone, <br>I have one problem is that. My goal is sending a PWM 100 kHz to pin 13 of arduino Atmega2560, and print data to serial port (&quot;testing&quot; string, for example as codes below). The problem is that, I can not receive the data ( that is &quot;tesing&quot; string). However, when I change to send PWM 1Hz instead of 100 kHz, result is OK. Could any one help me solve this problem? Thank you. Here are codes: <br>boolean toggle1 = 0; <br>void setup(){ <br> pinMode(13, OUTPUT); <br> cli();//stop interrupts <br>//set timer1 interrupt at 100kHz <br> TCCR1A = 0; // set entire TCCR1A register to 0 <br> TCCR1B = 0; // same for TCCR1B <br> TCNT1 = 0;//initialize counter value to 0; <br> // set compare match register to desired timer count: <br> OCR1A = 19; <br> TCCR1B |= (1 &lt;&lt; WGM12); <br> TCCR1B |= (1 &lt;&lt; CS10); <br> //TCCR1B |= (1 &lt;&lt; CS11); <br> // enable timer compare interrupt: <br> TIMSK1 |= (1 &lt;&lt; OCIE1A); <br> <br>sei();//allow interrupts <br>Serial.begin(9600); <br> <br>}//end setup <br>ISR(TIMER1_COMPA_vect){//timer1 interrupt 10kHz toggles pin 13 (LED) <br> if (toggle1){ <br> digitalWrite(13,HIGH); <br> toggle1 = 0; <br> } <br> else{ <br> digitalWrite(13,LOW); <br> toggle1 = 1; <br> } <br>} <br> <br>void loop(){ <br> while (Serial.available() &gt; 0) { <br> Serial.println(&quot;testing&quot;); <br> delay(1000); <br> } <br> <br>} <br>
hmm, the higher frequency interrupt must be disrupting Serial.print. did you find a workaround? you might try using an led indicator for your "testing" message instead.
I believe the following description is all wrong ---- &gt; This leads to the confusion of why this topic is hard. I'm trying but can't filter through the errors. Please re-edit your tutorial to be accurate. The TCCR#B is not matched to the CS#. I will not likely be able to understand and catch other errors. And if I do it will be because I'm confused from the error not knowing what is correct. Thanks for trying.... <br> <br> <br>&quot;Finally, notice how the setup for the prescalers follows the tables in the last step (the table for timer 0 is repeated above), <br>TCCR0B |= (1 &lt;&lt; CS22); // Set CS#2 bit for 64 prescaler for timer 2 <br>TCCR2B |= (1 &lt;&lt; CS11); // Set CS#1 bit for 8 prescaler for timer 1 <br>TCCR1B |= (1 &lt;&lt; CS02) | (1 &lt;&lt; CS00); // Set CS#2 and CS#0 bits for 1024 prescaler for timer 0&quot; <br> <br> <br>
thanks for finding that typo! it's fixed now
hola, amanda, <br> <br>I've been using this tutorial to set up my interrupts for a few times. It's been working great until today. I set timer1 at 2.5khz to perform the interrupt. Mainly use it as a clock and serial reading from the console. The problem is that when I use timer1, PWM on pin 9 and 10 is dead. Pin 9 is the worst one, if I try to use it as analogWrite, arduino will stall. If I use pin 10, arduino will ignore any analogWrite request. It doesn't affect pin 3 and 5. however, if I use timer0, i think it was pin 11 and 3 will be affected in the same way. <br> <br>Any suggestion to get rid of the problem? or if you know the reason behind it, please do explain here. maybe PWM for PIN 3, 5, 6, 9, 10, 11 use timer0, 1, 2? <br> <br>Thank you.
this is expected. if you look at the atmega 328 pin map: http://cdn3.raywenderlich.com/wp-content/uploads/2013/06/atmegaPinMap.jpg<br />you will see that timer 1 involves oc1A and oc1B, which are connected to pwm pins 9 and 10. timer0 involves oc0A and oc0B, tied to pins 5 and 6, and timer 2 has the same relationship to pins 3 and 11<br />the reason those pins are able to do pwm is because they use the timers, so you can't have both. you just have to pick which feature you want to enable.
Great article! I have additional question: when we modify timer interruption frequency, changing prescaller and so on, how it will affect analogWrite function call? I mean the frequency of PWM, which is &quot;normally&quot; 490Hz when just using arduino API and analogWrite function? In other words how to use PWM features to control external devices (like LEDs or DC engines) by analogWrite and internal interruptions together?
using interrupts, you can essentially create your own, custom analogWrite. You can set this "analogWrite" to any frequency that you want (under 16Mhz).
Awesome article! <br> <br>Sorry for the total newbie question here, but really struggling to understand the following code: <br> <br>TCCR0A = 0; ...This zeros out entire register including WGM01 <br>TCCR0B = 0; ..This zeros out entire register including WGM02 <br>. <br>. <br>TCCR0A |= (1 &lt; &lt; WGM01); <br>...since WGM01 was set to zero previously, doesn't this evaluate to TCCR0A = 1? <br> <br>I thought we needed to set <br>WGM00 = 0 <br>WGM01 = 1 <br>WGM02 = 0 <br> <br>..to get into CTC mode? <br> <br>In my thinking, this would set WGM00 = 1, WGM01 = 0, and WGM02, which is in TCCR0B is untouched since being reset in line 2. <br> <br>So this should put us into &quot;Mode 1 - PWM, Phase Correct Mode&quot; <br> <br>Cheers <br>
Oh, I see. I can't reply to a message because there is no reCAPTCHA under the reply box, not because the reCAPTCHA isn't working. It works fine if I create a new post. Someone should fix this. I'm using Firefox 19.0.2 if that make a difference.
Yeah, I know I could do that. I could also put in a function pointer into my interrupt handler, I was just wondering if it were possible to drop that overhead and go directly to the interrupt handler of my choice. <br> <br>P.S. This reCAPTCHA stuff is garbage.:( I've put in several words that I'm absolutely sure are what they should be and it keeps saying &quot;Please type the two words as seen on image&quot;
Can you only define one interrupt handler per interrupt? Can you not define multiple ones and switch it from one to another depending on circumstance?
put and if then statement inside the interrupt
Awesome. Thanks. This helped me a lot. I was struggling to understand timers in pic. This instructable made my mind clear. Also with arduino.

About This Instructable


419 favorites


Bio: I'm a grad student at the Center for Bits and Atoms at MIT Media Lab. Before that I worked at Instructables, writing code for ... More »
More by amandaghassaei: OTCA Metapixel - Conway's Game of Life "9 Degrees of Freedom" IMU Twitter Controlled Pet Feeder
Add instructable to: