Choosing Arduino Sleep Modes vs delay() for Battery‑Powered Projects
Learn when to use Arduino's built‑in delay() or low‑power sleep modes to extend battery life while keeping interrupt responsiveness and timing accuracy.
08 Sept 2025, 15:19 UTC

Problem and Takeaway
You are building a battery‑operated Arduino node that must stay idle until an external event (e.g., a button press or sensor trigger) occurs. While waiting, the MCU draws current that drains the battery. The useful takeaway is: you can cut the idle current by an order of magnitude by putting the AVR into a low‑power sleep mode instead of using delay(), provided you keep interrupt responsiveness and timing within ±10 ms.
Decision and Constraints
Decision: select either the Arduino delay() function or one of the AVR sleep modes (Idle, ADC Noise Reduction, Power‑down). Constraints:
- Must wake on an interrupt with < 1 ms latency (plus any wake‑up overhead).
- Timing accuracy of the wake‑up interval must stay within ±10 ms.
- No additional hardware (e.g., external RTC) may be added.
Option Comparison
| Mode | Typical Current (mA) | Wake‑up Sources | Latency (ms) |
|---|---|---|---|
delay() |
5‑10 (depends on clock) | Any interrupt | 0 (CPU runs) |
| Idle | 3‑5 | Any interrupt | <1 |
| ADC Noise Reduction | 2‑4 | ADC complete, any interrupt | <1 |
| Power‑down | 0.1‑0.5 | External interrupt, reset, watchdog | <1 (plus wake‑up time) |
Trade‑offs
delay() keeps the CPU executing a tight loop, so power draw is highest but the code is simplest and peripherals remain fully active. Idle mode stops the CPU clock while leaving most peripherals running, giving a modest current saving with virtually no latency penalty. ADC Noise Reduction further reduces power and improves ADC accuracy by disabling the CPU and most I/O clocks, but you cannot use other peripherals while the ADC is converting. Power‑down offers the greatest savings because the CPU and almost all I/O clocks are stopped; only asynchronous external interrupts (or the watchdog timer) can wake the MCU. This means you must design your ISR to be very short and re‑enable any peripherals (e.g., UART, timers) that you need after waking.
Concrete Implementation: Power‑down with External Interrupt
The following sketch targets an Arduino Uno (ATmega328P). It configures Power‑down sleep, attaches an external interrupt to pin 2 (INT0), toggles an LED on wake‑up, and then returns to sleep.
/* Arduino Uno Power‑down sleep example
Wake‑up on falling edge of pin 2 (INT0)
LED on pin 13 indicates wake‑up
*/
#include
#include
volatile bool woke = false;
void wakeISR() {
woke = true; // just set a flag; keep ISR short
}
void setup() {
pinMode(2, INPUT_PULLUP); // INT0 with pull‑up
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
attachInterrupt(digitalPinToInterrupt(2), wakeISR, FALLING);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
}
void loop() {
if (woke) {
woke = false;
digitalWrite(13, !digitalRead(13)); // toggle LED
// Optional: re‑enable peripherals that were disabled
power_all_enable();
}
sleep_mode(); // enters Power‑down; execution resumes after ISR
// After waking, peripherals are still disabled; re‑enable if needed
power_all_enable();
}
Where to run: copy the code into the Arduino IDE, select **Tools → Board → Arduino Uno**, choose the correct port, and click **Upload**. No special permissions are required beyond normal user access to the IDE and USB port.
Validation Steps
- Open the Serial Monitor at 9600 baud (optional, you can add
Serial.begin(9600)and print a message on wake‑up) to confirm the interrupt is being serviced. - With a digital multimeter set to µA‑mode, measure the current drawn from the VCC pin while the sketch is running and the interrupt is not triggered. You should observe a current in the range of 0.1‑0.5 mA (Power‑down) versus roughly 5‑10 mA when using
delay(1000)in place of the sleep loop. - To check timing, connect an oscilloscope (or a logic analyzer) to pin 2 (interrupt) and pin 13 (LED). Trigger on the falling edge of pin 2 and verify that the LED changes state within a few milliseconds (typically < 2 ms) of the edge, confirming the latency requirement.
Limitations and Practical Checks
- Watchdog‑timer wake‑up in Power‑down is limited to 8 s intervals on AVR‑based boards; longer periods require cascating watchdogs or an external real‑time clock.
- Peripherals such as UART, SPI, or timers remain disabled after waking from Power‑down; you must re‑enable them (as shown with
power_all_enable()) before using them. - If you need to keep the ADC running while sleeping, use ADC Noise Reduction mode instead, but note that most other I/O clocks are stopped.
- Always verify that the interrupt pin is configured correctly (e.g., pull‑up/pull‑down) to avoid spurious wake‑ups.
Practical way to confirm the result: after uploading the sketch, let the board sit idle for a minute, record the multimeter reading, then momentarily short pin 2 to ground to simulate an event. The LED should toggle and the current should briefly rise as the MCU wakes and executes the ISR, then drop back to the low‑sleep level. This cycle demonstrates both power saving and correct interrupt responsiveness.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.