Arduino Timer and Interrupt Tutorial
Arduino Timer and Interrupt Tutorial
This tutorial shows the use of timers and interrupts for Arduino boards. As Arduino
programmer you have probably used timers and interrupts without even knowing it’s
there, because all the low level hardware stuff is hidden by the Arduino API. Many
Arduino functions uses timers, for example the time functions: delay(), millis() and
micros(), the PWM functions analogWrite(), the tone() and the noTone() function, even
the Servo library uses timers and interrupts.
Some of the links on this page are affiliate links. I receive a commission (at no extra cost to you)
if you make a purchase after clicking on one of these affiliate links. This helps support the free
content for the community on this website. Please read our Affiliate Link Policy for more
information.
What is a timer?
A timer, A.K.A. counter is a piece of hardware built in the Arduino controller. It is like
a clock, and can be used to measure time events.
The timer can be programmed by some special registers. You can configure the pre-
scaler for the timer, or the mode of operation and many other things.
The Arduino board is based on the Atmel AVR ATmega168 or the ATmega328
microchip. These chips are pin compatible and only differ in the size of internal
memory. Both have 3 timers, called Timer0, Timer1 and Timer2. Timer0 and Timer2
are 8bit timer, where Timer1 is a 16bit timer.
The most important difference between 8bit and 16bit timer is the timer resolution. 8bits
means 256 values (two to the power of 8) where 16bit means 65536 values (two to the
power of 16) which is much higher resolution.
The Arduino Mega series is based on the Atmel AVR ATmega1280 or the
ATmega2560. They are almost identical to previous chips but only differs in memory
size. These chips have 6 timers. First 3 timers (Timer 0, Timer1 and Timer2) are
identical to the ATmega168/328. Timer3, Timer4 and Timer5 are all 16bit timers,
similar to Timer1.
All timers depends on the system clock of your Arduino system. Normally the system
clock is 16MHz, but the Arduino Pro 3/3V is 8Mhz, so be careful when writing your
own timer functions.
The timer hardware can be configured with some special timer registers. In the Arduino
firmware, all timers were configured to a 1kHz frequency and interrupts are generally
enabled.
To summarize:
PWM (Pulse width modulation) mode – the OCxy outputs are used to generate PWM
signals
CTC (Clear timer on compare match) mode – When the timer counter reaches the
compare match register, the timer will be cleared.
What is an interrupt?
The program running on a controller is normally running sequentially instruction by
instruction. An interrupt is an external event that interrupts the running program and
runs a special interrupt service routine (ISR). After the ISR has been finished, the
running program is continued with the next instruction. Instruction means a single
machine instruction, not a line of C or C++ code.
Before an pending interrupt will be able to call a ISR the following conditions must be
true:
When an interrupt occurs, a flag in the interrupt flag register (TIFRx) is been set. This
interrupt will be automatically cleared when entering the ISR or by manually clearing
the bit in the interrupt flag register.
The Arduino functions attachInterrupt() and detachInterrupt() can only be used for
external interrupt pins. These are different interrupt sources, not discussed here.
Timer interrupts
A timer can generate different types of interrupts. The register and bit definitions can be
found in the processor data sheet (Atmega328 or Atmega2560) and in the I/O definition
header file (iomx8.h for Arduino, iomxx0_1.h for Arduino Mega in the
hardware/tools/avr/include/avr folder). The suffix x stands for the timer number (0..5),
the suffix y stands for the output number (A,B,C), for example TIMSK1 (Timer1
interrupt mask register) or OCR2A (Timer2 output compare register A).
Table of Contents
o Timer Overflow:
o Output Compare Match:
o Timer Input Capture:
Usefull 3rd party libraries
Blinking LED with timer overflow interrupt
Reading quadrature encoders with a timer
Timer Overflow:
Timer overflow means the timer has reached is limit value. When a timer overflow
interrupt occurs, the timer overflow bit TOVx will be set in the interrupt flag register
TIFRx. When the timer overflow interrupt enable bit TOIEx in the interrupt mask
register TIMSKx is set, the timer overflow interrupt service routine
ISR(TIMERx_OVF_vect) will be called.
Output Compare Match:
When a output compare match interrupt occurs, the OCFxy flag will be set in the
interrupt flag register TIFRx . When the output compare interrupt enable bit OCIExy in
the interrupt mask register TIMSKx is set, the output compare match interrupt service
ISR(TIMERx_COMPy_vect) routine will be called.
When a timer input capture interrupt occurs, the input capture flag bit ICFx will be set
in the interrupt flag register TIFRx. When the input capture interrupt enable bit ICIEx in
the interrupt mask register TIMSKx is set, the timer input capture interrupt service
routine ISR(TIMERx_CAPT_vect) will be called.
The Arduino has 3 timers and 6 PWM output pins. The relation between timers and
PWM outputs is:
Ken Shirrifs IR library using Timer2 – Send and receive any kind of IR remote
signals
Timer1 and Timer3 library using Timer1 or tiner3 – easy way to write your own
timer interrupt service routines.
Examples
Blinking LED with compare match interrupt
The first example uses the Timer1 in CTC mode and the compare match interrupt to
toggle a LED. The timer is configured for a frequency of 2Hz. The LED is toggled in
the interrupt service routine.
[sourcecode language=”cpp”]
/*
* timer and interrupts
* Timer1 compare match interrupt example
* more infos: https://oscarliang.com
*/
#define ledPin 13
void setup()
{
pinMode(ledPin, OUTPUT);
// initialize Timer1
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
void loop()
{
// your program here…
}
[/sourcecode]
The timer must be pre loaded every time in the interrupt service routine.
[sourcecode language=”cpp”]
/*
* timer and interrupts
* Timer1 overflow interrupt example
* more infos: https://oscarliang.com
*/
#define ledPin 13
void setup()
{
pinMode(ledPin, OUTPUT);
// initialize Timer1
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
[/sourcecode]
The signals of a quadrature encoder is a 2bit Gray code. Only 1 bit is changing from
state to state. A state machine is perfect to check the signal and count the encoder ticks.
The timer must be fast enough, to recognize each state change. For the Pololu wheel
encoders used here, the 1ms timer is fast enough.
The following example has been modified to work with Arduino V1.x
[sourcecode language=”cpp”]
/*
* timer and interrupts
* Timer2 compare interrupt example. Quadrature Encoder
* more infos: https://oscarliang.com
*
* Credits:
* based on code from Peter Dannegger
* http://www.mikrocontroller.net/articles/Drehgeber
*/
#if ARDUINO >= 100
#include “Arduino.h”
#else
#include “WConstants.h”
#endif
// Encoder Pins
#define encLtA 2
#define encLtB 3
#define encRtA 11
#define encRtB 12
#define ledPin 13
ISR( Timer2_COMPA_vect )
{
int8_t val, diff;
val = 0;
if( RT_PHASE_A )
val = 3;
if( RT_PHASE_B )
val ^= 1; // convert gray to binary
diff = lastRt – val; // difference last – new
if( diff & 1 ){ // bit 0 = value (1)
lastRt = val; // store new as next last
encDeltaRt += (diff & 2) – 1; // bit 1 = direction (+/-)
}
digitalWrite(ledPin, LOW); // toggle LED pin
}
void QuadratureEncoderInit(void)
{
int8_t val;
cli();
TIMSK2 |= (1<<OCIE2A);
sei();
pinMode(encLtA, INPUT);
pinMode(encRtA, INPUT);
pinMode(encLtB, INPUT);
pinMode(encRtB, INPUT);
val=0;
if (LT_PHASE_A)
val = 3;
if (LT_PHASE_B)
val ^= 1;
lastLt = val;
encDeltaLt = 0;
val=0;
if (RT_PHASE_A)
val = 3;
if (RT_PHASE_B)
val ^= 1;
lastRt = val;
encDeltaRt = 0;
encLt = 0;
encRt = 0;
}
cli();
val = encDeltaLt;
encDeltaLt = 0;
sei();
return val; // counts since last call
}
cli();
val = encDeltaRt;
encDeltaRt = 0;
sei();
return val; // counts since last call
}
void setup()
{
Serial.begin(38400);
pinMode(ledPin, OUTPUT);
QuadratureEncoderInit();
}
void loop()
{
encLt += QuadratureEncoderReadLt();
encRt += QuadratureEncoderReadRt();
Serial.print(“Lt: “);
Serial.print(encLt, DEC);
Serial.print(” Rt: “);
Serial.println(encRt, DEC);
delay(1000);
}
[/sourcecode]
arduinotutorial
previous post
next post
Leave a Comment
Sign me up for the newsletter!
By using this form, you agree with the storage and handling of your data by this
website. Note that all comments are held for moderation before appearing.
21 comments
I used to be very happy to seek out this web-site.I needed to thanks for your time for
this wonderful read!! I definitely enjoying every little little bit of it and I’ve you
bookmarked to take a look at new stuff you weblog post.
Reply
Dimas Ramalho 18th January 2019 - 8:28 pm
Congratulations!
A simple, easy to understand explanation on how to use Timer and interupt on Arduino.
Thank You.
Reply
Gonzalo 12th April 2017 - 8:11 pm
I would really appreciate if you could help me with a problem. It seems there’s a way to
initiate the ATMEGA 2560 timer in order to generate a PWM waveform, but I’ve tried
quite many configurations and none of them could make my board to change a LED
intensity in a basic LED-Resistance circuit. The sketch I worte seems like this:
void setup()
{
pinMode(3,OUTPUT); // Set pin 3 as output to use it as PWM source.
//ISR(TIMER3_COMPA_vect){
//digitalWrite(3, digitalRead(3) ^ 1); // I think interruption might be like this in the case
to exist, but it's still commented
//TIFR3 |= (1 << OCF0A); // when I uncomment it, my LED circuit works, but I cannot
introduce any intensity
// control.
//}
void loop() {
}
If somebody could succesfully use some PWM control with ATMEGA 2560, please tell
me how did you manage to attain it, although it were using a specific Arduino library.
Thanks!
Reply
river 24th February 2017 - 10:52 am
Wishing to try something very simple which actually compiles. So I tried the first
example, just to blink the LED on pin13 of a UNO. The sketch compiles with errors.
Actually, have yet to find any simple such sketch, which blinks the LED on and off
under timer interrupt that does compile.
Reply
mahadevi 11th March 2019 - 4:57 am
how to set 70k frequency in timer 1 and prescalar . plz reply me with some examples
Reply
Maxim 7th December 2016 - 11:05 am
Thanks, Oscar!
I writing my library to work with 1-digit and 4-digits 7-segments led display. In case of
4 digits I need refresh display 24-30 times per second. As you explain timer 0 used by
Arduino for delay(). I use timer 1 interrupt. But when I use delay() in loop() nothing
work.
void setup()
{
noInterrupts();
interrupts();
}
ISR(TIMER1_COMPA_vect)
{
Led1.Refresh();
}
void loop()
{
Led1.Print4("ABCD");
// delay(1000);
Led1.Print4("1234");
// delay(100);
Led1.Print4("5678");
// delay(10);
}
With delay() commented display change value 1 time per second. If I uncomment it
show first value (ABCD) and stop. Can you help me why?
Reply
HijoDePuta 16th November 2016 - 2:02 pm
Reply
Reibel 6th October 2016 - 8:14 pm
Hi
Very interesting tuto on timers and interrupts.
I get an arduino m0pro board. I would like to know what to do to adapt your examples
to the relevant IDE and microprocessor ?
Many thanks
Daniel
Reply
Stefan 10th June 2015 - 2:57 pm
Hi,
I need some help. i have 2 libraries that use one timer, How can I change the timer on
one of them. I use arduino uno , ethernet shield, rf transmitter and receiver.
These are libraries that use:
#include
#include
#include
#ifdef __AVR_ATtiny85__
if (!prescaler)
{
return; // fault
}
TCCR0A = 0;
TCCR0A = _BV(WGM01); // Turn on CTC mode / Output Compare pins disconnected
#else // ARDUINO
if (!prescaler)
{
return; // fault
}
// Enable interrupt
#ifdef TIMSK1
// atmega168
TIMSK1 |= _BV(OCIE1A);
#else
// others
TIMSK |= _BV(OCIE1A);
#endif // TIMSK1
#endif // __AVR_ATtiny85__
thanks in advance