Best Simple Arduino Guide To Interrupts

Do you like to be interrupted? From my own experience and observations, I’ve come to find that almost everyone hates interruptions. Yet, in this guide, I’ll make you love interrupts. These interrupts will make your life easier when working with the Arduino.

I’ll be covering why interrupts are important, how you can implement them, what pins you’ll need to use them, the different types of interrupts, and what happens if multiple interrupts are interrupting each other.

But let’s start with the question:

What Is An Interrupt?

An interrupt basically signals the Arduino’s processor to stop running the program that it’s in the middle of doing and focus on performing high-priority tasks. These tasks are described by the code in the interrupt handler, which is the same as any other void function. However, when the interrupt is triggered, the code inside the interrupt handler runs first while all the other code is paused.

In essence, the interrupt makes sure that the processor can react quickly and efficiently to time-critical events. The interrupt is activated when it detects a stimulus, which can be either internal or external.

Why Is An Interrupt Important?

An interrupt is a very important and useful feature because it prioritizes important tasks or events when your program is running. For some projects, Arduino users incorporate code that protects their projects from danger during cases of emergencies.

Without the interrupts, the user’s “protection” code would be useless because the processor of the Arduino doesn’t understand which code should be the priority.

That’s because the processor defaults to a structure called polling. Polling in this context doesn’t mean recording someone else’s opinions.

Throughout this method, the processor goes through tasks one by one starting from the top and working its way down to the bottom. This is similar to people reading a book. It is commonly used and should suffice for beginners.

To solidify your understanding, let’s use an example. Because I’ve worked in the restaurant business for a long time, this example will be based on my own experience.

Imagine a humanoid robot. For all the Star Wars fans out there, you can picture my robot looking similar to C-3PO. Anyways, I built and programmed this robot to take over for me. It does all my tasks at the restaurant. It talks to customers, takes their orders, prepares their food, and packages their food.

Since I’m in a restaurant and working with fire to cook food, I’ll need to program my droid to constantly check to make sure there isn’t any fire-related incidents. If there is and my robot doesn’t catch it, my whole business will burn down. Here’s a mockup of what my code would look like (notice I put the checkFire() function first since it’s my biggest concern):

void loop() {

// check if there's a fire or not and resolve it
checkFire();

// check if there are any customers
checkCustomer();

// talk to customers if there are any
talkCustomer();

// take customer order
customerOrder();

// prepare or cook food
foodPrep();

// package the order and hand it off
packageFood();

}

Let’s say that the first function only takes 20 seconds to complete. The second one would take 30 seconds, the third will take 1 minute, the fourth would take another minute, the fifth would take 10 minutes, and the last one would take 3 minutes.

Now, you may be wondering, why is this important? Let’s say that while the robot is in the middle of talking to a customer, a fire suddenly erupts out of nowhere.

What does the robot do now? Well, I have fire detections and protections built into the droid like smoke detectors and a fire extinguisher. However, because this structure is solely based on polling, which means it lacks interrupts, the droid will continue to do the other functions until it reaches the end and loops back to the top to check for any fires.

If you do the math, my bot will actually start handling the fire after 15 minutes. However, my business would’ve already burned down along with the robot in it by that time. It takes the average house today to burn down between 3 and 4 minutes (according to Angi). This would be very devastating to me, which is why the interrupt is so important.

Some of you may object and point out that I could add the checkFire() function after each function to get the robot to react faster.

void loop() {

// check if there's a fire or not and resolve it
checkFire();

// check if there are any customers
checkCustomer();

// check if there's a fire or not and resolve it
checkFire();

// talk to customers if there are any
talkCustomer();

// check if there's a fire or not and resolve it
checkFire();

// take customer order
customerOrder();

// check if there's a fire or not and resolve it
checkFire();

// prepare or cook food
foodPrep();

// check if there's a fire or not and resolve it
checkFire();

// package the order and hand it to the customer
packageFood();

}

That may seem like a good idea, but remember, there are still functions that will take a long time to complete. In the worst-case scenario, my robot will react to the fire in 10 minutes because the foodPrep() function will have to take 10 minutes to complete. I concede that 10 minutes is faster and better than 15 minutes, but again, my restaurant reduced to ashes within 3 to 4 minutes.

Thankfully, the interrupt can actually interrupt a function while it’s in the middle of running, so that means my robot will get to extinguish the fire as soon as possible once it detects a fire. That’s why the interrupt is the best solution for emergency cases, and it’s the quickest and easiest method of doing so (compared to my previous example).

I know I keep talking about fires a lot, but did you know your Arduino can also catch on fire? You should go check out my blog on temperatures to learn the fire prevention tips you can take to prevent this from happening.

What Are The Interrupt Pins For Arduino?

The best pins to use for interrupts to trigger an event are pins 2 and 3 on the Arduino Uno R3 board. These 2 pins are the best options because they have dedicated interrupt vectors attached to them. Pin 2 has the name INT0 since it corresponds to the interrupt vector 0 and pin 3 has the name INT1 since it corresponds to the interrupt vector 1.

As you will see in the next section, interrupt vectors will prove to be essential when using interrupts. That’s because they are the first argument the attachInterrupt() function takes when called.

If you want to see what other pins other types of Arduino boards can use, check out the official documentation from Arduino here.

How Do You Use An Interrupt?

To use an interrupt for your Arduino project, you’ll need to use the attachInterrupt() function. It has the following syntax:

attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);

As you can see, this function takes 3 different parameters: the interrupt vector, the function name of the ISR (interrupt service routine), and the interrupt mode. Here’s what they mean:

  1. Interrupt vector: This holds a numerical value that lets the processor know which pin on your Arduino board can create the interrupt. Unlike what beginners may think, this number is not the number of the pin you’re using to implement the interrupt. Instead, the number is going to tell the Arduino processor where to look in its memory.
    1. Like I mentioned before, the interrupt vector numbers for pin 2 and pin 3 on the Uno R3 board is 0 and 1 respectively.
    2. If you don’t know what the interrupt vector number is for the pin you’re using, you can use the digitalPinToInterrupt() function and pass the pin number as its argument.
  2. ISR’s function name: This is basically the name of the function that has high priority. It’s for special events that you want to run.
    1. Going back to my restaurant example, the checkFire() function is what I would pass in as the second argument because I want it to be quickly engaged if there is a fire.
  3. Interrupt mode: This figures out what pin action to use to trigger an interrupt. For this function, you can use 4 different modes: rising, falling, change, and low. Here’s what they mean:
    1. RISING: An interrupt is activated on the rising edge of the interrupt pin.
      1. Basically, this means an interrupt is triggered when the signal goes from low to high or 0V to 5V.
    2. FALLING: An interrupt is activated on the falling edge of the interrupt pin.
      1. This essentially means that the interrupt is triggered when the signal goes from high to low or 5V to 0V.
    3. CHANGE: An interrupt is activated any moment when the signal changes either by rising or falling.
    4. LOW: An interrupt is activated whenever the signal is low or continously at 0V.

Note: There is also a fifth mode for the attachInterrupt() function, but it’s exclusive to only the Due, Zero, and MKR1000 Arduino boards. That mode is called HIGH, and it’s when the signal is continuously at 5V.

What Are The Different Types of Interrupts?

There are many different types of interrupts, but the most commonly used ones are the external interrupt and the internal interrupt. Like their names suggest, the external interrupt is activated when it’s stimulated by hardware (or the environment) while the internal interrupt is stimulated by software.

External Interrupt

A common example of external interrupts being activated is when there is a voltage change. For example, let’s say you have a push-button hooked up to a pin (preferably pin 2 or pin 3).

When the button is not being pressed, the pin you’re using applies a voltage of 5V (volts) to it. However, once you press the button, the ground voltage will be applied to it. Ground voltage basically means that 0 volts are being supplied.

As you can see, this voltage change from 5V to 0V is enough to trigger an interrupt. This is useful and can be utilized in projects as a “break in case of an emergency” last resort.

Internal Interrupt

The internal interrupt is triggered based on the timer housed in the Arduino’s microcontroller. The clock has ticks that are either counted in milliseconds if you use the millis() function or in microseconds if you use the micros() function.

You can use this type of interrupt when you want a specific action to be performed at a certain time. For example, you can program the Arduino to check something after 2,000 milliseconds (which is basically 2 second).

Can An Interrupt Interrupt Each Other?

Interrupts can interrupt each other based on the priority level. That means if multiple interrupts are triggered at the same time, the interrupt with the highest priority will go first. After it has finished running its function, the one with the second-highest priority will go next, and so on.

Let’s go back to my restaurant example again. Pretend the business at my imaginary restaurant is booming. It’s really busy, and there’s a lot of customers coming in and ordering food. Instead of only taking a customer’s order, preparing their food, packaging it, and giving it to them one at a time, I want my robot to multitask.

For example, it could be in the middle of talking to a customer while the food is cooking. However, I don’t want my food to burn, so I’ll make another interrupt to have my robot check on my food: checkFood().

But wait! We already have an interrupt that checks to see if there is a potential fire or not. Consequently, I’ll need to give my checkFood() function second priority and my checkFire() function the highest priority. Understandably, it’s better to have a burned chicken dinner than a burned building. Hopefully, the food won’t overcook and start another fire if my robot has to deal with a fire.

So which interrupt has the highest priority? Interestingly, the reset pin has the highest priority. This is basically the reset button on your Arduino board since the pin is connected to it.

I’ve written a great article on reset buttons on the Arduino. You should go check it out to see the other methods to reset your board in case the reset button doesn’t work for you.

The next pin on the Arduino Uno R3 board that has the highest interrupt priority is pin 2. That leaves pin 3 as the lowest priority interrupt.

If you’re using a different board, you may find a list of interrupts for the associated pins and their order of importance online.

Summary – tl;dr (Too Long; Didn’t Read)

Here are the key takeaway points you should keep in mind after reading this article:

  • An interrupt will direct your Arduino to perform tasks that are the most urgent
  • Interrupts are important since they can be used to protect your Arduino in case of emergencies when programmed correctly
  • The interrupt pins are the 2 and 3 pins
  • You can use interrupts by implementing the attachInterrupt function
  • There are two types of interrupts: internal and external
    • Internal interrupt is triggered by the timer in the Arduino
    • External interrupt is triggered when there is a voltage change
  • Interrupts can interrupt each other based on levels of priority

Now, go make learning interrupts your priority, and don’t let anything or anyone interrupt your work!

References

I’ve used the following source(s) to ensure my content is relevant and updated:

Similar Posts