
WLED Deep Sleep usermod 详解让 ESP32 在关灯后进入深度睡眠的 GPIO 唤醒、定时唤醒与功耗实践【免费下载链接】WLEDControl WS2812B and many more types of digital RGB LEDs with an ESP32 over WiFi!项目地址: https://gitcode.com/GitHub_Trending/wl/WLED本文围绕 WLED 仓库中的 Deep Sleep usermodusermods/deep_sleep/readme.md展开当你通过 UI 电源按钮或宏关闭 LED 后ESP32 会进入深度睡眠Deep Sleep功耗降至微安级唯一唤醒途径是外部信号、按键或预设定时器唤醒后设备会重启因此必须配合开机预设使用。读完后你将掌握该 usermod 的完整安装配置方法、可用的唤醒 GPIO 清单、#define编译参数的含义以及从 源码实现 中看到的进入睡眠、定时器唤醒、触摸唤醒与防变砖安全机制的完整链路。工作原理关灯即关机唤醒即重启Deep Sleep usermod 利用的是 ESP 芯片的最低功耗模式。当 LED 被关掉UI 电源按钮或宏触发后usermod 会将 ESP 放入深度睡眠深度睡眠期间 ESP 完全关闭无 WiFi、无 CPU、无任何输出唤醒方式只有三种外部 GPIO 信号按键/传感器、自动化定时器Wake after秒数或预设到点前唤醒、以及 C3 以外的芯片支持的触摸唤醒从深度睡眠醒来后 ESP 会重新启动整个系统所以必须在 WLED 中配置一个开机预设boot-up preset否则醒来后灯光状态不可控。它监听的核心状态是 WLED 全局的offMode标志——在 wled00/wled.h 中声明为WLED_GLOBAL bool offMode _INIT(!turnOnAtBoot);即LED 已关闭状态。只要offMode为真且满足延迟条件usermod 就执行休眠流程。重要警告配置错误可能导致无法唤醒原文档特别强调了一条高风险组合如果同时关闭 WLED 的 Turn LEDs on after power up/reset上电开启 LED选项并且将DelaySleep设为 0则 ESP 在上电后会直接进入深度睡眠只有在被唤醒后 WLED 才会启动。 若 ESP 因配置错误无法从深度睡眠中被唤醒只能通过**恢复出厂设置factory reset**来禁用上电即睡眠没有其他唤醒办法。源码 中为此设计了保护逻辑powerup标志存于RTC_DATA_ATTR即 RTC 数据区重启后依然保留标记上一次是断电重启配合delaycounter默认 10给予约 10 秒窗口让用户在 UI 里手动开灯如果设备在sleepDelay0、无开机预设、turnOnAtBootfalse的组合下依然处于关灯状态源码会在delaycounter1时强制点亮亮度最低设为 10 并应用预设 0含继电器输出避免设备变砖。深度睡眠功耗5µA–20µA 的芯片基础 板级寄生功耗原文档给出了各芯片深度睡眠下的静态电流参考值单位微安芯片深度睡眠电流ESP3210 µAESP32 S38 µAESP32 S220 µAESP32 C35 µAESP826620 µA本 usermod 不支持但实际板子的功耗远高于芯片本身原文档列出了三个主要来源电源指示灯Power LED常见 ESP 板载的电源 LED 消耗 500 µA – 1 mA是深睡功耗的最大来源之一LDO 稳压芯片线性稳压器自身有静态电流从约 50 µA 到 10 mA 不等如 LM1117 高达 10 mA 级别也存在超低静态电流的专用低功耗 LDO灯带本身WS2812 类数码 LED 即使熄灭每条灯珠仍有约 1 mA 的电流。要真正利用本 usermod必须用 MOSFET 或继电器给灯带断电。原文档给出的实测参考在移除电源 LED无其他改动的 ESP32-C3 Supermini 上经 5V 引脚供电深度睡眠电流实测50 µA。因此最低功耗的操作建议是移除电源 LED、避免使用 LM1117 级别的 LDO、灯带用电控开关切断。可用的唤醒 GPIO仅限 RTC 单元引脚并非所有 GPIO 都能用作深度睡眠唤醒脚只有连接到内部 RTC 单元的引脚才行。原文档与 源码中的pin_is_valid()给出的清单一致ESP32GPIO 0、2、4、12–15、25–39。注意输入专用脚 34–39没有内部上拉/下拉电阻必须外接电阻ESP32 S3GPIO 0–21ESP32 S2GPIO 0–21ESP32 C3GPIO 0–5ESP8266不支持。一个实用的点是所选唤醒引脚在 WLED 正常运行时可以照常当普通引脚使用比如按钮脚只有当 LED 被关闭、即将入睡时它才被配置为唤醒脚。源码印证了这一点——loop()中只有在offMode为真、延迟到期后才执行rtc_gpio_init()/rtc_gpio_set_direction(RTC_GPIO_MODE_INPUT_ONLY)等 RTC 引脚接管操作其余时间该引脚归 WLED 主程序支配。安装platformio.ini 加入 custom_usermods按照原文档安装方式是把deep_sleep加进 platformio.ini 的custom_usermods中custom_usermods deep_sleep各构建环境在 platformio.ini 中均有独立的custom_usermods变量例如esp32、esp32c3、esp32s3等需要加在你要烧录的那个 env下也可以参考usermods/usermods/...中的*通配写法一次性引入全部 usermod仅适用于实验性 env。usermod 的元数据声明在 usermods/deep_sleep/library.jsonname: deep_sleeplibArchive: false并已在 wled00/const.h 注册了唯一 ID#define USERMOD_ID_DEEP_SLEEP 55对应源码中getId()返回USERMOD_ID_DEEP_SLEEP用于系统识别该 usermod 是否安装。配置入口在 WLED 的 usermod 设置页settings → usermods → DeepSleep页面控件由源码的appendConfigData()动态生成GPIO 下拉框只列出pin_is_valid()通过的引脚wakeWhen下拉框提供 Low/High 两个选项触摸唤醒的通道下拉框则遍历SOC_TOUCH_SENSOR_NUM并过滤掉无 IO 映射的通道。配置参数详解UI 参数与#define编译参数原参数体系2024-10 起从纯#define迁移到 UI 配置包含以下可设置项UI 中的值可以覆盖编译期默认值1. GPIO唤醒引脚对应DEEPSLEEP_WAKEUPPIN默认 0。选择上面可用 GPIO清单中的引脚该引脚平时可继续作为 WLED 按钮等用途。2. WakeWhen High/Low唤醒电平对应DEEPSLEEP_WAKEWHENHIGH默认 0即低电平触发。定义为 1 时引脚拉高唤醒为 0 时引脚拉低唤醒。源码中该参数直接决定使用ESP_EXT1_WAKEUP_ANY_HIGH/ESP_EXT1_WAKEUP_ALL_LOWESP32/S2/S3或ESP_GPIO_WAKEUP_GPIO_HIGH/LOWC3。3. Pull-up/down disable睡眠期间禁用内部上下拉对应DEEPSLEEP_DISABLEPULL源码默认值为 1即默认禁用内部上下拉电阻。只影响睡眠状态不影响正常运行。C3 上该项的实现有特殊之处C3 调用esp_deep_sleep_enable_gpio_wakeup()会自动使能上下拉因此源码额外用gpio_hold_en()覆写该行为。4. Wake after定时自动唤醒秒对应DEEPSLEEP_WAKEUPINTERVAL默认 0 永不。设为大于 0 的秒数后ESP 将在该时长后自动唤醒文档提示定时器精度约 2%期间按键仍可提前唤醒。此模式下**Turn LEDs on after power up/reset 被覆盖**——醒来后灯一定会点亮。5. Delay sleep关灯到入睡的延迟秒对应DEEPSLEEP_DELAY默认 1 秒。设为大于 0 后关灯不会立即入睡而是等待该时长等待期间如果重新开灯计时器复位。设为 0 则关灯即刻入睡配合上电不开灯选项时请注意前文的变砖警告UI 提示文字为 seconds (0 sleep at powerup)。6. 触摸唤醒与预设唤醒源码可见的扩展项除了原文档列出的五个参数源码配置接口 还持久化了另外两组字段C3 不支持触摸唤醒编译期排除enableTouchWakeuptouchPin启用触摸唤醒对应编译参数DEEPSLEEP_WAKEUP_TOUCH_PIN默认 1。源码调用touchSleepWakeUpEnable()并且区分了芯片差异——S2/S3 的 Touch V2 阈值量级更高阈值按touchThreshold 4传递低阈值 高灵敏度而经典 ESP32 直接使用touchThreshold高阈值 高灵敏度。这与 wled00/cfg.cpp 中按钮触摸中断的注释Touch V2 阈值 1500 为官方示例值相互印证。presetWake开启后入睡时 usermod 会调用findNextTimerInterval()扫描 WLED 的预设定时器timers计算距下一个有效预设到点的最短分钟差并提前 1 分钟唤醒wakeupAfterSec (nextInterval - 1) * 60同时把该预设号存入wakeupPreset若用户设定的Wake after更短则取更短者。唤醒原因若不是ESP_SLEEP_WAKEUP_TIMERsetup()会把wakeupPreset清零即只有定时器唤醒才会自动应用预设若定时器唤醒后错过了到点时刻loop()中也会在开机后补应用该预设applyPreset(wakeupPreset)保证宏按时生效。注意findNextTimerInterval()依赖本地时间已同步toki.getTimeSource() ! TOKI_TS_NONE时间未同步时跳过定时器检查仅按键/秒数计时器可用。#define覆盖默认值原文档说明若要覆盖默认值把#define放进wled.h或加入platformio_override.ini的 build flags。完整参数对照宏作用默认DEEPSLEEP_WAKEUPPIN x唤醒引脚须在上表可用清单内平时可当普通按钮脚0DEEPSLEEP_WAKEWHENHIGH定义为 1 时高电平唤醒0低电平唤醒DEEPSLEEP_DISABLEPULL定义为 1 时深睡期间禁用内部上下拉1DEEPSLEEP_WAKEUPINTERVAL自动唤醒秒数0 永不精度约 2%0DEEPSLEEP_DELAY关灯到入睡的延迟秒数1DEEPSLEEP_WAKEUP_TOUCH_PIN触摸唤醒使用的 GPIO1原文档给出的 env build flags 示例安装 usermod 与设置默认值build_flags -D USERMOD_DEEP_SLEEP -D DEEPSLEEP_WAKEUPPIN4 -D DEEPSLEEP_DISABLEPULL0 ;enable pull-up/down resistors by default -D DEEPSLEEP_WAKEUPINTERVAL43200 ;wake up after 12 hours (or when button is pressed)硬件接线外部触发信号是必须项原文档的硬件要点从深度睡眠唤醒必须在配置的 GPIO 上有外部触发信号或依靠定时/触摸唤醒若只用定时唤醒请选用板载已有上拉电阻的 GPIO多数板子上是 GPIO0使用机械按键时强烈建议外接上拉电阻——并非所有芯片的所有 IO 内部电阻都工作正常除按键外PIR 人体感应、红外、触摸等任何带数字输出的传感器都可以作为触发源。从源码看按键方案的标准接法是按键一端接唤醒 GPIO、另一端接地配合上拉电阻内部或外部。因为默认wakeWhenHigh0低电平唤醒按下按键把引脚拉低即触发ESP_EXT1_WAKEUP_ALL_LOW唤醒条件。若希望松开按键唤醒则接法与电平定义相应调换并设置DEEPSLEEP_WAKEWHENHIGH。源码纵览从关灯到esp_deep_sleep_start()的完整链路deep_sleep.cpp 约 350 行实现了DeepSleepUsermod : public Usermodusermod v2 接口。核心流程在loop()中可以拆解为四个阶段1. 灯亮状态!offMode复位延迟计时器lastLoopTime 0递减启动保护计数器delaycounter并在唤醒场景下补应用wakeupPreset。这就是Delay sleep 期间重新开灯会重置计时的实现。2. 关灯且未到延迟时限记录millis()基准millis() - lastLoopTime sleepDelay * 1000期间直接返回sleepDelay为 0 时则走powerup delaycounter分支用delay(1000)循环给用户约 10 秒的 UI 操作窗口。3. 安全强制点亮若powerup false但delaycounter仍在递减且递减到 1 时仍为offMode则强制开灯——设bri10防止 0 亮度被自动关闭、应用预设 0失败回退 static 效果、继电器引脚同步驱动。这是防变砖的最后防线。4. 真正入睡源码 L174–L243顺序为powerup false; // 此后每次重启都强制开灯 if (!pin_is_valid(wakeupPin)) return; // 引脚非法则放弃睡眠 pinMode(wakeupPin, INPUT); esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); // 计算唤醒秒数presetWake 定时器差 vs Wake after取较小者 if (wakeupAfterSec 0) esp_sleep_enable_timer_wakeup(wakeupAfterSec * (uint64_t)1e6); #if defined(CONFIG_IDF_TARGET_ESP32C3) gpio_hold_dis / esp_deep_sleep_enable_gpio_wakeup / gpio_pullup_dis... gpio_hold_en((gpio_num_t)wakeupPin); // 覆写 C3 自动上下拉 #else rtc_gpio_hold_dis / rtc_gpio_init / rtc_gpio_set_direction(INPUT_ONLY); rtc_gpio_pullup_dis / rtc_gpio_pulldown_dis; // 默认禁内部上下拉 if (!noPull) { ...按 wakeWhenHigh 选 enable pulldown/pullup... } esp_sleep_enable_ext1_wakeup(1ULL wakeupPin, wakeWhenHigh ? ESP_EXT1_WAKEUP_ANY_HIGH : ESP_EXT1_WAKEUP_ALL_LOW); if (enableTouchWakeup) touchSleepWakeUpEnable(...); // 与 ext1 共存故不用 ext0 delay(1); rtc_gpio_hold_en((gpio_num_t)wakeupPin); // 锁存引脚状态 #endif WiFi.mode(WIFI_OFF); // 彻底关闭 WiFi if (halerror ESP_OK) esp_deep_sleep_start();几个值得注意的实现细节为什么用 ext1 而不用 ext0源码注释明确说明 use ext1 as ext0 does not work with touch wakeup——esp_sleep_enable_ext0_wakeup()与触摸唤醒互斥所以 ESP32/S2/S3 统一走esp_sleep_enable_ext1_wakeup()这样 GPIO 唤醒与触摸唤醒可以共存RTC_DATA_ATTR持久化powerup与wakeupPreset两个变量存放在 RTC 数据区注释指出variable in RTC data persists on a reboot这是深睡重启后仍知道上次是否断电启动该应用哪个预设的关键拉锁策略入睡前先把引脚交给 RTC 域配置方向与上下拉最后hold_en锁存电平确保睡眠期间引脚状态稳定减少漏电流与误唤醒唤醒原因检查setup()里读esp_sleep_get_wakeup_cause()非ESP_SLEEP_WAKEUP_TIMER唤醒即按键/触摸唤醒就把wakeupPreset清零只有定时器唤醒才自动应用预设。已知限制原文档在 Limitations 一节坦承为了保持简单易用这是一个对 ESP 低功耗能力的基础实现没有更复杂的控制如部分唤醒、UPT 独立供电等高级特性。作者欢迎有需要的用户以此为基座自行实现增强版本——从源码看其结构usermod v2 标准接口setup/loop/addToConfig/readFromConfig/appendConfigData也确实适合作为二次开发模板。变更日志2024-09初始版本2024-10从#define编译配置改为 UI 配置编译宏仅用于设默认值。按原文档结语现在可以去省点电了now go on and save some power——配置好唤醒脚、开机预设与灯带断电开关Deep Sleep usermod 就能让常亮的灯带在非工作时真正进入微安级待机。【免费下载链接】WLEDControl WS2812B and many more types of digital RGB LEDs with an ESP32 over WiFi!项目地址: https://gitcode.com/GitHub_Trending/wl/WLED创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考