ESP 低功耗参数配置
引言
本文档介绍了在 ESP-IDF 环境下如何配置以优化 ESP 系列芯片的功耗,在保证功能与性能的同时有效降低系统能耗。
系统低功耗优化配置
本节将首先从纯系统角度介绍,不涉及具体工作场景的低功耗模式。
动态调频(DFS)
CPU 工作的频率越高,功耗消耗也越大。通过 DFS,系统可以根据运行状态自动切换 CPU 工作频率,在负载较高时运行于高频、空闲时降低频率,从而在性能与功耗之间取得平衡。
配置步骤如下:
备注
在包含 Wi-Fi 应用的自动调频场景中,需注意以下限制:
最小频率不低于 40 MHz,否则 CPU 处理能力将显著下降,且低功耗优化效果有限;
最大频率不低于 80 MHz,否则 Wi-Fi RF 模块将无法正常工作。
备注
在开启了自动调频后,一些外设的通信会因频率变化受到影响,具体说明见 动态调频和外设驱动。
若希望在保持低功耗的同时使用 LEDC 和 UART,可参考以下方法:
如果希望在自动睡眠时使用 UART 中断,建议使用 GPIO 唤醒。
如果硬件上搭载了 外部 32 KHz 晶振,建议将外设时钟切换为该晶振。
在通信期间可使用锁机制禁用动态调频,具体操作可参考 低功耗 LEDC 开发指南。
自动 Light sleep
在 自动 Light sleep 模式下,CPU 会在空闲时周期性暂停运行并进入 Light Sleep,Wi-Fi / BLE 的射频及相关基带模块在非通信窗口进入低功耗状态,仅在需要维持连接(如接收 Beacon、广播或进行数据收发)时被唤醒。
配置步骤如下:
esp_pm_config_t pm_config = {
.max_freq_mhz = CONFIG_EXAMPLE_MAX_CPU_FREQ_MHZ,
.min_freq_mhz = CONFIG_EXAMPLE_MIN_CPU_FREQ_MHZ,
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
.light_sleep_enable = true
#endif
};
ESP_ERROR_CHECK(esp_pm_configure(&pm_config));
此外,在启用自动 Light sleep 后,还可通过调整以下配置项,进一步降低休眠阶段的系统功耗。但不同配置在功耗、功能可用性以及系统资源占用之间存在一定取舍,需根据具体应用场景和需求进行选择与组合。
调整间隔时间
可通过调整以下配置项,进一步缩短系统进入 Light sleep 的间隔时间。
CONFIG_FREERTOS_HZ 为 FreeRTOS 的 Tick 频率,默认为 100,即每个 Tick 为 1000/100 = 10 ms;
CONFIG_FREERTOS_IDLE_TIME_BEFORE_SLEEP 为系统自动进入 Light sleep 状态所需的最小空闲 Tick 数,默认为 3。
通过提高 CONFIG_FREERTOS_HZ,系统能够以更高的时间分辨率检测空闲状态。例如将其配置为 1000 时,每个 Tick 为 1 ms,在 CONFIG_FREERTOS_IDLE_TIME_BEFORE_SLEEP = 3 的情况下,若系统预测未来约 3 ms 内不会有任务或定时事件需要处理,即可进入 Light sleep,从而进一步降低功耗。
隔离 GPIO
系统在休眠过程中,GPIO 漏电会产生额外电流损耗,增加功耗。
在 ESP-IDF 中,可通过使能 CONFIG_PM_SLP_DISABLE_GPIO 禁止 GPIO 内部上下拉电阻并隔离管脚输入输出,从而消除漏电流,降低休眠功耗。
打开该选项后,系统在进入休眠状态时会禁用所有 GPIO 管脚,以消除 GPIO 漏电对休眠功耗的影响,从而获得更低的休眠电流。但同时,该选项也导致了所有 GPIO 在休眠过程中将无法进行信号输入、输出以及内部上下拉配置。
启用该功能后,所有 GPIO 在休眠期间将无法进行信号输入、输出或内部上下拉配置。因此,对于在系统休眠过程中仍需使用 GPIO(如输入检测、输出控制或保持上下拉状态)的应用,ESP-IDF 提供了一组 API,即使启用了该选项,仍然可以在休眠期间对指定 GPIO 进行单独配置或恢复使用。相关接口如下:
设置休眠状态下的 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 调用:
gpio_hold_en(gpio_num_t gpio_num)
在系统唤醒后,再调用:
gpio_hold_dis(gpio_num_t gpio_num)
Flash 断电
ESP32 系列芯片通过外接 Flash 和 PSRAM 来增大系统存储器资源。Flash 具有掉电后数据不丢失特性,PSRAM 掉电后数据无法保持。
当系统中 没有使用到 PSRAM 时,可以使能 Flash 断电功能来降低芯片休眠电流,但该行为存在一定风险,具体说明及相关配置项请参考 Flash 断电。
CPU 断电
备注
该优化项在 ESP32, ESP32-C2 和 ESP32-S2 芯片上无法使用。
使能 CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP 可以在休眠模式下对 CPU 断电,以进一步降低休眠功耗。例如,对于 ESP32-C3,休眠电流可减少约 100 μA;对于 ESP32-S3,休眠电流可减少约 650 μA。
然而,断电会导致 CPU 的执行上下文(包括专用、通用以及状态寄存器等)丢失,若不处理,唤醒后 CPU 将无法正常执行。因此,系统将在断电前备份上下文信息,并在唤醒后从恢复该信息,这一步骤将消耗系统存储器资源,例如对于 ESP32-C3,将消耗 1.6 KB 的 DRAM 空间,对于 ESP32-S3,将消耗 8.58 KB 的 DRAM 空间。
外围设备下电
备注
该优化项仅适用于 ESP32-C6 及其后续系列芯片,包括 ESP32-C6, ESP32-H2, ESP32-C5(ECO3之后版本), ESP32-C61。
使能 CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP 后,数字外设将在 Light sleep 模式下尝试断电,可以将底电流降低约 100 μA。
需要注意的是,当外设电源域在睡眠期间断电时,IO_MUX 和 GPIO 模块都将处于下电状态,芯片引脚状态不再受这些模块控制。因此,如果希望在休眠期间保持 IO 状态,需要在配置 GPIO 状态前后调用 gpio_hold_dis() 和 gpio_hold_en(),以确保 IO 配置被锁存,防止 IO 在睡眠期间浮空。
此外,该配置项还存在较多限制,例如使能后无法使用 GPIO 和 UART 作为唤醒源,更多限制请参考 配置项说明,请根据实际应用谨慎使用。
Wi-Fi/低功耗蓝牙优化
乐鑫芯片为无线 MCU,因此大部分时候,低功耗功能都需配合 Wi-Fi/蓝牙功能一起使用。PHY 作为 Wi-Fi 与蓝牙通信的物理层,负责射频信号的收发。
下文将针对 Wi-Fi、BLE、PHY 相关的低功耗配置展开说明。
PHY 低功耗优化项
无线数字电路掉电
在使能 自动 Light sleep 后,可通过使能 CONFIG_ESP_PHY_MAC_BB_PD,让无线数字电路模块在关闭物理层时也相应掉电,大约能节省 100 μA 左右的底电流。
降低 TX power
使能 CONFIG_ESP_PHY_REDUCE_TX_POWER 后,当检测到系统电压不稳定或电源电压不足,ESP32 内置的电源管理模块自动触发复位时(欠压复位),将减小 PHY TX power,使代码能继续运行。
蓝牙低功耗优化项
BLE Modem sleep
使能 CONFIG_BTDM_CTRL_MODEM_SLEEP 后,在 BLE 保活阶段,即 BLE 保持连接但短时间内没有数据传输的状态时,系统会自动将 RF 模块进入 Modem Sleep 模式;一旦有数据需要发送或接收,射频模块会自动唤醒,从而在空闲期间实现低功耗且保证连接可靠性。
如果希望在保活时进入 Light sleep 而不是 Modem sleep,可参考 自动 Light sleep 的做法。
可以通过配置 BLE 使用的低功耗时钟源来优化功耗,在搭载了 外部 32 KHz 晶振 的情况下,推荐使用 32 kHz 晶振作为休眠时钟,以获得最低的 Light Sleep 底电流。
在 4.4 及之后的 IDF 版本里,蓝牙已支持用主晶振作为休眠时钟,不使用 32 kHz 晶振的代价是 Light sleep 时底电流会上升。参考电流:
ESP32-C3: 2.3 mA
ESP32-S3: 3.3 mA
Nimble – BLE only
在 BLE only 的场景下,启用 CONFIG_BT_NIMBLE_ENABLED 可以减少内存占用和协议栈处理开销,使 CPU 更易进入低功耗模式,从而降低整体功耗。
但需要注意,启用该配置项后,只能使用 NimBLE 协议栈 进行开发,无法使用 Bluedroid 协议栈。
广播/连接模式设置
BLE 的功耗可以通过调整广播、扫描和连接模式下的关键配置参数来优化。
在 广播模式 下,可以通过调整以下参数优化功耗:
广播间隔:增大广播间隔可以延长设备空闲时间,减少唤醒次数,从而降低平均功耗,但响应延迟将增加。其配置方法如下:
基于 Bluedroid 协议栈:配置
esp_ble_adv_params_t结构体时,增大.adv_int_min或.adv_int_max,以增大广播间隔;基于 Nimble 协议栈:配置
ble_gap_adv_params结构体时,增大.itvl_min或.itvl_max,以增大广播间隔。
广播包大小:广播包越小,每次的发射时间和电流消耗越小。广播数据包内含有的信息可参考 广播数据包结构。
基于 Bluedroid 协议栈:定义
esp_ble_adv_data_t结构体时,只保留必要字段,例如设备名称,去掉可选字段,例如制造商数据和服务数据;基于 Nimble 协议栈:定义
ble_hs_adv_fields结构体时,只保留必要字段,去掉可选字段。
发射功率:降低发射功率,减少每次发送广播包时的功耗,但覆盖范围会缩小。
调用
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, level)调整发射功率,对于不同芯片,level的取值可能有所不同,具体请参考对应芯片的 esp_bt.h 文件。
在 连接模式 下,可以通过调整以下参数优化功耗:
连接间隔:增大连接间隔可以延长设备空闲时间,减少唤醒次数,从而降低平均功耗,但响应延迟将增加。其配置方法如下:
基于 Bluedroid 协议栈:配置
esp_ble_conn_update_params_t结构体时,增大.interval,以增大连接间隔;基于 Nimble 协议栈:配置
ble_gap_upd_params结构体时,增大.itvl_min或.itvl_max,以增大连接间隔。
从机延迟:增大允许从机跳过的连接事件数量,可以延长休眠时间,进一步降低功耗。
基于 Bluedroid 协议栈:配置
esp_ble_conn_update_params_t结构体时,增大.latency,以增大从机延迟;基于 Nimble 协议栈:配置
ble_gap_upd_params结构体时,增大.latency,以增大从机延迟。
连接监督超时:当 BLE 连接在设置的连接监督超时时间内未收到对方响应时,将被判定为断开。合理设置超时时间可以避免因断线重连导致的额外唤醒和能量消耗。
基于 Bluedroid 协议栈:配置
esp_ble_conn_update_params_t结构体时,增大.timeout,以增大连接监督超时时间;基于 Nimble 协议栈:配置
ble_gap_upd_params结构体时,增大.supervision_timeout,以增大连接监督超时时间。
发射功率:降低发射功率,减少每次发送广播包时的功耗,但覆盖范围会缩小。
调用
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, level)调整发射功率,对于不同芯片,level的取值可能有所不同,具体请参考对应芯片的 esp_bt.h 文件。
在 扫描模式 下,可以通过调整以下参数优化功耗:
扫描窗口与扫描间隔:减小扫描窗口或扩大扫描间隔,将缩短射频部分的开启时间,以降低平均功耗;当扫描窗口和扫描间隔相等时,为连续扫描,功耗最高,但发现设备最快。
基于 Bluedroid 协议栈:配置
esp_ble_scan_params_t结构体时,增大.scan_interval或减小.scan_window,以降低平均功耗;基于 Nimble 协议栈:配置
ble_gap_disc_params结构体时,增大.itvl或减小.window,以降低平均功耗。
主动扫描/被动扫描:被动扫描模式仅接收广播包,功耗最低;主动扫描模式会发送 Scan Request 并接收 Scan Response,信息更完整,但功耗更高。在不需要获取完整广播数据时,优先使用被动扫描。
基于 Bluedroid 协议栈:通过
esp_ble_scan_params_t结构体中的.scan_type配置,设置为BLE_SCAN_TYPE_PASSIVE代表被动扫描,设置为BLE_SCAN_TYPE_ACTIVE代表主动扫描。基于 Nimble 协议栈:通过
ble_gap_disc_params结构体中的.passive配置,设置为 1 代表被动扫描,设置为 0 代表主动扫描。
扫描持续时间:通过应用层逻辑控制扫描的启停,避免长时间连续扫描,可显著降低平均功耗。
基于 Bluedroid 协议栈:可通过
esp_ble_gap_start_scanning(duration)设置扫描持续时间,也可将duration设置为 0,并在发现目标设备后调用esp_ble_gap_stop_scanning()立即停止扫描。基于 Nimble 协议栈:通过
ble_gap_disc()或ble_gap_ext_disc()的duration参数控制。
重复过滤:启用后,控制器会过滤重复的广播报告,减少 Host 侧处理和唤醒次数,间接降低系统功耗。
基于 Bluedroid 协议栈:通过
esp_ble_ext_scan_params_t结构体中的.scan_duplicate配置,具体可参考 扫描重复过滤说明。基于 Nimble 协议栈:通过
ble_gap_disc_params结构体中的.filter_duplicates配置,设置为 1 代表过滤重复广播,设置为 0 代表不过滤(每个广播都上报)。
扫描过滤策略:可设置为仅扫描指定设备,以减少无关广播带来的处理开销,适合已知目标设备地址的场景。
基于 Bluedroid 协议栈:通过
esp_ble_scan_params_t结构体中的.scan_filter_policy配置,具体可参考 过滤策略说明。基于 Nimble 协议栈:通过
ble_gap_disc_param结构体中的.filter_policy配置,设置为 0 代表使用默认策略。
扫描时 TX 功率影响说明:扫描本身主要是 RX 行为,TX 功率对功耗影响较小;仅在主动扫描发送 Scan Request 时才涉及发射功率。一般无需单独为扫描模式调整 TX 功率,除非对链路可靠性有特殊要求。
Wi-Fi 低功耗优化项
Wi-Fi 优化涉及的配置项较多,以下仅列出部分通用配置项,更多说明请参考 Wi-Fi 场景下低功耗模式介绍。
Wi-Fi Modem sleep
对于 Wi-Fi,该模式只能应用于 STA 模式,可调用 esp_err_t esp_wifi_set_ps(wifi_ps_type_t type) 开启或选择启用状态:
type = WIFI_PS_NONE,关闭 Modem sleep 模式,此时 RF 会一直处于打开状态。type = WIFI_PS_MIN_MODEM,芯片每隔一个 DTIM 会和路由器进行一次交互,交互结束后暂时关闭 RF,然后在下一个 DTIM 再醒来。type = WIFI_PS_MAX_MODEM,芯片每隔一个 listen interval 会和路由器进行一次交互,交互结束后暂时关闭 RF,然后在下一个 listen interval 醒来。
备注
DTIM 和 listen interval 的区别可参考 此处
在 ESP32 系列芯片中,Wi-Fi Modem sleep 模式是默认打开的,其默认值为 WIFI_PS_MIN_MODEM。
进一步说明请参考 Modem-sleep 模式配置。
更改最小等待时间和最大保活时间
最小等待时间
当 ESP32 作为 STA 和 AP 进行通信时,启用 Modem-sleep 后,STA 在接收完一次数据后不会立即关闭 RF,而是会保持一段最短活动时间,这段时间称为 Minimum active time,默认值为 50 ms。在保证每次数据吞吐量的基础上,可以通过调整 CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME 适当减少这个等待时间,从而降低功耗。
最大保活时间
当 ESP32 处于 power save 模式时,需要周期性地向 AP 发送一个 keep alive 包来告诉 AP 自己仍保持连接。Maximum keep alive time 即是发送这个 keep alive 包的时间周期,默认为 10 s。可以通过调整 CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME 增大该时间间隔以减少发包,从而降低功耗。
推荐配置
Minimum active time = 15~20
Maximum keep alive time = 60
开启断连电源管理
使能 CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE 后,即使 Wi-Fi STA 断开连接,Wi-Fi 模块仍可保持在 Modem-sleep 模式,从而降低断连期间的功耗。
开启 Beacon lost 优化
备注
该优化项仅适用于 ESP-IDF v4.4 及以上版本。
Wi-Fi 保活的一个基础是能够定时接收到路由器发送的 Beacon 包。在实际使用环境中,因各种原因会导致 Beacon 丢失。
在 release/v4.4 之前的版本中,丢失 Beacon 后 ESP32 会保持 RF 继续开启,直到接收到下一个 Beacon。
v4.4 以后的版本可通过使能 CONFIG_ESP_WIFI_SLP_Beacon_LOST_OPT 以开启 Beacon lost 优化,避免这一行为对功耗造成的影响。
如下图所示,优化原理是在丢失 Beacon 时不会一直开着 RF 接收,而是开一段时间没接收到就进入睡眠模式,然后再起来收包,重复几次后如果还没收到,才会和常规操作一样开着 RF 直到接收到位置。这样可大大提高未接收到 Beacon 时的容错率,从而减少功耗。
Beacon lost 优化示意图-1
Beacon lost 优化示意图-2
开启此选项后会引出额外配置项,主要需要关注:
CONFIG_ESP_WIFI_SLP_Beacon_LOST_TIMEOUT:表示等待多久没收到 Beacon 就进入休眠。
CONFIG_ESP_WIFI_SLP_Beacon_LOST_THRESHOLD:表示重复多少次没收到才持续开启,该选项不应设得过大,一般设为 3 个即可。
设置最大 Wi-Fi TX power
使能 CONFIG_ESP_PHY_MAX_WIFI_TX_POWER 后,可限制 Wi-Fi 的最大发射功率,从而降低发送过程中的瞬时电流和平均功耗;在信号条件良好的场景下,可有效减少能耗并提升系统稳定性,但会缩小通信距离并可能影响链路可靠性,应根据实际使用环境进行权衡配置。
在代码中,可通过调用 esp_wifi_set_max_tx_power() 进行设置。
优化 Wi-Fi 执行速度
将部分 Wi-Fi 相关内容放入 IRAM 中,可以提升 Wi-Fi 执行速度。此操作可以缩短 RF 和 CPU 的活跃时间,使系统能够更早进入 Modem sleep 或 Light sleep 模式,从而降低整体平均功耗。
相关配置项如下:
CONFIG_ESP_WIFI_IRAM_OPT:将 Wi-Fi 库中频繁调用的函数放入 IRAM 中执行。
CONFIG_ESP_WIFI_EXTRA_IRAM_OPT:将额外一部分频繁调用的 Wi-Fi 库函数放入 IRAM 中执行。
CONFIG_ESP_WIFI_SLP_IRAM_OPT:将 Wi-Fi 库中与 TBTT 处理(目标 Beacon 发送时间)及接收 Beacon 相关的函数放入 IRAM 中执行。请注意,该选项和前两项存在部分功能重叠。
CONFIG_ESP_WIFI_RX_IRAM_OPT:将 Wi-Fi 库中频繁调用的接收(RX)相关函数 放入 IRAM 中执行。
Wi-Fi 物理层收包
备注
该优化项仅适用于 ESP32-C6, ESP32-C5, ESP32-C61 芯片。且目前该功能无法与 外围设备下电 同时使用。
使能 CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP 后,在 Light sleep 期间,PHY 层自动收包,Wi-Fi 接收 Beacon 不再需要 CPU 参与,只有 Wi-Fi MAC + Baseband + RF 工作,以节省功耗。
为了更直观地展示各模块在不同模式下的工作状态,可通过 不同 mode 下接收发射波形图 观察 CPU、MAC、Baseband 和 RF 的活动差异。
补充内容
DTIM 和 listen interval 的区别
当芯片作为 STA 和路由器建立连接的时候,会被告知路由器的 DTIM,即每隔多少时间路由器会发送一个 beacon,STA 需要在这个时间起来接收 beacon,查看是否有需要自己处理的信息。
而 listen interval 则是 STA 告诉路由,我需要隔多少时间起来接受 beacon,即前者是根据路由端来定的,后者是可以自己配置到芯片里的。时间间隔为 DTIM 或者 listen interval 的值 * 100 MS,如果当 DTIM=10,即每次唤醒的时间间隔为 10 * 100 ms = 1 s。
外部 32 KHz 晶振
使用外部 32 KHz 晶振可以获得更低的功耗。主要有以下几个原因:
内部的晶振容易受到干扰,相比之下外接晶振的精度更高,并可以在各种睡眠情况下使用。
对于时间精度要求比较高的应用,如蓝牙和 Wi-Fi 的保活,需要定时起来接受 Beacon,一旦时钟漂移过大,错过了接收的点,会导致打开 RF 等待的窗口期变长,从而大大增加功耗。
外部晶振有两种:
External 32kHz crystal: 为外部无源晶振,也是大部分时候推荐的晶振
External 32kHz oscillator at 32K_XP pin: 为外部有源晶振,价格更贵,同时会造成底电流上升 50 ~ 100 μA
使能外部时钟源需要如下配置:
使能外部晶振
配置项名称:
ESP32C3_RTC_CLK_SRC_EXT_CRYS配置路径:
(Top) → Component config → ESP32XX-Specific → RTC clock source
备注
ESP32-C2 内部没有无源晶振的起振电路,只支持外部有源晶振;晶振的布局可以参考各芯片对应的硬件设计指南。
不同 mode 下接收发射波形图
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 信道相关。