ESP 低功耗参数配置
引言
Light Sleep 工作模式下,RF 模块会被关闭,除 RTC 相关模块外大多数模块都会被下电或者进行动态频率调节,以此来达到功耗降低的结果。其中有一些 menuconfig 可以按需求配置,本文将对这些配置项做一些介绍。 此时的芯片底电流可以参考 datasheet 上的功耗,如ESP32-C3 为 130 μA,ESP32-S3为 240 μA,ESP32-C6为 35 μA(实测是 45 μA,后续 datasheet 会修正这一项)。
1. 常用功耗优化配置选项
1.1. 动态调频
CPU 工作的频率越高,功耗消耗也越大。通过 DFS(dynamic frequency scaling,动态调频)可以让系统自动切换工作频率,达到功耗和性能间的平衡。开启该功能需要使能如图2-1的这两项,这样系统会在工作的时候切换到最大频率,在系统空闲时切换到最低频率,最大频率默认为主频,如 ESP32-C3 为160 MHz, 最低频率为外部主晶振的频率,一般为 40 MHz。最大和最小的频率可以通过调用esp_pm_configure进行设置。
备注
如果是带有Wi-Fi 应用的自动调频,最小频率不能小于 40 MHz。低于40 MHz CPU处理速度会慢,低功耗收益不高,且 C6 没有适配好,会有 beacon loss 的问题。
图 2-1 动态调频配置项
配置项名称:
PM_ENABLE
配置项路径:
(Top) -> Component config -> Power Management -> Support for power management
配置项名称:
PM_DFS_INIT_AUTO
配置项路径:
(Top) -> Component config -> Power Management -> Support for power management -> Enable dynamic frequency scaling (DFS) at startup
1.2 自动 light sleep
在开启动态调频后如果需要进一步降低功耗,如图2-1所示,需要开启自动light sleep。 Modem sleep模式加上自动light sleep 也就是我们常说的 power save 模式。
图 2-2 自动 light sleep配置项
配置项名称:
FREERTOS_HZ
配置项路径:
(Top) -> Component config -> FreeRTOS -> Tick rate (Hz)
配置项名称:
FREERTOS_USE_TICKLESS_IDLE
配置项路径:
(Top) -> Component config -> FreeRTOS -> Tickless idle support
这里涉及两个配置项,A 项为 freeRTOS 的Tick 频率,默认为 100,即每个 Tick 需要1000 / 100=10 ms。B项是自动进入 light sleep 状态需要的最小空闲 Tick 数,默认为3,即当系统检测到空闲时间大于3个Tick 时就会自动进入 light sleep。如上图所示,当空闲时间大于 3*10=30 ms 时系统将自动进入 light sleep。通过增加A项,可以让系统更敏感地检测到空闲时间并进入睡眠。如将 tick rate配置为1000,即当3 ms内没有任务工作就进入睡眠,从而达到更低的功耗。
备注
自动进入 light sleep 必须在使能 2.1 的配置项后才能进行配置。
在开启了自动调频和自动睡眠后,一些外设的通信会受到影响,具体可以参照编程指南。
客户最容易问的是如何在保持功耗的情况下使用LEDC和 UART,解决方法: - 对于在自动睡眠时想使用UART中断的客户,首先问他们是否还有多余的GPIO 管脚,优先推荐 GPIO 唤醒。 - 询问客户硬件上是否有外接32K晶振,如果有,改变外设时钟源为外部32K晶振。 - 使用锁,可以在进行通信时禁用动态调频,例子可以看附件2。
1.3 隔离 GPIO
系统休眠过程中的 GPIO 漏电会产生电流损耗,增大系统功耗。esp-idf 中 light sleep 休眠时通过 GPIO 管脚悬空(禁止管脚内部上下拉电阻)及隔离(断开管脚输入输出)来消除 GPIO 漏电流,该功能对应的 menuconfig 配置项如下。
备注
该配置项必须在使能 2.2 的自动睡眠后才能启用。
图 2-3 隔离 GPIO 配置项
配置项名称:
PM_SLP_DISABLE_GPIO
配置项路径:
(Top) -> Component config -> Power Management -> Disable all GPIO when chip at sleep
打开该选项,系统休眠过程中所有 GPIO 管脚将被禁用,消除了 GPIO 漏电对休眠功耗的影响,但也导致了休眠过程中 GPIO 无法进行信号输入和输出,然而在一些应用中,应用层希望在系统休眠过程中能够正常使用 GPIO 功能(输入/输出/内部上下拉),因此 IDF 中提供了一组 API 用于管理休眠过程中的 GPIO 状态,相关 API 参考表 2-1。
表 2-1 休眠过程 GPIO 管理 API
设置休眠状态下的 GPIO 输入输出状态:
esp_err_t gpio_sleep_set_direction(gpio_num_t gpio_num, gpio_mode_t mode);
设置休眠状态下的 GPIO 上下拉状态:
esp_err_t gpio_sleep_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull);
使能自动 GPIO 状态切换:
esp_err_t gpio_sleep_sel_en(gpio_num_t gpio_num);
禁止自动 GPIO 状态切换:
esp_err_t gpio_sleep_sel_dis(gpio_num_t gpio_num);
如果想在睡眠时保持GPIO管脚的状态,比如控制灯输出,控制开关闭合,可以使用 gpio_hold_en(gpio_num_t gpio_num)
和 gpio_hold_dis(gpio_num_t gpio_num)
两个 API,在进入睡眠前对需要保持电平的 GPIO 进行 hold,醒来后进行 hold_dis。
1.4 flash 下电
ESP32通过外接 flash 和 PSRAM 来增大系统存储器资源。flash 具有掉电后数据不丢失特性,PSRAM 掉电后数据无法保持,当系统中没有使用到 PSRAM 时,可以使能 flash 下电功能来降低芯片休眠电流,相关 menuconfig 选项如下:
图 2-4 Flash 掉电配置项
配置项名称:
ESP_SYSTEM_PD_FLASH (release/v4.3)
配置项名称:
ESP_SLEEP_POWER_DOWN_FLASH (4.4以后)
配置项路径:
(Top) -> Component config -> ESP System Settings -> PD flash at light sleep when there is no SPIRAM (release/v4.3)
配置项路径:
(Top) -> Component config -> Hardware Settings -> Sleep Config -> Power down flash in light sleep when there is no SPIRAM (4.4以后)
备注
现实情况中 flash 断电所需的时间很难预测,即使可以预知 flash 彻底断电所需的时间,有时也不能通过设置足够长的睡眠时间来确保 flash 断电的安全(比如,突发的异步唤醒源会使得实际的睡眠时间不可控),此时,断电尚未完成又重新上电的硬件行为有可能导致 flash 无法正常工作。因此可以对配置项进行以下调整:
图 2-5 Flash 掉电配置优化
配置项名称:
ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND
配置项路径:
(Top) -> Component config -> Hardware Settings -> Sleep Config -> Pull-up Flash CS pin in light sleep
这种方式比断电 flash 更好,相比之下增加了十几 μA 的底电流消耗,但同时兼顾了安全性和功耗。如果在 flash 的供电电路上添加了滤波电容,那么应当尽一切可能避免 flash 断电。
1.5 CPU 下电
对于 light sleep 模式下功耗有更高要求的应用,可以使能休眠时 CPU 下电功能来减小休眠电流,对于 ESP32-C3,休眠电流减小 100 μA 左右,对于 ESP32-S3,休眠电流减小 650 μA 左右。目前仅在这两个芯片上可用,ESP32 和 ESP32-S2 无法使用。
休眠时对 CPU 下电会造成 CPU 执行上下文信息(专用、通用以及状态寄存器等)丢失,导致休眠唤醒后 CPU 执行异常,因此需要在 CPU 下电前备份上下文信息到 retention memory,系统唤醒后 CPU 执行前从 retention memory 中恢复上下文信息,备份 CPU 上下文信息需要消耗系统存储器资源,对于 ESP32-C3,将消耗 1.6 KB 的 DRAM 空间,对于 ESP32-S3,将消耗 8.58 KB 的 DRAM 空间。
图 2-6 CPU 掉电配置
配置项名称:
PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
配置项路径:
(Top) -> Component config -> Power Management -> Power down CPU in light sleep
1.6 外围设备下电(light sleep)
通过关闭此项,可以将底电流降低约 100 μA。
配置项名称:
PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
配置路径:
(Top) -> Component config -> Power Management -> Power down Digital Peripheral in light sleep (EXPERIMENTAL)
当外设电源域在睡眠期间断电时,IO_MUX
和 GPIO
模块都处于下电状态,这意味着芯片引脚的状态不会受这些模块控制。要在休眠期间保持 IO
的状态,需要在配置 GPIO 状态前后调用 gpio_hold_dis()
和 gpio_hold_en()
。此操作可确保 IO 配置被锁存,防止 IO 在睡眠期间浮空。
2. Wi-Fi/蓝牙低功耗优化配置
乐鑫芯片是无线 MCU,因此大部分时候的低功耗功能都需要和 Wi-Fi/蓝牙功能一起使用。这里对 Wi-Fi/蓝牙相关的一些低功耗配置和参数进行解释。
2.1 蓝牙低功耗优化项
2.1.1 BLE sleep
目前蓝牙端可以优化配置比较少,可以使能 BLE modem sleep。
配置项名称:
BT_CTRL_MODEM_SLEEP
和BT_LE_SLEEP_ENABLE(V5.2)
配置路径: -
(Top) -> Component config -> Bluetooth -> Bluetooth -> Bluetooth controller -> MODEM SLEEP Options
-(Top) → Component config → Bluetooth → Controller Options(V5.2)
如果希望在保活时进入 light sleep 而不是 modem sleep,可参考 2.2 的做法。
需要注意的是,在 4.4 及之后的 IDF 版本里,蓝牙已支持用主晶振作为休眠时钟,不使用外部 32 KHz 晶振的代价是 light sleep 时底电流会上升。参考电流: - ESP32-C3: 2.3 mA - ESP32-S3: 3.3 mA
2.1.2 Nimble – BLE only
配置项名称:
BT_NIMBLE_ENABLED
配置路径:
(Top) -> Component config -> Bluetooth -> Bluetooth -> Host
在 BLE only 的场景下,可配置此项以减少内存消耗。
2.2 Wi-Fi 低功耗优化项
Wi-Fi 优化涉及的配置项较多,比较通用的有以下几点:
2.2.1 无线数字电路掉电
在使能自动 light sleep 后,可以开启此选项,让无线数字电路模块在关闭物理层时也相应掉电,大约能节省 100 μA 左右的底电流。
配置项名称:
ESP_PHY_MAC_BB_PD
配置路径:
(Top) -> Component config -> PHY -> Power down MAC and baseband of Wi-Fi and Bluetooth when PHY is disabled
2.2.2 更改最小等待时间和最大保活时间
当 ESP32 作为 STA 和 AP 进行通信时,接收完一次数据后需要等待一段时间再关闭 RF,这个时间称为 Minimum active time,默认值为 50 ms。在保证每次数据吞吐量的基础上,可以适当减少这个等待时间来降低功耗。
而当 ESP32 处于 power save 模式下时,需要周期性地向 AP 发送一个 keep alive 包来告诉 AP 自己仍保持连接。Maximum keep alive time 即是发送这个 keep alive 包的时间周期,默认为 10 s。可以通过增大该参数来减少发包,从而降低功耗。
配置项名称:
ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME
配置路径:
(Top) -> Component config -> Wi-Fi -> Wi-Fi SLP IRAM speed optimization -> Minimum active time
配置项名称:
ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME
配置路径:
(Top) -> Component config -> Wi-Fi -> Wi-Fi SLP IRAM speed optimization -> Maximum keep alive time
推荐配置: Minimum active time = 15~20,Maximum keep alive time = 60。
2.2.3 开启断连电源管理
使能该配置项后,发生断连时依旧可以保持 Modem sleep 状态。
配置项名称:
ESP_WIFI_STA_DISCONNECTED_PM_ENABLE
配置路径:
(Top) → Component config → Wi-Fi → Power Management for station at disconnected
2.2.4 开启 Beacon lost 优化(仅 release/v4.4 及以上)
Wi-Fi 保活的一个基础是能够定时接收到路由器发送的 beacon 包。在实际使用环境中,因各种原因会导致 beacon 丢失。在 release/v4.4 之前的版本中,丢失 beacon 后 ESP32 会保持 RF 继续开启,直到接收到下一个 beacon。4.4 以后的版本可通过开启 beacon lost 优化来避免这一行为对功耗造成的影响。
配置项名称:
ESP_WIFI_SLP_BEACON_LOST_OPT
配置路径:
(Top) → Component config → Wi-Fi → Wifi sleep optimize when beacon lost
如图 2-6 所示,优化原理是在丢失 beacon 时不会一直开着 RF 接收,而是开一段时间没接收到就睡下去,然后再起来收包,重复几次后如果还没收到,才会和常规操作一样开着 RF 直到接收到位置。这样可大大提高未接收到 beacon 时的容错率,从而减少功耗。
开启此选项后会引出四个额外的配置项,主要需要关注前两个配置项:
A 选项: Beacon loss timeout 表示等待多久没收到 beacon 就进入休眠。
B 选项: Maximum number of consecutive lost beacons allowed 表示重复多少次没收到才持续开启。
需注意,B 选项不应设得过大,一般设为 3 个即可。
2.2.5 降低 TX power
使能该项后,检测到 brownout reset 后将减小 PHY TX power,使代码能继续运行。
配置项名称:
ESP_PHY_REDUCE_TX_POWER
配置路径:
(Top) → Component config → PHY → Reduce PHY TX power when brownout reset
2.2.6 优化 Sleep IRAM Speed
选择此选项可将 Wi-Fi 库的 TBTT 进程和 receive beacon 函数放置在 IRAM 中。如果启用此选项,Wi-Fi powersave 模式平均电流将减少。
配置项名称:
ESP_WIFI_SLP_IRAM_OPT
配置路径:
(Top) → Component config → Wi-Fi → WiFi SLP IRAM speed optimization
2.2.7 优化 IRAM Speed
以下三项都可以开启。
配置项名称: -
ESP_WIFI_IRAM_OPT
-ESP_WIFI_EXTRA_IRAM_OPT
-ESP_WIFI_RX_IRAM_OPT
配置路径:
(Top) → Component config → Wi-Fi → WiFi IRAM speed optimization
2.2.8 Wi-Fi 物理层收包
ESP32-C6 的可选功能,在 light sleep 期间,PHY 层自动收包,Wi-Fi 接收 beacon 不再需要 CPU 参与,只有 Wi-Fi MAC + Baseband + RF 工作,以节省功耗。
备注
补充内容:不同 mode 下 T/RX 波形图
配置项名称: -
ESP_WIFI_ENHANCED_LIGHT_SLEEP
-ESP_WIFI_EXTRA_IRAM_OPT
-ESP_WIFI_RX_IRAM_OPT
配置路径:
(Top) → Component config → Wi-Fi → WiFi modem automatically receives the beacon
3. 补充内容
3.1. DTIM 和 listen interval 的区别
当芯片作为 STA 和路由器建立连接的时候,会被告知路由器的 DTIM,即每隔多少时间路由器会发送一个 beacon,STA 需要在这个时间起来接收 beacon,查看是否有需要自己处理的信息。而 listen interval 则是 STA 告诉路由,我需要隔多少时间起来接受 beacon,即前者是根据路由端来定的,后者是可以自己配置到芯片里的。时间间隔为 DTIM 或者 listen interval 的值 * 100 MS,如果当 DTIM=10,即每次唤醒的时间间隔为 10 * 100 ms = 1 s。
3.2. 外接 32KHz 晶振
使用外接 32KHz 晶振可以获得更低的功耗。主要有以下几个原因:
内部的晶振容易受到干扰,相比之下外接晶振的精度更高,并可以在各种睡眠情况下使用。
对于时间精度要求比较高的应用,如蓝牙和 Wi-Fi 的保活,需要定时起来接受 beacon,一旦时钟漂移过大,错过了接收的点,会导致打开 RF 等待的窗口期变长,从而大大增加功耗。
使能外部时钟源需要如下配置:
配置项名称: -
ESP32C3_RTC_CLK_SRC_EXT_CRYS
-ESP_WIFI_EXTRA_IRAM_OPT
-ESP_WIFI_RX_IRAM_OPT
配置路径:
(Top) → Component config → ESP32XX-Specific → RTC clock source
外部晶振有两种:
External 32kHz crystal: 为外部无源晶振,也是大部分时候推荐的晶振
External 32kHz oscillator at 32K_XP pin: 为外部有源晶振,价格更贵,同时会造成底电流上升 50 ~ 100 μA
ESP32-C2 由于内部没有无源晶振的起振电路,只支持外部有源晶振;晶振的布局可以参考各芯片对应的硬件设计指南。
3.3. 不同 mode 下 T/RX 波形图
Modem Mode(物理层收 beacon): 一次收包时间开销为 2.1 ms 左右,收包电流为 64 mA ~ 70 mA 左右。
Active Mode RX: 一次收包时长 5.3 ms 左右,收包电流 80 mA 左右。
RX 没收到包: 对比没收到包的情况,不会有持续一段时间电流的波形。
Active Mode TX: 持续时间不定,TX 电流与 Wi-Fi 信道相关。