Wake-up from sleep with interrupt in Arduino - Time & Space Complexity
When using sleep mode with interrupts on Arduino, we want to know how the program's running time changes as input or events happen.
We ask: How often does the code run and how does that affect time?
Analyze the time complexity of the following code snippet.
#include <avr/sleep.h>
volatile bool wokeUp = false;
void wakeUp() {
wokeUp = true; // interrupt sets flag
}
void setup() {
pinMode(2, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2), wakeUp, FALLING);
}
void loop() {
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_cpu(); // sleeps until interrupt
sleep_disable();
if (wokeUp) {
// do something after wake-up
wokeUp = false;
}
}
This code puts the Arduino to sleep and wakes it up when a button press triggers an interrupt.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The
loop()function runs repeatedly, but most time is spent sleeping. - How many times: It runs once per wake-up event, which depends on external interrupts (button presses).
The program mostly sleeps, so execution time depends on how often the interrupt happens.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 interrupts | Runs loop 10 times |
| 100 interrupts | Runs loop 100 times |
| 1000 interrupts | Runs loop 1000 times |
Pattern observation: The number of operations grows linearly with the number of interrupts (events).
Time Complexity: O(n)
This means the program runs once for each interrupt event, so time grows directly with the number of wake-ups.
[X] Wrong: "The loop runs continuously and uses a lot of CPU time even when sleeping."
[OK] Correct: The CPU actually sleeps and does almost no work until an interrupt wakes it, so time spent running code depends on interrupts, not continuous looping.
Understanding how interrupts affect program flow and timing shows you can write efficient code that waits for events without wasting time.
"What if we replaced the interrupt with a polling check inside the loop? How would the time complexity change?"
Practice
Solution
Step 1: Understand sleep mode purpose
Arduino sleep mode reduces power consumption by stopping most activities.Step 2: Role of interrupts in sleep mode
Interrupts allow the Arduino to wake up immediately when an external event occurs, saving power while staying responsive.Final Answer:
To allow the Arduino to respond immediately to an external event while saving power -> Option AQuick Check:
Interrupt wakes Arduino from sleep to save power [OK]
- Thinking interrupts speed up normal running
- Confusing interrupts with reset functions
- Believing interrupts increase memory
Solution
Step 1: Use digitalPinToInterrupt() for pin mapping
Pin 2 must be converted using digitalPinToInterrupt(2) for portability.Step 2: Set correct trigger mode
RISING triggers interrupt when signal goes from LOW to HIGH.Final Answer:
attachInterrupt(digitalPinToInterrupt(2), ISR, RISING); -> Option BQuick Check:
Correct pin and RISING trigger = attachInterrupt(digitalPinToInterrupt(2), ISR, RISING); [OK]
- Using pin number directly without digitalPinToInterrupt()
- Choosing wrong trigger mode like FALLING or LOW
- Attaching interrupt to wrong pin number
void ISR() {
Serial.println("Woke up!");
}
void setup() {
Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(2), ISR, RISING);
sleep_enable();
sleep_mode();
Serial.println("Sleeping...");
}
void loop() {
// Empty loop
}Solution
Step 1: Analyze print locations
"Sleeping..." prints after sleep_mode(), so it executes after waking up.Step 2: ISR execution order
ISR prints "Woke up!" immediately upon interrupt, before resuming code after sleep_mode().Final Answer:
Sleeping...\nWoke up! -> Option DQuick Check:
Code after sleep_mode() runs after ISR, so output order is Sleeping... then Woke up! [OK]
- Thinking "Sleeping..." prints before sleep
- Believing no output after wake
- Expecting Sleeping... before ISR
void ISR() {
// Empty ISR
}
void setup() {
attachInterrupt(3, ISR, FALLING);
sleep_enable();
sleep_mode();
}
void loop() {
// Empty
}Solution
Step 1: Check attachInterrupt() usage
Pin number must be converted with digitalPinToInterrupt(pin) for correct interrupt mapping.Step 2: Validate other parts
Empty ISR is allowed; sleep_mode() can be in setup; sleep_enable() must be before sleep_mode().Final Answer:
attachInterrupt() uses pin number directly instead of digitalPinToInterrupt() -> Option AQuick Check:
Pin mapping requires digitalPinToInterrupt() [OK]
- Not using digitalPinToInterrupt() for pin mapping
- Thinking ISR must have code
- Misplacing sleep_enable() call
Solution
Step 1: Attach interrupt correctly
Use digitalPinToInterrupt(4) and FALLING trigger for button press (assuming active LOW button).Step 2: Enable sleep and enter sleep mode
Call sleep_enable() before sleep_mode() to allow waking on interrupt.Final Answer:
attachInterrupt(digitalPinToInterrupt(4), wakeISR, FALLING); sleep_enable(); sleep_mode(); -> Option CQuick Check:
Correct pin, trigger, and sleep calls = attachInterrupt(digitalPinToInterrupt(4), wakeISR, FALLING); sleep_enable(); sleep_mode(); [OK]
- Using sleep_disable() before sleep_mode()
- Wrong trigger mode like LOW or CHANGE for button press
- Not enabling sleep before entering sleep_mode()
Ready to prove it?
Pass the test and this pattern moves unknown
