ESP32深度睡眠电流怎样低于10uA

陈拓 2022/05/26-2022/05/29

1. 概述

本文以官方例程为基础,实验ESP32模块在Deep-sleep模式下超低功耗的实现。

1.1 深度睡眠Deep-sleep

官方文档:

https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-reference/system/sleep_modes.html

ESP32具有Light-sleep和Deep-sleep两种睡眠节能模式。

在Light-sleep模式下,数字外设、CPU、以及大部分RAM都使用时钟门控,同时电源电压降低。退出该模式后,数字外设、CPU和RAM恢复运行,内部状态保持不变。

在Deep-sleep模式下,CPU、大部分RAM、以及所有由时钟APB_CLK驱动的数字外设都会被断电。芯片上继续处于供电状态的部分仅包括:

  • RTC 控制器
  • RTC 外设
  • ULP 协处理器
  • RTC 高速内存
  • RTC 低速内存

Light-sleep和Deep-sleep模式有多种唤醒源。这些唤醒源也可以组合在一起,此时任何一个唤醒源都可以触发唤醒。

[APB_CLK(APB时钟)]

ESP32的CPU主时钟CPU_CLK主频可以达到160MHz,对于外部设备来说太高了,不能直接使用,需要分频。ESP32提供了多种不同频率的时钟选择,可以灵活的配置 CPU,外设,以及 RTC 的工作频率,以满足不同功耗和性能需求。

外设时钟包括APB_CLK,REF_TICK,LEDC_SCLK,APLL_CLK和PLL_D2_CLK。

1.2 不同模式的功耗

1.3 本实验的唤醒源

为测试最低电流消耗,本实验不使用触摸唤醒、ULP唤醒和GPIO唤醒,只使用定时器唤醒。其他唤醒方式,以后的文章会有讲述。

1.4 官方例程国内镜像

本文的主要内容来自官方例程Deep Sleep Example

https://gitee.com/EspressifSystems/esp-idf/tree/master/examples/system/deep_sleep

1.5 测试电路板

市面上常见的下面这种ESP32开发板由于有外围电路不能用于本实验。

本文后面附有这种开发板的电路原理图。

为减少附加电路对测量的影响,我们需要自己制作一个测试电路板。制作方法:1个ESP32-S模块焊在一个底板上,加2个按钮(RESET和IO0),2个按钮各带1个10k的上拉电阻,如下图右侧所示。

用2个电流表头测量电流。大电流时2个表头需并联否则uA表头内阻太大带不动,另外会打表。小电流时拿掉mA表头。

廉价而有效的测量方法:

烧写程序和查看串口LOG还需要一个USB转串口下载器:

2. 开发环境

《用乐鑫国内Gitee镜像搭建ESP32开发环境》

https://zhuanlan.zhihu.com/p/348106034

https://blog.csdn.net/chentuo2000/article/details/113424934?spm=1001.2014.3001.5501

3. 构建项目

此示例演示如何使用esp_sleep.h API进入深度睡眠模式,然后从定时器源唤醒。

定时器是一种RTC定时器,可编程为在预设时间后触发唤醒。此示例将每20秒触发一次唤醒。

  • 复制官方例程

将官方例子项目复制到ESP-IDF开发工具之外:

cd ~/esp

cp -r esp-idf/examples/system/deep_sleep/ ~/esp/esp32_deep_sleep

  • 项目树

cd esp32_deep_sleep

4. 构建项目

  • 刷新esp-idf环境

get_idf

  • 设定目标芯片

idf.py set-target esp32

  • 配置项目

idf.py menuconfig

1) 设置Flash存储器大小为4MB

2) 为测试最低电流消耗,不使用触摸唤醒、ULP唤醒和GPIO唤醒

3) 选择Skip image validatin when exiting deep sleep

使用该选项,它允许您在从深度睡眠中醒来时减少引导加载程序的引导时间。引导加载程序将运行分区的地址存储在rtc内存中,并在唤醒时使用它。此示例允许您跳过所有映像检查并加快引导速度。

保存,退出。

  • 编译项目

idf.py build

  • 烧写项目

查看USB转串口的COM口号:

烧写:

idf.py -p /dev/ttyS3 -b 115200 flash

写入操作(可以在发送上面的命令之前或之后):

1) 按住IO0按钮

2) 按下RST按钮,再松开

3) 松开IO0按钮

如果不成功重新上电再试。

  • 启用监视器

idf.py monitor -p /dev/ttyS3

(Ctrl+]可以退出监视器程序)

第一次运行

之后的运行

  • 唤醒电流(并联mA表)

  • deep sleep电流(断开mA表)

deep sleep电流为66uA,距离手册中的20uA相差太远。

5. 减小deep-sleep电流

  • 主要参考

https://electronics.stackexchange.com/questions/530151/esp32-wroom32-consuming-77-%c2%b5a-much-too-high-in-deep-sleep

  • 修改程序

在deep_sleep_example_main.c的app_main函数开始处添加下面的语句:

void app_main(void)
{
    gpio_reset_pin(GPIO_NUM_0);
    gpio_reset_pin(GPIO_NUM_2);
    gpio_reset_pin(GPIO_NUM_4);
    gpio_reset_pin(GPIO_NUM_12);
    gpio_reset_pin(GPIO_NUM_13);
    gpio_reset_pin(GPIO_NUM_14);
    gpio_reset_pin(GPIO_NUM_15);
    gpio_reset_pin(GPIO_NUM_25);
    gpio_reset_pin(GPIO_NUM_26);
    gpio_reset_pin(GPIO_NUM_27);
    gpio_reset_pin(GPIO_NUM_32);
    gpio_reset_pin(GPIO_NUM_33);
    gpio_reset_pin(GPIO_NUM_34);
    gpio_reset_pin(GPIO_NUM_35);
    gpio_reset_pin(GPIO_NUM_36);
    gpio_reset_pin(GPIO_NUM_37);
    gpio_reset_pin(GPIO_NUM_38);
    gpio_reset_pin(GPIO_NUM_39);

说明:

gpio_reset_pin函数将gpio引脚重置为默认状态(选择gpio功能,启用上拉并禁用输入和输出)。

重新编译、烧写、执行。

  • 唤醒电流(并联mA表)

  • deep sleep电流(断开mA表)

电流小于10uA。

6. 添加一个LED作为gpio的负载

6.1 添加gpio负载

  • 添加对电源的负载(灌电流 sink current)

GPIO_NUM_2,GPIO_NUM_4和GPIO_NUM_15这几个引脚添加对地负载(拉电流 source current)会使深度睡眠电流增大到60uA以上。像后面所附的电路图那样连接LED1是不行的,要将LED的正极通过限流电阻接到3.3v电源上,LED的负极接GPIO引脚,也就是灌电流接法,这样才能使睡眠电流降下来。

  • 注意不要使用GPIO_NUM_2

灌电流接法使用GPIO2会影响固件烧写。

  • 我们使用GPIO4连接LED

6.2 修改程序

在deep_sleep_example_main.c中有改变的语句如下,请对照原来的代码查看。

#define GPIO_OUTPUT_IO_LED 4 // LED接在gpio引脚4

void led_init(void)
{
    gpio_pad_select_gpio(GPIO_OUTPUT_IO_LED);
    gpio_set_direction(GPIO_OUTPUT_IO_LED, GPIO_MODE_OUTPUT); // Set the GPIO as a push/pull output
}

void led_on(void) {
    gpio_set_level(GPIO_OUTPUT_IO_LED, 0);
}

void led_off(void) {
    gpio_set_level(GPIO_OUTPUT_IO_LED, 1);
}

void app_main(void)
{
    // 做了下面这些设置后电流从63uA下降到了3uA
    gpio_reset_pin(GPIO_NUM_0);
    gpio_reset_pin(GPIO_NUM_2);
    gpio_reset_pin(GPIO_NUM_4);
    gpio_reset_pin(GPIO_NUM_12);
    gpio_reset_pin(GPIO_NUM_13);
    gpio_reset_pin(GPIO_NUM_14);
    gpio_reset_pin(GPIO_NUM_15);
    gpio_reset_pin(GPIO_NUM_25);
    gpio_reset_pin(GPIO_NUM_26);
    gpio_reset_pin(GPIO_NUM_27);
    gpio_reset_pin(GPIO_NUM_32);
    gpio_reset_pin(GPIO_NUM_33);
    gpio_reset_pin(GPIO_NUM_34);
    gpio_reset_pin(GPIO_NUM_35);
    gpio_reset_pin(GPIO_NUM_36);
    gpio_reset_pin(GPIO_NUM_37);
    gpio_reset_pin(GPIO_NUM_38);
    gpio_reset_pin(GPIO_NUM_39);

    led_init();
    led_off();

    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()) {
#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
#if SOC_GPIO_SUPPORT_DEEPSLEEP_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 //SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
        case ESP_SLEEP_WAKEUP_TIMER: {
            printf("Wake up from timer. Time spent in deep sleep: %dms\n", sleep_time_ms);
            //led_init();
            led_on();
            vTaskDelay(150 / portTICK_RATE_MS); // 延时150ms
            led_off();
            break;
        }
#ifdef CONFIG_EXAMPLE_TOUCH_WAKEUP

6.3 测试结果

deep sleep电流和前面一样,小于10uA。

附:ESP32开发板电路原理图

参考文档

  1. https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-reference/system/sleep_modes.html?highlight=apb_clk
  2. https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/sleep_modes.html#wakeup-sources
  3. https://lastminuteengineers.com/esp32-sleep-modes-power-consumption/

  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晨之清风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值