Interrupt-driven button handling lets your Arduino react immediately when a button is pressed, without waiting or checking all the time.
Interrupt-driven button handling in Arduino
attachInterrupt(digitalPinToInterrupt(pin), ISR_function, mode);
pin is the Arduino pin number connected to the button.
ISR_function is the name of the function to run when the button is pressed.
mode defines when the interrupt triggers: RISING, FALLING, or CHANGE.
buttonPressed function when pin 2 goes from HIGH to LOW (button press).attachInterrupt(digitalPinToInterrupt(2), buttonPressed, FALLING);buttonPressed function when pin 3 goes from LOW to HIGH (button release).attachInterrupt(digitalPinToInterrupt(3), buttonPressed, RISING);This program uses an interrupt to detect when the button connected to pin 2 is pressed (goes from HIGH to LOW). The interrupt sets a flag. The main loop checks the flag and prints a message when the button is pressed.
#define BUTTON_PIN 2 volatile bool buttonPressedFlag = false; void setup() { pinMode(BUTTON_PIN, INPUT_PULLUP); // Button connected to pin 2 with internal pull-up Serial.begin(9600); attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), handleButtonPress, FALLING); } void loop() { if (buttonPressedFlag) { Serial.println("Button was pressed!"); buttonPressedFlag = false; // Reset flag } } void handleButtonPress() { buttonPressedFlag = true; // Set flag to indicate button press }
Use volatile for variables shared between interrupt and main code to avoid errors.
Keep interrupt service routines (ISR) very short and fast.
Use INPUT_PULLUP mode for buttons to avoid needing extra resistors.
Interrupts let your Arduino react instantly to button presses.
Use attachInterrupt() with a pin, function, and trigger mode.
Keep ISR code short and use flags to communicate with the main program.
Practice
Solution
Step 1: Understand what interrupts do
Interrupts pause the main program to run a special function immediately when an event happens, like a button press.Step 2: Compare interrupt behavior to normal checking
Without interrupts, the program must keep checking the button, which can delay response. Interrupts react instantly.Final Answer:
The Arduino can react immediately when the button is pressed without waiting. -> Option AQuick Check:
Interrupts = Immediate reaction [OK]
- Thinking interrupts slow down button response
- Believing interrupts disable other code permanently
- Confusing interrupts with polling multiple presses
buttonPressed on a FALLING edge?Solution
Step 1: Recall attachInterrupt syntax
The correct syntax is attachInterrupt(digitalPinToInterrupt(pin), ISR_function, mode).Step 2: Match parameters to the question
Pin is 2, function is buttonPressed, mode is FALLING edge.Final Answer:
attachInterrupt(digitalPinToInterrupt(2), buttonPressed, FALLING); -> Option AQuick Check:
attachInterrupt(pin, function, mode) = attachInterrupt(digitalPinToInterrupt(2), buttonPressed, FALLING); [OK]
- Swapping function and pin arguments
- Using pin number directly without digitalPinToInterrupt
- Mixing up trigger modes like RISING and FALLING
volatile bool pressed = false;
void setup() {
Serial.begin(9600);
pinMode(2, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2), buttonISR, FALLING);
}
void loop() {
if (pressed) {
Serial.println("Button pressed!");
pressed = false;
}
}
void buttonISR() {
pressed = true;
}Solution
Step 1: Understand ISR and flag usage
The ISR sets the volatile flag 'pressed' to true when the button is pressed.Step 2: Check loop behavior
The loop prints "Button pressed!" once when 'pressed' is true, then resets it to false, so it prints only once per press.Final Answer:
Button pressed! (printed once) -> Option DQuick Check:
ISR sets flag, loop prints once [OK]
- Thinking the message prints repeatedly without reset
- Assuming volatile causes errors
- Ignoring that flag resets after printing
volatile int count = 0;
void setup() {
Serial.begin(9600);
pinMode(3, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(3), countPresses, FALLING);
}
void loop() {
Serial.println(count);
delay(1000);
}
void countPresses() {
count++;
}Solution
Step 1: Check variable type and ISR safety
'count' is volatile int (multi-byte). Incrementing it in ISR and reading in loop can cause inconsistent values.Step 2: Understand atomicity issue
Incrementing multi-byte variables is not atomic; main code reading 'count' may see partial updates causing errors.Final Answer:
Modifying a multi-byte variable without disabling interrupts -> Option BQuick Check:
Multi-byte variable access must be atomic [OK]
- Ignoring atomicity of multi-byte variables
- Thinking delay() blocks interrupts
- Assuming attachInterrupt pin is wrong without checking
Solution
Step 1: Understand requirement for press duration
Counting only if pressed for 2 seconds means timing the press length, not just detecting press.Step 2: Use interrupt to detect press start and timer in loop
Interrupt on FALLING edge detects press start; loop checks if button held 2 seconds before counting.Final Answer:
Use attachInterrupt on FALLING edge to start a timer, then check duration in loop before incrementing count. -> Option CQuick Check:
Interrupt detects press start; loop checks hold time [OK]
- Incrementing count immediately without timing
- Using CHANGE edge causing multiple triggers
- Polling without interrupts misses instant detection
Ready to prove it?
Pass the test and this pattern moves unknown
