Deep Power Consumption Development of ESP32: Data Preservation in Sleep Mode

In the Deep Sleep mode of the ESP32, data in ordinary memory is lost because the main CPU and most peripherals are powered off. However, RTC Memory (RTC Slow/Fast Memory) and non-volatile storage (such as Flash/NVS) can be used to preserve data during sleep. Below are detailed methods and considerations for data preservation:

1. Data Preservation in RTC Memory

RTC Memory (RTC Slow/Fast Memory) remains powered during deep sleep, making it suitable for storing temporary runtime data (such as counters, status flags, etc.).

1.1 Using <span>RTC_DATA_ATTR</span> to Preserve Data

By using the macro <span>RTC_DATA_ATTR</span>, variables can be declared in RTC memory to ensure data is retained after deep sleep.

#include "esp_sleep.h"

// Define RTC memory variable (value retained after wakeup)
RTC_DATA_ATTR int bootCount = 0; // Record wakeup count

void setup() {
    Serial.begin(115200);
    delay(1000);

    // Configure wakeup source (example: timer wakeup)
    esp_sleep_enable_timer_wakeup(10 * 1000000); // Wake up after 10 seconds

    // Print wakeup count after waking up
    Serial.printf("Wakeup count: %d\n", ++bootCount);

    esp_deep_sleep_start();
}

void loop() {}

1.2 Limitations of RTC Memory

  • Capacity Limit The RTC Slow Memory of the ESP32 typically has only 8 KB, suitable for storing small data.
  • Access Speed RTC memory access speed is relatively slow and not suitable for frequent read/write of large data.
  • Data Types Only basic data types (such as <span>int</span>, <span>float</span>, <span>bool</span>, etc.) are supported.

2. Non-volatile Storage (Flash/NVS)

After deep sleep ends, the main memory is reset, so long-term data needs to be saved to non-volatile storage (Flash/NVS).

2.1 Using NVS to Save Data

NVS (Non-Volatile Storage) is a storage interface provided by ESP-IDF, suitable for saving WiFi credentials, device configurations, and other data.

#include "nvs_flash.h"
#include "nvs.h"

void save_data_to_nvs() {
    nvs_handle_t my_handle;
    esp_err_t err;

    // Open NVS partition
    err = nvs_open("storage", NVS_READWRITE, &my_handle);
    if (err != ESP_OK) return;

    // Write data (example: save wakeup count)
    int wake_count = 5;
    nvs_set_i32(my_handle, "wake_count", wake_count);

    // Commit changes
    nvs_commit(my_handle);
    nvs_close(my_handle);
}

void read_data_from_nvs() {
    nvs_handle_t my_handle;
    esp_err_t err;

    err = nvs_open("storage", NVS_READONLY, &my_handle);
    if (err != ESP_OK) return;

    // Read data
    int wake_count = 0;
    nvs_get_i32(my_handle, "wake_count", &wake_count);

    Serial.printf("Wakeup count read from NVS: %d\n", wake_count);
    nvs_close(my_handle);
}

2.2 Using Flash to Store Data

Directly operate Flash partitions to save data (suitable for advanced users):

#include "esp_flash.h"

void write_to_flash() {
    uint32_t data = 0x12345678;
    esp_flash_write(FLASH_DEVICE, &data, 0x1000, sizeof(data)); // Write to Flash address 0x1000
}

void read_from_flash() {
    uint32_t data = 0;
    esp_flash_read(FLASH_DEVICE, &data, 0x1000, sizeof(data)); // Read from Flash address 0x1000
    Serial.printf("Data read from Flash: 0x%x\n", data);
}

3. Wake Stub

The wake stub is a code snippet that executes immediately after waking up, suitable for quickly saving sensor data or triggering wake conditions.

3.1 Configuring the Wake Stub

The wake stub needs to reside in RTC memory and execute immediately after waking up:

#include "esp_sleep.h"

// Wake stub function (executes immediately after waking up)
void RTC_IRAM_ATTR wake_stub() {
    // Example: Read ADC sensor data and save to RTC memory
    uint32_t sensor_value = 0;
    adc_read(&sensor_value);
    RTC_DATA_ATTR uint32_t rtc_sensor_value = sensor_value;
}

void setup() {
    // Register wake stub
    esp_sleep_set_wake_stub(wake_stub);

    // Configure wakeup source (example: timer wakeup)
    esp_sleep_enable_timer_wakeup(5 * 1000000); // Wake up after 5 seconds

    esp_deep_sleep_start();
}

void loop() {}

3.2 Limitations of the Wake Stub

  • Code Size The wake stub code must be less than 8 KB (limited by RTC memory).
  • Function Limitations Can only access RTC peripherals (such as RTC GPIO, ADC, temperature sensors, etc.).

4. Typical Application Scenarios for Data Preservation

Scenario Preservation Method Example
Wakeup Count Tracking RTC Memory <span>RTC_DATA_ATTR int bootCount = 0;</span>
WiFi Connection Status NVS Save SSID and password to NVS
Sensor Data Buffering RTC Memory + Flash Temporarily save sensor data to RTC, write to Flash after waking up
ULP Coprocessor Monitoring Data RTC Memory ULP program writes data to RTC memory
Long-term Configuration Parameters NVS Save device configurations (such as sampling intervals, thresholds)

5. Key Considerations

  1. RTC Memory Data Lifecycle
  • Data is retained after waking up but lost after power off.
  • RTC data needs to be periodically backed up to Flash/NVS.
  • Flash/NVS Write Limitations
    • Flash write lifespan is about 100,000 times; frequent writes need optimization.
  • Debugging the Wake Stub
    • Use <span>esp_rom_printf()</span> to print debug information in the wake stub (note serial initialization).
  • Data Consistency
    • Data integrity needs to be verified after waking up (e.g., checksum).

    6. Comprehensive Example: Saving Wakeup Count to NVS

    #include "nvs_flash.h"
    #include "esp_sleep.h"
    
    RTC_DATA_ATTR int bootCount = 0; // RTC memory variable
    
    void save_boot_count_to_nvs() {
        nvs_handle_t my_handle;
        nvs_open("storage", NVS_READWRITE, &my_handle);
        nvs_set_i32(my_handle, "boot_count", bootCount);
        nvs_commit(my_handle);
        nvs_close(my_handle);
    }
    
    void read_boot_count_from_nvs() {
        nvs_handle_t my_handle;
        nvs_open("storage", NVS_READONLY, &my_handle);
        nvs_get_i32(my_handle, "boot_count", &bootCount);
        nvs_close(my_handle);
    }
    
    void setup() {
        // Initialize NVS
        nvs_flash_init();
    
        // Read wakeup count from NVS
        read_boot_count_from_nvs();
    
        Serial.begin(115200);
        delay(1000);
    
        // Configure wakeup source
        esp_sleep_enable_timer_wakeup(10 * 1000000); // Wake up after 10 seconds
    
        // Update wakeup count and save to NVS
        bootCount++;
        save_boot_count_to_nvs();
    
        Serial.printf("Current wakeup count: %d\n", bootCount);
        esp_deep_sleep_start();
    }
    
    void loop() {}
    

    7. Summary of Applicable Scenarios

    • RTC Memory is suitable for storing temporary runtime data (such as wakeup counts, sensor buffers).
    • NVS/Flash is suitable for saving long-term configurations (such as WiFi credentials, device IDs).
    • Wake Stub is suitable for quickly responding to wake events (such as sensor monitoring, emergency wake).

    By effectively utilizing RTC memory and non-volatile storage, the ESP32 can achieve reliable data preservation and recovery in deep sleep mode, meeting the needs of low-power IoT devices.

    Leave a Comment