







You can download our e-book ‘Learn Arduino from Scratch’ from this link

What are interrupts? Well they interrupt something for sure, precisely they interrupt the main program execution of the CPU. In Arduino we have 2 main functions the setup() and the loop(). Interrupts interrupt code execution in the loop().

But why should we care about interrupts anyway? They are not something to be feared, they make your code cleaner and they work much more efficient than conventional coding. An interrupt listens for an external event and reacts to it immediately. The main program pauses the execution and enters the function attached to the interrupt. At this point, it executes whatever there is in this function, and returns to the main program as if nothing happened. That is the beauty of interrupts.

Let’s make a little comparison, we are going to compare 2 sketches which produce the same result but work in a different way.

const int buttonPin = 2; // push button pin const int ledPin = 13; // the LED pin int buttonState = 0; // keeps the state of our button void setup() { pinMode(ledPin, OUTPUT); pinMode(buttonPin, INPUT); } void loop() { // read the button state buttonState = digitalRead(buttonPin); // check if the pushbutton is pressed. // if it is, the buttonState is HIGH: if (buttonState == HIGH) { digitalWrite(ledPin, HIGH); } else { digitalWrite(ledPin, LOW); } }

In this example we are listening to a push button on pin 2, by reading the digital buttonPin. Then checking the button state with an if statement and turning the led on and off.

SImple no? But inefficient, looks ugly and is not real time. Interrupts are real time, as soon as the interrupt is raised the attached function is fired.









Let’s look at the same program written using interrupts.

const int buttonPin = 2; // push button pin const int ledPin = 13; // the LED pin volatile int buttonState = 0; // keeps the state of our button void setup() { pinMode(ledPin, OUTPUT); pinMode(buttonPin, INPUT); //Attach an interrupt to the ISR vector attachInterrupt(0, pin_ISR, CHANGE); } void loop() { //empty } void pin_ISR() { buttonState = digitalRead(buttonPin); digitalWrite(ledPin, buttonState); }

The AttachInterrupt() function

As you might have already noticed there are some differences from the previous example. Particularly the loop() function, which contains nothing. Everything that was handled by the if statement is now handled inside the pin_ISR(). You might have noticed already, this is the function that is executed when the interrupt is raised.

attachInterrupt(0, pin_ISR, CHANGE);

The attachInterrupt() function attaches the function with the interrupt. The first parameter is an index to identify to which pin the interrupt is attached (in Arduino Uno – 0 means pin 2 and 1 means pin 3). The seconds parameter is the name of the function to be executed. The third parameter is the mode by which the interrupt is raised. There are 4 + 1 modes which can be used these are:

FALLING: fires the interrupt when the pin is on the falling edge

RISING: fires the interrupt when the pin is on the rising edge

CHANGE: fires on any change in the pin

LOW: fires when the pin is low

HIGH: (Supported only Due) fires when the pin is high









The volatile keyword

You might have noticed that buttonState has another keyword, which is volatile. This keyword indicates that the variable value cannot be predicted. Why? Because interrupts cannot be predicted by the compiler and thus the state of a variable which changes inside a function triggered by an interrupt is also unpredictable. So in this case it is worth adding the volatile keyword.