关于 ESP32 开发板深度睡眠模式电流 11mA 这件事

在官方渠道购买的 ESP32-Pico-Kit V4.1 的板子,然后尝试了 ESPIDF 官方例程以及 GPT 帮忙生成的 Arduino 和 ESPIDF 的最小代码烧录测量,结果发现通过 USB 测量板子进入深度睡眠之后的电流均为 11mA 多点,和官方说的 10uA 以下有这天然之别,但是看过程也确实在重启,看内存也只有 RTC 内存会保留状态,也就是说模块符合预期,但是结果功耗不符合,哪里出了问题呢?查了一圈,看到两篇相关 的答案:CP2102转换芯片和线性稳压器芯片导致的。
【其实 GPT 告诉我答案了,但是我不是硬件工程师,没法办进一步定位,最后还是 Google 给了我认知范围内的答案!!!】

尝试各种姿势的例程

尝试了各种最小 deepsleep 的例程代码后,直接把板子接到 USB 测量器上,发现都是 11mA 最左右如下:

但是各种现象和功能模块确实是符合预期的,有意思的是,这个过程 GPT 其实已经告诉我答案了,就在第一条,但是我还是没有办法在我能力范围内确定,也被我忽略了接着 Google 找来找去【如果是硬件工程师,可能一下子就知道啥原理以及定位到哪个芯片了】。

直到在 Google 中找到很类似 的,也给出了具体芯片,这时候就基本确定了。

有机会把下面那两个拆掉看下吧,,,【估计就搁置了XD】

最简单的 Arduino 例程

#include <Arduino.h>
#include <esp_sleep.h>

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

  // 给串口足够的时间来初始化
  delay(1000);
  Serial.println("Entering deep sleep for 10 seconds");

  // 设置ESP32在10秒后自动唤醒
  esp_sleep_enable_timer_wakeup(10 * 1000000);

  // 进入深度睡眠
  esp_deep_sleep_start();

  // 注意:ESP32进入深度睡眠后,不会执行下面的代码
}

void loop() {
  // 这里的代码在深度睡眠后不会被执行
}

最简单的 ESPIDF 例程

#include "esp_sleep.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"

void app_main() {
    // 在进入深度睡眠之前打印一条日志
    ESP_LOGI("Sleep", "Entering deep sleep for 10 seconds");

    // 设置唤醒设备的条件,这里设置为10秒后自动唤醒
    esp_sleep_enable_timer_wakeup(10 * 1000000);

    // 进入深度睡眠模式
    esp_deep_sleep_start();

    // 代码不会执行到这里
}

官方例程

/*
 * SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: Unlicense OR CC0-1.0
 */

#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include "sdkconfig.h"
#include "soc/soc_caps.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_sleep.h"
#include "esp_log.h"
#include "driver/rtc_io.h"
#include "nvs_flash.h"
#include "nvs.h"
//#include "deep_sleep_example.h"

#if SOC_RTC_FAST_MEM_SUPPORTED
static RTC_DATA_ATTR struct timeval sleep_enter_time;
#else
static struct timeval sleep_enter_time;
#endif

static void deep_sleep_task(void *args)
{
    /**
     * Prefer to use RTC mem instead of NVS to save the deep sleep enter time, unless the chip
     * does not support RTC mem(such as esp32c2). Because the time overhead of NVS will cause
     * the recorded deep sleep enter time to be not very accurate.
     */
#if !SOC_RTC_FAST_MEM_SUPPORTED
    // Initialize NVS
    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");
    }

    // Get deep sleep enter time
    nvs_get_i32(nvs_handle, "slp_enter_sec", (int32_t *)&sleep_enter_time.tv_sec);
    nvs_get_i32(nvs_handle, "slp_enter_usec", (int32_t *)&sleep_enter_time.tv_usec);
#endif

    struct timeval now;
    gettimeofday(&now, NULL);
    int sleep_time_ms = (now.tv_sec - sleep_enter_time.tv_sec) * 1000 + (now.tv_usec - sleep_enter_time.tv_usec) / 1000;

    switch (esp_sleep_get_wakeup_cause()) {
        case ESP_SLEEP_WAKEUP_TIMER: {
            printf("Wake up from timer. Time spent in deep sleep: %dms\n", sleep_time_ms);
            break;
        }

#if CONFIG_EXAMPLE_GPIO_WAKEUP
        case ESP_SLEEP_WAKEUP_GPIO: {
            uint64_t wakeup_pin_mask = esp_sleep_get_gpio_wakeup_status();
            if (wakeup_pin_mask != 0) {
                int pin = __builtin_ffsll(wakeup_pin_mask) - 1;
                printf("Wake up from GPIO %d\n", pin);
            } else {
                printf("Wake up from GPIO\n");
            }
            break;
        }
#endif //CONFIG_EXAMPLE_GPIO_WAKEUP

#if CONFIG_EXAMPLE_EXT0_WAKEUP
        case ESP_SLEEP_WAKEUP_EXT0: {
            printf("Wake up from ext0\n");
            break;
        }
#endif // CONFIG_EXAMPLE_EXT0_WAKEUP

#ifdef CONFIG_EXAMPLE_EXT1_WAKEUP
        case ESP_SLEEP_WAKEUP_EXT1: {
            uint64_t wakeup_pin_mask = esp_sleep_get_ext1_wakeup_status();
            if (wakeup_pin_mask != 0) {
                int pin = __builtin_ffsll(wakeup_pin_mask) - 1;
                printf("Wake up from GPIO %d\n", pin);
            } else {
                printf("Wake up from GPIO\n");
            }
            break;
        }
#endif // CONFIG_EXAMPLE_EXT1_WAKEUP

#ifdef CONFIG_EXAMPLE_TOUCH_WAKEUP
        case ESP_SLEEP_WAKEUP_TOUCHPAD: {
            printf("Wake up from touch on pad %d\n", esp_sleep_get_touchpad_wakeup_status());
            break;
        }
#endif // CONFIG_EXAMPLE_TOUCH_WAKEUP

        case ESP_SLEEP_WAKEUP_UNDEFINED:
        default:
            printf("Not a deep sleep reset\n");
    }

    vTaskDelay(1000 / portTICK_PERIOD_MS);

#if CONFIG_IDF_TARGET_ESP32
    // Isolate GPIO12 pin from external circuits. This is needed for modules
    // which have an external pull-up resistor on GPIO12 (such as ESP32-WROVER)
    // to minimize current consumption.
    rtc_gpio_isolate(GPIO_NUM_12);
#endif

    printf("Entering deep sleep\n");

    // get deep sleep enter time
    gettimeofday(&sleep_enter_time, NULL);

#if !SOC_RTC_FAST_MEM_SUPPORTED
    // record deep sleep enter time via nvs
    ESP_ERROR_CHECK(nvs_set_i32(nvs_handle, "slp_enter_sec", sleep_enter_time.tv_sec));
    ESP_ERROR_CHECK(nvs_set_i32(nvs_handle, "slp_enter_usec", sleep_enter_time.tv_usec));
    ESP_ERROR_CHECK(nvs_commit(nvs_handle));
    nvs_close(nvs_handle);
#endif

    // enter deep sleep
    esp_deep_sleep_start();
}

static void example_deep_sleep_register_rtc_timer_wakeup(void)
{
    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));
}

void app_main(void)
{
    /* Enable wakeup from deep sleep by rtc timer */
    example_deep_sleep_register_rtc_timer_wakeup();

#if CONFIG_EXAMPLE_GPIO_WAKEUP
    /* Enable wakeup from deep sleep by gpio */
    example_deep_sleep_register_gpio_wakeup();
#endif

#if CONFIG_EXAMPLE_EXT0_WAKEUP
    /* Enable wakeup from deep sleep by ext0 */
    example_deep_sleep_register_ext0_wakeup();
#endif

#if CONFIG_EXAMPLE_EXT1_WAKEUP
    /* Enable wakeup from deep sleep by ext1 */
    example_deep_sleep_register_ext1_wakeup();
#endif

#if CONFIG_EXAMPLE_TOUCH_WAKEUP
    /* Enable wakeup from deep sleep by touch */
    example_deep_sleep_register_touch_wakeup();
#endif

    xTaskCreate(deep_sleep_task, "deep_sleep_task", 4096, NULL, 6, NULL);
}

参考链接