espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.57k stars 7.27k forks source link

ESP32 Deep sleep power consumption too high (IDFGH-10693) #11918

Closed krupis closed 11 months ago

krupis commented 1 year ago

Answers checklist.

General issue report

Hello. I am testing ESP32 power consumption during deep sleep.

HW used: https://www.dfrobot.com/product-1590.html ESP-IDF used: v5.0.3 FW used:

/*
 * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: CC0-1.0
 */

#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"

#include "esp_sleep.h"
#include "esp_log.h"
#include "driver/rtc_io.h"
#include "soc/rtc.h"
#include "nvs_flash.h"
#include "nvs.h"

#define GPIO_OUTPUT_BUILTIN_LED 2

#define GPIO_BUILTIN_LED_PIN_SEL   ((1ULL<<GPIO_OUTPUT_BUILTIN_LED) )

static void configure_gpio();
static void get_wake_up_reason();

void app_main(void)
{
    esp_err_t err = nvs_flash_init();
    if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        // NVS partition was truncated and needs to be erased
        // Retry nvs_flash_init
        ESP_ERROR_CHECK(nvs_flash_erase());
        err = nvs_flash_init();
    }
    ESP_ERROR_CHECK(err);

    nvs_handle_t nvs_handle;
    err = nvs_open("storage", NVS_READWRITE, &nvs_handle);
    if (err != ESP_OK) {
        printf("Error (%s) opening NVS handle!\n", esp_err_to_name(err));
    } else {
        printf("Open NVS done\n");
    }

    /* Print chip information */
    esp_chip_info_t chip_info;
    uint32_t flash_size;
    esp_chip_info(&chip_info);
    printf("This is %s chip with %d CPU core(s), WiFi%s%s, ",
           CONFIG_IDF_TARGET,
           chip_info.cores,
           (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
           (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");

    unsigned major_rev = chip_info.revision / 100;
    unsigned minor_rev = chip_info.revision % 100;
    printf("silicon revision v%d.%d, ", major_rev, minor_rev);
    if(esp_flash_get_size(NULL, &flash_size) != ESP_OK) {
        printf("Get flash size failed");
        return;
    }

    const int wakeup_time_sec = 20;
    printf("Enabling timer wakeup, %ds\n", wakeup_time_sec);
    ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000));

    get_wake_up_reason();
    printf("Going to sleep in 5 second \n");

  // Turn off and keep off the built-in led during deep sleep
    configure_gpio();
    gpio_set_level(GPIO_OUTPUT_BUILTIN_LED, 0);
    gpio_hold_en(GPIO_OUTPUT_BUILTIN_LED);
    gpio_deep_sleep_hold_en();

    vTaskDelay(5000/portTICK_PERIOD_MS);
    esp_deep_sleep_start();

}

static void configure_gpio(){
    gpio_config_t io_conf;

// OUTPUTS
    //disable interrupt
    io_conf.intr_type = GPIO_INTR_DISABLE;
    //set as output mode
    io_conf.mode = GPIO_MODE_OUTPUT;
    //bit mask of the pins that you want to set
    io_conf.pin_bit_mask = GPIO_BUILTIN_LED_PIN_SEL;
    //disable pull-down mode
    io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    //disable pull-up mode
    io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
    //configure GPIO with the given settings
    gpio_config(&io_conf);
}

static void get_wake_up_reason(){
    uint8_t wakeup_reason = esp_sleep_get_wakeup_cause();
    switch(wakeup_reason)
    {
        case ESP_SLEEP_WAKEUP_EXT0: {
            printf("Wakeup caused by external signal using RTC_IO \n"); 
            break;
        }
        case ESP_SLEEP_WAKEUP_EXT1 : {
            printf("Wakeup caused by external signal using RTC_CNTL \n"); 
            break;
        }
        case ESP_SLEEP_WAKEUP_TIMER : {
            printf("Wakeup caused by timer \n"); 
            break;
        }
        case ESP_SLEEP_WAKEUP_TOUCHPAD : {
            printf("Wakeup caused by touchpad \n"); 
            break;
        }
        case ESP_SLEEP_WAKEUP_ULP : {
            printf("Wakeup caused by ULP program \n"); 
            break;
        }
        default : {
            printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); 
            break;
        }
    }
}

I am simply connecting 3.8V power source to battery input terminals of the FireBeetle ESP32 board and monitoring current consumption via our custom HW board.

The results: image

We use custom HW to measure the current consumption. It is based on INA190 and capable of measuring within range 10uA -> 1A. We have used this current measurement tool for many of our projects and it proved to be quite accurate.

As you can see from the graph, when the device wakes up, it peaks to about 50mA and then drops to 27mA for 5 seconds. After 5 seconds, the device enters deep sleep and draws 0.4mA.

0.4mA is way too much for the application that I plan to use the ESP32 for. Ideally, I need to get it into 10-20uA range.

Are there any suggestions, tips on how to improve the deep sleep current consumption of the ESP32?

igrr commented 1 year ago

Just to check, have you taken this into consideration?

Low-power Solder Jumper Pad

Designed for low power mode and default to be connected. Slightly cut off the thin wire with a knife to disconnect it. When disconnected, static power consumption can be reduced by 500 μA. The power consumption can be reduced to 13 μA after controlling the maincontroller to enter the sleep mode through the program.

See also this

krupis commented 1 year ago

Just to check, have you taken this into consideration?

Low-power Solder Jumper Pad

Designed for low power mode and default to be connected. Slightly cut off the thin wire with a knife to disconnect it. When disconnected, static power consumption can be reduced by 500 μA. The power consumption can be reduced to 13 μA after controlling the maincontroller to enter the sleep mode through the program.

See also this

This is some interesting reading material, however, my DFRobot development board is slightly different. The DFRobot wiki that you provided link for is for FireBeetle 2 ESP32-E. I use FireBeetle ESP32 IoT development board.

https://wiki.dfrobot.com/FireBeetle_ESP32_IOT_Microcontroller(V3.0)__Supports_Wi-Fi_&_Bluetooth__SKU__DFR0478

I have tried to look for any simmilar jumper or anything but there does not seem to be one on this particular board. I am now looking into what exactly does that jumper pad do and why it is even implemented on the FireBeetle 2 ESP32-E board. Perhaps I can "modify" my board and achieve simillar results.

The schematic for the FireBeetle 2 ESP32-E can be found here: https://dfimg.dfrobot.com/nobody/wiki/fd28d987619c16281bdc4f40990e5a1c.PDF

I believe the jumper pad is shown as R11 in the schematic:

image

Is it possible that connected RGB LED is leaking current so it needs to be disconnected?

Stencht commented 1 year ago

Hi krupis, do you have hardware specs of the LDO used on the board? Some cheap ESP32 dev-boards have LDO's with a very large quiescent current, making it impossible to get that low current consumption.

krupis commented 1 year ago

Hi krupis, do you have hardware specs of the LDO used on the board? Some cheap ESP32 dev-boards have LDO's with a very large quiescent current, making it impossible to get that low current consumption.

Yes. The schematic of the development board can be found here: [DFR0478]FireBeetle Board-ESP32(V4.0)生产检查图 (1).PDF

https://wiki.dfrobot.com/FireBeetle_ESP32_IOT_Microcontroller(V3.0)__Supports_Wi-Fi_&_Bluetooth__SKU__DFR0478

I believe they use: RT9080-33GJ5 https://www.digikey.com/en/products/detail/richtek-usa-inc/RT9080-33GJ5/6161634

krupis commented 1 year ago

@esp-lis @esp-wzh Hello guys. I have noticed that you have been assigned to this issue.

Perhaps you have any ideas about this?

esp-wzh commented 1 year ago

Hi, @krupis I tried to use your program to reproduce it on our current test board (esp32 minimal system board without any redundant devices) and got normal power consumption data (5.2uA in deep sleep), so rule out software problems. 20230724_062940

I'm guessing the extra 300+ uA of current should come mainly from the serial converter chip according to ch340 datasheet image

Of course LDO and LEDs contribute a small portion of the leakage

krupis commented 1 year ago

@esp-wzh

Thanks for the response. I will try to desolder or disable the CH340C somehow. Additionally, can you clarify what current consumption tool did you use to capture the current consumption?

esp-wzh commented 1 year ago

@krupis I'm using Joulescope 220

krupis commented 1 year ago

@krupis I'm using Joulescope 220

I have replaced the measuring tool and managed to get it down to 12uA. Everything works as expected. It was faulty measurement scope.

krupis commented 1 year ago

@esp-wzh @esp-lis Since we are talking about the deep sleep here, do you mind if I ask question about optimizing power consumption during active mode?

Currently, in my example code the device consumes about 30mA when it is powered ON even though it is not really doing anything. Is there any way to optimize this as much as possible to reduce the current consumption during active mode?

Even though the device stays on for only 3-4 seconds, the current consumption quickly adds up and I would like to reduce it as much as I can.

esp-lis commented 1 year ago

Since we are talking about the deep sleep here, do you mind if I ask question about optimizing power consumption during active mode?

Currently, in my example code the device consumes about 30mA when it is powered ON even though it is not really doing anything. Is there any way to optimize this as much as possible to reduce the current consumption during active mode?

Even though the device stays on for only 3-4 seconds, the current consumption quickly adds up and I would like to reduce it as much as I can.

Perhaps you can try to enable the auto light sleep mode, which has a leakage current of about 1 mA.

krupis commented 1 year ago

@esp-lis I have added the following to my code:

    #if CONFIG_PM_ENABLE
        // Configure dynamic frequency scaling:
        // maximum and minimum frequencies are set in sdkconfig,
        // automatic light sleep is enabled if tickless idle support is enabled.
        esp_pm_config_esp32_t pm_config = {
                .max_freq_mhz = 80,
                .min_freq_mhz = 10,
    #if CONFIG_FREERTOS_USE_TICKLESS_IDLE
                .light_sleep_enable = true
    #endif
        };
        ESP_ERROR_CHECK( esp_pm_configure(&pm_config) );
    #endif // CONFIG_PM_ENABLE

And I can see that when the device wakes up, it consumes about 30mA for initial moment and then drops down to about 2mA (I assume it enters light sleep at this point).

image

esp-lis commented 1 year ago

@krupis can you provide your configure file?

krupis commented 1 year ago

@esp-lis

You can access all project files here: https://github.com/krupis/ESP32_Deep_Sleep

esp-lis commented 1 year ago

@esp-lis

You can access all project files here: https://github.com/krupis/ESP32_Deep_Sleep

@krupis You can try to enable some of the following options after testing CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL CONFIG_PM_SLP_DISABLE_GPIO

With the above two options enabled, call gpio_sleep_sel_dis(gpio_num) for GPIO that needs to enable ext1 wake-up.

krupis commented 1 year ago

@esp-lis

Are these options supposed to help save even more power during active mode? Since currently after waking up I believe it enters auto light sleep mode successfully.

esp-lis commented 1 year ago

@esp-lis

Are these options supposed to help save even more power during active mode? Since currently after waking up I believe it enters auto light sleep mode successfully.

It can help reduce the leakage current of IOs.

krupis commented 1 year ago

@esp-lis Are these options supposed to help save even more power during active mode? Since currently after waking up I believe it enters auto light sleep mode successfully.

It can help reduce the leakage current of IOs.

After enabling these options, I can confirm that current consumption during auto light sleep decreased from about 2mA to 1.5mA.

However, I have noticed something else, please see my full code below:

/*
 * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: CC0-1.0
 */

#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"

#include "esp_pm.h"
#include "esp_sleep.h"
#include "esp_log.h"
#include "driver/rtc_io.h"
#include "soc/rtc.h"
#include "nvs_flash.h"
#include "nvs.h"

#define GPIO_OUTPUT_BUILTIN_LED 2
#define GPIO_BUILTIN_LED_PIN_SEL   ((1ULL<<GPIO_OUTPUT_BUILTIN_LED) )

static void configure_gpio();
static void get_wake_up_reason();

void app_main(void)
{
    esp_err_t err = nvs_flash_init();
    if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        // NVS partition was truncated and needs to be erased
        // Retry nvs_flash_init
        ESP_ERROR_CHECK(nvs_flash_erase());
        err = nvs_flash_init();
    }
    ESP_ERROR_CHECK(err);

    configure_gpio();
    gpio_set_level(GPIO_OUTPUT_BUILTIN_LED, 0);
    gpio_hold_en(GPIO_OUTPUT_BUILTIN_LED);

    #if CONFIG_PM_ENABLE
        // Configure dynamic frequency scaling:
        // maximum and minimum frequencies are set in sdkconfig,
        // automatic light sleep is enabled if tickless idle support is enabled.
        esp_pm_config_esp32_t pm_config = {
                .max_freq_mhz = 80,
                .min_freq_mhz = 10,
    #if CONFIG_FREERTOS_USE_TICKLESS_IDLE
                .light_sleep_enable = true
    #endif
        };
        ESP_ERROR_CHECK( esp_pm_configure(&pm_config) );
    #endif // CONFIG_PM_ENABLE

    /* Print chip information */
    esp_chip_info_t chip_info;
    uint32_t flash_size;
    esp_chip_info(&chip_info);
    printf("This is %s chip with %d CPU core(s), WiFi%s%s, ",
           CONFIG_IDF_TARGET,
           chip_info.cores,
           (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
           (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");

    unsigned major_rev = chip_info.revision / 100;
    unsigned minor_rev = chip_info.revision % 100;
    printf("silicon revision v%d.%d, ", major_rev, minor_rev);
    if(esp_flash_get_size(NULL, &flash_size) != ESP_OK) {
        printf("Get flash size failed");
        return;
    }

    const int wakeup_time_sec = 80;
    printf("Enabling timer wakeup, %ds\n", wakeup_time_sec);
    ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000));
    get_wake_up_reason();

    printf("Going to sleep in 5 second \n");

    configure_gpio();
    gpio_set_level(GPIO_OUTPUT_BUILTIN_LED, 0);
    gpio_hold_en(GPIO_OUTPUT_BUILTIN_LED);
    gpio_deep_sleep_hold_en();

    vTaskDelay(5000/portTICK_PERIOD_MS);
    esp_deep_sleep_start();

}

static void configure_gpio(){
    gpio_config_t io_conf;

// OUTPUTS
    //disable interrupt
    io_conf.intr_type = GPIO_INTR_DISABLE;
    //set as output mode
    io_conf.mode = GPIO_MODE_OUTPUT;
    //bit mask of the pins that you want to set
    io_conf.pin_bit_mask = GPIO_BUILTIN_LED_PIN_SEL;
    //disable pull-down mode
    io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    //disable pull-up mode
    io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
    //configure GPIO with the given settings
    gpio_config(&io_conf);
}

static void get_wake_up_reason(){
    uint8_t wakeup_reason = esp_sleep_get_wakeup_cause();
    switch(wakeup_reason)
    {
        case ESP_SLEEP_WAKEUP_EXT0: {
            printf("Wakeup caused by external signal using RTC_IO \n"); 
            break;
        }
        case ESP_SLEEP_WAKEUP_EXT1 : {
            printf("Wakeup caused by external signal using RTC_CNTL \n"); 
            break;
        }
        case ESP_SLEEP_WAKEUP_TIMER : {
            printf("Wakeup caused by timer \n"); 
            break;
        }
        case ESP_SLEEP_WAKEUP_TOUCHPAD : {
            printf("Wakeup caused by touchpad \n"); 
            break;
        }
        case ESP_SLEEP_WAKEUP_ULP : {
            printf("Wakeup caused by ULP program \n"); 
            break;
        }
        default : {
            printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); 
            break;
        }
    }
}

As you can see I have:

const int wakeup_time_sec = 80;
    printf("Enabling timer wakeup, %ds\n", wakeup_time_sec);
    ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000));
    get_wake_up_reason();

    printf("Going to sleep in 5 second \n");

    configure_gpio();
    gpio_set_level(GPIO_OUTPUT_BUILTIN_LED, 0);
    gpio_hold_en(GPIO_OUTPUT_BUILTIN_LED);
    gpio_deep_sleep_hold_en();

    vTaskDelay(5000/portTICK_PERIOD_MS);
    esp_deep_sleep_start();

So I expect the device to go enter deep sleep mode for 80 seconds after 5 seconds delay, but it wakes up after about 6 seconds for some reason.

The serial logs:

rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:6992
load:0x40078000,len:15512
load:0x40080400,len:3860
entry 0x40080650
[1B][0;32mI (27) boot: ESP-IDF v5.0.3-dirty 2nd stage bootloader[1B][0m
[1B][0;32mI (27) boot: compile time 15:25:31[1B][0m
[1B][0;32mI (27) boot: Multicore bootloader[1B][0m
[1B][0;32mI (31) boot: chip revision: v1.0[1B][0m
[1B][0;32mI (35) boot.esp32: SPI Speed      : 40MHz[1B][0m
[1B][0;32mI (40) boot.esp32: SPI Mode       : DIO[1B][0m
[1B][0;32mI (44) boot.esp32: SPI Flash Size : 4MB[1B][0m
[1B][0;32mI (49) boot: Enabling RNG early entropy source...[1B][0m
[1B][0;32mI (54) boot: Partition Table:[1B][0m
[1B][0;32mI (58) boot: ## Label            Usage          Type ST Offset   Length[1B][0m
[1B][0;32mI (65) boot:  0 nvs              WiFi data        01 02 00009000 00006000[1B][0m
[1B][0;32mI (72) boot:  1 phy_init         RF data          01 01 0000f000 00001000[1B][0m
[1B][0;32mI (80) boot:  2 factory          factory app      00 00 00010000 00100000[1B][0m
[1B][0;32mI (87) boot: End of partition table[1B][0m
[1B][0;32mI (92) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=0aeb8h ( 44728) map[1B][0m
[1B][0;32mI (116) esp_image: segment 1: paddr=0001aee0 vaddr=3ff80063 size=00008h (     8) [1B][0m
[1B][0;32mI (116) esp_image: segment 2: paddr=0001aef0 vaddr=3ffb0000 size=021ach (  8620) load[1B][0m
[1B][0;32mI (125) esp_image: segment 3: paddr=0001d0a4 vaddr=40080000 size=02f74h ( 12148) load[1B][0m
[1B][0;32mI (135) esp_image: segment 4: paddr=00020020 vaddr=400d0020 size=1c128h (114984) map[1B][0m
[1B][0;32mI (180) esp_image: segment 5: paddr=0003c150 vaddr=40082f74 size=0ca44h ( 51780) load[1B][0m
[1B][0;32mI (202) esp_image: segment 6: paddr=00048b9c vaddr=400c0000 size=00064h (   100) [1B][0m
[1B][0;32mI (210) boot: Loaded app from partition at offset 0x10000[1B][0m
[1B][0;32mI (210) boot: Disabling RNG early entropy source...[1B][0m
[1B][0;32mI (221) cpu_start: Multicore app[1B][0m
[1B][0;32mI (221) cpu_start: Pro cpu up.[1B][0m
[1B][0;32mI (222) cpu_start: Starting app cpu, entry point is 0x40081348[1B][0m
[1B][0;32mI (0) cpu_start: App cpu up.[1B][0m
[1B][0;32mI (240) cpu_start: Pro cpu start user code[1B][0m
[1B][0;32mI (240) cpu_start: cpu freq: 80000000 Hz[1B][0m
[1B][0;32mI (240) cpu_start: Application information:[1B][0m
[1B][0;32mI (244) cpu_start: Project name:     Sleep_test[1B][0m
[1B][0;32mI (250) cpu_start: App version:      05a84b5-dirty[1B][0m
[1B][0;32mI (255) cpu_start: Compile time:     Jul 25 2023 08:33:37[1B][0m
[1B][0;32mI (261) cpu_start: ELF file SHA256:  38434bf1143ca2e3...[1B][0m
[1B][0;32mI (267) cpu_start: ESP-IDF:          v5.0.3-dirty[1B][0m
[1B][0;32mI (272) cpu_start: Min chip rev:     v0.0[1B][0m
[1B][0;32mI (277) cpu_start: Max chip rev:     v3.99 [1B][0m
[1B][0;32mI (282) cpu_start: Chip rev:         v1.0[1B][0m
[1B][0;32mI (287) heap_init: Initializing. RAM available for dynamic allocation:[1B][0m
[1B][0;32mI (294) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM[1B][0m
[1B][0;32mI (300) heap_init: At 3FFB2E18 len 0002D1E8 (180 KiB): DRAM[1B][0m
[1B][0;32mI (306) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM[1B][0m
[1B][0;32mI (313) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM[1B][0m
[1B][0;32mI (319) heap_init: At 4008F9B8 len 00010648 (65 KiB): IRAM[1B][0m
[1B][0;32mI (327) spi_flash: detected chip: generic[1B][0m
[1B][0;32mI (330) spi_flash: flash io: dio[1B][0m
[1B][0;33mW (334) spi_flash: Detected size(16384k) larger than the size in the binary image header(4096k). Using the size in the binary image header.[1B][0m
[1B][0;32mI (348) sleep: Configure to isolate all GPIO pins in sleep state[1B][0m
[1B][0;32mI (354) sleep: Enable automatic switching of GPIO sleep configuration[1B][0m
[1B][0;32mI (373) cpu_start: Starting scheduler on PRO CPU.[1B][0m
[1B][0;32mI (0) cpu_start: Starting scheduler on APP CPU.[1B][0m
[1B][0;32mI (416) gpio: GPIO[2]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (416) pm: Frequency switching config: CPU_MAX: 80, APB_MAX: 80, APB_MIN: 10, Light sleep: ENABLED[1B][0m
This is esp32 chip with 2 CPU core(s), WiFi/BT/BLE, silicon revision v1.0, Enabling timer wakeup, 80s
Wakeup caused by timer 
Going to sleep in 5 second 
[1B][0;32mI (436) gpio: GPIO[2]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
ets Jun  8 2016 00:22:57

rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:6992
load:0x40078000,len:15512
load:0x40080400,len:3860
entry 0x40080650
[1B][0;32mI (27) boot: ESP-IDF v5.0.3-dirty 2nd stage bootloader[1B][0m
[1B][0;32mI (27) boot: compile time 15:25:31[1B][0m
[1B][0;32mI (27) boot: Multicore bootloader[1B][0m
[1B][0;32mI (31) boot: chip revision: v1.0[1B][0m
[1B][0;32mI (35) boot.esp32: SPI Speed      : 40MHz[1B][0m
[1B][0;32mI (40) boot.esp32: SPI Mode       : DIO[1B][0m
[1B][0;32mI (44) boot.esp32: SPI Flash Size : 4MB[1B][0m
[1B][0;32mI (49) boot: Enabling RNG early entropy source...[1B][0m
[1B][0;32mI (54) boot: Partition Table:[1B][0m
[1B][0;32mI (58) boot: ## Label            Usage          Type ST Offset   Length[1B][0m
[1B][0;32mI (65) boot:  0 nvs              WiFi data        01 02 00009000 00006000[1B][0m
[1B][0;32mI (72) boot:  1 phy_init         RF data          01 01 0000f000 00001000[1B][0m
[1B][0;32mI (80) boot:  2 factory          factory app      00 00 00010000 00100000[1B][0m
[1B][0;32mI (87) boot: End of partition table[1B][0m
[1B][0;32mI (92) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=0aeb8h ( 44728) map[1B][0m
[1B][0;32mI (116) esp_image: segment 1: paddr=0001aee0 vaddr=3ff80063 size=00008h (     8) [1B][0m
[1B][0;32mI (116) esp_image: segment 2: paddr=0001aef0 vaddr=3ffb0000 size=021ach (  8620) load[1B][0m
[1B][0;32mI (125) esp_image: segment 3: paddr=0001d0a4 vaddr=40080000 size=02f74h ( 12148) load[1B][0m
[1B][0;32mI (135) esp_image: segment 4: paddr=00020020 vaddr=400d0020 size=1c128h (114984) map[1B][0m
[1B][0;32mI (180) esp_image: segment 5: paddr=0003c150 vaddr=40082f74 size=0ca44h ( 51780) load[1B][0m
[1B][0;32mI (202) esp_image: segment 6: paddr=00048b9c vaddr=400c0000 size=00064h (   100) [1B][0m
[1B][0;32mI (210) boot: Loaded app from partition at offset 0x10000[1B][0m
[1B][0;32mI (210) boot: Disabling RNG early entropy source...[1B][0m
[1B][0;32mI (221) cpu_start: Multicore app[1B][0m
[1B][0;32mI (221) cpu_start: Pro cpu up.[1B][0m
[1B][0;32mI (222) cpu_start: Starting app cpu, entry point is 0x40081348[1B][0m
[1B][0;32mI (0) cpu_start: App cpu up.[1B][0m
[1B][0;32mI (240) cpu_start: Pro cpu start user code[1B][0m
[1B][0;32mI (240) cpu_start: cpu freq: 80000000 Hz[1B][0m
[1B][0;32mI (240) cpu_start: Application information:[1B][0m
[1B][0;32mI (244) cpu_start: Project name:     Sleep_test[1B][0m
[1B][0;32mI (250) cpu_start: App version:      05a84b5-dirty[1B][0m
[1B][0;32mI (255) cpu_start: Compile time:     Jul 25 2023 08:33:37[1B][0m
[1B][0;32mI (261) cpu_start: ELF file SHA256:  38434bf1143ca2e3...[1B][0m
[1B][0;32mI (267) cpu_start: ESP-IDF:          v5.0.3-dirty[1B][0m
[1B][0;32mI (272) cpu_start: Min chip rev:     v0.0[1B][0m
[1B][0;32mI (277) cpu_start: Max chip rev:     v3.99 [1B][0m
[1B][0;32mI (282) cpu_start: Chip rev:         v1.0[1B][0m
[1B][0;32mI (287) heap_init: Initializing. RAM available for dynamic allocation:[1B][0m
[1B][0;32mI (294) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM[1B][0m
[1B][0;32mI (300) heap_init: At 3FFB2E18 len 0002D1E8 (180 KiB): DRAM[1B][0m
[1B][0;32mI (306) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM[1B][0m
[1B][0;32mI (313) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM[1B][0m
[1B][0;32mI (319) heap_init: At 4008F9B8 len 00010648 (65 KiB): IRAM[1B][0m
[1B][0;32mI (327) spi_flash: detected chip: generic[1B][0m
[1B][0;32mI (330) spi_flash: flash io: dio[1B][0m
[1B][0;33mW (334) spi_flash: Detected size(16384k) larger than the size in the binary image header(4096k). Using the size in the binary image header.[1B][0m
[1B][0;32mI (348) sleep: Configure to isolate all GPIO pins in sleep state[1B][0m
[1B][0;32mI (354) sleep: Enable automatic switching of GPIO sleep configuration[1B][0m
[1B][0;32mI (373) cpu_start: Starting scheduler on PRO CPU.[1B][0m
[1B][0;32mI (0) cpu_start: Starting scheduler on APP CPU.[1B][0m
[1B][0;32mI (416) gpio: GPIO[2]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (416) pm: Frequency switching config: CPU_MAX: 80, APB_MAX: 80, APB_MIN: 10, Light sleep: ENABLED[1B][0m
This is esp32 chip with 2 CPU core(s), WiFi/BT/BLE, silicon revision v1.0, Enabling timer wakeup, 80s
Wakeup caused by timer 
Going to sleep in 5 second 

image

Does auto light sleep mode affect the timer wake up ?

krupis commented 1 year ago

Update:

I have tried to disable light sleep mode by commenting out the following code

   #if CONFIG_PM_ENABLE
       // Configure dynamic frequency scaling:
       // maximum and minimum frequencies are set in sdkconfig,
       // automatic light sleep is enabled if tickless idle support is enabled.
       esp_pm_config_esp32_t pm_config = {
               .max_freq_mhz = 80,
               .min_freq_mhz = 10,
   #if CONFIG_FREERTOS_USE_TICKLESS_IDLE
               .light_sleep_enable = true
   #endif
       };
       ESP_ERROR_CHECK( esp_pm_configure(&pm_config) );
   #endif // CONFIG_PM_ENABLE

After commenting out the above code block, I can confirm that device now enters deep sleep and sleeps for 60 seconds. Perhaps I am misunderstanding something, can automatic low power mode and deep sleep be used together?

image

esp-lis commented 1 year ago

You can start an oneshot_timer (timeout = 10000 us or ...) before enabling light sleep as shown in the following code:

    const esp_timer_create_args_t oneshot_timer_args = {
            .callback = &oneshot_timer_callback,
            /* argument specified here will be passed to timer callback function */
            .arg = NULL,
            .name = "one-shot"
    };
    esp_timer_handle_t oneshot_timer;
    ESP_ERROR_CHECK(esp_timer_create(&oneshot_timer_args, &oneshot_timer));

    /* Start the timers */
    ESP_ERROR_CHECK(esp_timer_start_once(oneshot_timer, 10000));

After that, start deep sleep in the timeout callback, as shown in the following code:

static void oneshot_timer_callback(void* arg)
{
    configure_gpio();
    gpio_set_level(GPIO_OUTPUT_BUILTIN_LED, 0);
    gpio_hold_en(GPIO_OUTPUT_BUILTIN_LED);
    gpio_deep_sleep_hold_en();

    vTaskDelay(5000/portTICK_PERIOD_MS);
    esp_deep_sleep_start();
}
esp-wzh commented 1 year ago

That's because deepsleep & lightsleep shares the same timer wakeup source, it's suggest that you can disable the auto lightsleep before set deepsleep timer wakeup.

    pm_config = {
        .light_sleep_enable = false
    };
    esp_pm_configure(&pm_config)

        .......

    ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000));
    esp_deep_sleep_start();
krupis commented 1 year ago

@esp-wzh

Ahh thanks for clarifying. Thats much better now.

Now my device:

  1. Wakes up and enters light sleep as soon as it can. Stay there for 5 seconds 2.Disable light sleep and enter deep sleep immediately
  2. Stay in deep sleep for 60 seconds
  3. Repeat the cycle

image

According to my measurement tool, the average current consumption is around 0.3 - 0.35mA

krupis commented 1 year ago

@esp-wzh

Hello. I know this issue has been closed but could you confirm if it possible to reduce the initial current consumption when the device starts.

As you can see it peaks to about 20mA for short amount of time. Is there any particular reason why it is so high? Since I am not using WiFi/BLE on my device (it only wakes up, collects readings from SPI sensor and then goes back to sleep), is there any chance to reduce this initial current ?

esp-wzh commented 1 year ago

Hi~ @krupis, The current in the graph is reasonable, according to esp32 datasheet, image

The current of the dual-core at 160MHz working at full speed is around 40mA, In your example you entered vTaskDelay soon after entering app_main, without automatic light sleep enabled, the CPU is executing waiti instruction when the system is idle, this is where the current will be much lower (~20mA).

krupis commented 1 year ago

@esp-wzh I have automatic light sleep enabled. Aftee it peaks at about 38mA, it then enters light sleep and drops to about 1mA.

38mA startup current still seems too high for ultra low power applications. Are you sure nothing can be done to further reduce it? Can I decrease the CPU clock below 80MHZ? Can I disable something else to further reduce it?

esp-wzh commented 1 year ago

Since the main application scenarios of the esp32 series are wifi//bt applications, and wifi/bt restricts the CPU frequency to no less than 80MHz, the IDF does not support frequency options below 80MHz.

And reducing the frequency also increases the time to startup, which is not a significant reduction in overall energy consumption.

I think one of the more worthwhile optimizations at the moment is that you can suppress the log in the bootloader, which will greatly speed up start time.

esp-wzh commented 1 year ago

@krupis https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/deep-sleep-stub.html If your application is run some lightweight tasks periodically, you can learn some of this feature, wake stub code runs at 40MHz and executes immediately after the chip wakes up, which does not bring a lot of power consumption.

Alvin1Zhang commented 11 months ago

Thanks for reporting, feel free to reopen.

ltwin8 commented 2 months ago

hi, i can confirm a similar issue, but worse! the three current readings are average 13.8uA deep sleep at 3.335V battery voltage as expected, 33uA pulses at 3.325V, 1.35mA constant at 3.305V

at 3.335V the current is pulse shaped, 4mA amplitude thus i think the LDO is maybe oscillating.

tested down to 3.0V, still 1.32mA

the low power trace is cut.

ltwin8 commented 2 months ago

grafik

esp-wzh commented 2 months ago

Hi~ @ltwin8

Can you reproduce this problem using the deepsleep example from IDF?

Can the current from the LDO to the chip 3V3 be intercepted to eliminate the influence of LDO selection and other components on the board?