Chapter 9

Arduino Interruptions
Atmel microcontrollers incorporate a mechanism that is often unknown to all of us. The interruptions with Arduino allow us to react to external events to the plate in a quick way. When a signal is detected, an interruption interrupts the process that is running. This will allow us two things. On the one hand, quickly execute a piece of code, and on the other hand, stop the execution of the code that was being executed.
For example, imagine that you want to cook a pizza in the oven. Typically, heat the oven to a certain temperature, put the pizza in, and set the clock for 25 minutes. Meanwhile, you are going to watch TV.
When the clock ends the countdown, a bell rings, and you interrupt watching television to attend the oven. You take the pizza out of the oven, take it to the living room, and keep watching TV. This would be a real-life example of how interruptions work.
Interruptions are not simply to change and do something different. For example, we are riding a bicycle, we get home and keep the bike in the garage, or a button is pressed by the user and allows you to stop the DFRobot.
In these two cases, we do not interrupt an action; we go on to do something different. We finish doing one thing and do another. In the case of the button, the most we can do is remember the state of the pressed button. We must use the interruptions for what they are, interrupt what is being executed, and perform another task, then return to the same place where we had left.
Within the range of interruptions with Arduino are scheduled interruptions and external interruptions. The philosophy is the same, to be able to execute a code when a specific event happens. In the case of scheduled interruptions, the event will trigger every certain interval of time that we must configure.
This type of interruptions is not the object of this article. If you want to know more, you can see the reference of the TimerOne library that is responsible for configuring and managing this type of interruptions.
The other type of interruptions, the external ones, allows us to react to external events. An event may be that a button is pressed, or that a sensor captures certain information.
What will you learn in this chapter?
Why Use Interrupts with Arduino?
Using interruptions will allow us to forget about controlling certain pins. This is very important because, within an application or program, we will not do a single thing. For example, we want an LED to turn on or off when we press a button. This is really simple, but when we also want another LED to flash, things get complicated.
The probability of capturing the event when the button is pressed decreases with the increase in flashing time. In these cases, and many others, we are interested in releasing the Arduino processor so that only when the button is pressed, it takes a specific action. So we will not have to be constantly checking the X pin if you have pressed the button.
Precisely this is the sense of interruptions, to be able to do other things as long as the event does not happen, but when that external event is present, to quickly execute the associated code.
Internally, Arduino (or rather the AtMega microcontroller) has certain configured interrupts that it throws according to the situation. For the transmission of data through the serial port, to reset the board before loading a program, I2C communication, etc ...
In this case, we will create our own interruptions associated with certain pins according to the type of board.
How to Use Interrupts with Arduino
Inside the Arduino board, we find different pins that allow us to have interruptions. It will depend on the type of plate.
LICENSE PLATE
PINS INTERRUPTIONS
One, Nano, Mini
2. 3
Mega, Mega2560, MegaADK
2, 3, 18, 19, 20, 21
Micro, Leonardo
0, 1, 2, 3, 7
Zero
All digital pins except 4
MKR1000
0, 1, 4, 5, 6, 7, 8, 9, A1, A2
Due, 101
All digital pins
In order to use interruptions with Arduino, we do not need to incorporate any type of library into our program. We only need to make references to certain functions or methods. Now we will see what they are.
attachInterrupt (pin, ISR, mode)
This function will allow us to define or configure one of the pins as an interrupt port. The three parameters it supports are:
There is the fifth state that only the Arduino Due, Zero and MKR1000 allow:
detachInterrupt (pin)
If attachInterrupt () allows us to configure a pin as an interrupt, the detachInterrupt () method overrides that setting. As a parameter, we pass the pin, and we can do it with the digital function  PinToInterrupt (pin number)  that will return the ordinal of the pin from which we want to cancel the configuration.
Practical Example: Controlling the Speed of Fantastic Car Lights
The best way to learn is to put into practice what is learned in theory. For this, what we are going to do is the typical sketch with the fantastic car lights. In this case, we will control the speed with which it moves through two buttons .
Electrical Circuit
We will need the following material:
Each button will be connected to a pin and will have a pull-down resistor. This will make in a normal state, without pressing, the pin will have a low state. When the button is activated, we will have a high state. Therefore we must detect a change of state from low to high (RISING).
On the other hand, the LEDs will do a sequence of turning on and off from left to right and from right to left. Simulate the fantastic car lights. We will start with speed, and as we press the buttons, the speed will increase or decrease.
The electrical scheme is as follows.
Programming the Interruption Sketch with Arduino
The first part is the declaration of counters and variables. At this point, it is necessary to make a clarification. When we work with interruptions with Arduino, we must take special care with the ISR methods that will be executed when the event occurs.
In general, we must make ISR methods or functions as short and as fast as possible. A blockage between the different ISRs can occur. What happens in these cases is that only one is executed at a time, the rest of the interruptions being queued.
Within the interruptions, the delay () (delay) does not work; therefore, do not use it. Remember that it is about executing code as quickly as possible. If you want to make the process stop within an ISR, use the delayMicrosends () function since it works normally.
The variables that we will use both within the ISR methods and outside, either in the loop () or in any other function, we must declare them as volatile. This reserved word tells the compiler that these variables can change their value at any time and, therefore, the compiler must reload the variable every time reference is made to it. In contrast, other variables require the compiler to rely on a copy that it may have in a processor register.
Sketch Fantastic Car Lights with Interruptions
* /
// Global speed variable
volatile int speed = 20;
// Constants of maximum, minimum speed and how much increases
maximum int const = 1000;
minimum int const = 20;
const int increases = 20;
// Array with the pin numbers where they are connected
// the LEDs of the fantastic car lights
int leds [5] = {8, 9, 10, 11, 12};
void setup () {
// Initialize the LED pins as output and at low state
for (int i = 0; i <5; i ++)
{
pinMode (leds [i], OUTPUT);
digitalWrite (leds [i], LOW);
}
// We assign the minimum speed
speed = minimum;
// Configure the interrupt pins so that
// detect a change from low to high
attachInterrupt (digitalPinToInterrupt (2), speedLess, RISING) ;
attachInterrupt (digitalPinToInterrupt (3), speedMas, RISING);
}
void loop () {
// This first loop travels the array from left to right
for (int i = 0; i <5; i ++)
{
// Only for the second and consecutive pin, we turn off the previous pin
// In the case of 0, it is not necessary since by default it is off
// Be careful that we go out of the range of the array 0-1 = -1 this element does not exist
if (i> 0)
{
// Turn off the LED on the left
digitalWrite (leds [i - 1], LOW);
}
// We turn on the LED in which we are
digitalWrite (leds [i], HIGH);
// We wait for the time marked by speed
delay (speed);
}
// Turn off the last LED on, element 5 of the array
digitalWrite (leds [4], LOW);
// We traverse the array in the reverse direction from right to left
for (int i = 4; i> = 0; i--)
{
// In the first case as the LED is off, we do nothin g
// Be careful that we go out of the range of the 4 + 1 = 5 array this element does not exist
if (i <4)
{
// Turn off the LED on the right
digitalWrite (leds [i + 1], LOW);
}
// We turn on the LED in which we are
digitalWrite (leds [i], HIGH);
// We wait for the time marked by speed
delay (speed);
}
// Turn off the last LED on, element 0 of the array
digitalWrite (leds [0], LOW);
}
// ISR pin 2, slow down
void speed Less ()
{
// Decrease the set value
speed = speed - increases;
// If we have reached the minimum speed we do not decrease more
if (speed <minimum)
{
speed = minimum;
}
}
// ISR pin 3, increase the speed
void speedMore ()
{
// Increase the set value
speed = speed + increases;
// If we have reached the maximum speed we do not increase more
if (speed> maximum)
{
speed = maximum;
}
}
And finally, here in this chapter, we have seen the interruptions with Arduino. It is very important to know this technique very well since it will save us a lot of work on certain occasions.