
Ever write an Arduino sketch filled with delay() functions, only to realize your buttons are completely ignoring you? Your Arduino is too busy doing nothing during that delay to notice your frantic button pressing.
Stop polling like a chump. Enter the magic of hardware interrupts. Itâs the microcontroller equivalent of tapping someone on the shoulder and screaming âPAY ATTENTION TO ME NOW.â
Think of a hardware interrupt as a tap on the shoulder for your microcontroller. No matter what your Arduino is currently doing (even if itâs stuck in a long delay or a heavy calculation), an interrupt forces it to drop everything, handle the event immediately, and then resume exactly where it left off.
Here are a few reasons why interrupts are game-changers:
digitalRead() in your loop() to see if a button state changed.loop() to focus on the big picture instead of micro-managing inputs.attachInterrupt()To use a hardware interrupt on an Arduino Uno, you typically use pins 2 or 3. Here is a simple example that turns on an LED when a button is pressed, using an interrupt.
const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
// Attach the interrupt to pin 2
// Trigger the blink() function when the pin goes from HIGH to LOW (FALLING edge)
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, FALLING);
}
void loop() {
// The main loop can do whatever it wants!
// The LED state is handled entirely in the background.
digitalWrite(ledPin, state);
// Let's pretend we are doing some heavy processing here
delay(1000);
}
// This is the Interrupt Service Routine (ISR)
void blink() {
state = !state; // Toggle the state
}
volatile keyword: Notice how the state variable is declared as volatile byte. This tells the compiler that this variable can change at any time (outside the normal flow of the program), so it shouldnât try to optimize it away. Always use volatile for variables modified inside an ISR!digitalPinToInterrupt(pin): You should always use this function rather than just typing the interrupt number directly. It ensures your code is portable across different Arduino boards.blink()): This is the Interrupt Service Routine. Itâs the function that gets called when the interrupt triggers. ISRs should be as short and fast as possible. Donât use delay() or Serial.print() inside an ISR!FALLING: This is the trigger mode. Because we used INPUT_PULLUP, the pin is normally HIGH. Pressing the button connects it to ground, making it go LOW. The transition from HIGH to LOW is a âfallingâ edge.Interrupts are an essential tool for building responsive, professional-grade projects. Start incorporating them into your builds and see the difference!
To follow along with this lesson, youâll need the following components: