Chapter 39: WiFi Power Saving Modes

Chapter Objectives

By the end of this chapter, you will be able to:

  • Understand the principles behind WiFi power-saving mechanisms.
  • Explain the roles of DTIM, TIM, Beacon Frames, and Listen Interval in power management.
  • Identify the different WiFi power-saving modes available in ESP-IDF (WIFI_PS_NONE, WIFI_PS_MIN_MODEM, WIFI_PS_MAX_MODEM).
  • Configure and enable WiFi power-saving modes on ESP32 variants.
  • Analyze the trade-offs between power consumption, latency, and throughput.
  • Recognize potential differences in power-saving behavior across various ESP32 chip variants.

Introduction

One of the most significant challenges in designing battery-operated IoT devices is managing power consumption. Wireless communication, particularly WiFi, is often one of the most power-hungry operations an embedded system performs. The WiFi radio requires substantial power when actively transmitting or receiving data. For devices that need to operate for weeks, months, or even years on a single battery charge, minimizing this power draw is absolutely critical.

Fortunately, the IEEE 802.11 standard includes power-saving mechanisms that allow WiFi clients (like the ESP32) to turn off their radio for periods while remaining associated with the network. This mechanism, commonly referred to as Modem Sleep, relies on cooperation between the client device and the Access Point (AP). This chapter explores how WiFi power saving works, how the ESP32 implements it through ESP-IDF, and how you can leverage these features to significantly extend the battery life of your connected projects.

Theory

The Need for Power Saving

A WiFi radio consumes the most power when it’s actively transmitting (TX) or receiving (RX). Even when idle but associated with an AP, the radio needs to be awake periodically to listen for Beacon frames sent by the AP. Beacons are essential management frames broadcast periodically by the AP (typically every 100ms, though configurable) containing network information, timing synchronization, and traffic indications. Keeping the radio fully powered on just to listen for beacons is inefficient if the device doesn’t expect frequent communication.

Modem Sleep: The Core Concept

The fundamental idea behind 802.11 power saving (often called Legacy Power Save or PS-Poll mode) is for the client device to inform the AP that it intends to enter a low-power state, primarily by turning off its radio transceiver (Modem Sleep).

While the client is “sleeping”:

  1. AP Buffering: The Access Point buffers any incoming data (unicast packets) destined for the sleeping client.
  2. Traffic Indication: The AP uses special fields within its periodic Beacon frames to indicate which sleeping clients have buffered data waiting for them.

Beacon Frames, TIM, and DTIM

Understanding Beacon frames is key to understanding power saving:

  • Beacon Interval: The time between consecutive beacon frames (e.g., 100ms).
  • TIM (Traffic Indication Map): A specific Information Element (IE) within every beacon frame. It contains a bitmap where each bit corresponds to a specific client’s Association ID (AID). If a client’s bit is set in the TIM, it means the AP has buffered unicast data for that client. A sleeping client must wake up periodically to check the TIM in beacons. If its bit is set, it stays awake to retrieve the buffered data from the AP (often using a PS-Poll frame to request it).
  • DTIM (Delivery Traffic Indication Map): A special type of TIM announced periodically. The DTIM interval (or DTIM period) specifies how many beacon intervals occur between DTIM beacons (e.g., a DTIM interval of 1 means every beacon is a DTIM beacon; a DTIM interval of 3 means every 3rd beacon is a DTIM beacon).
    • The DTIM indicates whether the AP has buffered broadcast or multicast data. All stations using power save must wake up to receive DTIM beacons to get this group traffic.
    • APs often use the DTIM beacon transmission time as the moment they will also deliver any buffered unicast traffic indicated in previous TIMs.
%%{ init: { 'theme': 'base', 'themeVariables': {
  'fontFamily': 'Open Sans, sans-serif',
  'primaryColor': '#DBEAFE',      /* Process Nodes BG - Light Blue */
  'primaryTextColor': '#1E40AF',  /* Process Nodes Text - Dark Blue */
  'primaryBorderColor': '#2563EB',/* Process Nodes Border - Blue */
  'lineColor': '#4B5563',         /* Arrow/Line color - Gray */
  'textColor': '#1F2937',         /* Default text color - Dark Gray */
  'mainBkg': 'transparent',       /* Diagram background */
  'actorBorder': '#5B21B6',       /* Purple for actors */
  'actorBkg': '#EDE9FE'           /* Light Purple for actor background */
}} }%%

timeline
    title WiFi Power Saving: Beacon, DTIM, and Client Activity (DTIM Period = 3)
    section Access Point (AP) Activity
        Beacon Frames : TIM information sent every 100ms (Beacon Interval)
        DTIM Beacons : Special beacons with DTIM, every 3rd beacon (DTIM Period = 3)
    section Client Activity - WIFI_PS_MIN_MODEM (Maximum Power Saving)
        Wake for DTIMs : Client wakes only for DTIM beacons : Every 300ms
        Sleep : Deep sleep with radio off : Between DTIM beacons
    section Client Activity - WIFI_PS_MAX_MODEM with Listen Interval = 2
        Wake for Selected Beacons : Client wakes based on Listen Interval : Every 200ms
        Wake for DTIMs : Client always wakes for DTIM beacons : Every 300ms
        Sleep : Radio off between scheduled wake-ups : Between wake events

    AP Timeline : B1(TIM), B2(TIM), B3(TIM+DTIM), B4(TIM), B5(TIM), B6(TIM+DTIM), B7(TIM)
    
    MIN_MODEM Client : Sleep, Sleep, Wake(DTIM), Sleep, Sleep, Wake(DTIM), Sleep
    
    MAX_MODEM Client (LI=2) : Wake(B1), Sleep, Wake(B3/DTIM), Sleep, Wake(B5), Sleep, Wake(B7)

Listen Interval

While clients must wake for DTIMs, they don’t necessarily need to wake for every beacon in between DTIMs just to check the TIM for unicast traffic, especially if they don’t expect frequent data. The Listen Interval allows the client to further optimize sleep.

  • Definition: The Listen Interval is a value (measured in number of Beacon Intervals) configured by the client and communicated to the AP during association.
  • Function: It tells the AP the maximum number of beacon intervals the client might sleep consecutively. The AP must buffer unicast frames for the client for at least this duration.
  • Impact: A longer Listen Interval allows the client to sleep for longer periods between checking beacons (potentially only waking for DTIM beacons if the Listen Interval is longer than the DTIM period), saving more power. However, it also increases the latency for receiving unicast packets, as the client might not check the TIM for several beacon intervals.

ESP-IDF WiFi Power Save Modes

ESP-IDF provides an API to configure the WiFi power-saving behavior: esp_wifi_set_ps(). It accepts one of the following modes:

  1. WIFI_PS_NONE:
    • No power saving is enabled. The WiFi radio remains active.
    • Lowest latency and highest potential throughput.
    • Highest power consumption.
    • This is the default mode if esp_wifi_set_ps() is not called.
  2. WIFI_PS_MIN_MODEM (Minimum Modem Sleep):
    • Enables modem sleep power saving.
    • The ESP32 wakes up automatically to receive every DTIM beacon.
    • Provides a balance between power saving and responsiveness. Latency is primarily determined by the network’s DTIM interval (typically 100-300ms).
    • Recommended for most applications needing moderate power saving without significantly impacting responsiveness to broadcast/multicast traffic or typical unicast delays.
  3. WIFI_PS_MAX_MODEM (Maximum Modem Sleep):
    • Enables modem sleep power saving with potentially longer sleep durations.
    • The ESP32 wakes up based on the listen_interval parameter configured in the wifi_sta_config_t structure before connecting.
    • The ESP32 will sleep for up to listen_interval beacon intervals, but must still wake for DTIM beacons regardless of the listen interval setting to receive broadcast/multicast traffic.
    • Offers the most significant power savings, especially if the listen_interval is set higher than the AP’s DTIM period.
    • Increases the latency for receiving unicast packets, as the device might only check the TIM according to its listen interval schedule (aligned with DTIMs if listen interval is large).
    • Requires careful configuration of listen_interval based on application latency requirements and AP capabilities.

Important: The listen_interval parameter (part of wifi_sta_config_t) is only effective when WIFI_PS_MAX_MODEM is used. It should be configured before calling esp_wifi_connect(). The esp_wifi_set_ps() function to select the mode (WIFI_PS_MIN_MODEM or WIFI_PS_MAX_MODEM) can typically be called after the connection is established (IP_EVENT_STA_GOT_IP).

Trade-offs

Choosing a power-saving mode involves balancing:

  • Power Consumption: NONE > MIN_MODEM > MAX_MODEM
  • Latency (Downstream): NONE < MIN_MODEM < MAX_MODEM (Latency increases as sleep duration increases)
  • Throughput: High throughput activities (like file downloads, streaming) might be negatively impacted by MAX_MODEM sleep due to the intermittent radio activity. MIN_MODEM usually has less impact.
Feature WIFI_PS_NONE WIFI_PS_MIN_MODEM WIFI_PS_MAX_MODEM
Description No power saving. WiFi radio is always active. Minimum modem sleep. ESP32 wakes for every DTIM beacon. Maximum modem sleep. ESP32 wakes based on listen_interval and DTIM beacons.
Wake-up Logic Always awake. Wakes automatically for every DTIM beacon from the AP. Wakes for DTIM beacons. Additionally, wakes to check TIM based on its listen_interval (if shorter than DTIM period).
Key Configuration N/A (Default if esp_wifi_set_ps() not called). Call esp_wifi_set_ps(WIFI_PS_MIN_MODEM) after connection. Set wifi_config.sta.listen_interval before connecting. Call esp_wifi_set_ps(WIFI_PS_MAX_MODEM) after connection.
Relative Power Consumption Highest Medium (Significant saving over NONE) Lowest (Most significant saving)
Relative Downstream Latency Lowest (Immediate reception) Medium (Up to DTIM interval, e.g., 100-300ms) Highest (Up to Listen Interval or DTIM interval, potentially seconds)
Throughput Impact Minimal impact, highest potential. Minor impact for typical bursty traffic. Can significantly impact sustained high throughput.
Typical Use Case Applications requiring constant low-latency communication or very high throughput (e.g., streaming video server, OTA updates). Mains powered devices. Good balance for many battery-powered IoT devices needing responsiveness to network events (e.g., MQTT commands) without extreme power saving. Battery-powered devices sending infrequent data and can tolerate higher latency for received data (e.g., periodic sensor logging, once-a-day check-ins).
AP Dependency Minimal. Relies on AP correctly sending DTIM beacons. DTIM interval on AP affects performance. Relies on AP correctly sending DTIMs and honoring the client’s Listen Interval for buffering unicast packets.

Practical Examples

Let’s see how to configure these modes in ESP-IDF.

1. Project Setup

  • Use a standard WiFi station project setup.
  • Include necessary headers: esp_wifi.h, esp_log.h, freertos/FreeRTOS.h, freertos/task.h, wifi_config_t related headers.

2. Configuring Listen Interval (for MAX_MODEM)

The listen_interval must be set in the wifi_config_t before connecting if you intend to use WIFI_PS_MAX_MODEM.

C
// In your wifi initialization function, before connecting:

#define EXAMPLE_WIFI_LISTEN_INTERVAL 3 // Wake every 3 beacon intervals (if DTIM allows)

// ... inside wifi_init_sta() or similar ...

wifi_config_t wifi_config = {
    .sta = {
        .ssid = EXAMPLE_ESP_WIFI_SSID,
        .password = EXAMPLE_ESP_WIFI_PASS,
        /* Authmode threshold defaults to WPA2 PSK */
        // .threshold.authmode = WIFI_AUTH_WPA2_PSK, // Or configure as needed

        /* Listen Interval: Relevant for WIFI_PS_MAX_MODEM */
        /* Value is in units of Beacon Intervals (typically 100ms). */
        /* AP must buffer unicast packets for at least this long. */
        /* ESP32 will wake up at least every listen_interval * beacon_interval milliseconds */
        /* (but also always wakes for DTIM beacons). */
        .listen_interval = EXAMPLE_WIFI_LISTEN_INTERVAL,
    },
};
ESP_LOGI(TAG, "Setting Listen Interval to %d", wifi_config.sta.listen_interval);
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));

// ... proceed with esp_wifi_start() and esp_wifi_connect() ...

Tip: Common DTIM intervals on home routers are 1, 2, or 3 (meaning DTIM beacons every 100ms, 200ms, or 300ms). Setting listen_interval to 3 is a common starting point for MAX_MODEM. Setting it much higher (e.g., 10) saves more power but significantly increases latency and relies on the AP supporting and respecting such a long buffering period. Check your AP’s DTIM setting if possible.

3. Enabling Power Save Modes

You can enable the desired power save mode after the WiFi connection is established, typically after the IP_EVENT_STA_GOT_IP event.

C
// Example: Enabling MIN_MODEM sleep after getting an IP

static void wifi_event_handler(void* arg, esp_event_base_t event_base,
                               int32_t event_id, void* event_data)
{
    // ... handle other events like WIFI_EVENT_STA_START, WIFI_EVENT_STA_DISCONNECTED ...

    if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGI(TAG, "Got IP address: " IPSTR, IP2STR(&event->ip_info.ip));

        // --- Enable WiFi Power Save ---
        ESP_LOGI(TAG, "Enabling WiFi Power Save mode: MIN_MODEM");
        esp_err_t ps_err = esp_wifi_set_ps(WIFI_PS_MIN_MODEM);
        if (ps_err != ESP_OK) {
             ESP_LOGE(TAG, "Failed to set WiFi power save mode: %s", esp_err_to_name(ps_err));
        }

        // Signal connection success (e.g., set event group bit)
        // ...
    }
}

// --- OR ---

// Example: Enabling MAX_MODEM sleep (assuming listen_interval was set pre-connect)
static void enable_max_modem_sleep(void) {
     ESP_LOGI(TAG, "Enabling WiFi Power Save mode: MAX_MODEM");
     esp_err_t ps_err = esp_wifi_set_ps(WIFI_PS_MAX_MODEM);
     if (ps_err != ESP_OK) {
         ESP_LOGE(TAG, "Failed to set WiFi power save mode: %s", esp_err_to_name(ps_err));
     }
}

// Call enable_max_modem_sleep() after IP_EVENT_STA_GOT_IP

4. Disabling Power Save

You might want to temporarily disable power saving for operations requiring low latency or high throughput (e.g., OTA updates).

C
void disable_wifi_power_save(void) {
    ESP_LOGI(TAG, "Disabling WiFi Power Save mode (setting to NONE)");
    esp_err_t ps_err = esp_wifi_set_ps(WIFI_PS_NONE);
     if (ps_err != ESP_OK) {
         ESP_LOGE(TAG, "Failed to disable WiFi power save mode: %s", esp_err_to_name(ps_err));
     }
}

void enable_wifi_min_modem(void) {
     ESP_LOGI(TAG, "Enabling WiFi Power Save mode: MIN_MODEM");
     esp_err_t ps_err = esp_wifi_set_ps(WIFI_PS_MIN_MODEM);
     if (ps_err != ESP_OK) {
         ESP_LOGE(TAG, "Failed to set WiFi power save mode: %s", esp_err_to_name(ps_err));
     }
}

// Example Usage:
// disable_wifi_power_save();
// // Perform high-throughput/low-latency operation (e.g., OTA update)
// enable_wifi_min_modem(); // Re-enable power saving afterwards

5. Observing the Effect (Conceptual)

Directly measuring the power savings requires hardware tools:

  • Multimeter: Measure average current draw in different modes (requires careful setup to capture fluctuating current).
  • Power Monitor/Profiler: Tools like Nordic’s Power Profiler Kit II or specialized source measure units (SMUs) can provide detailed current consumption profiles over time.

Expected Observation: You should see a significant drop in the average current consumption when switching from WIFI_PS_NONE to WIFI_PS_MIN_MODEM or WIFI_PS_MAX_MODEM. The current will fluctuate more in power-saving modes as the radio cycles between sleep and brief wake periods. MAX_MODEM (with a suitable listen_interval) should yield the lowest average current among the connected states.

You might also observe increased latency. For example, pinging the ESP32’s IP address might show slightly higher or more variable response times in MIN_MODEM mode compared to NONE, and potentially significantly higher/more variable latency in MAX_MODEM mode.

6. Build, Flash, and Run

  1. Modify your WiFi station code to include setting the listen_interval (if testing MAX_MODEM) and calling esp_wifi_set_ps() after connection.
  2. Build and flash the project.
  3. Monitor the serial output to confirm the power save mode is being set.
  4. (If you have measurement tools) Measure the average current consumption in WIFI_PS_NONE, WIFI_PS_MIN_MODEM, and WIFI_PS_MAX_MODEM modes while the device is idle but connected.
  5. (Optional) Try pinging the device or sending it data (e.g., via MQTT) and observe any differences in response time between the modes.

Variant Notes

While the ESP-IDF API (esp_wifi_set_ps) and the concepts (DTIM, Listen Interval) are consistent, the actual power consumption figures and the efficiency of the power-saving modes can vary significantly between different ESP32 variants:

  • ESP32 (Original): Baseline WiFi power consumption is relatively high compared to newer variants. Power saving modes provide noticeable benefits but might still consume tens of milliamperes on average in MIN_MODEM sleep.
  • ESP32-S2, ESP32-S3: Generally offer improved power performance over the original ESP32 due to architectural and process node improvements. Modem sleep modes are more effective.
  • ESP32-C3 (RISC-V): Designed with low power in mind. Often shows significantly lower power consumption in modem sleep modes compared to older variants.
  • ESP32-C6 (RISC-V, WiFi 6): Also designed for low power. Includes WiFi 6 features like Target Wake Time (TWT), which offers more advanced, negotiated sleep scheduling than legacy power save. While ESP-IDF v5.x primarily exposes legacy power save (WIFI_PS_MIN/MAX_MODEM), the underlying hardware and future IDF versions might leverage TWT for even greater efficiency when connected to compatible WiFi 6 APs. Legacy power save modes are still expected to be very effective.
ESP32 Variant General WiFi Power Performance Modem Sleep Effectiveness (Legacy PS) Key Low-Power WiFi Features / Notes
ESP32 (Original) Baseline; relatively higher consumption compared to newer variants. Noticeable benefits, but average current in MIN_MODEM can still be tens of mA. Supports legacy power save modes. Power consumption figures are well-documented but higher than S/C series.
ESP32-S2 Improved over original ESP32. Better architecture for low power. More effective; lower average current in sleep modes. Single-core, designed with power efficiency improvements.
ESP32-S3 Dual-core with AI capabilities, but also offers power improvements over original ESP32. Effective modem sleep. Balances performance with power options. Often used where more processing is needed alongside WiFi. Power modes are crucial for battery applications.
ESP32-C3 (RISC-V) Designed with low power as a key focus. Generally excellent power efficiency. Highly effective. Can achieve very low average currents in modem sleep. Single-core RISC-V. Strong candidate for ultra-low-power WiFi applications.
ESP32-C6 (RISC-V, WiFi 6) Designed for low power with WiFi 6 capabilities. Legacy power save modes are very effective. Supports WiFi 6 Target Wake Time (TWT), which allows for more advanced and efficient negotiated sleep schedules with compatible APs. ESP-IDF v5.x primarily exposes legacy PS, but TWT is a hardware capability.
Note: Absolute power consumption figures vary based on application, AP settings, and environment. Always refer to the specific chip datasheet and conduct measurements for precise values. ESP32-H2 is excluded as it does not have WiFi.

Key Takeaway: Always consult the datasheet for your specific ESP32 variant for detailed power consumption figures in different operating modes. The relative difference between NONE, MIN_MODEM, and MAX_MODEM should be observable, but the absolute current values will differ.

Common Mistakes & Troubleshooting Tips

Mistake / Issue Symptom(s) Troubleshooting / Solution
Calling esp_wifi_set_ps() Too Early Function returns an error (e.g., ESP_ERR_WIFI_NOT_INIT or ESP_ERR_WIFI_NOT_STARTED). Power saving mode is not applied. Ensure WiFi is initialized, started, and ideally connected before calling esp_wifi_set_ps(). A safe place is after receiving the IP_EVENT_STA_GOT_IP event.
Forgetting listen_interval for MAX_MODEM Using WIFI_PS_MAX_MODEM, but power savings are not as expected, or behavior resembles WIFI_PS_MIN_MODEM. Latency might be lower than anticipated for MAX_MODEM. Always configure wifi_config.sta.listen_interval to a desired value (e.g., 3-10) before calling esp_wifi_connect() if you intend to use WIFI_PS_MAX_MODEM.
Unrealistic listen_interval Setting listen_interval too high (e.g., > 50-100) leads to packet loss or disconnections because the AP might not buffer data for that long or may disassociate an overly sleepy client. Start with conservative listen_interval values (e.g., 3 to 10, corresponding to 300ms to 1s if beacon interval is 100ms). Test thoroughly. Check AP documentation for maximum supported listen interval if available.
AP DTIM Configuration Not Considered In WIFI_PS_MIN_MODEM, power savings are less than expected. In WIFI_PS_MAX_MODEM, device wakes more frequently than listen_interval suggests. The ESP32 must wake for DTIM beacons. If AP’s DTIM interval is short (e.g., 1), MIN_MODEM wakes every beacon. If DTIM period is shorter than (Listen Interval * Beacon Interval), MAX_MODEM will also wake for DTIMs. Check AP’s DTIM setting if possible.
Latency Impact on Application Ignored Application misses time-sensitive incoming data or commands, or appears unresponsive when WIFI_PS_MAX_MODEM is enabled. Analyze application latency requirements. If low latency is critical for certain operations, use WIFI_PS_MIN_MODEM or temporarily switch to WIFI_PS_NONE during those operations. Design the application to tolerate delays associated with the chosen power save mode.
Power Measured Incorrectly Average current measurements don’t show expected savings, or are misleading. Use appropriate tools (power profiler, oscilloscope with current probe) that can capture fast current fluctuations and calculate true averages. Simple multimeter readings might not be accurate for sleeping devices. Ensure no other peripherals (like an active UART for logging) are consuming significant power.
Not Re-enabling Power Save Power save is disabled for a high-throughput task (e.g., OTA) using esp_wifi_set_ps(WIFI_PS_NONE), but not re-enabled afterwards. Always ensure that after temporarily disabling power save, it is explicitly re-enabled (e.g., to WIFI_PS_MIN_MODEM or WIFI_PS_MAX_MODEM) once the critical operation is complete.

Exercises

  1. Mode Switching: Create a simple application that connects to WiFi and initially enables WIFI_PS_MIN_MODEM. Add a FreeRTOS task that, every 30 seconds, toggles the power save mode between WIFI_PS_MIN_MODEM and WIFI_PS_NONE, logging the change. (Conceptual: If you have power measurement tools, observe the average current change).
  2. Latency Test with MAX_MODEM: Configure your ESP32 to use WIFI_PS_MAX_MODEM.
    • Set listen_interval to 3 in wifi_config_t. Connect and enable MAX_MODEM. Try pinging the ESP32 from another computer on the network and note the typical response time.
    • Modify the code to set listen_interval to 10. Re-flash and repeat the ping test. Observe if the average ping time or variability increases. (Note: Ping might not always be reliable for testing latency with sleeping devices, as the first ping might wake it).
  3. Power Save Aware Task: Imagine an application that periodically sends sensor data (e.g., every minute) but also needs to react quickly if a button is pressed. Implement logic where WIFI_PS_MAX_MODEM is normally enabled. When the button ISR signals the task (using a semaphore or queue), the task immediately calls disable_wifi_power_save(), performs the necessary network action (e.g., sends an alert), and then re-enables WIFI_PS_MAX_MODEM (or MIN_MODEM).

Summary

  • WiFi is power-intensive; Modem Sleep is the primary mechanism for reducing consumption while connected.
  • Power saving relies on APs buffering data and indicating pending traffic via TIM (unicast) and DTIM (broadcast/multicast) fields in Beacon frames.
  • Clients must wake for DTIM beacons. The DTIM Interval (AP setting) determines DTIM frequency.
  • The Listen Interval (client setting) allows clients to sleep longer between checking beacons (up to listen_interval beacons), impacting latency but saving more power. It’s used with WIFI_PS_MAX_MODEM.
  • ESP-IDF offers WIFI_PS_NONE, WIFI_PS_MIN_MODEM (wakes every DTIM), and WIFI_PS_MAX_MODEM (wakes based on listen_interval and DTIMs), configured via esp_wifi_set_ps().
  • There’s a direct trade-off between power saving and latency/throughput.
  • Actual power consumption varies by ESP32 variant, with newer chips generally being more efficient.

Further Reading

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top