You are on page 1of 20

Interrupts in Arduino

Reference: Arduino
Cookbook (1st ed.)
by Michael Margolis.

CPE 355 - Real Time Embedded Kernels - Spring 12


Nuno Alves (nalves@wne.edu), College of Engineering

Sample Code
You have an IR detector
connected to pin 2.

This program monitors pulses

on pin 2 and stores the duration


of each pulse in an array.

When the array has been filled

each duration is displayed on the


Serial Monitor.

CPE 355 - Real Time Embedded Kernels - Spring 12


Nuno Alves (nalves@wne.edu), College of Engineering

Volatile
Keyword
Its a variable qualifier; it is
used before the datatype of a
variable, to modify the way in
which the compiler and
subsequent program treats the
variable.

Compiler will load the variable

from RAM and not from a storage


register.

Under certain conditions, such


as through interrupts, the value
for a variable stored in registers
can be inaccurate.
CPE 355 - Real Time Embedded Kernels - Spring 12
Nuno Alves (nalves@wne.edu), College of Engineering

attachInterrupt
function
The attachInterrupt(0, analyze,
CHANGE); call enables the
program to handle interrupts.

The first number in the call


specifies which interrupt to
initialize.

On a standard Arduino board

(such as UNO), two interrupts are


available: number 0, which uses pin
2, and number 1 on pin 3.

Interrupt 0 and interrupt 1 have


the same priorities (with Wiring).
CPE 355 - Real Time Embedded Kernels - Spring 12
Nuno Alves (nalves@wne.edu), College of Engineering

A lot more
interrupts
Yes, there are a lot of other

interrupts, but they are internal.

We will user the timer


interrupts very soon.

Unsurprisingly the RESET


interrupt has the highest
priority.

This table is from Russells


book (listed on syllabus).

CPE 355 - Real Time Embedded Kernels - Spring 12


Nuno Alves (nalves@wne.edu), College of Engineering

attachInterrupt
function
The second parameter specifies

what function to call (interrupt


handler) when the interrupt
event happens.

The final parameter specifies

what should trigger the interrupt:


- CHANGE: whenever the pin
level changes (low to high or
high to low).
- LOW: when the pin is low.
- RISING: when the pin goes
from low to high.
- FALLING: when the pin goes
from high to low.
CPE 355 - Real Time Embedded Kernels - Spring 12
Nuno Alves (nalves@wne.edu), College of Engineering

Main loop
The main loop just checks the
index variable to see if all the
entries have been set by the
interrupt handler.

... And it will print the contents of


the array results only once.

Nothing in loop changes the


value of index. The index is
changed inside the analyze
function when the interrupt
condition occurs.
CPE 355 - Real Time Embedded Kernels - Spring 12
Nuno Alves (nalves@wne.edu), College of Engineering

Termination
condition

The code stays in the while loop

at the end of the inner block, so


you need to reset the board when
you want to do another run.

CPE 355 - Real Time Embedded Kernels - Spring 12


Nuno Alves (nalves@wne.edu), College of Engineering

micros()
function
The micros() function returns

the number of micro-seconds


since the Arduino began running
the current program.

This number will overflow after

This number will overflow (go


back to zero), after approximately
70 minutes.

On 16 MHz Arduino boards

(e.g. UNO), this function has a


resolution of four microseconds
(i.e. the value returned is always a
multiple of four).
CPE 355 - Real Time Embedded Kernels - Spring 12
Nuno Alves (nalves@wne.edu), College of Engineering

analyze()
function
The index value is used to store
the time since the last state
change into the next slot in the
results array.

The time is calculated by

subtracting the last time the state


changed from the current time in
microseconds.

The current time is then saved


as the last time a change
happened.
CPE 355 - Real Time Embedded Kernels - Spring 12
Nuno Alves (nalves@wne.edu), College of Engineering

Changing
variables
The variables that are changed in
an interrupt function are declared
as volatile.

This lets the compiler know that


the values could change at any
time (by an interrupt handler).

Without using the volatile

keyword, the compiler would


think these variables are not being
changed by any code getting called
and would replace these variables
with constant values.
CPE 355 - Real Time Embedded Kernels - Spring 12
Nuno Alves (nalves@wne.edu), College of Engineering

Whats the
code doing?
Each time an interrupt is

triggered, index is incremented


and the current time is saved.

The time difference is calculated


and saved in the array (except for
the first time the interrupt is
triggered, when index is 0).

When the maximum number of


entries has occurred, the inner
block in loop runs, and it prints
out all the values to the serial
port.
CPE 355 - Real Time Embedded Kernels - Spring 12
Nuno Alves (nalves@wne.edu), College of Engineering

Another sample code


int pin = 13;
volatile int state = LOW;
void setup()
{
pinMode(pin, OUTPUT);
attachInterrupt(0, blink, CHANGE);
}
void loop()
{
digitalWrite(pin, state);
}
void blink()
{
state = !state;
}

Attach something that will

trigger an interrupt in digital


pin #2 (e.g. resistive sensor,
button, ...)

Make sure its either pulled-up


or pull-down, as shown on the
right.

Attach a LED to digital pin 13. Whenever,

the interrupt is triggered (through pin #2


changes), the LED will change state.

CPE 355 - Real Time Embedded Kernels - Spring 12


Nuno Alves (nalves@wne.edu), College of Engineering

Arduino wiring C limitations


int pin = 13;
volatile int state = LOW;
void setup()
{
pinMode(pin, OUTPUT);
attachInterrupt(0, blink, CHANGE);
}
void loop()
{
digitalWrite(pin, state);
}
void blink()
{
state = !state;
}

Inside the interrupt function, delay() won't


work

Values returned by the millis() and micros()


functions will not increment.

Serial communications while in the


function may be lost!

You should declare as volatile any variables


that you modify within the attached
function.

By default, interrupts are atomic.


CPE 355 - Real Time Embedded Kernels - Spring 12
Nuno Alves (nalves@wne.edu), College of Engineering

Atomic sections in Arduino


We can enable/disable interrupts on certain
sections of code with interrupts() and
noInterrupts().

Interrupts in Arduino are enabled by default.


Some functions will not work while

interrupts are disabled, and incoming


communication may be ignored. Interrupts
can slightly disrupt the timing of code,
however, and may be disabled for particularly
critical sections of code.

CPE 355 - Real Time Embedded Kernels - Spring 12


Nuno Alves (nalves@wne.edu), College of Engineering

Interrupts default
By default you can not have interrupts inside interrupts.
With C-Wiring both interrupt 0 and interrupt 1 are assigned the same
priority.

If you have a way to have interrupts inside interrupts, then when an


interrupt is issued, you immediately leave the current interrupt and
execute the new interrupt.

Enabling interrupts inside interrupts is a hack :

Is not recommended as
it raises all sorts of issues with preserving the state of the machine before
the interrupting interrupt is serviced.

CPE 355 - Real Time Embedded Kernels - Spring 12


Nuno Alves (nalves@wne.edu), College of Engineering

Enabling interrupts inside interrupts


volatile int i,j,z;

void interrupt0()
{
interrupts();
digitalWrite(13,HIGH);
artificialdelay();
digitalWrite(13,LOW);
noInterrupts(); //not really needed
}

void artificialdelay()
{
for (i=0; i<900; i++){
for (j=0; j<900; j++){
z=i*10;}}
}
void setup()
{
Serial.begin(9600);
attachInterrupt(0, interrupt0, CHANGE);
attachInterrupt(1, interrupt1, CHANGE);
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
}
void loop()
{
Serial.println("entering main loop");
artificialdelay();
Serial.println("leaving main loop");
}

void interrupt1()
{
interrupts();
digitalWrite(12,HIGH);
artificialdelay();
digitalWrite(12,LOW);
noInterrupts(); //not really needed
}

If I press pin2 will go into interrupt0().


While it is processing, I can press pin3 and

CPE 355 - Real Time Embedded Kernels - Spring 12


Nuno Alves (nalves@wne.edu), College of Engineering

jump into function interrupt1().

Operation scenarios

CPE 355 - Real Time Embedded Kernels - Spring 12


Nuno Alves (nalves@wne.edu), College of Engineering

What happens if you trigger


interrupt0 when inside interrupt0 ?
volatile int i,j,z;
void artificialdelay()
{
for (i=0; i<900; i++){
for (j=0; j<900; j++){
z=i*10;}}
}
void setup()
{
Serial.begin(9600);
attachInterrupt(0, interrupt0, CHANGE);
attachInterrupt(1, interrupt1, CHANGE);
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
}
void loop()
{
Serial.println("entering main loop");
artificialdelay();
Serial.println("leaving main loop");
}

CPE 355 - Real Time Embedded Kernels - Spring 12


Nuno Alves (nalves@wne.edu), College of Engineering

void interrupt0()
{
interrupts();
digitalWrite(13,HIGH);
artificialdelay();
digitalWrite(13,LOW);
noInterrupts(); //not really needed
}
void interrupt1()
{
interrupts();
digitalWrite(12,HIGH);
artificialdelay();
digitalWrite(12,LOW);
noInterrupts(); //not really needed
}

Nothing! Each interrupt has a register flag


that indicates which interrupt needs
attention. If we are inside a particular
interrupt, the interrupt flag is already ON.

What happens if you trigger


interrupt1 when inside interrupt0 ?
volatile int i,j,z;
void artificialdelay()
{
for (i=0; i<900; i++){
for (j=0; j<900; j++){
z=i*10;}}
}
void setup()
{
Serial.begin(9600);
attachInterrupt(0, interrupt0, CHANGE);
attachInterrupt(1, interrupt1, CHANGE);
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
}
void loop()
{
Serial.println("entering main loop");
artificialdelay();
Serial.println("leaving main loop");
}

CPE 355 - Real Time Embedded Kernels - Spring 12


Nuno Alves (nalves@wne.edu), College of Engineering

void interrupt0()
{
//interrupts();
digitalWrite(13,HIGH);
artificialdelay();
digitalWrite(13,LOW);
//noInterrupts();
}
void interrupt1()
{
//interrupts();
digitalWrite(12,HIGH);
artificialdelay();
digitalWrite(12,LOW);
//noInterrupts();
}

function will be executed


immediately after we are done
interrupt0().
interrupt1()