能压到2.5–5 μA,但必须关掉所有“偷偷耗电”的东西,否则实测电流可能高10倍以上;esp_deep_sleep_start()不是终点而是起点,需显式禁用全部唤醒源、彻底关闭Wi-Fi/蓝牙、锁定RTC_GPIO电平、使用RTC_DATA_ATTR保存变量,并确保外围电路无漏电。

直接结论:能压到 2.5–5 μA,但必须关掉所有“偷偷耗电”的东西,否则实测电流可能高 10 倍以上。
esp_deep_sleep_start() 不是终点,而是起点
调用 esp_deep_sleep_start() 后芯片确实会断电大部分模块,但唤醒源、RTC 内存、外部电路是否干净,决定了你最终看到的是 5 μA 还是 50 μA。它不是“一键省电”,而是一次系统级断电操作——CPU 停、Wi-Fi 射频关、主内存失电、晶振停振,只剩 RTC 控制器和一小块 RTC_SLOW_MEM 在呼吸。
- 每次唤醒都等同于冷启动,
setup()重新执行,loop()不会被运行 - 所有非 RTC 内存变量(比如普通
int counter)都会丢失,必须用RTC_DATA_ATTR标记需保留的变量 - 如果你没禁用其他唤醒源,设备可能刚睡下去就被 GPIO 毛刺或触摸噪声吵醒,反复重启反而更耗电
唤醒源配置必须显式控制
默认没有任何唤醒源启用,必须手动打开且只留你需要的那个。常见误操作是漏掉 esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL),导致多个源同时生效,或者忘记关闭 Wi-Fi/蓝牙残留电源域。
- 定时唤醒:
esp_sleep_enable_timer_wakeup(60 * 1000000)(单位是微秒,60 秒 = 60,000,000 μs) - GPIO 唤醒(仅限 RTC_GPIO 引脚,如 GPIO13/GPIO14):
gpio_wakeup_enable(GPIO_NUM_13, GPIO_INTR_LOW_LEVEL)+esp_sleep_enable_gpio_wakeup() - 务必在配置前先清空所有源:
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL),避免历史配置干扰 - 实测发现:未禁用全部唤醒源时,即使没接外部信号,某些开发板上的浮空引脚也会引发意外唤醒
外设与电源路径是功耗黑洞
芯片本身可做到 5 μA,但整机实测常达 20–100 μA,问题几乎全出在外围——LED、LDO、传感器、浮空 IO、未切断的屏幕供电。
立即学习“C++免费学习笔记(深入)”;
- 关闭 Wi-Fi/蓝牙射频不是靠
WiFi.disconnect()就完事,要彻底停底层:esp_wifi_stop()+btStop()+esp_bt_controller_deinit() - 所有非 RTC_GPIO 的输出引脚,在进深睡前应设为
INPUT或明确拉低/拉高,避免浮空驱动外部电路 - 若用 GPIO 直接给外设(如墨水屏)供电,必须调用
gpio_hold_en()+gpio_deep_sleep_hold_en()锁住电平,否则深睡时 IO 状态丢失会导致外设异常耗电 - 检查 LDO 是否支持关断模式;有些 AMS1117 类 LDO 静态电流就达 5–10 μA,换成 TPS63031 等低 IQ DC-DC 更稳妥
RTC 内存和状态恢复要小心“失忆”
深度睡眠后程序从头跑,但你可以靠 RTC 内存记住上次做了什么。不过这块内存极小(约 8 KB),且分 FAST/SLOW 两块,只有 SLOW 支持深睡保留。
- 声明变量必须加
RTC_DATA_ATTR:RTC_DATA_ATTR static uint32_t boot_count = 0; - 别在 RTC 内存里放指针或复杂结构体,只存基础类型或扁平化数据
- 用
esp_sleep_get_wakeup_cause()判断唤醒原因(ESP_SLEEP_WAKEUP_TIMER/ESP_SLEEP_WAKEUP_GPIO),决定后续逻辑分支 - 时间同步不能依赖
time(NULL)醒来就用——RTC 时钟可能漂移或未校准,首次唤醒建议强制 NTP 同步再写回 RTC
真正难的不是让 ESP32 睡着,而是让它睡得安稳、醒得精准、醒来不乱套。那些多出来的几十微安,往往藏在一行没写的 gpio_deep_sleep_hold_en() 里,或一个没断开的 LED 限流电阻上。


















