家庭自动化 / WLED 桌面实验发布 内容更新

ESP32 刷 WLED:把一条桌面灯分段、存预设,再接入 HA

固定S3 N8R8、WLED16.0.1与30颗RGB SK6812灯条,核固件和5V供电,把分段、亮度、预设备份与HA控制逐层走通。

读完能做什么
得到可核版本的官方固件安装方案、两段低亮度配置、可保存与备份的预设,以及按真实实体接入HA的步骤。
开始之前
会核板后缀、GPIO、供电和桥USB上传;HA已准备好,实物结果另行记录。
所需器材
官方DevKitC-1 v1.1 / N8R8,桥USB线、Adafruit PID3812 1m/30 RGB SK6812灯条、TI SN74AHCT125N PDIP14、330Ω、100nF、1000µF≥10V、稳压5V PID1466适配器、额定分路端子/线材、1A/2A DC保险与座、电脑Chrome/Edge、Python3.9+;HA2026.10.2运行环境另备
版本组合
板与器件:DevKitC-1 v1.1 N8R8 / PID3812 RGB SK6812 / SN74AHCT125N官方固件:WLED16.0.1 /29b389df;S3_8MB_opi预编译,未本站重编安装器:35d7284fe64d4c22d2a32bd4ea9d7bee6f52a959;Advanced8MB/OPI PSRAM/Default检查与HA:esptool5.3.1 / Python3.12.13;HA Core2026.10.2源码/语法,runtime pending
适用范围

只限官方S3 DevKitC-1 v1.1 N8R8、指定30颗RGB灯条及电平缓冲。S3仍为上游实验性支持;本文不是长期照明/稳定性结果。

这篇验证到了哪一步

资料核对已通过
docs/esp32-evidence/wled-root.md;固定官方/厂家来源与文件SHA验证日期:
构建 / 配置已通过
docs/esp32-evidence/wled-root-checks.json;只读镜像/分区/JSON/Python/YAML检查,非固件构建对象:官方S3预编译镜像的离线检查;未源码重编版本:WLED16.0.1 / esptool5.3.1验证日期:
仿真不适用
没有WLED、LED时序、电气、无线或HA运行仿真;本地输入文件检查不冒充仿真
本站实板待验证
无本套板/灯条,未刷板、点灯、测电流/电压、检查PSRAM或运行HA

构建通过只说明指定环境中的代码或配置通过检查;实物功能、功耗和稳定性以对应的实板记录为准。

01 / WLED 桌面实验

先锁定S3固件和RGB灯条,再谈氛围灯

WLED把灯光控制、网页、分段和预设集成在上游固件中,本篇使用官方预编译v16.0.1,不把它叫本站Arduino或IDF例程。本次成品是可检查的安装方案、14文件下载包、两段颜色配置与HA操作路径;本站没有刷板、点灯、连Wi-Fi或运行HA。安装器和镜像检查通过,与这些物理结果分别记录。

固定官方DevKitC-1 v1.1 / WROOM-1-N8R8:8MB Quad SPI Flash加8MB OPI PSRAM。WLED指定资产名_ESP32-S3_8MB_opi中的opi指PSRAM;不能据此套用另一块OPI Flash板的启动文件。官方控制器文档仍把S3列为实验性并不建议生产使用,本篇保持桌面学习范围,不宣称长期稳定或整屋照明适用。

灯条固定Adafruit PID3812、未裁切1m/30颗RGB SK6812,三线和24位GRB;它不是SK6812 RGBW。厂商其他SKU和批次曾换芯片,不能只看到“NeoPixel”就照抄白光通道或电流参数。

做到这里,你应该看到
板后缀、Flash、PSRAM、灯条SKU和RGB通道全部能对应具体来源。

参考:[1] WLED v16.0.1官方发布与指定S3_8MB_opi资产[2] 固定WebInstaller:S3、存储后缀和清单偏移[4] 官方控制器支持:S3仍注明实验性[5] Adafruit PID3812具体RGB SK6812灯条、电流两种口径和端点[6] PID3812厂家链接SK6812 Rev01:24位GRB与DIN/DOUT

02 / WLED 桌面实验

板上GPIO只传数据,灯条电源从端子分路

采用TI SN74AHCT125N的PDIP14封装,按缺口/点确定顶视pin1。芯片供电4.5–5.5V时高输入门限2V、低门限0.8V,适合把S3的3.3V数据变成5V输出。GPIO12接2/1A,3/1Y经靠近灯条的330Ω到白线DIN,1/OE接地使能。14/VCC接5V、7/GND共地,14↔7就近100nF。未用OE4/10/13接5V、A5/9/12接地,Y6/8/11留空;不能用双向I2C转换板替代。

只使用密封稳压5V适配器PID1466的低压输出,正中心端子先核极性:板5V/J1-21走1A额定DC保险分支,灯条和缓冲器走2A分支,负端到所有GND。每支线、绝缘端子和保险座按其额定电流选用;灯条大电流不穿开发板、面包板轨或GPIO线。输入端并1000µF≥10V电容,+到5V、−到地。PID3812说这SKU不必串数据电阻,本例仍按同厂系统指南选330Ω。

USB安装与外部供电运行是两个阶段:安装时外部5V及灯条/缓冲器支路完全断开;运行灯条前拔掉全部USB,再用单适配器同时给板和灯条供电。所有改线都断电,可靠焊接排针与端子固定,鳄鱼夹只接灯条自带线到隔离端子,不夹相邻裸针。5V不能进3V3或GPIO。

端点连接
GPIO12AHCT125 pin2/1A
AHCT125 pin3/1Y330Ω→PID3812白线DIN
AHCT125 pin1/1OEGND
AHCT125 pin14/75V/GND;100nF就近跨接
DevKit5V/J1-21、GND/J1-22单适配器的板分支;运行时USB拔掉
灯条红/黑线5V灯条分支/GND;输入端并极性电容
未用门OE4/10/13到5V,A5/9/12到GND,Y6/8/11空置
做到这里,你应该看到
逐端追线后能指明灯条电流路径与数据路径,两个供电阶段不重叠。

参考:[5] Adafruit PID3812具体RGB SK6812灯条、电流两种口径和端点[7] TI SN74AHCT125 SCLS264R:PDIP引脚、TTL门限与未用输入[8] Adafruit NeoPixel电容、电阻、5V电平和供电次序[9] 指定稳压5V/4A适配器PID1466:输出与正中心端点[10] DevKitC-1 v1.1固定排针与互斥供电方式

03 / WLED 桌面实验

先按保守电流留容量,亮度限制只是软件估算

PID3812同页既有约4.8W/m的描述,也给每段最大60mA;本例按后者预算30×60mA=1.8A、5V时9W,并另留板和缓冲器负载容量。这是选电源的计算,不是本站测得电流;4A代表适配器容量,不会强迫负载吸4A。分支保险也不能凭本文数字就宣称已完成短路动作测试。

配置只用500mA自动亮度限制和32/255初始亮度,限制器根据模型估计LED电流,并不测量导线、接触或短路。线材与保护不能按“软件已限500mA”降低容量。首次从低亮度单色红绿蓝开始,用合适量程电流表及万用表记输入/远端电压,观察端子和线材温升,逐步核真实负载;不从全白满亮开始,不把卷起/覆盖的灯条当持续散热条件。

做到这里,你应该看到
把保守预算、软件估值、额定容量与真实测量分成四个字段。

参考:[5] Adafruit PID3812具体RGB SK6812灯条、电流两种口径和端点[8] Adafruit NeoPixel电容、电阻、5V电平和供电次序[9] 指定稳压5V/4A适配器PID1466:输出与正中心端点[12] WLED16.0.1 LED设置页:Custom电流、ABL、启动亮度和预设

04 / WLED 桌面实验

先只接桥USB,用安装器选8MB和S3 OPI PSRAM

保留旧固件/配置的私有备份,再在桌面Chrome或Edge打开官方安装器,选择Advanced→16.0.1→Plain→8MB→PSRAM(S3 OPI)→Flash mode Default;Basic默认4MB,不能当N8R8配置。等固件下载检测完成才点Install。本站实际打开该UI并读取生成清单,S3部分是bootloader@0、分区表@0x8000、指定app@0x10000,镜像检验为S3/8MB,应用1,232,640B能放入2MiB OTA槽;没有执行串口连接或写入。

选插拔确认的USB-to-UART桥口、关闭监视器,必要时BOOT+EN进下载,成功后松BOOT再EN。只有已备份旧内容才选择擦除;不能把应用单文件写到0,也不能用经典ESP32.bin代替S3。实际镜像报告IDF4.4.8.240628,本篇未用本站其他教程的IDF5.5.5或Arduino3.3.12重新编译这份WLED。

首次按官方默认WLED-AP/wled1234连接,AP内开4.3.2.1,Config→WiFi Setup填自己的2.4GHz网络和新AP密码。保存后电脑回同一LAN,用路由器租约查真实IP;4.3.2.1是AP地址,不是加入家庭网络后的固定地址。发现失败用IP,私有配置不入仓库,不将控制界面端口映射到公网。

做到这里,你应该看到
能从板存储类型选对资产,并区分AP地址、LAN地址与串口写入结果。

参考:[1] WLED v16.0.1官方发布与指定S3_8MB_opi资产[2] 固定WebInstaller:S3、存储后缀和清单偏移[3] 固定安装器boot资产的用途与分区[10] DevKitC-1 v1.1固定排针与互斥供电方式[11] 固定QuickStart:AP与LAN地址分开

05 / WLED 桌面实验

下载包的只读检查器能核镜像,不能代替刷板

assets.lock.json固定三资产的来源、字节数、SHA和偏移;boot/分区链接固定安装器commit,应用来自官方v16.0.1 release。先在电脑安装requirements.txt里的esptool5.3.1,再把这三个官方文件按原名放同一assets目录,运行下面脚本。只检查已有文件,不会下载、打开USB或向设备发请求。完整命令见README;默认不传assets目录时只检查本地JSON并明确跳过镜像。

实际运行验证了两个S3镜像的checksum/hash、分区MD5、偏移不重叠、8MiB结尾和2MiB app0容量。SHA是本站本次下载的身份摘要,不是上游签名证书;校验成功也不能推出PSRAM、无线、供电或LED驱动已在板上工作。WLED仍为EUPL1.2+,本站包内仅原创MIT方案/检查器和上游链接,不重新分发固件。

代码 / 配置
# SPDX-License-Identifier: MIT
"""Read-only checks. Never opens a serial port, flashes or sends network commands."""
import argparse
import hashlib
import json
import pathlib
import struct
import subprocess
import sys

BASE = pathlib.Path(__file__).resolve().parent

def check_payloads():
    plan = json.loads((BASE / "settings-plan.json").read_text())
    assert plan["wledType"] == 22 and plan["length"] == 30
    assert plan["gpio"] == 12 and plan["maxCurrentMA"] == 500
    for name in ("warm-state.json", "cool-state.json"):
        state = json.loads((BASE / name).read_text())
        assert state["bri"] == 32 and state["on"] is True
        assert [(s["id"], s["start"], s["stop"]) for s in state["seg"]] == [(0, 0, 15), (1, 15, 30)]
        assert all(s["fx"] == 0 and len(s["col"][0]) == 3 for s in state["seg"])
    print("PASS local JSON setup plan and two segment payloads. Not a WLED parser/runtime check.")

def check_assets(folder):
    lock = json.loads((BASE / "assets.lock.json").read_text())
    assert [p["offset"] for p in lock["parts"]] == [0, 0x8000, 0x10000]
    assert lock["parts"][0]["bytes"] <= 0x8000
    assert 0x8000 + lock["parts"][1]["bytes"] <= 0x9000
    for part in lock["parts"]:
        path = folder / part["name"]
        content = path.read_bytes()
        assert len(content) == part["bytes"], path
        assert hashlib.sha256(content).hexdigest() == part["sha256"], path
        assert part["offset"] + len(content) <= lock["flashBytes"]
        print("PASS hash/size", part["name"], len(content))
        if part["name"] != "partitions_s3_8m.bin":
            subprocess.run([sys.executable, "-m", "esptool", "image-info", str(path)], check=True)
    raw = (folder / "partitions_s3_8m.bin").read_bytes()
    entries = []
    found_md5 = False
    for i in range(0, len(raw), 32):
        row = raw[i:i + 32]
        magic = struct.unpack_from("<H", row)[0]
        if magic == 0xFFFF:
            break
        if magic == 0xEBEB:
            assert hashlib.md5(raw[:i]).digest() == row[16:32], "partition MD5"
            found_md5 = True
            break
        assert magic == 0x50AA, "partition magic"
        _, kind, subtype, offset, size, label, flags = struct.unpack("<HBBII16sI", row)
        entries.append((label.rstrip(b"\0").decode(), kind, subtype, offset, size, flags))
    assert found_md5, "partition MD5 entry missing"
    ordered = sorted(entries, key=lambda e: e[3])
    assert all(a[3] + a[4] <= b[3] for a, b in zip(ordered, ordered[1:])), "overlapping partitions"
    app = next(e for e in entries if e[0] == "app0")
    assert app[3] == 0x10000 and app[4] == 0x200000
    assert lock["parts"][2]["bytes"] < app[4], "application exceeds OTA slot"
    assert max(e[3] + e[4] for e in entries) == 0x800000
    print("PASS partition MD5, 2MiB app0 slot, non-overlap with boot/partition files, 8MiB end.")
    print("No firmware compilation, USB/flash, PSRAM, radio, strip or HA runtime was tested.")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--assets-dir", type=pathlib.Path, help="Existing downloaded official files; no download occurs")
    args = parser.parse_args()
    check_payloads()
    if args.assets_dir:
        check_assets(args.assets_dir)
    else:
        print("Asset checks skipped: supply --assets-dir after downloading the three pinned files.")

参考:[1] WLED v16.0.1官方发布与指定S3_8MB_opi资产[2] 固定WebInstaller:S3、存储后缀和清单偏移[3] 固定安装器boot资产的用途与分区

06 / WLED 桌面实验

只建一个RGB输出,先让颜色和电流参数对应

灯条仍断开时,在Config→LED Preferences只保留一个WS281x RGB输出,GPIO12、Start0、Length30、GRB;不是SK6812 RGBW。mA/LED选择Custom再填60;勾Enable automatic brightness limiter,取消Use per-output limiter,Maximum PSU Current填500mA。其他按钮/继电器若占GPIO12须移除该占用。settings-plan.json是人看的核对单,不能作为完整cfg.json导入。

首次接线检查把Bootup brightness设32、Apply preset设0,取消Turn LEDs on after power up/reset,先让启动保持暗。保存、断电拔USB、接好单外部5V方案后上电,再从网页以低亮度手动开单色。红绿蓝与实际像素逐项核对;颜色错先查GRB、RGB/RGBW,尾部不亮先查30颗数量、输入箭头、接触与真实电压,不随机换一堆固件。

做到这里,你应该看到
真实单色检查、实际电压/电流与保存后的配置都有记录;网页响应不是光学证明。

参考:[5] Adafruit PID3812具体RGB SK6812灯条、电流两种口径和端点[6] PID3812厂家链接SK6812 Rev01:24位GRB与DIN/DOUT[8] Adafruit NeoPixel电容、电阻、5V电平和供电次序[12] WLED16.0.1 LED设置页:Custom电流、ABL、启动亮度和预设

07 / WLED 桌面实验

把0…29分成两段,Stop端点不包含

Segment0设Start0/Stop15覆盖0…14,Segment1设Start15/Stop30覆盖15…29,Grouping1、Spacing0,不重叠;删掉或禁用额外段。网页颜色/效果会同时作用于已选中段,展开哪段不代表只选了哪段。先用Solid,把动画和布局问题分开。

warm-state.json是两段低亮度目标配置,cool-state.json在包中给第二组完整目标色;它们不是本站灯光照片或测量结果。确认供电设置后,从电脑对真实IP的/json/state发送完整文件,读回on/bri/seg/start/stop/col,再看实际像素。README的192.0.2.1是故意不可达的文档地址,必须换成路由器实际租约;命令不会自动寻找或控制陌生设备。

代码 / 配置
{
  "on": true,
  "bri": 32,
  "transition": 7,
  "mainseg": 0,
  "seg": [
    {
      "id": 0,
      "start": 0,
      "stop": 15,
      "grp": 1,
      "spc": 0,
      "of": 0,
      "on": true,
      "bri": 255,
      "col": [
        [
          255,
          128,
          16
        ],
        [
          0,
          0,
          0
        ],
        [
          0,
          0,
          0
        ]
      ],
      "fx": 0,
      "sx": 128,
      "ix": 128,
      "pal": 0,
      "sel": true
    },
    {
      "id": 1,
      "start": 15,
      "stop": 30,
      "grp": 1,
      "spc": 0,
      "of": 0,
      "on": true,
      "bri": 255,
      "col": [
        [
          96,
          32,
          0
        ],
        [
          0,
          0,
          0
        ],
        [
          0,
          0,
          0
        ]
      ],
      "fx": 0,
      "sx": 128,
      "ix": 128,
      "pal": 0,
      "sel": false
    }
  ]
}
做到这里,你应该看到
像素14在第一段、15在第二段,30这个下标不属于灯条。

参考:[13] 固定分段文档:Stop排除、选中段与分组[14] WLED16.0.1 JSON解析:范围/颜色/预设

08 / WLED 桌面实验

预设必须保存亮度和边界,再验证重启恢复

先读/presets.json备份已有列表,选未用ID;本文示例ID1/2若已有内容会被覆盖。应用warm-state后以psave=1、n=DeskWarm、ib=true、sb=true保存;应用cool-state同理存2/DeskCool。psave走异步保存,不能凭一次HTTP响应宣布已持久化;稍后读回预设文件并核名称/亮度/边界/颜色,再用ps=1调用验证。不要把每帧动画保存到Flash。

网页Create Preset时选择Use current state、Include brightness、Save segment bounds。启动预设另在LED设置中指定为已验证的1,之后重新上电检查两段范围和低亮度;未保存的当前状态不等于重启配置。Security & Updates里的Backup & Restore分配置和预设两份;恢复前断开灯条电源,使用同硬件/固件的私有备份,恢复后重查GPIO/count/ABL再接灯。/edit路径也能按官方文档取presets.json,但受OTA锁/文件编辑权限约束。

cfg.json/私有备份可能含网络与安全信息,不能加入Git或公开分享。下载包的settings-plan不是完整备份,不能上传冒充cfg.json。包内README保留从冷启动、误配到桥USB重写的恢复顺序,没有本站恢复成功记录。

代码 / 配置
curl --fail --max-time 5 -H 'Content-Type: application/json' --data-binary @warm-state.json http://192.0.2.1/json/state
curl --fail --max-time 5 -H 'Content-Type: application/json' --data '{"psave":1,"n":"DeskWarm","ib":true,"sb":true}' http://192.0.2.1/json/state
做到这里,你应该看到
读回确认与真实重启后观察分开记录,覆盖已有ID前先保留备份。

参考:[12] WLED16.0.1 LED设置页:Custom电流、ABL、启动亮度和预设[14] WLED16.0.1 JSON解析:范围/颜色/预设[15] 固定预设文档:保存亮度/边界、psave及备份[16] WLED16.0.1预设异步保存实现[17] WLED16.0.1 Security备份/恢复页

09 / WLED 桌面实验

HA按真实预设名控制,最后分层排查离线与不亮

HA Core2026.10.2在设置→设备与服务→添加集成→WLED,发现不到就填真实IP;官方要求WLED≥0.14。本例两段应对应各自灯实体及主灯,预设通过Preset select按名称选择。先确认实际选项已有DeskWarm/DeskCool并记entity_id,再把包中完整ha-package.yaml的占位ID替换为自己的实体。合并已有packages入口,执行用户HA自己的配置检查并按需重载;本站只做YAML语法与固定源码核对,没有运行HA检查/集成/脚本。

包内两脚本只供手动选择预设,没有自动触发。HA动作完成后仍逐层对照WLED状态和实际灯光。停止HA时,本地WLED网页是否能用另测;路由器断开后的恢复热点取决于你设定的AP策略,不能保证改过策略仍总出现WLED-AP。网络错先核租约/SSID/AP密码,完全不可达时断开外部灯电源,回桥USB安装并使用自己的备份。

验收依次记录低亮度RGB、0/14/15/29边界、预设1→2→1、启动预设、HA手动调用、HA关闭、本地网页、网络丢失/AP策略与备份恢复;近端/末端电压、电流和端子温升用实测值填写。整条不亮先核电源极性/共地/DIN/缓冲器OE和GPIO,只有部分不亮先核数量/分段/供电。observations.csv仍只有表头,所有这些实物与HA项保持pending。

代码 / 配置
# Replace this entity with the real WLED Preset select entity after integration.
# Merge packages into an existing HA configuration; do not duplicate top-level keys.
script:
  h08_desk_warm:
    alias: H08 DeskWarm preset
    sequence:
      - action: select.select_option
        target:
          entity_id: select.replace_with_real_wled_preset
        data:
          option: DeskWarm
  h08_desk_cool:
    alias: H08 DeskCool preset
    sequence:
      - action: select.select_option
        target:
          entity_id: select.replace_with_real_wled_preset
        data:
          option: DeskCool
做到这里,你应该看到
能够指出故障出在设备/网络/HA/配置/光学哪一层,不拿成功响应替灯光实测。

参考:[11] 固定QuickStart:AP与LAN地址分开[17] WLED16.0.1 Security备份/恢复页[18] HA WLED官方集成:版本、分段、主灯和预设[19] HA2026.10.2预设select按实际名称选择

BACK TO THE SOURCE

资料来源与版本说明

实读固定WLED/安装器/文档与HA源码、具体厂家引脚和PDF;实际检查官方镜像及安装器UI,没有本站重编、刷板或HA运行。资料核对日期:。资料核对、程序构建与实板测试分别记录,不互相替代。

  1. WLED v16.0.1官方发布与指定S3_8MB_opi资产
  2. 固定WebInstaller:S3、存储后缀和清单偏移
  3. 固定安装器boot资产的用途与分区
  4. 官方控制器支持:S3仍注明实验性
  5. Adafruit PID3812具体RGB SK6812灯条、电流两种口径和端点
  6. PID3812厂家链接SK6812 Rev01:24位GRB与DIN/DOUT
  7. TI SN74AHCT125 SCLS264R:PDIP引脚、TTL门限与未用输入
  8. Adafruit NeoPixel电容、电阻、5V电平和供电次序
  9. 指定稳压5V/4A适配器PID1466:输出与正中心端点
  10. DevKitC-1 v1.1固定排针与互斥供电方式
  11. 固定QuickStart:AP与LAN地址分开
  12. WLED16.0.1 LED设置页:Custom电流、ABL、启动亮度和预设
  13. 固定分段文档:Stop排除、选中段与分组
  14. WLED16.0.1 JSON解析:范围/颜色/预设
  15. 固定预设文档:保存亮度/边界、psave及备份
  16. WLED16.0.1预设异步保存实现
  17. WLED16.0.1 Security备份/恢复页
  18. HA WLED官方集成:版本、分段、主灯和预设
  19. HA2026.10.2预设select按实际名称选择