# Pharos LPC RS485 串口链路验证 —— 设计与实施计划 > 目标:PC(USB-485)与 Pharos LPC 控制器共用一条 RS485 总线,实测验证 > **PC 发命令 → LPC Serial Input 触发器 → Lua 脚本 → 时间线(场景)整体亮度调节** 全链路, > 以及 LPC→PC 反向应答。判据 = LPC 实际行为(灯光变化 / 日志 / 回包),非文档推断。 --- ## 0. 前置条件 | 项 | 动作 | 状态 | |----|------|------| | P1 | USB-485 插在 **Ubuntu(192.168.58.7)**:`/dev/ttyUSB0` = FTDI FT232R(S/N B002S2QN),用户在 `dialout` 组,pyserial 可用 | ✅ 已通 | | P2 | Windows 本机只做离线验证与远程驱动(Posh-SSH/SSH 免密已打通);Windows 板载 COM1~6 与 USB-485 无关(已实测:全为 ACPI\PNP0501) | ✅ 已确认 | | P3 | LPC 上电联网,Designer 2 项目可烧录;串口模式选 **RS-485**,波特率两端一致(先 9600) | 待执行 | | P4 | 项目内已建测试时间线 1~3(场景素材),可通过 HTTP API 或触发器手动启动 | 待执行 | | P5 | 接线:USB-485 A/B/G ↔ LPC 端子 A(−)/B(+)/G,共地 | 待执行 | | P6 | 参考依据:Serial_Integration.pdf(触发器/缓冲匹配机制)、Pharos Scripting Guide(`variable[1]`、`get_timeline()`) | 已读 | --- ## 1. 系统架构与接口定义 ``` PC (Test-Rs485.ps1) ──USB── USB-485 ──A/B/G── RS485 总线 ──A/B/G── LPC 串口 主站,只发命令+收应答 Serial Input 触发器 → Lua → set_intensity ``` ### 1.1 命令协议(ASCII,行尾 `\n`=0x0A 作帧界) | 命令 | 方向 | 含义 | LPC 侧响应 | |------|------|------|-----------| | `BRT=NNN\n` | PC→LPC | 组 0 整体亮度 = NNN%(3 位补零) | 触发器 #2 挂 `lpc_serial_brt.lua` | | `LUX=NNNNNN\n` | →LPC | 实测照度 0~200000 Lux(6 位补零)→ 闭环自动调光 | 触发器 #8 挂 `lpc_serial_lux.lua` | | `LXT=NNNNNN\n` | →LPC | 设定目标照度(全局变量 `lux_target`,默认 500) | 触发器 #9 挂 `lpc_serial_lxt.lua` | > 注:早期设想的固定五档 `BRT_x`、`OK\n` 应答、备选时间线方案均未采用;实测语法以 §6.4 为准。 ### 1.2 LPC 触发器配置(实际部署) | # | 类型 | Match string | 动作 | |---|------|--------------|------| | 2 | Serial Input | `BRT=<3d>` | Run Script(Quick Script = `lpc_serial_brt.lua`) | | 8 | Serial Input | `LUX=<6d>` | Run Script(`lpc_serial_lux.lua`) | | 9 | Serial Input | `LXT=<6d>` | Run Script(`lpc_serial_lxt.lua`) | `lpc_serial_brt.lua` 实际内容见本目录文件(Designer 2 用 `get_trigger_variable(1)`, `variable[1]` 为 v1 旧语法已废弃)。 --- ## 2. 验证项分解(判据=实测) | ID | 类型 | 验证内容 | 方法 | PASS 判据 | |----|------|----------|------|-----------| | S1 | 离线 | 测试工具帧编码正确 | `Verify-Rs485.ps1`:`BRT=80\n` → 7 字节含 0x0A,转义替换逻辑与工具一致 | 字节序列 42 52 54 3D 38 30 0A ✓ | | S2 | 离线 | 行帧解析正确 | 多行混入 `\r\n` 混合行尾的缓冲拆分 | 每行完整、无串包 ✓ | | S3 | 离线 | Lua 脚本结构完备 | 静态检查:引用 `variable[1]`、边界钳位、对每条时间线调用 `set_intensity` | 检查项全过 ✓ | | S4 | 离线 | 工具参数模式完备 | `-ListPorts/-Send/-Listen/-Interactive` 帮助与执行路径 | 各模式可运行 ✓ | | H1 | 硬件·单机 | USB-485 发送路径 | 已执行:端口打开/写入无错,**无自回显**(FT232+自动收发适配器不发回显属正常,判 TX 通需上真机) | ✅ TX 路径 OK | | H1b | 硬件·总线 | 被动监听总线流量 | 已执行:9600 波特率监听 5s | 总线静默(LPC 未发包/未接入) | | H2 | 硬件·总线 | 链路通 + 固定档触发 | 发 `BRT_50\n` | LPC 触发器日志出现对应触发;灯光变化 | | H3 | 硬件·总线 | A/B 极性 | H2 无反应时对调 A/B 重测 | 对调后 H2 通过 | | H4 | 硬件·总线 | 连续调光 + 通配符捕获 | 循环发 `BRT=0,25,50,75,100` | 灯光台阶变化;`variable[1]` 数值正确 | | H5 | 硬件·总线 | 连续扫描鲁棒性 | 0→100 步进 5 循环 3 遍,行间隔 100ms | 全部命中无丢帧(串行缓冲匹配→清空机制下无粘包) | | H6 | 硬件·总线 | 反向应答 | 触发器挂 Output Serial `OK\n`,PC `-Listen 3` | PC 收到 `OK` | | N1 | 负例 | 波特率不一致 | 双端 9600/115200 错配 | 收乱码或无触发(预期现象,作对照) | | N2 | 负例 | 串口模式误设 RS232 | 模式错配 | 无触发(预期现象) | --- ## 3. 执行阶段 - **阶段0 离线**(本机即可):运行 `Verify-Rs485.ps1` → S1~S4 全 PASS。 - **阶段1 单机**:USB-485 单独接总线 → H1(确认 PC 发送路径)。 - **阶段2 打通**:接入 LPC → P3 配置 → H2/H3(固定档,先证明物理链路与触发机制)。 - **阶段3 连续调光**:H4 → H5(通配符 + Lua 连续值)。 - **阶段4 反向与负例**:H6 应答;N1/N2 记录对照现象。 - **阶段5 收尾**:实测结论回填本表状态列,修正文档中"以版本说明为准"的待确认项 (通配符语法、`set_intensity` 可用性、老 DE-9 机型跳线)。 ## 4. 风险与对策 | 风险 | 对策 | |------|------| | A/B 标各厂家不统一,接反无响应 | H3 对调实验,1 分钟排除 | | 通配符语法随版本差异 | 首测用固定档触发器(零语法依赖),再看 Log Console 中实际收到的字节核对 Match string | | 串行缓冲粘包/半包(连续发送过快) | 帧尾 `\n` + 行间隔 ≥100ms;H5 专门验证 | | RS485 半双工冲突 | 约定 PC 为主站,LPC 仅应答,不同时发送 | | `set_intensity` 不可用 | 备选:多条固定亮度时间线副本切换(§1.2) | | 老 LPC(DE-9)RS485 为跳线配置 | 查对应安装指南;验证前确认跳线 | | USB-485 被其他程序占用 | 探测工具报告"端口被占",先关 SymphoLight 等软件 | ## 6. 实测发现与自动闭环验证(2026-10-09 更新) ### 6.1 已确认的环境事实 | 项 | 结果 | |----|------| | LPC 位置 | **192.168.58.109**(Web 标题 `Pharos LPC 0140650`,MAC `00:13:B2:01:39:1A`) | | HTTP API | 免认证可用;`GET /api/timeline`、`GET /api/group`、`GET /api/trigger`、`POST /api/timeline`(HTTP 204)实测通过 | | 项目内容 | 1 条时间线(Timeline 1,未运行);**1 个组:num=0 "All Fixtures"(level:100)**;触发器仅 1 个 Startup(eDMX 直通)——**无串行触发器** | | 亮度 API 修正 | Lua `Timeline` 对象无 `set_intensity`;正确做法 = `get_group(n):set_master_intensity(level[,fade[,delay]])`(0.0~1.0),`/api/group` 的 `level` 字段可回读 → **闭环判据** | | 灯具 | `/api/fixtures` 返回空 —— 调组亮度可能无可见光效,但 level 回读仍可全自动判定 | ### 6.2 闭环自动验证(Ubuntu 上 `loop_test.sh`) ``` 发送 BRT= (RS485) → sleep 1 → GET /api/group 读 level → 与 v 比对 → PASS/FAIL 用法: bash loop_test.sh 80 (单点) bash loop_test.sh loop (扫 100/0/50/80/25 汇总 PASS/FAIL) ``` ### 6.3 最终验证结果(2026-10-09 全部通过) | 验证项 | 结果 | |--------|------| | 离线 S1~S4 | ✅ 16/16 PASS(Verify-Rs485.ps1) | | H1 RS485 发送路径 | ✅(FT232R 无自回显属正常,LPC 日志证实收包) | | H2/H3 链路+触发 | ✅ LPC 日志 "RS485 input (N bytes)" + "Trigger 2 (Serial Input)" | | H4/H5 连续调光+鲁棒性 | ✅ loop_test.sh:PASS=5 FAIL=0(100/0/50/80/25) | | H6/N1/N2 | 按需(协议已闭环,负例未单测) | ### 6.4 实测确认的关键语法(文档未载,逆向自 pharos_designer.exe) | 项 | 结论 | |----|------| | 串行通配符 | 尖括号语法 `<...>`:`<3d>` = 恰好 3 位数字;类型 `[cCdDxXsS]`;可带 `` 变体;`` 仅匹配 1 个字符;`?` `*` `#` `%` 均为普通字符 | | 触发变量 | Designer 2 用 `get_trigger_variable(1)`(v1 的 `variable[1]` 已废弃) | | 亮度 API | Timeline 无 set_intensity;用 `get_group(n):set_master_intensity(level)` | | 最终协议 | PC 发 `BRT=NNN\n`(3 位补零,0~100)→ 组 0 整体亮度 = NNN% | | 照度协议 | 发 `LUX=NNNNNN\n`(6 位补零,0~200000 Lux,仁科大量程)→ 闭环自动调光(lpc_serial_lux.lua);`LXT=NNNNNN\n` 设定目标照度(默认 500 Lux,全局变量 lux_target) | | 照度实测 | 2026-10-09 闭环验证通过:BRT=050→level 50;LXT=000300 设目标 300 Lux;LUX=001000(超目标)→ 亮度 50→30(降 20% 步进);LUX=000100(低于目标)→ 30→50(升 20%),方向与步进均正确。触发器 #8 Lux Auto Dim / #9 Lux Target Set 已上传 LPC | | LX2 指示模式 | 触发器 #10 Lux Display Map `LX2=<6d>`:照度→亮度对数映射 `level=log(lux+1)/log(200001)`(0.5s 渐变),灯即照度计;lx2_test.sh 8/8 PASS(0/10/100/500/1k/10k/100k/200k Lux → 0/20/38/51/57/75/94/100%) | | 仁科寄存器 | 大量程 0~200000 Lux 型用 32 位寄存器对 0x0002(hi)/0x0003(lo),单位 1 Lux(esp32-voice src/config.rs MODBUS_ILLUMINANCE_REG=0x0002, COUNT=2;poll_illuminance() in src/modbus/master.rs);0~65535 型 reg 0x0006 单位 1 Lux | | 工具链 | Designer 2 GUI 全程自动化操作(截图视觉闭环 + SendKeys/剪贴板);Download/Upload 同步项目 | API 无法增改项目触发器,须在 Designer 2 中完成并上传: 1. LPC 设置:Serial Port → 模式 **RS-485**,波特率 **9600**(已完成) 2. 触发器:#2 `BRT=<3d>`、#8 `LUX=<6d>`、#9 `LXT=<6d>`,各挂对应 Quick Script(已完成并上传) 3. 回归:`bash loop_test.sh loop`(BRT 5 项)+ `bash lux_test.sh`(照度闭环 7 项) ## 7. 附录 ### 7.1 工程文件 | 文件 | 用途 | |------|------| | `test_rs485.py` | **Ubuntu 侧主工具**(pyserial):`-l` 枚举 / `-s` 发送 / `-w` 监听 / `-i` 交互 | | `Test-Rs485.ps1` | Windows 备用工具(当前无 USB-485,仅保留) | | `lpc_serial_brt.lua` / `lpc_serial_lux.lua` / `lpc_serial_lxt.lua` | LPC 触发器 #2/#8/#9 Quick Script | | `Verify-Rs485.ps1` | Windows 离线验证 S1~S4(已通过 16/16) | | `loop_test.sh` / `lux_test.sh` | Ubuntu 闭环回归:BRT 5 项 / 照度 7 项(均已 PASS) | | `api_smoke.sh` | LPC HTTP API 冒烟测试 | | `0140650.pd2` | Designer 2 项目文件(已上传 LPC) | | `ui.ps1` / `Run-Remote.ps1` / `Get-Remote.ps1` | GUI 自动化 / SSH 远程执行 / SFTP 下载 | | `docs/` | 仁科 20w 说明书 PDF + Modbus 帧格式实测笔记 | ### 7.2 常用命令(Ubuntu 192.168.58.7) ```bash # 枚举串口,确认 /dev/ttyUSB0 存在且权限可读(不在 dialout 组时用 sudo) python3 test_rs485.py -l # H1 单机自发自收(确认适配器 TX 路径) python3 test_rs485.py -p /dev/ttyUSB0 -b 9600 -s 'BRT=80\n' -w 2 # 手动亮度 / 交互 python3 test_rs485.py -p /dev/ttyUSB0 -b 9600 -s 'BRT=080\n' -w 3 python3 test_rs485.py -p /dev/ttyUSB0 -b 9600 -i # 照度闭环:设目标 500 Lux / 上报实测照度 python3 test_rs485.py -p /dev/ttyUSB0 -b 9600 -s 'LXT=000500\n' python3 test_rs485.py -p /dev/ttyUSB0 -b 9600 -s 'LUX=001000\n' # 回归 bash loop_test.sh loop # BRT 5 项 bash lux_test.sh # 照度闭环 7 项 # 无 pyserial 时 sudo apt install python3-serial ``` ### 7.3 参考资料 - Serial Integration 应用说明:https://dl.pharoscontrols.com/documentation/application_notes/Serial_Integration.pdf - 针脚定义(Pinouts):https://dl.pharoscontrols.com/documentation/single_line_diagrams/9401%20Detailed%20wiring%20examples_pinouts.pdf - Designer 2 在线帮助:https://dl.pharoscontrols.com/software_help/designer2/Default.htm - Designer 2 用户手册(A4 PDF):https://dl.pharoscontrols.com/documentation/manuals/Pharos%20Designer%202%20User%20Manual%20-%20A4.pdf