ESP32

ESP32 Power Management: Sleep Modes & Battery Optimization

ESP32 Deep Sleep ~10μA Z Z Z Light Sleep ~800μA Modem Sleep ~15mA Active Mode ~240mA BATTERY ESP32 Sleep Modes Power Optimization Strategies Deep Sleep: ~10μA Light Sleep: ~800μA Modem Sleep: ~15mA Automatic Light Sleep: ~3mA Active Mode: ~240mA Deep Light Modem Auto Light Active Power Consumption (not to scale)

Introduction to ESP32 Power Management

The ESP32 offers sophisticated power management capabilities that can dramatically extend battery life in IoT applications. By strategically using the different sleep modes, you can reduce power consumption from hundreds of milliamps to just a few microamps when the device is idle.

This guide explores the various sleep modes available on the ESP32, their power characteristics, and how to implement them in your projects. Understanding these modes is essential for creating battery-powered IoT devices that can operate for months or even years on a single charge.

Looking for more advanced implementation details? Check out our Advanced ESP32 Sleep Modes Guide for ESP32 model differences, UART wake-up, touch wake-up, and more.

ESP32 Sleep Modes Overview

The ESP32 supports five main power modes, each with different characteristics:

Mode Power Wake-up Sources Features
Active Mode ~240mA N/A CPU, Wi-Fi, Bluetooth all active
Modem Sleep ~15mA Any CPU active, Wi-Fi/BT off between beacons
Auto Light Sleep ~3mA Any CPU inactive but clock running
Light Sleep ~800μA GPIO, Timer, UART, Touch, ULP CPU paused, RTC active, RAM retained
Deep Sleep ~10μA GPIO, Timer, Touch, ULP Only RTC memory retained, ULP coprocessor can run
Hibernation ~5μA GPIO, Timer RTC slow memory shut down, only timer and ext. wakeup

Note: Actual power consumption may vary depending on specific hardware, enabled peripherals, and supply voltage. The values provided here are approximate.

ESP32 Model Differences

Different ESP32 models (ESP32, ESP32-S2, ESP32-S3) have varying capabilities regarding sleep modes and available wake-up sources. See our advanced guide for detailed comparison.

Deep Sleep Mode

Deep Sleep is the most power-efficient sleep mode where most of the ESP32 is powered down, leaving only the RTC memory and basic RTC peripherals active. This mode uses around 10μA of current, making it ideal for battery-powered applications that need to wake up periodically.

Wake-up Sources in Deep Sleep

  • Timer: Wake up after a specified duration
  • External wake-up: Wake on GPIO state change (RTC GPIOs only)
  • Touch sensors: Wake on capacitive touch threshold
  • ULP (Ultra Low Power) coprocessor: Wake when a condition is detected by the ULP

Need more control over external wake-up? Check out our detailed comparison of ext0, ext1, and GPIO wake-up methods.

Deep Sleep Example Code

#include 

// Define the GPIO pin connected to the sensor
#define SENSOR_PIN 33

// Define wake-up sources
#define uS_TO_S_FACTOR 1000000  // Conversion factor for micro seconds to seconds
#define TIME_TO_SLEEP  60       // Time ESP32 will go to sleep (in seconds)

RTC_DATA_ATTR int bootCount = 0; // Stored in RTC memory, persists through deep sleep

void setup() {
    Serial.begin(115200);
    delay(1000); // Allow serial connection to establish
    
    // Increment and print the boot count
    bootCount++;
    Serial.println("Boot number: " + String(bootCount));
    
    // Print wake-up reason
    print_wakeup_reason();
    
    // Set GPIO33 as input for external wake-up
    esp_sleep_enable_ext0_wakeup(GPIO_NUM_33, HIGH);
    
    // Configure the timer wake-up
    esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
    Serial.println("Setting up ESP32 to sleep for " + String(TIME_TO_SLEEP) + " seconds");
    
    // Do your sensor readings or other work here
    read_sensor();
    
    // Enter deep sleep
    Serial.println("Going to deep sleep now");
    Serial.flush(); 
    esp_deep_sleep_start();
}

void loop() {
    // This is never executed in this example
    // Because we go to deep sleep at the end of setup()
}

void print_wakeup_reason() {
    esp_sleep_wakeup_cause_t wakeup_reason;
    wakeup_reason = esp_sleep_get_wakeup_cause();

    switch(wakeup_reason) {
        case ESP_SLEEP_WAKEUP_EXT0:
            Serial.println("Wakeup caused by external signal using RTC_IO");
            break;
        case ESP_SLEEP_WAKEUP_EXT1:
            Serial.println("Wakeup caused by external signal using RTC_CNTL");
            break;
        case ESP_SLEEP_WAKEUP_TIMER:
            Serial.println("Wakeup caused by timer");
            break;
        case ESP_SLEEP_WAKEUP_TOUCHPAD:
            Serial.println("Wakeup caused by touchpad");
            break;
        case ESP_SLEEP_WAKEUP_ULP:
            Serial.println("Wakeup caused by ULP program");
            break;
        default:
            Serial.println("Wakeup was not caused by deep sleep: " + String(wakeup_reason));
            break;
    }
}

void read_sensor() {
    // Example sensor reading code
    int sensorValue = analogRead(SENSOR_PIN);
    Serial.println("Sensor value: " + String(sensorValue));
    
    // You would typically process this data, maybe send it to a server
    // or make decisions based on the reading
}

Important Notes about Deep Sleep:

  • Only RTC GPIOs can be used as wake-up sources (GPIO0, GPIO2, GPIO4, GPIO12-15, GPIO25-27, GPIO32-39)
  • After waking from deep sleep, the ESP32 restarts, so any data in RAM is lost
  • To preserve data between sleep cycles, use RTC memory with the RTC_DATA_ATTR attribute
  • When using external wake-up, include a debounce circuit if connecting to a mechanical switch

Light Sleep Mode

Light Sleep mode uses around 800μA and offers a good balance between power saving and wake-up time. Unlike Deep Sleep, the ESP32 can resume exactly where it left off after waking up from Light Sleep. The CPU is paused, but memory contents are preserved.

Light Sleep supports additional wake-up sources like Touch and UART. Learn more in our advanced guide.

Light Sleep Example Code

#include 

// Define the GPIO pin used for wake-up
#define BUTTON_PIN GPIO_NUM_32

// Variables to track execution
int sleepCount = 0;

void setup() {
  Serial.begin(115200);
  delay(1000); // Allow serial connection to establish
  
  Serial.println("ESP32 Light Sleep Demo");
  
  // Configure GPIO for wake-up
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  
  // Initialize variables
  sleepCount = 0;
}

void loop() {
  // Do some work
  Serial.println("Doing some work... Iteration: " + String(sleepCount));
  delay(1000);
  
  // Prepare for light sleep
  Serial.println("Entering light sleep");
  Serial.flush();

  // Configure wake-up sources:
  // 1. Timer wake-up after 10 seconds
  esp_sleep_enable_timer_wakeup(10 * 1000000); // 10 seconds in microseconds
  
  // 2. GPIO wake-up (can use any GPIO, not just RTC GPIOs)
  esp_sleep_enable_ext0_wakeup(BUTTON_PIN, LOW); // Wake on button press (LOW)
  
  // Enter light sleep
  esp_light_sleep_start();
  
  // Code continues here after waking up
  sleepCount++;
  
  // Print wake-up reason
  esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause();
  if (wakeup_reason == ESP_SLEEP_WAKEUP_EXT0) {
    Serial.println("Woke up from light sleep due to GPIO (button press)");
  } else if (wakeup_reason == ESP_SLEEP_WAKEUP_TIMER) {
    Serial.println("Woke up from light sleep due to timer");
  } else {
    Serial.println("Woke up from light sleep for other reason");
  }
  
  delay(500); // Short delay to allow button release if woken by button
}

Advantages of Light Sleep over Deep Sleep:

  • Much faster wake-up time (milliseconds vs hundreds of milliseconds)
  • Program execution continues from where it left off, no reset occurs
  • All memory contents are preserved
  • More wake-up sources available, including UART
  • Can use any GPIO for wake-up, not just RTC GPIOs

Modem Sleep Mode

Modem Sleep is designed for wireless applications that need to maintain a Wi-Fi or Bluetooth connection while minimizing power consumption. It turns off the RF components between beacon intervals, reducing power usage to around 15mA.

This mode is automatically enabled when using power save mode with Wi-Fi station mode:

#include 
#include 

const char* ssid = "YourWiFiSSID";
const char* password = "YourWiFiPassword";

void setup() {
  Serial.begin(115200);
  delay(1000);
  
  Serial.println("ESP32 Modem Sleep Demo");
  
  // Connect to Wi-Fi with power save mode enabled
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi");
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("WiFi connected");
  
  // Enable modem sleep (power save mode)
  // Available modes:
  // WIFI_PS_NONE: No power save
  // WIFI_PS_MIN_MODEM: Minimum modem power saving
  // WIFI_PS_MAX_MODEM: Maximum modem power saving
  esp_wifi_set_ps(WIFI_PS_MAX_MODEM);
  
  Serial.println("Modem sleep enabled");
}

void loop() {
  // Periodic tasks while maintaining power efficiency
  Serial.println("Device is active but using modem sleep between data transfers");
  
  // Perform a data transfer (e.g., HTTP request)
  // This will temporarily wake the modem
  Serial.println("Making a data transfer...");
  // Your HTTP or MQTT code here
  
  // After data transfer, the modem will automatically go back to sleep 
  // between beacon intervals
  
  // Wait before next data transfer
  delay(60000); // Wait 1 minute before next transfer
}

Note: Modem Sleep is most effective with longer beacon intervals. You can configure your router's beacon interval (typically 100ms by default) to a larger value if possible. Be aware that longer beacon intervals may affect network responsiveness.

Hibernation Mode

Hibernation is the most power-efficient sleep mode, using only about 5μA. It turns off even more components than Deep Sleep, including the RTC slow memory. Only the RTC controller remains powered to provide wake-up capability.

In this mode:

  • The ULP coprocessor is disabled
  • RTC slow memory is powered off
  • Only timer and external wake-up sources (RTC GPIOs) can be used
#include 

#define uS_TO_S_FACTOR 1000000  // Conversion factor for micro seconds to seconds
#define TIME_TO_SLEEP  3600     // Time ESP32 will go to sleep (in seconds) - 1 hour

void setup() {
  Serial.begin(115200);
  delay(1000);
  
  Serial.println("ESP32 Hibernation Mode Demo");
  
  // Configure hibernation wake-up sources:
  // 1. Timer wake-up
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  Serial.println("Setup ESP32 to wake up after " + String(TIME_TO_SLEEP) + " seconds");
  
  // 2. External wake-up on GPIO
  // Only RTC GPIOs can be used in hibernation mode
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_32, LOW);
  Serial.println("Setup ESP32 to wake up on GPIO 32 going LOW");
  
  // Perform critical operations before hibernation
  // For example, save any critical data to flash if needed
  
  // Enter hibernation mode - this turns off RTC slow memory
  Serial.println("Going to hibernation...");
  Serial.flush();
  
  // Power down RTC peripherals and enter hibernation
  esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
  esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_OFF);
  esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF);
  esp_deep_sleep_start();
}

void loop() {
  // This is never executed
}

Hibernation Limitations:

Hibernation is extremely power efficient but comes with significant limitations:

  • Cannot use ULP coprocessor as a wake-up source
  • Cannot use touch sensors as a wake-up source
  • No data can be retained in RTC slow memory
  • Limited to timer and external GPIO wake-up sources only

Additional Wake-up Methods

The ESP32 offers several specialized wake-up methods that can be useful for specific applications:

Touch Wake-up

Wake up your ESP32 when a user touches capacitive sensors. Ideal for touch-activated devices with minimal power consumption.

Learn more

UART Wake-up

Wake up your ESP32 when serial data is received. Perfect for sensor modules or other microcontrollers that communicate via UART.

Learn more

Visit our Advanced ESP32 Sleep Modes Guide for detailed implementation of these wake-up methods with code examples and wiring diagrams.

Power Optimization Best Practices

To maximize battery life in your ESP32 projects, consider these best practices:

  1. Use the appropriate sleep mode for your application:
    • Deep Sleep for periodic wake-up applications (sensor monitoring)
    • Light Sleep for faster wake-up needs
    • Modem Sleep for applications that need to maintain a Wi-Fi connection
  2. Minimize active time:
    • Complete tasks quickly and return to sleep
    • Avoid unnecessary delays
    • Optimize code for efficiency
  3. Configure peripherals correctly:
    • Disable unused peripherals
    • Set appropriate ADC and GPIO states before sleep
    • Consider lower CPU frequency when high performance isn't needed
  4. Hardware considerations:
    • Use low quiescent current voltage regulators
    • Add power isolation for sensors that aren't needed during sleep
    • Consider removing power LEDs for battery applications
  5. Use the Ultra Low Power (ULP) coprocessor for simple tasks:
    • Offload simple monitoring tasks to the ULP
    • Only wake the main CPU when necessary

Battery Life Calculations

To estimate battery life for your ESP32 application, you need to consider the duty cycle (ratio of active to sleep time) and the current consumption in each state.

Battery Life Estimation Formula:

Battery Life (hours) = Battery Capacity (mAh) / Average Current (mA)

Average Current (mA) = (Active Time × Active Current + Sleep Time × Sleep Current) / (Active Time + Sleep Time)

Example:

  • Battery Capacity: 2000mAh
  • Active Time: 2 seconds (every 10 minutes)
  • Sleep Time: 598 seconds (10 minutes - 2 seconds)
  • Active Current: 150mA
  • Deep Sleep Current: 0.01mA (10μA)

Average Current = (2s × 150mA + 598s × 0.01mA) / (2s + 598s) = (300 + 5.98) / 600 = 0.51mA

Battery Life = 2000mAh / 0.51mA = 3922 hours = ~163 days