100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Power Management and Sleep Modes

Learn how to slash an Arduino's current draw from milliamps to microamps using the AVR sleep modes, watchdog timers, and interrupt-driven wake-ups for battery-powered projects.

Practical ArduinoIntermediate10 min readJul 10, 2026
Analogies

Why Power Management Matters

A stock Arduino Uno running loop() at full speed draws roughly 45-50 mA, most of it wasted spinning the ATmega328P and powering the onboard regulator and USB chip. On a 2000 mAh battery that is barely two days of life. Power management is about doing nothing efficiently: putting the microcontroller into a low-power sleep state whenever it is not actively sensing or transmitting, then waking it only when work arrives. The deepest AVR sleep mode drops current draw to under 1 microampere, a reduction of four to five orders of magnitude, which turns a two-day project into a multi-year one.

🏏

Cricket analogy: Like a fielder at deep fine leg who jogs only when the ball comes his way instead of sprinting every delivery — he conserves energy for the moments that actually matter over a long Test match.

The AVR Sleep Modes

The ATmega328P offers six sleep modes selected through the SLEEP_MODE_* constants in avr/sleep.h, ordered from lightest to deepest. SLEEP_MODE_IDLE only halts the CPU clock but keeps timers, SPI, and the ADC running, so it saves little. SLEEP_MODE_PWR_DOWN is the workhorse: it stops the main and peripheral clocks and shuts down everything except the watchdog timer and external interrupts, reaching roughly 0.1 microamps on the bare chip. Between them sit SLEEP_MODE_ADC (for quiet analog reads), SLEEP_MODE_PWR_SAVE, and two standby modes that trade a faster crystal restart time for slightly higher current. Choosing the mode is a trade-off between how deeply you sleep and which peripherals must survive to wake you.

🏏

Cricket analogy: Like the graded rest between a drinks break, tea interval, and stumps — a drinks break is a light pause where play resumes instantly, while stumps shuts everything down until the next day's fresh start.

cpp
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <avr/power.h>

volatile bool wdtFired = false;

ISR(WDT_vect) {          // watchdog interrupt fires on wake
  wdtFired = true;
}

void setupWatchdog() {
  cli();
  wdt_reset();
  // enter WDT config mode
  WDTCSR = (1 << WDCE) | (1 << WDE);
  // interrupt mode, ~8 s timeout (WDP3 | WDP0)
  WDTCSR = (1 << WDIE) | (1 << WDP3) | (1 << WDP0);
  sei();
}

void sleepNow() {
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  power_all_disable();      // kill ADC, TWI, timers, USART
  sleep_mode();             // <-- CPU stops here until WDT wakes it
  // execution resumes on the next line after wake
  sleep_disable();
  power_all_enable();
}

void setup() {
  Serial.begin(9600);
  setupWatchdog();
}

void loop() {
  Serial.println("Awake: reading sensor...");
  delay(50);                // real work here
  Serial.flush();           // finish TX before sleeping
  sleepNow();               // sleep ~8 s at <1 uA
}

Always call Serial.flush() before sleeping. The serial hardware buffers outgoing bytes, and if you enter PWR_DOWN mid-transmission the clock stops and the last characters are lost or corrupted. flush() blocks until the buffer is empty.

Waking the Chip: Watchdog vs External Interrupts

In power-down mode almost every clock is dead, so only two things can wake the chip: the watchdog timer or a level/edge change on an external interrupt pin. The watchdog runs off an independent 128 kHz internal oscillator and can be configured for timed wake-ups from 16 ms up to about 8 seconds; chaining multiple 8-second sleeps in software gives you arbitrary intervals for periodic sensors. External interrupts via attachInterrupt() on pins 2 and 3 (INT0/INT1), or pin-change interrupts on any pin, wake the chip instantly when a button, motion sensor, or RTC alarm pulls the line — this is the event-driven pattern for devices that must sleep indefinitely until something physically happens.

🏏

Cricket analogy: Like the two ways an umpire ends an over: the automatic six-ball count (the watchdog ticking to its limit) or a sudden appeal for a wicket that stops play instantly (an external interrupt firing on an event).

The onboard voltage regulator and USB-to-serial chip on an Uno keep drawing 10-30 mA even when the ATmega328P is fast asleep, so a stock Uno never reaches microamp figures. For true low-power battery projects, use a bare ATmega328P on a breadboard, a Pro Mini with the regulator/LED removed, or a board designed for it, and power the chip directly from a clean regulated source.

  • A stock Uno draws ~45 mA active; SLEEP_MODE_PWR_DOWN on a bare ATmega328P drops that below 1 uA.
  • avr/sleep.h exposes six modes; PWR_DOWN is deepest and most useful, IDLE is lightest and saves little.
  • In power-down mode only the watchdog timer or an external/pin-change interrupt can wake the CPU.
  • The watchdog gives timed wake-ups up to ~8 s; chain them in software for longer periodic intervals.
  • Always Serial.flush() and disable unused peripherals with power_all_disable() before sleeping.
  • The onboard regulator and USB chip dominate current on an Uno, so use a bare or stripped-down board for real battery gains.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#ArduinoProgrammingStudyNotes#PowerManagementAndSleepModes#Power#Management#Sleep#Modes#StudyNotes#SkillVeris#ExamPrep