14 KiB
14 KiB
RS485 → Pharos LPC 灯光控制项目总结
日期:2026-10-09(2026-10-10 更新:LPC 自治架构——照度采集+闭环移入 LPC Lua,Ubuntu 只做监控/记录) 状态:✅ 全部验证通过(LPC 自治闭环实测收敛 484 Lux≈目标 500;网页控制台 v3 回归全过:FX/SC/BRT 经 HTTP 触发器下发、联动开关切换 lux_link_on、历史曲线含 LPC lux)
LPC 自治架构(2026-10-10)
- 传感器、LPC 串口、Ubuntu USB-485 同一条 RS485 总线;LPC 串口改 RS485/4800/8N1 后由 LPC 独占主机轮询,Ubuntu 串口命令链路废弃
- 新增触发器:#14 LuxPoll(Real Time 高级掩码每秒)→ Output Serial hex
02030002000265F8(Modbus 读地址 2 输入寄存器 0x0002,32 位 lux);#15 LuxIn(Serial Input,Hex 匹配020304<4c><2c>,<4c>捕获 32 位 lux 到变量 1,<2c>吞 CRC)→lpc_modbus_lux.lua(lux_value=lux全局暴露 +lux_link_on开关 +lux_poll_s调节间隔闸门 +lux_fade渐变 + 自适应模型闭环:在线辨识 k=Δlux/Δlevel(EMA、限 100~10000、限幅时不采样),步长err/k一步到位、上限 20%,误差变号减半防震荡,基准亮度lux_cur_level累加避免硬件量化吞小步长、偏差>5% 重同步;替代旧 P 调节 GAIN 0.3/最小步长 2% 的死区极限环);#16/#17 LuxLinkOn/Off(ASCIILLON/LLOFF);#18 LuxFadeSet(FAD=<4d>,0.1s 单位→lux_fade)/ #19 LuxPeriodSet(PER=<4d>1~60→lux_poll_s)/ #20 LuxDeadbandSet(DBD=<4d>1~1000→lux_deadband,默认 1 Lux),均可 HTTP?num=N&var=V触发 - 注意:LPC Lua 直接调
os.time()会中断脚本(无报错日志),须pcall(function() return os.time() end)兜底(失败退化为计数分频) - lux 对外暴露用 Lua 全局变量 +
GET /api/lua?variables=lux_value(set_text_slot在 Lua 不可用;text slot 仅 HTTP PUT/GET) - HTTP 触发器带参:
POST /api/trigger?num=N&var=V(实测 #9 var=600→lux_target=600) - 网页控制台 v3:
/send改POST /api/trigger(BRT→#2、LUX→#8、LXT→#9、LX2→#10、FX→#11、SC→#12),/luxlink改 #16/#17 + 读lux_link_on/lux_value,采样器不再碰串口;lux_sync.py/poll_lux.py停用(避免双主机抢总线) - 实测:上传后 T1 重启,lux 0→(升光)→饱和回落→收敛 484 Lux(死区内),level 稳定 100%;LLON/LLOFF HTTP 切换正常
系统架构
照度传感器(地址2) ─┐
发送方(PC/ESP32)─┼─ RS485 总线(4800 8N1,2026-10-10 起)──> Pharos LPC 0140650 (192.168.58.109)
Ubuntu USB-485 ────┘ (LPC 为主机每秒轮询传感器;ASCII 命令帧仍可用)
│ Serial Input 触发器 + Quick Script (Lua)
├─> get_group(0):set_master_intensity() → "All Fixtures" 组
└─> 32 × Generic Conventional 8 bit 灯具 → DMX universe 1 通道 1~32
Patch(2026-10-09 新增)
- Layout 1:32 个
Generic > Conventional 8 bit灯具(8 列 × 4 行),自动归入组All Conventional 8 bit - Patch:灯具 1~32 → DMX universe 1 通道 1~32(
dmx:1:N),Controller 2 占用 32/512 - 调光粒度:Group 0
All Fixtures的 master_intensity 作为总调光作用于全部 32 通道(现有 BRT/LUX/LX2 脚本无需修改) - eDMX Pass-Through 已改为 None(本地模式):实测直通优先级高于本地输出(外部源发黑场时本地 255 也出不来,通道显示
=0),二者无法叠加,只能二选一;如需恢复直通:Patch 视图 → DMX universe 1 → eDMX Pass-Through 下拉选1: ArtNet In - 灯具强度来源:组 master_intensity 只是缩放系数,灯具自身 intensity 须由 Timeline/Override 提供;当前用
PUT /api/override {"target":"group","num":0,"intensity":255}拉满。注意 Upload 会清空 Override,上传后需重新下发 - 输出回读:
GET /api/output?universe=dmx:1("0"=已patch,"=0"=外部直通,"!255"=override) /api/fixtures现返回 32 个灯具;/api/group返回All Fixtures(num 0) +All Conventional 8 bit- GUI 操作要点:Patch 视图从左侧灯具树拖拽灯具到通道网格格子即完成 Patch(点击/双击格子无效)
通信协议(ASCII 帧,\n 结尾)
| 帧格式 | 含义 | LPC 触发器 |
|---|---|---|
BRT=NNN |
手动亮度 0~100%(3 位补零) | #2 |
LUX=NNNNNN |
实测照度 0~200000 Lux(6 位补零)→ 闭环自动调光 | #8 Lux Auto Dim |
LXT=NNNNNN |
设定目标照度(默认 500 Lux,全局变量 lux_target) |
#9 Lux Target Set |
LX2=NNNNNN |
照度→亮度对数映射(指示模式,灯=照度计):level=log(lux+1)/log(200001),0.5s 渐变 |
#10 Lux Display Map |
FX=NN |
灯光效果 01~04 → 启动 Timeline N(2 位数字) | #11 FXSelect |
SC=NN |
场景 01~04 → 释放全部 Timeline + 组 Override 静态亮度(2 位数字) | #12 SC Select |
FX/SC 效果与场景(2026-10-09 新增)
- Timeline(FX):T1 常亮(White 0-30s 直出 255);T2 呼吸(4 个 White 块 0-8/8-16/16-24/24-30s,Fade 4/Release 4,末块 3/3);T3 闪烁(White 0-30s,Shape=Square,Base 0 / Size 255 / Period 1s);T4 缓变(White 0-30s,Fade 15/Release 15)
- 场景(SC):SC=01 全亮 255 / 02 半亮 128 / 03 微亮 26 / 04 全灭 0,由
get_group_override(0):set_intensity(level, 1.0)实现(0-255 整数) - 互斥逻辑:FX 脚本先
get_group_override(0):clear(1.0)再get_timeline(n):start_release_others();SC 脚本先release()全部 4 条 Timeline 再设 Override,避免互相遮蔽 - 循环播放(2026-10-10 修复):Timeline 播完 Length 默认 released(灯灭)。工具栏 Loop 按钮(x=358,标尺末端出循环标记)已开启但实测对控制器不生效;实际靠触发器 #13 FXLoop(Timeline Ended, Any →
get_timeline(tv.integer):start())重启实现无限循环。SC 的 release() 属 Timeline Released,不会触发 FXLoop 误重启。实测 FX=01 两次跨过 30s 边界 pos 回绕、state 恒 running、onstage 恒 true - 照度叠加不变:BRT/LUX/LX2 仍写 Group 0 master_intensity,作为总调光系数乘在 Timeline/Override 基础亮度之上
- Timeline GUI 操作要点:双击右侧 Built-in 面板效果进入放置模式(画布蓝框),再单击画布空白处提交(拖拽不可靠;落在已有块上会被拒绝);块只在选中时渲染;后块紧邻时前块 Release 字段锁定置灰(需在放置后块之前设好 Release);Ctrl+C/V 复制块无效
LX2 映射对照:1 Lux→6% / 10→19% / 100→38% / 500→51% / 1k→57% / 10k→75% / 100k→94% / 200k→100%(与 LUX 闭环相互独立,后到的帧生效)
闭环调光参数:死区 ±50 Lux,步进 = |误差|/目标 × 0.3(限幅 2%~20%),亮度限幅 5%~100%,1 秒渐变。
成果文件清单
Windows 侧 C:\Users\tonycao\work\lpc-rs485\
| 文件 | 说明 |
|---|---|
rs485_verification_plan.md |
设计/验证文档(含实测结论、通配符语法、API 要点) |
SETUP.md |
搭建步骤说明(硬件接线 / Designer 项目 / Timeline / 触发器 / Ubuntu 部署) |
USAGE.md |
使用说明(协议命令表 / 发送方式 / API 查询 / 常见问题) |
TEST_REPORT.md |
功能测试报告(50 项全部通过,含 FX/SC 现场回归取证) |
SUMMARY.md |
本文档 |
lpc_serial_brt.lua |
LPC 触发器 #2 脚本:BRT 手动亮度 |
lpc_serial_lux.lua |
LPC 触发器 #8 脚本:LUX 闭环自动调光 |
lpc_serial_lxt.lua |
LPC 触发器 #9 脚本:LXT 设目标照度 |
lpc_serial_lx2.lua |
LPC 触发器 #10 脚本:LX2 照度→亮度对数映射 |
lpc_serial_fx.lua |
LPC 触发器 #11 脚本:FX 效果选择(清 Override + 启 Timeline N) |
lpc_serial_sc.lua |
LPC 触发器 #12 脚本:SC 场景选择(释放 Timeline + Override 亮度预设) |
lpc_fxloop.lua |
LPC 触发器 #13 脚本:Timeline Ended → 重启该时间线(FX 循环播放) |
lpc_modbus_lux.lua |
LPC 触发器 #15 脚本:Modbus 照度闭环(复用 #8 逻辑 + lux_value 全局暴露 + lux_link_on 开关) |
lpc_web.py |
网页控制台 v3(部署于 Ubuntu ~/rs485-lpc/,http://192.168.58.7:8090):实时状态 + FX/SC/BRT(HTTP 触发器)+ 联动开关(#16/#17)+ 48h 历史曲线(30s 采样 LPC API,存 history.jsonl) |
lx2_test.sh |
LX2 映射回归(8 档照度→亮度对照,PASS=8) |
loop_test.sh |
BRT 闭环回归(5 项,PASS=5) |
lux_test.sh |
照度闭环回归(7 项:死区/降光/升光/上下限幅,PASS=7) |
api_smoke.sh |
LPC HTTP API 冒烟测试 |
test_rs485.py |
Ubuntu 串口收发工具(-l/-p/-b/-s/-w/-i) |
Test-Rs485.ps1 |
Windows 串口自收发测试 |
Verify-Rs485.ps1 |
离线 S1~S4 验证脚本(16/16 PASS,需 UTF-8 BOM) |
ui.ps1 |
Designer 2 GUI 自动化(点击/双击/右键/拖拽/SendKeys/截图/窗口最大化) |
Run-Remote.ps1 |
Posh-SSH 远程执行(Ubuntu 192.168.58.7) |
Get-Remote.ps1 |
Posh-SSH SFTP 下载 |
Designer 2 项目
| 文件 | 说明 |
|---|---|
0140650.pd2(本目录) |
项目文件(触发器 #1/#2/#8-#20 含 LuxPoll/LuxIn/LuxLinkOn/Off/LuxFadeSet/LuxPeriodSet/LuxDeadbandSet + 4 条 Loop Timeline,串口 RS485 4800 8N1),已上传 LPC(2026-10-10 19:56 归档) |
参考文档 docs\
| 文件 | 说明 |
|---|---|
renke-illuminance-485-200k-manual.pdf |
仁科光照度变送器(485 型 20w)使用说明书 |
modbus-illuminance-packet-formats.md |
仁科/耘农 Modbus 帧格式实测笔记 |
Ubuntu 侧(192.168.58.7,USB-485 = /dev/ttyUSB0)
| 路径 | 说明 |
|---|---|
~/rs485-lpc/loop_test.sh |
BRT 回归(与 Windows 侧同步) |
~/rs485-lpc/lux_test.sh |
照度闭环回归(已部署,7/7 PASS) |
~/rs485-lpc/api_smoke.sh |
LPC HTTP API 冒烟测试 |
~/rs485-lpc_test_rs485.py |
串口发送工具 |
验证记录
- 2026-10-09 离线 S1~S4:16/16 PASS
- 2026-10-09 BRT 闭环:5/5 PASS(100/0/50/80/25)
- 2026-10-09 LUX 闭环回归:死区 / 超目标降光 / 欠目标升光 / 上下限限幅 全部通过(lux_test.sh 7/7 PASS)
- 2026-10-09 LX2 照度指示映射:8 档对数映射全过(lx2_test.sh 8/8 PASS)
- 2026-10-09 Patch 32 通道(DMX 1~32)并 Upload;回归抽测 BRT=050→level 50、BRT=000→level 0 通过
- 2026-10-09 FX/SC:FX=01 常亮 255(T1 running)/ FX=02 呼吸(255→202 渐变)/ FX=03 闪烁(255/0 交替)/ FX=04 缓变(39→75→110 缓升);SC=02→128 / SC=04→0(Override 生效、Timeline 释放);FX 与 SC 互斥切换正常
- 2026-10-10 FX 循环修复:发现 FX 播完 30s 即 released 灯灭;Loop 工具栏按钮单独开启无效,加触发器 #13 FXLoop(Timeline Ended 重启)后实测 FX=01 连续 2 个循环 pos 回绕(29500→1550→…→27980→20)输出不掉 0;FX=02 跨 30s 仍 running;SC=04 释放后 35s 保持 released 无误重启
- 2026-10-10 照度功能验证:传感器在线(Modbus 地址 2 @4800,实测 26 Lux);手动 LUX 闭环升/降/死区正常(LUX=10→level 50→70,LUX=10000→50,LUX=500 死区不动);LX2=10→level≈20;lux_sync.py 端到端 26 Lux → BRT=73 → group level=73 → 输出随动
- 2026-10-10 LPC 自治改造:触发器 #14(每秒 Modbus 轮询)+#15(hex 通配符捕获+Lua 闭环)+#16/#17(联动开关)建成并上传;LPC 日志确认 #14 Matched 207 次 / #15 Captured 2 variables 244 次;闭环实测 lux 0→饱和→收敛 484(目标 500±50 死区),
/api/lua?variables=lux_value实时可读;HTTP 带参触发(?num=9&var=600)验证通过;网页控制台 v3 回归:FX=02→T2 running、BRT=060→level 60、luxlink off/on→lux_link_on false/true、history 采样含 LPC lux=479
关键技术结论(官方文档未载)
- 串行通配符语法:
<3d>= 恰好 3 位数字(数字在前,类型[cCdDxXsS]);?*#%均为普通字符 - Designer 2 触发变量:
get_trigger_variable(1)(v1 的variable[1]已废弃) - 组亮度 API:
get_group(n):set_master_intensity(level[, fade]),读当前值用grp.master_intensity_level.integer / .range - LPC HTTP API 免认证:
GET /api/group(level字段回读)、/api/trigger、/api/log - LPC 自治照度闭环(2026-10-10):Serial Input hex 匹配串支持通配符
<4c>(捕获 32 位)/<2c>(吞 16 位 CRC);Real Time 触发器高级掩码秒级分辨率可每秒触发 Output Serial 静态 hex 帧(Modbus 轮询);lux 经 Lua 全局变量 +GET /api/lua?variables=暴露(set_text_slot非 Lua 函数);HTTP 触发器带参POST /api/trigger?num=N&var=V。GUI 自动化:Serial Input/Output 的 String 框逐键输<不进(中文布局/过滤),须 Set-Clipboard + ^v 粘贴;Upload 对话框须先点选设备行再点 Upload All - Timeline 循环(2026-10-10):工具栏三个易混按钮——Hold At End(→|)、Loop(↻ 单环,运行时循环)、Enable Looping(↻ 两点,仅编辑器仿真,不上传)。实测 Loop 按钮开启(标尺末端有循环标记、保存、上传)后控制器仍在 Length 处 released;可靠方案是 Timeline Ended 触发器 +
tl:start()(Timeline Ended/Started/Released 在 Timeline=Any 时把时间线号捕获到变量 1;Ended 不在 Hold 时触发,Released 是独立类型,SC 释放不会误触发)。本地帮助:C:\Program Files\Pharos Controls\Designer 2\help\content\help\reference\timeline\working with timelines.htm
仁科照度计参考(esp32-voice 项目)
- 大量程 0~200000 Lux 型:32 位寄存器对 0x0002(hi)/0x0003(lo),单位 1 Lux
- ESP32 侧实现:
src/config.rs(MODBUS_ILLUMINANCE_REG=0x0002, COUNT=2)、src/modbus/master.rspoll_illuminance() - 文档:esp32-voice
docs/原件;本项目docs/已归档副本(20w 说明书 PDF + 帧格式笔记)