Interrupt-driven button handling in Arduino - Time & Space Complexity
When using interrupts to handle button presses, we want to know how the program's work changes as more button events happen.
We ask: how does the time spent reacting to button presses grow as the number of presses increases?
Analyze the time complexity of the following code snippet.
volatile int buttonPressCount = 0;
void setup() {
pinMode(2, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2), countPress, FALLING);
}
void loop() {
// Main code runs here
}
void countPress() {
buttonPressCount++;
}
This code counts how many times a button connected to pin 2 is pressed using an interrupt.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The interrupt service routine (ISR) increments a counter each time the button is pressed.
- How many times: Once per button press event, which can happen many times independently of the main program.
Each button press triggers a quick increment operation. The total work grows directly with the number of presses.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 increments |
| 100 | 100 increments |
| 1000 | 1000 increments |
Pattern observation: The work grows in a straight line as button presses increase.
Time Complexity: O(n)
This means the time spent handling button presses grows directly with how many times the button is pressed.
[X] Wrong: "The interrupt runs constantly and slows down the program regardless of button presses."
[OK] Correct: The interrupt code only runs when the button is pressed, so the time spent depends on the number of presses, not on time passing.
Understanding how interrupts affect program time helps you write responsive and efficient embedded programs, a useful skill in many real projects.
What if we added a delay inside the interrupt routine? How would the time complexity change?
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
