Interrupts in Arduino
Reference: Arduino Cookbook (1st ed.) by Michael Margolis.
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves ([email protected]), 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 lled
each duration is displayed on the Serial Monitor.
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves ([email protected]), College of Engineering
Volatile Keyword
Its a variable qualier; 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 (
[email protected]), College of Engineering
attachInterrupt function
The attachInterrupt(0, analyze,
CHANGE); call enables the program to handle interrupts.
The rst number in the call
species 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 (
[email protected]), College of Engineering
A lot more interrupts
Yes, there are a lot of other We will user the timer
interrupts very soon. interrupts, but they are internal.
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 ([email protected]), College of Engineering
attachInterrupt function
The second parameter species
what function to call (interrupt handler) when the interrupt event happens.
The nal parameter species
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 ([email protected]), 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. the array results only once.
... And it will print the contents of 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 ([email protected]), 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 ([email protected]), 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 overow after
This number will overow (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 ([email protected]), 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 (
[email protected]), College of Engineering
Changing variables
The variables that are changed in
an interrupt function are declared as volatile. the values could change at any time (by an interrupt handler).
This lets the compiler know that
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 ([email protected]), 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 rst 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 (
[email protected]), 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. the interrupt is triggered (through pin #2 changes), the LED will change state.
Attach a LED to digital pin 13. Whenever,
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves ([email protected]), 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. function may be lost!
Serial communications while in the 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 (
[email protected]), 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 ([email protected]), 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 ([email protected]), College of Engineering
Enabling interrupts inside interrupts
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"); } 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 }
If I press pin2 will go into interrupt0(). While it is processing, I can press pin3 and
jump into function interrupt1().
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves ([email protected]), College of Engineering
Operation scenarios
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves ([email protected]), 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"); } 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 ag that indicates which interrupt needs attention. If we are inside a particular interrupt, the interrupt ag is already ON.
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves ([email protected]), College of Engineering
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"); } 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()
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves ([email protected]), College of Engineering