Table of Contents
KEY TAKEAWAYS
- Sleep modes reduce power consumption by disabling the CPU, peripherals, or both while idle
- Common modes range from idle (CPU halted, peripherals active) to deep sleep (most systems off)
- Wake-up sources include external interrupts, timers, and communication events
- Effective low-power design combines sleep modes with duty cycling and peripheral power gating
What are Sleep Modes?
Sleep modes are low-power states that a microcontroller can enter when it has no immediate work to do. Instead of wasting energy running an idle loop, the MCU shuts down some or all of its internal components to reduce current draw from milliamps down to microamps or even nanoamps.
The MCU wakes up when an event occurs: a timer expires, an external interrupt triggers, or a communication peripheral receives data.
Common Sleep Mode Levels
Most microcontrollers offer several sleep modes with increasing levels of power savings:
| Sleep Mode | What is OFF | What is ON | Typical Current | Wake-up Time |
|---|---|---|---|---|
| Idle / Sleep | CPU clock | Peripherals, RAM, clock system | 1-5 mA | Instant (1-2 cycles) |
| Light Sleep | CPU, most peripherals | RAM, RTC, selected peripherals | 0.1-1 mA | Fast (microseconds) |
| Deep Sleep | CPU, RAM, most peripherals | RTC, wake-up logic | 1-50 uA | Slow (milliseconds, re-init needed) |
| Shutdown / Hibernate | Nearly everything | Only wake-up pin logic | 0.1-1 uA | Slowest (full reboot) |
The deeper the sleep, the more power you save, but the longer it takes to wake up and the more state you lose.
Sleep Modes on Popular Platforms
ESP32
| Mode | Current | Wake Sources |
|---|---|---|
| Active (WiFi) | 95-240 mA | N/A |
| Modem Sleep | 20 mA | Automatic (WiFi stays associated) |
| Light Sleep | 0.8 mA | Timer, GPIO, touch, UART |
| Deep Sleep | 10 uA | Timer, ext0/ext1 GPIO, touch, ULP |
| Hibernation | 5 uA | Timer, RTC GPIO only |
// ESP32 Deep Sleep example (ESP-IDF)
#include "esp_sleep.h"
void app_main(void) {
// Read sensor
float temp = read_temperature();
send_data_mqtt(temp);
// Configure wake-up after 15 minutes
esp_sleep_enable_timer_wakeup(15 * 60 * 1000000ULL); // microseconds
// Or wake on GPIO (e.g., button press)
esp_sleep_enable_ext0_wakeup(GPIO_NUM_33, 0); // Wake when GPIO33 goes LOW
// Enter deep sleep
esp_deep_sleep_start();
// Code after this line never executes
// On wake-up, the program restarts from app_main()
}STM32 (Cortex-M)
| Mode | Current (STM32L4) | Wake Sources |
|---|---|---|
| Run | 3-10 mA | N/A |
| Sleep | 1-3 mA | Any interrupt |
| Low-Power Sleep | ~100 uA | Any interrupt |
| Stop 0/1/2 | 1-10 uA | EXTI, RTC, LPUART, I2C |
| Standby | 0.3 uA | WKUP pins, RTC |
| Shutdown | 0.03 uA (30 nA) | WKUP pins only |
// STM32 HAL - Enter Stop Mode 2
void enter_low_power(void) {
// Disable unused clocks
__HAL_RCC_GPIOB_CLK_DISABLE();
__HAL_RCC_GPIOC_CLK_DISABLE();
// Configure wake-up source (e.g., RTC alarm in 60 seconds)
set_rtc_alarm(60);
// Enter Stop Mode 2
HAL_SuspendTick();
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
// Execution resumes here after wake-up
HAL_ResumeTick();
SystemClock_Config(); // Reconfigure clocks
}Arduino (ATmega328P)
#include <avr/sleep.h>
#include <avr/wdt.h>
void enter_sleep(void) {
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Deepest sleep
sleep_enable();
// Disable ADC (saves ~300 uA)
ADCSRA &= ~(1 << ADEN);
// Disable BOD during sleep (saves ~25 uA)
sleep_bod_disable();
sleep_cpu(); // Actually go to sleep
// Execution continues here after wake-up
sleep_disable();
ADCSRA |= (1 << ADEN); // Re-enable ADC
}
// Wake-up via watchdog timer interrupt
ISR(WDT_vect) {
// Watchdog fired - MCU wakes up
}Wake-up Sources
Timer / RTC Wake-up
The most common method. A low-power timer (RTC) counts while the MCU sleeps and triggers a wake-up after a set duration. Ideal for periodic tasks like sensor readings.
External Interrupt (GPIO)
A change on a pin (button press, sensor alert, motion detection) wakes the MCU. Ideal for event-driven devices that should only wake when something happens.
Communication Peripheral
Some MCUs can wake on UART data received or I2C address match while in light sleep. This allows the device to respond to external commands without staying fully awake.
Touch Pad (ESP32)
The ESP32 can wake from deep sleep when a capacitive touch pad is activated, useful for devices with touch interfaces.
The Duty Cycling Pattern
The most common low-power design pattern is duty cycling: wake up, do work, go back to sleep.
Active Sleep Active Sleep
|‾‾‾‾|___________________|‾‾‾‾|___________________
2ms 14,998ms 2ms 14,998ms
10mA 5uA 10mA 5uA
Duty Cycle = 2ms / 15,000ms = 0.013%
Average Current = (10mA x 0.00013) + (5uA x 0.99987) = 6.3 uAEven though the active current is 10mA, the average drops to just 6.3 uA because the device sleeps 99.99% of the time.
Practical Low-Power Tips
- Disable ADC before sleeping. The ADC draws significant current even when not converting. On AVR, this alone saves 300 uA.
- Configure unused GPIO pins. Floating input pins can oscillate and draw current. Set unused pins as outputs (driven low) or inputs with pull-ups/pull-downs.
- Use the lowest clock speed needed. Run at 1 MHz for simple tasks, boost to full speed only for computation-heavy work.
- Minimize LED usage. A single LED at 10mA can consume more than the entire MCU in sleep. Use brief blinks instead of steady-on indicators.
- Store data in RTC memory. On ESP32, RTC memory survives deep sleep. Store state there to avoid re-initialization:
RTC_DATA_ATTR int boot_count = 0; // Persists across deep sleep cycles void app_main(void) { boot_count++; printf("Boot #%d\n", boot_count); } - Batch operations. If you need to send 6 sensor readings per hour, sleep for 10 minutes, store the reading in RAM, and send all 6 at once every hour. One WiFi connection every hour uses far less energy than six.
Summary
Sleep modes are the most effective tool for extending battery life in embedded systems. The key principle is simple: if the MCU has nothing to do, put it to sleep. Choose the deepest sleep mode your application allows, wake up only when needed, do the work as fast as possible, and go back to sleep. A well-designed duty cycling system can extend battery life from days to years.

Vivek Bhageria — Lead Firmware R&D Engineer, 12+ years. Ex-Bosch (automotive powertrain), MusicTribe (real-time audio), medical devices. M.Tech BITS Pilani. I write at NerdyElectronics — practical, register-level embedded systems for engineers who want to understand what’s actually happening under the hood.






