WLED LD2410_v2 Usermod 实战:用 24GHz 毫米波雷达实现移动检测与 MQTT/Home Assistant 集成 📅 发布时间:2026/9/13 21:28:11 👁 浏览次数: WLED LD2410_v2 Usermod 实战用 24GHz 毫米波雷达实现移动检测与 MQTT/Home Assistant 集成【免费下载链接】WLEDControl WS2812B and many more types of digital RGB LEDs with an ESP32 over WiFi!项目地址: https://gitcode.com/GitHub_Trending/wl/WLED本文基于 WLED 官方仓库中的 LD2410_v2 usermod 及其完整实现源码展开讲解如何把 LD2410 毫米波雷达传感器接入 WLEDESP32实现“移动/静止”两种存在检测状态状态不仅会显示在 WLED Web UI 的 Info 页面还会发布到 MQTT 话题并自动完成 Home Assistant Discovery。读完本篇后你可以独立完成该 usermod 的编译启用、串口引脚配置、MQTT 话题订阅以及 Home Assistant 中 motion/occupancy 二进制传感器的落地并能对照源码理解其 1 秒轮询与 5 分钟心跳保活的完整数据流。一、功能定位与硬件前提该 usermod 的核心功能是读取 LD2410 移动/存在movement/presence雷达传感器的状态并将两类状态分别呈现移动状态movement检测到运动目标静止状态stationary检测到静止目标有人但不动。原始文档明确了两个关键前提需要第二路 UART传感器通过独立串口ESP32 上的Serial1通信占用一对 GPIO 引脚仅在 ESP32 上经过测试不支持 ESP8266 等平台。从源码 LD2410_v2.cpp 还能看到第三个硬性前提#ifdef WLED_DISABLE_MQTT #error This user mod requires MQTT to be enabled. #endif也就是说如果在构建时禁用了 MQTT该模块会直接在编译期报错。文档中的 Dependencies 一节也对应说明数据通过 MQTT 发布必须先启用 WLED 的 MQTT 同步接口。二、依赖库ncmreynolds/ld2410该 usermod 本身不包含 LD2410 协议实现而是依赖 PlatformIO 注册表中的ncmreynolds/ld2410库版本约束见 library.json{ name: LD2410_v2, build: { libArchive: false }, dependencies: { ncmreynolds/ld2410: ^0.1.3 } }两个细节值得注意^0.1.3表示允许 0.1.x 范围内的较新版本build: { libArchive: false }是 WLED usermod 的强制要求——usermod 必须直接链接进可执行文件而不是归档成静态库。构建脚本 load_usermods.py 会在构建期检查此项缺失时会以ERROR: libArchivefalse is missing on usermod(s) ...报错并终止构建。WLED 的构建系统在启用 usermod 时会自动把该库声明的dependencies一起解析为lib_deps无需手工在 platformio 配置里重复声明。三、编译启用custom_usermods 机制3.1 在 platformio_override.ini 中启用原始文档给出的编译方式为在custom_usermods中加入该模块名例如放入 platformio_override.ini文档示例如下[env:usermod_USERMOD_LD2410_esp32dev] extends env:esp32dev custom_usermods ${env:esp32dev.custom_usermods} LD2140_v2勘误提示原文档中出现的LD2140/LD2140_v2是笔误“4”与“1”位置颠倒且文档 H1 标题误写为 “BH1750 usermod”均为复制残留。实际目录名为 usermods/LD2410_v2应填写LD2410_v2或简写LD2410。这里的关键在于${env:esp32dev.custom_usermods}写法它继承所选基础环境如esp32dev已有的 usermod 列表并追加本模块避免清空原有配置。仓库中的示例文件 platformio_override.sample.ini 展示了完全相同的继承模式例如custom_usermods ${env:esp32dev.custom_usermods} Temperature four_line_display_ALT3.2 名称解析规则为什么可以省略 _v2 后缀从构建脚本 load_usermods.py 的find_usermod()可以看到解析逻辑def find_usermod(mod: str) - Path: mp usermod_dir / mod # 精确匹配 if mp.exists(): return mp mp usermod_dir / f{mod}_v2 # 尝试 name_v2 if mp.exists(): return mp mp usermod_dir / fusermod_v2_{mod} # 尝试 usermod_v2_name if mp.exists(): return mp raise RuntimeError(fCouldnt locate module {mod} in usermods directory!)因此写LD2410会被自动解析到usermods/LD2410_v2/目录写LD2410_v2则直接命中。这与 AGENTS.md 中 “usermod_v2_prefix or_v2suffix can be omitted” 的规范一致。解析成功后模块以symlink://形式注入lib_deps参与编译。四、初始化与串口通信setup() 的实现启用模块后WLED 启动阶段会调用Usermod::setup()。该模块的 setup() 实现为void setup() { Serial1.begin(256000, SERIAL_8N1, uart_rx_pin, uart_tx_pin); Serial.print(F(\nLD2410 radar sensor initialising: )); if(radar.begin(Serial1)){ Serial.println(F(OK)); } else { Serial.println(F(not connected)); } initDone true; }要点使用 ESP32 的Serial1第二路 UART波特率2560008N1 格式——这是 LD2410 模块的出厂通信参数默认引脚default_uart_rx 19、default_uart_tx 18源码 L18-L19初始化结果会打印到串口监视器OK/not connected但注意即使radar.begin()返回失败initDone仍会置为 true后续loop()会持续尝试并在每秒的连接检查中更新sensorFound标志。五、主循环逻辑1 秒轮询 状态变化发布 5 分钟心跳loop()每轮主循环被调用一次其完整逻辑源码 L103-L133可以拆解为四层快速退出if (!enabled || strip.isUpdating()) return;—— 模块被禁用、或 LED 灯带正在刷新时直接返回。注释中特别提示在超长灯带上strip.isUpdating()可能恒为 true此时轮询会被永久跳过需要“update accordingly”每秒一次采样radar.read()每次都会执行但状态评估与发布被节流到1000ms 间隔curr_time - lastTime 1000连接检查优先sensorFound radar.isConnected()未连上传感器时直接 return不发布任何状态变化触发发布 心跳presenceDetected()得到静止状态movingTargetDetected()得到移动状态仅当状态相对上一次发生变化时才发布 MQTT 消息若 5 分钟内没有任何状态变化会主动重发当前两个状态作为“活着”的心跳curr_time - last_mqtt_sent 1000*60*5保证 HA 侧的expire_after不会误判离线。stationary_detected radar.presenceDetected(); if(stationary_detected ! last_stationary_state){ if (WLED_MQTT_CONNECTED){ publishMqtt(/ld2410/stationary, stationary_detected ? ON:OFF, false); last_stationary_state stationary_detected; } } movement_detected radar.movingTargetDetected(); if(movement_detected ! last_movement_state){ if (WLED_MQTT_CONNECTED){ publishMqtt(/ld2410/movement, movement_detected ? ON:OFF, false); last_movement_state movement_detected; } }其中WLED_MQTT_CONNECTED是 WLED 核心提供的宏定义于 wled00/wled.h#define WLED_MQTT_CONNECTED (mqtt ! nullptr mqtt-connected())即“MQTT 客户端存在且已连接”。所有发布都通过它做双重保护循环内判断一次publishMqtt()内部再判断一次避免未连接时调用mqtt-publish()崩溃。六、MQTT 话题结构与 Home Assistant Discovery6.1 状态话题原文档说明状态发布到/movement和/stationary话题结合 源码 中publishMqtt()的拼接逻辑mqttDeviceTopic 子话题实际完整话题为话题载荷触发时机WLED设备话题/ld2410/movementON/OFF移动状态变化、5 分钟心跳WLED设备话题/ld2410/stationaryON/OFF静止状态变化、5 分钟心跳WLED设备话题/ld2410/statusI am alive!MQTT 连接建立且传感器已连接时onMqttConnect所有消息均为非保留retain false发布。6.2 Home Assistant 自动发现源码中HomeAssistantDiscovery默认为trueL25。MQTT 首次连接后_mqttInitialize()会调用_createMqttSensor()为两个状态各发布一条发现配置L44-L85配置话题homeassistant/binary_sensor/mqttClientID/Movement/config与.../Stationary/config设备类Movement 为motionStationary 为occupancy载荷约定payload_on ONpayload_off OFF离线判定expire_after 180030 分钟无消息 HA 判定实体离线——与第五节的 5 分钟心跳配合正常情况下不会误报设备聚合两个传感器挂在同一虚拟设备下identifiers wled-sensor-mqttClientIDmanufacturer 为WLEDmodel 为FOSSsw_version 取当前固件版本串在 HA 中呈现为一个 WLED 设备下的两个二进制传感器。这意味着在 WLED 中开启 MQTT 同步后Home Assistant 中无需手动建模即可出现“移动”和“占用”两个传感器实体。七、Web UI Info 页面展示addToJsonInfo()L136-L156向/json/info的uusermod对象中追加两个数组Web UI 的 Info 区块会显示为两行文本场景LD2410 Stationary 显示LD2410 Movement 显示模块被禁用disableddisabled未检测到传感器LD2410 Not Found空正常工作Sta ON/Sta OFFMov ON/Mov OFF这是无需 MQTT 客户端即可肉眼确认传感器是否在线、状态是否正常跳变的最快途径。八、配置项详解enabled 与 UART 引脚8.1 持久化配置addToConfig()/readFromConfig()L158-L188定义了写入 cfg.json 的键节点名LD2410Usermod键名类型默认值说明enabledbooltrue启用/禁用 usermoduart_rx_pinint819Serial1 的 GPIO 输入引脚uart_tx_pinint818Serial1 的 GPIO 输出引脚readFromConfig()中使用了三参数getJsonValue()的缺省回退写法——即使 cfg.json 被手工编辑导致某个键缺失也能用默认值兜底源码注释明确说明这一设计考虑。8.2 一个需要留意的实现细节原文档称 “Usermod 设置页可以配置 RX/TX 引脚”。但从源码结构看当前实现没有重写appendConfigData()该方法在 Usermod 基类 中用于向设置页注入 UI 控件因此设置页面上实际没有可编辑的引脚滑杆addToConfig()每次保存设置时写入的也是编译期默认值19/18。也就是说若要改用其他 UART 引脚只能修改源码中的default_uart_rx/default_uart_tx后重新编译——这是使用与二开该模块时最容易被文档与代码差异“坑到”的一点。九、注册机制与唯一 ID模块通过 WLED 的 linker-section 注册机制接入主循环static LD2410Usermod ld2410_v2; REGISTER_USERMOD(ld2410_v2);其中REGISTER_USERMOD宏定义在 wled00/fcn_declare.h本质是把模块实例指针放入名为usermods的 DYNARRAY 链接段UsermodManager启动时遍历该段完成 setup/loop 调度。本模块重写了getId()并返回USERMOD_ID_LD2410值为 52注册于 wled00/const.h。按 AGENTS.md 的规范唯一 ID 只在需要跨 usermod 查找、PinManager 引脚所有权、或在/json/info的um数组中可识别时才必须——本模块采用固定 ID 使其在 JSON info 输出中可被明确辨识。十、排障清单结合源码与文档常见故障可按以下路径排查Info 页显示 LD2410 Not Foundradar.isConnected()为 false。确认接线是否接对了 Serial1 的 RX/TX交叉连接WLED TX → 模块 RXWLED RX → 模块 TX、供电是否正常、串口监视器中是否打印了not connectedMQTT 一直无消息先确认 WLED 已启用 MQTT 同步接口且WLED_MQTT_CONNECTED为真可在 HA 中观察.../ld2410/status话题的I am alive!消息是否收到未连接时模块按设计不发布任何状态构建报错 “This user mod requires MQTT to be enabled.”当前构建环境定义了WLED_DISABLE_MQTT需更换启用 MQTT 的环境超长灯带上状态永远不更新strip.isUpdating()恒真导致loop()提前返回这是源码注释中明确提示的已知限制名称写错导致编译找不到模块find_usermod()会抛出Couldnt locate module ...注意区分LD2410正确与文档笔误LD2140。十一、版本沿革文档 Change log 记录2024 年 6 月由 wesleygas 创建。当前仓库中的实现1 秒轮询、HA Discovery、5 分钟心跳、I am alive!状态话题即为该 v2 版本的完整形态代码位于 usermods/LD2410_v2/LD2410_v2.cpp依赖声明位于 usermods/LD2410_v2/library.json。参考文件模块文档usermods/LD2410_v2/readme.md模块实现usermods/LD2410_v2/LD2410_v2.cpp依赖声明usermods/LD2410_v2/library.jsonUsermod 基类与注册宏wled00/fcn_declare.hUsermod ID 定义wled00/const.hMQTT 连接状态宏wled00/wled.husermod 构建解析脚本pio-scripts/load_usermods.py构建配置示例platformio_override.sample.iniUsermod 开发规范AGENTS.md【免费下载链接】WLEDControl WS2812B and many more types of digital RGB LEDs with an ESP32 over WiFi!项目地址: https://gitcode.com/GitHub_Trending/wl/WLED创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考