ESP32 低功耗方案

标签: LowerPower


概要:

ESP32 系列芯片提供三种可配置的睡眠模式,针对这些睡眠模式,我们提供了了多种低功耗解决方案,用户可以结合具体需求选择睡眠模式并进行配置。三种睡眠模式如下:

三种模式的区别如下: 三种模式的区别


Modem-sleep 模式

目前 ESP32 的 Modem-sleep 仅工作在 Station 模式下,连接路由器后生效。Station 会周期性在工作状态和睡眠状态两者之间切换。 ESP32 通过 Wi-Fi 的 DTIM Beacon 机制与路由器保持连接。在 Modem-sleep 模式下,系统可以自动被唤醒,无需配置唤醒源。

一般路由器的 DTIM Beacon 间隔为 100 ms ~ 1,000 ms。

DTIM (Delivery Traffic Indication Message): 使用无线路由器时无线发送数据包的频率。

在 Modem-sleep 模式下,ESP32 会在两次 DTIM Beacon 间隔时间内,关闭 Wi-Fi 模块电路,达到省电效果,在下次 Beacon 到来前自动唤醒。睡眠时间由路由器的 DTIM Beacon 时间决定。Modem-sleep 模式可以保持与路由器的 Wi-Fi 连接,并通过路由器接收来自手机或者服务器的交互信息。

API 说明

通过以下接口配置 Modem-sleep 模式,type 可选参数:

  1. type 参数为 WIFI_PS_MAX_MODEM ,ESP32 接收 Beacon 的间隔 listen_interval 配置方法:

应用

Modem-sleep 一般用于 CPU 持续处于工作状态并需要保持 Wi-Fi 连接的应用场景,例如,使用 ESP32 本地语音唤醒功能,CPU 需要持续采集和处理音频数据。


Light-sleep 模式

Light-sleep 的工作模式与 Modem-sleep 相似,不同的是,除了关闭 Wi-Fi 模块电路以外,在 Light-sleep 模式下,还会关闭时钟并暂停内部 CPU,比 Modem-sleep 功耗更低。有两种方式使 CPU 进入 Light-sleep 模式:

强制 Light-sleep

参考示例: light_sleep

开发者可以使系统强制进入 Light-sleep 模式,即调用强制 Light-sleep 接口,强制关闭 Wi-Fi 模块电路并暂停内部 CPU。强制休眠后,能通过定时器、 GPIO(RTC IO 和 Digital IO)和 UART 唤醒。从 Light-sleep 唤醒后,会从进入休眠的位置继续执行程序。强制进入 Light-sleep 模式后,可以保持与路由器的 Wi-Fi 连接,但不能通过路由器接收来自手机或者服务器的交互信息。

注意:

  1. 强制 Light-sleep 接口调用后,并不会立即休眠,而是等到系统空闲后才进入休眠,
  1. 强制进入 Light-sleep 模式后,不能接收 IP 网络发送的网络数据。

API 说明

  1. 配置唤醒源后,可使用 esp_light_sleep_start() 函数进入 Light-sleep 模式。在没有配置唤醒源的情况下也可以进入轻度睡眠状态,在这种情况下,芯片将无限期地处于 Light-sleep 模式,直到外部复位。

应用

强制 Light-sleep 模式可用于需要保持与路由器的连接,不需要实时响应路由器发来的数据的场景。

自动 Light-sleep

参考示例: power_save

开发者可配置系统在空闲时自动进入 Light-sleep 模式,并能在需要 CPU 工作时自动唤醒,无需配置唤醒源。在配置为自动 Light-sleep 后,可以保持与路由器的 Wi-Fi 连接,并通过路由器接收来自手机或者服务器的交互信息,对用户体验没有影响。 通常自动 Light-sleep 会与 Modem-sleep 模式 以及电源管理功能共同使用,电源管理功能允许系统根据 CPU 负载动态调节 CPU 频率以降低功耗。

若系统应用中有小于 DTIM Beacon 间隔时间的循环定时,系统将不能进入 Light-sleep 模式。

此处输入图片的描述

API 说明

  1. 通过 esp_err_t esp_pm_configure(const void* vconfig) 接口配置电源管理功能,参数 light_sleep_enable 为 true 时使能自动休眠功能。

使能 自动 Light-sleep 功能,需要使能 CONFIG_FREERTOS_USE_TICKLESS_IDLECONFIG_PM_ENABLE

应用

自动 Light-sleep 模式可用于需要保持与路由器的连接,可以实时响应路由器发来的数据的场景。并且在未接收到命令时,CPU 可以处于空闲状态。比如 Wi-Fi 开关的应用,大部分时间 CPU 都是空闲的,直到收到控制命令,CPU 才需要进行 GPIO 的操作。


Deep-sleep 模式

参考示例: deep_sleep

相对于其他两种模式,系统无法自动进入 Deep-sleep,需要由用户调用接口函数 esp_deep_sleep_start() 进入 Deep-sleep 模式。在该模式下,芯片会断开所有 Wi-Fi 连接与数据连接,进入 Deep-sleep 模式,只有 RTC 存储器和 RTC 外设以及 ULP 协处理器可以工作。从 Deep-sleep 唤醒后,CPU 将软件复位重启。

API 说明

  1. 配置唤醒源后,可使用 esp_deep_sleep_start() 函数进入 Deep-sleep 模式。在没有配置唤醒源的情况下也可以进入 Deep-sleep 状态,在这种情况下,芯片将无限期地处于 Deep-sleep 模式,直到外部复位。

应用

Deep-sleep 可以用于低功耗的传感器应用,或者大部分时间都不需要进行数据传输的情况。设备可以每隔一段时间从 Deep-sleep 状态醒来测量数据并上传,之后继续进入 Deep-sleep。也可以将多个数据存储于 RTC memory(RTC memory 在 Deep-sleep 模式下仍然可以保存数据),然后一次发送出去。


唤醒方式

针对 强制 Lighe-sleepDeep-sleep 需要配置唤醒源的情况,有以下唤醒方式可以选择:

部分唤醒方式仅支持 Light-sleep

GPIO

  1. External wakeup (ext0)

    RTC IO 模块包含当其中 一个 RTC IO 的电平为唤醒电平(可配置为逻辑高或低)触发唤醒的逻辑。

    RTC IO 是 RTC 外设电源域的一部分,因此如果使能该唤醒源,RTC 外设将在睡眠期间保持上电状态。在 ESP32 的修订版 0 和 1 中,此唤醒源与 ULP 和触摸唤醒源不兼容。

    由于在此模式下启用了 RTC IO 模块,因此也可以使用内部上拉或下拉电阻。

    esp_sleep_enable_ext0_wakeup() 函数可用于启用此唤醒源。

  2. External wakeup (ext1)

    RTC 控制器包含使用 多个 RTC IO 触发唤醒的逻辑。两个逻辑功能之一可用于触发唤醒:

    • 如果任何一个所选 IO 为高电平,则唤醒(ESP_EXT1_WAKEUP_ANY_HIGH
    • 如果所有选定的 IO 都为低电平,则唤醒(ESP_EXT1_WAKEUP_ALL_LOW

    该唤醒源由 RTC 控制器实现。因此,RTC 外设和 RTC 存储器可以在此模式下断电。

    但是,如果 RTC 外设断电,内部上拉和下拉电阻将被禁用。要使用内部上拉或下拉电阻,请在睡眠期间请求 RTC 外设电源域保持上电。

    esp_sleep_enable_ext1_wakeup() 函数可用于启用此唤醒源。

  3. Touch pad wakeup

    RTC IO 模块包含触摸传感器中断时触发唤醒的逻辑。您需要在芯片开始睡眠之前配置触摸传感器中断。

    当 RTC 外设未被强制上电时,ESP32 的修订版 0 和 1 仅支持此唤醒模式。

    esp_sleep_enable_touchpad_wakeup() 函数可用于启用此唤醒源。

  4. GPIO wakeup (light sleep only)

    除了上面描述的 EXT0 和 EXT1 唤醒源之外,在 Light-sleep 模式下还有一种从外部输入唤醒的方法。通过该唤醒源,每个引脚可以使用 gpio_wakeup_enable() 函数单独配置为高电平或低电平唤醒。与 EXT0 和 EXT1 唤醒源(只能与 RTC IO 一起使用)不同,此唤醒源可用于任何 IO(RTC 或数字)。

    esp_sleep_enable_gpio_wakeup() 函数可用于启用此唤醒源。

ULP coprocessor wakeup

参考示例: system/ulp

ULP 协处理器可以在芯片处于睡眠模式时运行,并且可以用于轮询传感器,监视 ADC 或触摸传感器值,并在检测到特定事件时唤醒芯片。ULP 协处理器是 RTC 外设电源域的一部分,它运行存储在 RTC 慢速存储器中的程序。如果请求此唤醒模式,RTC 慢速存储器将在睡眠期间启动。在 ULP 协处理器开始运行程序之前,RTC 外设将自动上电; 程序停止运行后,RTC 外设将再次自动关闭。

当 RTC 外设未被强制上电时,ESP32 的修订版 0 和 1 仅支持此唤醒模式。

esp_sleep_enable_ulp_wakeup() 函数可用于启用此唤醒源。

Timer

RTC 控制器具有内置定时器,可用于在预定义的时间后唤醒芯片。时间以微秒精度指定,但实际分辨率取决于为 RTC SLOW_CLK 选择的时钟源。

此唤醒模式不需要在睡眠期间打开 RTC 外设或 RTC 存储器。

esp_sleep_enable_timer_wakeup() 函数可用于启用此唤醒源。

UART wakeup (light sleep only)

仅支持 Light-sleep 模式。当 ESP32 从外部设备接收 UART 输入时,通常需要在输入数据可用时唤醒芯片。UART 外设包含一项功能,当看到 RX 引脚上的一定数量的上升沿时,可以将芯片从 Light-sleep 状态唤醒。可以使用 uart_set_wakeup_threshold() 函数设置此上升沿数。请注意,唤醒后 UART 不会接收触发唤醒的字符(及其前面的任何字符)。这意味着外部设备通常需要在发送数据之前向 ESP32 发送额外字符以触发唤醒。

esp_sleep_enable_uart_wakeup() 函数可用于启用此唤醒源。

GPIO Hold 功能

每个 IO pad(包括 RTC pad)都有单独的 hold 功能,由 RTC 寄存器控制。pad 的 hold 功能被置上后,pad 在置上 hold 那一刻的状态被强制保持,无论内部信号如何变化,修改 IO_MUX 配置或者 GPIO 配置,都不会改变 pad 的状态。应用如果希望在看门狗超时触发内核复位和系统复位时或者 Deep-sleep 时 pad 的状态不被改变,就需要提前把 hold 置上。

在 Deep-sleep 模式下使用 Hold 功能,可能会增加功耗。并且如果使用内部上拉或下拉电阻,需要在睡眠期间使 RTC 外设电源域保持上电。

针对 RTC IO,可对单个 RTC Pad 使能 Hold 功能:

针对 数字 IO,会对所有 数字 IO 使能 Hold 功能:

常见问题

  1. 进入 Deep-sleep 后,功耗较高

    有这些原因可能会导致功耗较高:

  1. 使能 自动 Light-sleep 后,功耗较高

    • 存在任务持续运行占用 CPU 资源,导致 CPU 负载过大无法休眠。若是这种情况,请检测是否存在 任务 持续运行,并优化当前应用程序流程使 CPU 能周期性空闲进入 Light-sleep 模式。
    • 若系统应用中有小于 DTIM Beacon 间隔时间的循环定时,系统将不能进入 Light-sleep 模式。
    • 若未使用最新 IDF 3.2 版本,可能会因为某些外设使用(例如:I2C、I2S),导致无法自动进入 Light-sleep 模式。若是这个问题,请更新到最新的 IDF 3.2 版本。
    • 若系统不需要 FreeRTOS 时钟配置为 1000 Hz,可将 FreeRTOS 时钟降低为 100 Hz,可显著降低功耗。
  2. 自动 Light-sleep 调试方法

    • 在 menuconfig 中使能 CONFIG_PM_PROFILING ,如果使能,esp_pm_* 函数将跟踪每个电源管理锁的保留时间,esp_pm_dump_locks 函数将打印此信息。 此功能可用于分析哪些锁阻止芯片进入低功耗状态,并查看芯片在每种省电模式下花费的时间,并应在应用程序中保持禁用状态。
    • 在 menuconfig 中使能 CONFIG_PM_TRACE,如果使能,某些 GPIO 将用于发出 RTOS 滴答,频率切换,进入/退出空闲状态等事件的信号。有关 GPIO 列表,请参阅 pm_trace.c 文件。 此功能旨在用于分析/调试电源管理实现的行为时使用,并应在应用程序中保持禁用状态。

不同功耗模式下的功耗

不同功耗模式下的功耗