WLED Battery Usermod 实战指南:用 ESP8266/ESP32 实现电池电压监测、电量百分比、自动关机与低电量指示
【免费下载链接】WLEDControl WS2812B and many more types of digital RGB LEDs with an ESP32 over WiFi!项目地址: https://gitcode.com/GitHub_Trending/wl/WLED
本文是 WLED 项目中 Battery usermod 的完整技术指南。该模块让以电池供电的 ESP8266 / ESP32 LED 控制器能够实时监测电池电压、计算剩余电量百分比,并具备可配置阈值的自动关机(Auto-Off)与低电量指示(Low-Power Indicator)能力,同时深度集成 WLED 的 JSON API、MQTT 与 Home Assistant 自动发现。读完本文,你将掌握 Battery usermod 的接线方案、编译配置、运行时参数调优与源码级工作原理,可直接为你的便携 LED 项目(灯带、灯笼、露营灯、可穿戴设备等)部署一套可靠的电源监测方案。
功能特性总览
根据 Battery readme 与 Battery.cpp,该 usermod 提供四项核心能力:
- 当前电池电压显示:通过 ADC 采样计算电池电压,显示在 WLED 信息界面与 JSON API 中;
- 电池电量百分比:根据电池类型对应的电压-电量映射曲线(mapVoltage)计算 0–100% 电量;
- 自动关机(Auto-Off):电量跌至设定阈值时自动将 WLED 主亮度(
bri)置 0,保护电池避免过度放电; - 低电量指示(Low-Power Indicator):电量低于阈值时自动播放预设(Preset)若干秒,提示用户充电,播完再切回之前的预设。
此外,自 2021-09-02 起该模块支持 MQTT 上报电压,2024-08-19 版本又增加了电池百分比与电压两个 MQTT topic,并支持 Home Assistant MQTT 自动发现(详见文末变更日志)。
安装与启用
WLED 采用 PlatformIO 构建,usermod 有两种启用方式(见 Battery readme 的 Installation 章节):
方式一:platformio_override.ini(推荐,参见 官方示例截图)
在platformio_override.ini(或platformio.ini)中,于custom_usermods =后追加Battery:
[platformio] default_envs = esp32dev_custom [env:esp32dev_custom] extends = env:esp32dev custom_usermods = Battery build_flags = ${env:esp32dev.build_flags} -D USERMOD_BATTERYcustom_usermods是 WLED 构建系统加载 usermod 库的入口(见 platformio.ini),构建脚本 pio-scripts/load_usermods.py 会解析该选项并把对应 usermod 目录(如usermods/Battery/,其下有 library.json 描述构建信息)加入编译。你还可以在build_flags中直接传递配置宏,例如设置测量引脚与采样间隔:
build_flags = ${env:esp32dev.build_flags} -D USERMOD_BATTERY -D USERMOD_BATTERY_MEASUREMENT_PIN=35 -D USERMOD_BATTERY_MEASUREMENT_INTERVAL=3000方式二:my_config.h
将wled00/my_config_sample.h复制为wled00/my_config.h,启用WLED_USE_MY_CONFIG后在文件中定义USERMOD_BATTERY,即可将该 usermod 纳入编译(源码注释中同样说明了这一点,参见 Battery.cpp 对my_config.h的引用)。配置示例见 my_config.h 配置截图。
提示:
USERMOD_BATTERY只是编译开关,真正把 usermod 实例挂入 WLED 运行循环的是源码末尾的static UsermodBattery battery; REGISTER_USERMOD(battery);(见 Battery.cpp),REGISTER_USERMOD宏定义在 wled00/fcn_declare.h。
典型接线方案
Battery usermod 通过单片机的 ADC 读取电池电压。不同平台 ADC 特性不同,接线方式也不同(图示见 Battery readme 的 Example wiring 章节):
ESP8266:单个 100kΩ 电阻
ESP8266 只有唯一模拟输入引脚A0,输入范围为 0–1V(无衰减选项,见 readVoltage() 源码注释)。文档要求:以 100kΩ 电阻将电池正极连接至A0,即构成上拉式分压采样。默认电压倍率(Voltage Multiplier)为4.2(定义于 battery_defaults.h),用于将 A0 采样的低电压换算回真实电池电压。
ESP32(含 S2/S3/C3 等):等值分压电阻对
ESP32 系列建议使用两个阻值相等的电阻构成分压器,将电池正极 → R1 → 分压节点 → R2 → GND,分压节点接入 ADC1 通道(GPIO32–GPIO39,默认 GPIO35,见 battery_defaults.h)。默认电压倍率为2.0,对应两个等值电阻将电压对半分压的场景。
配置参数详解
以下参数表格完整继承自 Battery readme 的 "Define Your Options" 章节,默认值与取值范围结合 battery_defaults.h 与 Battery.cpp 源码补充:
基础测量参数
| 名称 | 单位 | 说明 | 默认值 |
|---|---|---|---|
USERMOD_BATTERY | — | 在my_config.h中定义以启用本 usermod | — |
USERMOD_BATTERY_MEASUREMENT_PIN | — | 测量引脚,ESP8266 默认A0,ESP32 默认GPIO35 | A0 / 35 |
USERMOD_BATTERY_MEASUREMENT_INTERVAL | ms | 电池检测间隔 | 30000(30 秒) |
USERMOD_BATTERY_INITIAL_DELAY | ms | 首次读取前的延时,等待电压稳定 | 10000(10 秒) |
USERMOD_BATTERY_{TYPE}_MIN_VOLTAGE | V | 电池最低电压 | 2.6(18650 标准) |
USERMOD_BATTERY_{TYPE}_MAX_VOLTAGE | V | 电池最高电压 | 4.2(18650 标准) |
USERMOD_BATTERY_{TYPE}_TOTAL_CAPACITY | mAh | 并联所有电芯的容量总和 | — |
USERMOD_BATTERY_{TYPE}_CALIBRATION | — | 校准偏移量,微调单片机测得的电压 | 0 |
USERMOD_BATTERY_VOLTAGE_MULTIPLIER | — | 分压比倍率(ESP32 默认 2.0,ESP8266 默认 4.2) | 见左 |
Auto-Off(自动关机)
| 名称 | 单位 | 说明 | 默认值 |
|---|---|---|---|
USERMOD_BATTERY_AUTO_OFF_ENABLED | true/false | 启用自动关机 | true |
USERMOD_BATTERY_AUTO_OFF_THRESHOLD | %(0–100) | 达到该阈值时主电源(亮度)关闭 | 10 |
源码中当autoOffEnabled && (autoOffThreshold >= bat->getLevel())时调用turnOff(),即bri = 0; stateUpdated(CALL_MODE_DIRECT_CHANGE);(见 Battery.cpp 与 Battery.cpp)。
Low-Power Indicator(低电量指示)
| 名称 | 单位 | 说明 | 默认值 |
|---|---|---|---|
USERMOD_BATTERY_LOW_POWER_INDICATOR_ENABLED | true/false | 启用低电量指示 | true |
USERMOD_BATTERY_LOW_POWER_INDICATOR_PRESET | 预设 ID | 检测到低电量时播放的预设 | 0 |
USERMOD_BATTERY_LOW_POWER_INDICATOR_THRESHOLD | %(0–100) | 达到该阈值时触发低电量指示 | 20 |
USERMOD_BATTERY_LOW_POWER_INDICATOR_DURATION | 秒 | 播放该预设的时长 | 5 |
lowPowerIndicator()的实现逻辑为:电量低于阈值时记录当前预设、applyPreset()切换到指示预设,持续duration*1000毫秒后切回原预设;并带有防抖逻辑——只有当电量回升到threshold + 10(重新激活阈值,见 Battery.cpp)以上才允许再次触发(见 Battery.cpp)。
阈值联动约束(源码级细节)
setAutoOffThreshold()与setLowPowerIndicatorThreshold()之间存在相互钳制:
- 当低电量指示启用时,自动关机阈值会被强制设为
低电量阈值 - 1(保证先提示后关机); - 当自动关机启用时,低电量指示阈值会被钳制为不小于
自动关机阈值 + 1,且下限为 5(见 Battery.cpp 与 Battery.cpp)。
所有参数均可在运行时通过 Usermods 设置页面(/settings/um)动态调整,无需重新编译;编译期宏仅用于设定默认值。
电池类型预配置
每种电池类型可独立在my_config.h中预配置(来自 Battery readme 的 "Define Your Options" 末尾表格):
| 名称 | 别名 | my_config.h示例 |
|---|---|---|
| Lithium Polymer | lipo(Li-Po) | USERMOD_BATTERY_lipo_MIN_VOLTAGE |
| Lithium Ionen | lion(Li-Ion) | USERMOD_BATTERY_lion_TOTAL_CAPACITY |
对应宏名规则为USERMOD_BATTERY_{小写类型}_{参数},例如USERMOD_BATTERY_lion_MIN_VOLTAGE。各类型默认电压区间定义于 battery_defaults.h:
- Unkown(通用):3.3V – 4.2V(保守默认);
- LiPo:3.2V – 4.2V(注释特别提醒 1S LiPo 不应放电低于 3V);
- Li-Ion:2.6V – 4.2V(18650 电芯标准)。
工厂模式与电压-电量映射
自 2024-04-30 版本起,模块采用工厂模式设计:UMBattery为抽象基类(定义于 UMBattery.h),UnkownUMBattery、LipoUMBattery、LionUMBattery继承实现各自的mapVoltage()放电曲线:
- Li-Ion / Unkown:简单的线性映射
(v - min) * 100 / (max - min); - LiPo:按三段曲线近似真实放电特性——0–40% 区间快速下降段、40–90% 近线性段、90–105% 缓降段(见 LipoUMBattery.h)。
setup()中根据cfg.type实例化对应类型并注入配置(见 Battery.cpp),这就是 readme 提到的"工厂模式便于扩展自定义电池类型"。
电压校准(Calibration)
校准值是在最终计算电压经电压倍率(Voltage Multiplier)缩放之后再叠加的一个偏移量(见 Battery readme 的 Calibration 章节):
最终电压 = ADC 原始电压 ÷ ADC 精度 × 电压倍率 + 校准值ESP32 使用校准后的毫伏读数analogReadMilliVolts(),ESP8266 使用analogRead()/1023(见 Battery.cpp)。校准值可以是正数或负数,用于补偿分压电阻公差与 ESP ADC 固有测量误差。它既可在 Usermods 设置页面设置,也可在编译期于my_config.h或platformio_override.ini中指定。
读数平滑滤波
由于 ESP32 的 ADC 单次读数波动较大,loop()中对电压采用指数平滑(EMA)滤波,平滑系数alpha默认0.1(USERMOD_BATTERY_AVERAGING_ALPHA):
float filteredVoltage = bat->getVoltage() + alpha * (rawValue - bat->getVoltage());见 Battery.cpp。此外,USERMOD_BATTERY_INITIAL_DELAY(默认 10 秒)保证上电电压稳定后才进行首次测量,避免开机瞬间读数偏低(loop()中的initialDelay处理见 Battery.cpp)。
重要:务必核对电池规格
所有电池都不相同!在配置MIN_VOLTAGE/MAX_VOLTAGE前,务必查阅你所用电芯的官方数据手册。以 readme 中引用的 Molicel INR18650-M35A(3500mAh 10A 锂离子电池)为例:
| 电池规格表 | 数值 | 对应配置项 |
|---|---|---|
| 容量 | 3500mAh 12.5Wh | — |
| 最小容量 | 3350mAh 11.9Wh | — |
| 额定电压 | 3.6V – 3.7V | — |
| 充电截止电压 | 4.2V ± 0.05 | USERMOD_BATTERY_MAX_VOLTAGE |
| 放电截止电压 | 2.5V | USERMOD_BATTERY_MIN_VOLTAGE |
| 最大持续放电电流 | 10A (10000mA) | — |
| 最大充电电流 | 1.7A (1700mA) | — |
表格完整继承自 Battery readme 的 Important 章节。设置错误的电压区间会导致电量百分比严重失真,甚至因过度放电损坏电池。另外注意 UMBattery.h 中setLevel()将电量钳制在 0–110% 之间,setMaxVoltage()强制不低于minVoltage + 0.5V(LiPo 为 +0.7V,Li-Ion 为 +1.0V),这是基类对配置合法性的内置保护。
系统集成:JSON API、MQTT 与 Home Assistant
JSON API 与信息界面
模块通过addToJsonInfo()在/json/info的u对象中暴露Battery level(含%)、Battery voltage(含V)与Next update(秒)三个字段,初始化完成前显示init,引脚无效时显示n/a / invalid GPIO(见 Battery.cpp)。同时通过addToJsonState()/addToConfig()把min-voltage、max-voltage、calibration、voltage-multiplier、interval、auto-off、indicator等配置暴露到 JSON,供 Usermods 设置页与外部客户端读写(见 Battery.cpp)。电压值经dot2round()保留两位小数显示。
MQTT 上报
启用 MQTT 后(未定义WLED_DISABLE_MQTT),每次测量会发布两个主题:
{mqttDeviceTopic}/battery—— 电池百分比(整数);{mqttDeviceTopic}/voltage—— 电池电压(浮点)。
见 Battery.cpp。
Home Assistant 自动发现
当配置项HA-discovery开启后,MQTT 连接建立时会通过onMqttConnect()为 Battery 与 Voltage 各注册一个 Home Assistant MQTT 传感器(entity_category = diagnostic,过期时间 1800 秒,见 Battery.cpp),可在 Home Assistant 中直接以实体形式呈现电池状态。
引脚管理与引脚复用检测
在 ESP32 上,setup()会通过PinManager::allocatePin(batteryPin, false, PinOwner::UM_Battery)申请 ADC 引脚,申请失败(被其他外设占用或非 ADC 引脚)时batteryPin被置为-1并停止测量;在设置页修改引脚后还会先deallocatePin再重新setup()(见 Battery.cpp 与 Battery.cpp)。PinOwner::UM_Battery对应 usermod ID 18,定义于 const.h 与 pin_manager.h。
变更日志(2021 – 2024)
完整变更记录见 Battery readme 的 Change Log 章节,要点如下:
- 2024-08-19:改进 MQTT 支持,新增电池百分比与电压 MQTT topic;
- 2024-05-11:文档更新;
- 2024-04-30:引入工厂模式便于扩展自定义电池类型;首测延时以等待上电电压稳定;
- 2023-01-04:支持 LiPo 可充电电池(
-D USERMOD_BATTERY_USE_LIPO);改进 ESP32(读取校准电压);修复配置保存问题(此前测量引脚与电压上下限会丢失); - 2022-12-25:新增 auto-off、low-power-indication、校准/偏移字段、供其他 usermod 交互的 getter/setter;
- 2021-09-02:信息界面新增"Battery voltage"、新增电路图、MQTT 上报电压;
- 2021-08-15:默认最低电压改为 2.6V(18650 标准);
- 2021-08-10:模块创建。
排查建议
- 信息界面显示
n/a / invalid GPIO:检查测量引脚是否配置为 ADC1 通道(ESP32:GPIO32–39),或该引脚已被其他外设占用导致PinManager分配失败; - 电量百分比长期异常:核对电池数据手册中的充放电截止电压,并在设置页调整
min-voltage/max-voltage与calibration; - 首次读数明显偏低:这是上电瞬间电压未稳定所致,
USERMOD_BATTERY_INITIAL_DELAY(默认 10 秒)即为此设计,请勿随意改小; - 读数波动大:增大
USERMOD_BATTERY_AVERAGING_ALPHA(默认 0.1)以外的滤波相关参数需重新编译,波动剧烈时优先检查分压电阻焊点与电池接触。
相关接线参考资料(来自 Battery readme 的 Useful Links 章节,均为 ESP8266 A0 分压采样的实践文章):lazyzero 的 WeMos D1 mini A0 采样指南、arduinodiy 的 LiPo 电压监测 + ThingSpeak 教程。如需更深的 ADC 细节,可参考 ESP-IDF 官方 ADC 文档中关于 ADC1 通道与衰减配置的说明。
【免费下载链接】WLEDControl WS2812B and many more types of digital RGB LEDs with an ESP32 over WiFi!项目地址: https://gitcode.com/GitHub_Trending/wl/WLED
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考