需要 Chromium 内核浏览器(Chrome / Edge 89+),并通过 https:// 或 http://localhost 访问;没有硬件也可以打开左侧「测试」页签,一键开跑合成数据案例。
调电机、看编码器、抓 IMU 数据,几乎每个做机器人的人都会长期挂着一个串口调试助手。传统工具是桌面软件:装一次、换台电脑重装一次,画的曲线只能截图,解析规则只能靠记事本抄。这个工具换了个思路——用 Web Serial API 把串口助手做成一个网页,打开即用,解析规则、通道配色、图表布局全部记在配置里,可以导出一份 JSON 带走。
它对齐 Vofa+ 与市面上常见串口助手的基础能力:设备连接与参数配置、手动信号线控制、文本与 HEX 双模式收发、实时数据监视、波形的时域与频域展示、定时轮询与触发应答、预设快捷发送。在此之上补了三件更贴近「做实验」的事:一是时间线录制——把流过的帧录下来,事后回放、导出、复盘;二是面向 AI 的调试回路——一键导出一份自包含的调试包(配置 + 帧结构说明 + 通道统计 + 原始样本 + 失败样本),AI 读完就能给判断,而改完规则的验证靠「用缓存字节重放」完成,不必重烧固件;三是声明式显示——图表的种类、绑定哪几路数据、用什么公式换算、颜色与量程,都由一份 JSON 描述符决定,想加一个新视图不需要改代码。而界面布局本身也是围绕「调试时眼睛在看什么」设计的:串口监视器是绝对主视觉(占主区约 62% 的上半部分),波形带在下方的独立滚动区,中间一条分割线调比例——见下一节的界面分区说明。
整个应用是纯静态文件:没有后端、没有第三方运行时依赖、没有构建步骤,与本站其他页面共用一套离线缓存。它的解析内核、绘图内核、插件系统都是本站自研,源码可读、可改,也自带一份给 AI 读的开发说明(见第 7 节)。
23:06:40.125)与相对秒(1.235s/1m02.346s)两种口径,且与正文用不同颜色区分;字号可调,数字可标红,解析失败的行整行标红并写出原因。key=value 与 key:value,整数小数统一处理;temp1/temp2 这类后缀数字保留为独立通道;一行里多个数值对全部提取。name:value)、Teleplot(>name:value)、JustFloat(Vofa+ 二进制 float32 小端 + 帧尾 00 00 80 7F 定界)、匿名 V1.0(帧头 AA AA + 功能字 + 长度 + int16 大端数据 + SUM8)四套社区事实标准。点一下即套用,并立刻用缓存里的原始字节重放一遍,当场看效果。(cur*24) 换算功率)→ 调量程与配色,全程是 JSON 配置,零代码执行;整套面板可导出为「面板包」分享。打开应用会看到四块区域,划分依据是「调试时眼睛真正盯着什么」——
| 区域 | 位置与占比 | 为什么这么分 |
|---|---|---|
| A 顶栏 | 顶部一行,固定 | 只放「一眼要看到的状态」与「必须随手能点到的开关」:运行绿圆标(运行中/已暂停/未连接三态,一键暂停继续)、连接状态与设备 VID/PID、连接/断开、←下位机/→下位机收发字节计数,右侧是帮助、AI、主题、恢复默认、收起左栏。 |
| B 左栏 | 左侧固定宽,可整栏收起 | 「设置」性质的页签:设备 / 解析 / 显示 / 通道 / 发送 / 图表 / 录制 / 数据。调参是低频动作,不该占据主视觉;需要时展开,调完收起把宽度让给主区。 |
| C 主区(上下分割) | 占屏最大,约 62% 给监视器 | 串口监视器是绝对主导区域——调试时 90% 的时间在看打印。它占上方约 62%,波形带在下方的独立滚动区;中间一条分割线可拖拽调比例(双击复位、↑↓ 微调、Home 复位,比例会记住)。日志与波形各自独立滚动、互不拉伸:波形面板是固定高度的,监视器再高也不会把它压成一条竖线。主区还能全屏(波形区与分割线一起让位)或收起(只留标题条)。 |
| D 发送条 | 底部单行 | 发送是高频动作,压缩成一行贴在底部,光标就近、不打断视线。 |
「主区工具条」上另外放了六个全局动作:全屏主区 / 收起主区 / 重置分割,以及「新图表」下拉 + 添加 / 清空面板 / 清空缓存。每个面板标题栏的六枚小按钮各司其职:主位上是 ⛶ 全屏与 ▭ 收起,工作区里是 ⇱ 移到主位、⇔ 加宽、▾ 收起、✕ 移除。
| 能力 | 桌面串口助手 / Vofa+ | 本工具 |
|---|---|---|
| 安装方式 | 下载安装包,分平台 | 打开网页即用,零安装 |
| 支持的设备 | 系统串口(含 USB 转串口驱动) | 浏览器可访问的串口(Chromium 系,需 https/localhost) |
| 界面布局 | 监视器与波形按软件排布,比例多数不可调 | 监视器主位 + 上下分割,分割线可拖拽调比例并记忆;面板固定高度、独立滚动、可拖高、可全屏 |
| 时间戳 | 多为相对秒或关掉 | 绝对时刻 / 相对秒双口径可选,毫秒不丢,且与正文用不同颜色区分 |
| 打印可读性 | 字号与配色多固定 | 刷新节流、字号(11~18px)、数字标红、失败行整行标红并标注原因 |
| 文本解析 | 需按工具规定的分隔符书写 | 同时识别 = 与 :,后缀数字自动分通道 |
| HEX 解析 | 一般只按固定偏移显示 | 帧头/帧尾/长度字段定界 + 字段表 + 四种具名校验(另可选「无」) |
| 开源协议预设 | 需自己去对文档抄参数 | FireWater / Teleplot / JustFloat / 匿名 V1.0 四套一键套用,套完立刻用缓存字节重放验证 |
| 自定义视图 | 改软件代码或写插件脚本 | 声明式 JSON 描述符,禁 eval,导入即用 |
| 配置迁移 | 导出注册表/配置文件 | 一键复制或导出 JSON,换机器粘贴即恢复 |
| 给 AI 的输入 | 靠人工截图/复制粘贴 | 一键导出「AI 调试包」(配置 + 帧结构说明 + 通道统计 + 原始样本 + 失败样本 + 排查提示),摘要可直接粘贴 |
| 规则改了要重跑硬件吗 | 要 | 不用:改完规则用缓存里的原始字节重放一遍即可当场验证 |
| 离线使用 | 天然离线 | 支持本地静态服务离线;还能导出单文件离线版(仅查看) |
| 数据留痕 | 取决于软件,多数导出为 CSV | 录制 JSON(可再回放)+ 五种格式导出 |
第一步,把设备接上。点「连接设备」,浏览器会弹出一个端口列表(这一步必须由你亲手点,浏览器不允许网页自动打开串口)。选好设备后按你固件的设置调整波特率——默认 115200。如果你用的是 Arduino 或 ESP 系列,打开串口的瞬间 DTR 拉低会让板子复位,工具会显示「复位等待」,等它结束再发指令。手边没有硬件也不要紧:点「进入演示模式」,工具会用合成数据(位置/速度/电流/温度/母线电压五路正弦与噪声信号)走完全部流程,包括发送后的回显,用来验证解析规则刚刚好。
第二步,告诉它数据长什么样。串口来的数据无非两种形态。文本形态最常见,一行里写着键值对,比如 temp=25.3, cur:1.02——这种情况下什么都不用配,工具会自动把出现过的键建成通道,等宽曲线立刻就有。如果是 二进制帧,切到「十六进制」模式:先定义帧结构(帧头 AA55?有没有长度字段?帧尾是什么?有没有校验和?),再逐个字段声明它从第几个字节开始、是什么类型、要不要乘缩放系数。逗号分隔的演示帧结构可以点「套用示例」一键填入,对着改最快;如果你的设备已经在用开源生态的协议,直接点「解析」页签顶上的预设按钮(FireWater / Teleplot / JustFloat / 匿名 V1.0),工具会套好后立刻拿缓存数据重放一遍给你看效果。
第三步,挑一个顺眼的视图。切到「图表」页签(或直接用主区工具条上的「新图表」下拉),从七种渲染器里选一个加到工作区:看趋势用时域折线,查振荡找频域谱,盯一路即时值用仪表盘,看电机电流与位置的相位关系用二维轨迹。加进来的面板是固定高度的,右下角拖一下就能调高;点标题栏的「编辑」绑定它要显示哪几路通道、窗口显示最近多少点、纵轴要不要固定量程、每一路用什么颜色。想换算成更直观的量,就在「映射公式」里写一行算式:(cur*24) 把电流换算成功率,sqrt(ix*ix+iy*iy) 求合成矢量幅值。公式只支持四则运算与白名单数学函数,用通道名当变量,不支持任何脚本执行。
这套配置会自动存在本机浏览器里,下次打开还在原地。要换台电脑、或者分享给同学,去「数据」标签页复制配置,或者干脆导出「面板包」——里面装着图表框布局与通道配色。
这一节回答两个最常被问到的问题:默认格式到底是什么?我自己的协议怎么配上去?先说结论——文本数据几乎不用配,二进制帧需要你把帧结构告诉它。配好之后,任何被解析出来的数值字段都会自动成为一路通道,可以直接进时域折线、频域谱、柱状图、仪表盘或表格。
每行写一个或多个键值对,分隔符 = 与 : 都识别,数值对之间用逗号或空格分开,后缀数字(temp1 / temp2)会各自成为独立通道,数值支持整数、小数与科学计数法。若设备发的是没有换行的裸流,工具会在 60ms 静默后按一帧处理,不会一直卡着不动。
temp=25.3, cur:1.02
pos:90 vel=12.5
acc1=0.2, acc2=0.3
点「套用示例」或进入演示模式时用的就是这一帧。它不是任何标准协议,只是一个「结构完整、便于对照」的示例,你可以照它的形状改成自己的协议:
| 偏移 | 字节 | 含义 | 对应配置 |
|---|---|---|---|
| 0-1 | AA 55 | 帧头 | 帧头 = AA55 |
| 2 | seq | 序号,0~255 循环,用来观察丢帧 | 无需配置(演示帧自动填) |
| 3 | 06 | 长度字段 = 载荷长度 6 | 长度字段:偏移 3 / 1 字节 / 载荷长度 |
| 4-5 | pos | int16 小端,×0.01(度) | 字段 pos / int16 / 偏移 4 / 缩放 0.01 |
| 6-7 | cur | int16 小端,×0.001(安培) | 字段 cur / int16 / 偏移 6 / 缩放 0.001 |
| 8-9 | temp | int16 小端,×0.01(摄氏度) | 字段 temp / int16 / 偏移 8 / 缩放 0.01 |
| 10 | sum8 | 帧首到第 9 字节的累加和低 8 位 | 校验:累加和(8) / 起始 0 / 结束 -1 |
演示波形由三条互不相同的信号合成:pos = 90·sin(2π·0.5t)、cur = 3.2·sin(2π·0.5t+0.6)、temp = 42 + 3·sin(2π·0.02t)。所以时域上能看到慢变与快变叠加,频域谱上在 0.5Hz 附近有明确峰值——这也正好用来验证频域面板工作是否正常。
AA55)、帧尾(如 0D0A);留空表示不按该方式定界。(cur*24) 求功率),在面板「编辑」里写映射公式,用通道名当变量。
如果你的设备已经在用某个开源生态的协议,不必从零拼帧结构——「解析」页签顶上有四枚预设按钮,点一下即套用,并且会立刻用缓存里的原始字节按新规则重放一遍,当场看效果(不必让硬件重跑)。套用后仍可手动微调任何一项。
| 预设 | 来源 | 帧结构 | 示例 |
|---|---|---|---|
| FireWater | Vofa+ 文本协议 | 文本 name:value,按换行分帧;同一行可写多组,逗号或空格隔开;分隔符 = 与 : 都认 | temp:25.3, cur:1.02, rpm:1800 |
| Teleplot | Teleplot / VS Code 插件 | 文本 >name:value,前缀 > 只用于标识绘图变量,解析时自动忽略 | >rpm:1800 |
| JustFloat | Vofa+ 二进制协议 | float32 小端 ×N,帧尾固定 00 00 80 7F(即 +Inf)。无帧头,按帧尾定界;不校验 | 00 00 00 00 | 00 00 80 3F | 00 00 00 40 | 00 00 40 40 | 00 00 80 7F(4 路 float:0.0 / 1.0 / 2.0 / 3.0) |
| 匿名 V1.0 | 匿名上位机 / 野火例程 | 帧头 AA AA + 功能字(1B) + 长度(1B,数据段字节数) + 数据(int16 大端) + SUM8(从帧头累加取低 8 位) | AA AA 01 06 00 64 00 32 00 00 F1(func=1,x=1.00,y=0.50,z=0.00) |
定时轮询适合周期性问一个寄存器:填好内容和间隔(最小 20ms),勾上启用即可,工具会用与配置对账的方式管理计时器,改内容或改间隔下一次发送就生效,不用重启。触发应答适合「设备上报某状态,我立刻回一条控制字」的闭环:接收内容里出现你写的匹配词就自动发送应答。这里有一层保护——单条规则 250ms 冷却,自动发送每秒最多 30 次;如果匹配词与应答内容互相包含,工具会限流并提示,避免把串口打满。预设发送是给常用指令准备的:绑一个单字符快捷键(焦点不在输入框时生效),顺手敲一下就把指令发出去;还能填「期望回包」与超时时间,收到就提示往返耗时,超时也会明确告诉你——这比盯着屏幕数秒数靠谱。
调完一轮,最珍贵的往往是中间那段异常数据。录制标签页点「开始录制」,工具会把这期间流过的每一帧(含时间戳、方向、原始 HEX、文本与解析值)存进内存;停止后可以回放——按原始时间关系重新喂给图表,让当时的抖动重演一遍——也可以导出成 JSON 存档、或者粘回另一台机器继续分析。需要长时间留档时,用「数据」标签页导出解析结果 CSV 或原始记录 CSV:CSV 带 UTF-8 BOM,Excel 双击打开中文不乱码。
| 场景 | 能不能用真实串口 | 原因 |
|---|---|---|
| Chrome / Edge 89+ 访问 https:// 或 http://localhost | ✅ 可以 | Web Serial 要求安全上下文 |
| 直接双击本地 HTML 文件(file://)打开 | ❌ 不可以 | file:// 不是安全上下文,浏览器拒绝授权串口 |
| Firefox | ❌ 不可以 | 截至目前未实现 Web Serial |
| Safari / iOS / Android 浏览器 | ❌ 不可以 | 未实现 Web Serial,且移动端无系统串口授权通道 |
| 任何浏览器 + 演示模式 | — 用合成数据 | 解析、绘图、面板、录制、导出全部可用,仅不联真机 |
_本地工具/启动教学页面.bat(或任意静态 HTTP 服务)访问,而不是双击 HTML。页面顶部也会在检测到不支持时给出具体原因。
另外三条工程限制,用之前知道比踩到再查省事:改口串口参数必须关端口重开——波特率、数据位、停止位、校验、流控都不能热改,工具会自动完成「关闭→重开」,大约四分之一秒内不可发送。开启硬流控后不再手动控制 RTS——两者会打架,工具会自动让出控制权。页面关闭前会主动释放端口——否则下次打开会提示端口被占用,如果你强行关掉标签页导致占用,拔插一次设备即可。
这个应用不是一次性页面,而是按「可被复用的基座」写的。它把串口调试这类应用拆成了十四个职责单一的模块,全部挂在同一个命名空间 window.SerialLab 下,模块之间不互相持有引用、只通过事件总线通信:
| 模块 | 职责 |
|---|---|
util | 通用工具(叶子模块,零依赖) |
core | 事件总线、运行状态、配置默认值/版本迁移/持久化 |
codec | UTF-8 多字节切分保护、按行分帧、按帧头/帧尾/长度字段收帧、四种校验和(另可选「无」) |
parser | 文本 key=value/冒号解析、HEX 结构表解析、后缀数字分通道 |
expr | 安全表达式求值(词法分析 + 调度场 + RPN,禁 eval) |
fft | 零依赖 radix-2 FFT、汉宁窗、单边幅值谱 |
datastore | 环形缓冲(零分配遍历)、通道元数据、原始帧记录、即时统计 |
transport | Web Serial 状态机、读循环、写队列、参数变更重开、内置演示源 |
plugins | 声明式插件注册表 + 七个内置渲染器 + 面板包导入导出 |
views | 面板增删排序折叠、requestAnimationFrame 节流渲染 |
timeline | 录制 / 暂停刷新 / 回放 / 录制文件导入导出 |
exporters | CSV/JSON/BIN/TXT 导出、配置导入导出、单文件离线版装配 |
ui | DOM 绑定、控件与配置双向同步、对话框、主题、快捷键、发送引擎 |
app | 唯一编排者:装配数据管线并启动 |
同时,应用目录里自带三份给 AI 直接读取的文档:llms.txt(速览与关键约定)、AGENTS.md(工程硬约束与协作规则)、skills/html-webserial-app/SKILL.md(从零开发同类应用的完整流程与踩坑清单)。如果你想让 AI 帮你做一件类似的事——做一个网页端 CAN 调试器、一个串口协议分析器,或者在这个应用上加新图表、新发送方式——把这三份文档连同对应模块贴给它,比口头描述快得多。应用内「AI 开发提示词」按钮还提供了一份浓缩版,可一键复制或下载为 txt。
更直接的一条路:让 AI 来读你的现场数据。调试硬件时最费时间的往往不是点按钮,而是「把现在的现象讲清楚」——截图讲不全,复制日志又丢掉了解析上下文。所以这个应用把「给 AI 的输入」做成了一个按钮:「显示」页签里的 「导出 AI 调试包」会生成一份自包含 JSON,里面装着
同时会产出一段纯文本摘要并自动复制到剪贴板——不想传文件时直接粘进对话框即可。拿到 AI 给出的规则修改后,回到应用「按当前规则重放缓存」,用缓存里的原始字节重新解一遍就能验证,形成「AI 读数据 → 发现规律 → 改规则 → 当场重放验证」的闭环,不必让硬件重跑。这也是「实时暂停继续」在架构上要配合的一环:运行绿圆标暂停的只是屏幕刷新,数据仍在后台缓冲,所以暂停期间的数据同样能进调试包、同样能被重放。
transport 换成 WebSocket 或 Web Bluetooth 传输层,整套解析、绘图、录制与导出链路可以原样复用;把 plugins 的渲染器注册表加一项,就有了新图表类型;把 parser 的字段表扩成完整的 CAN 报文定义,就有了一个浏览器内的总线调试器。三条路都不需要改动数据管线的其他部分。
上面两条路(调试包 / 复制提示词)仍需要人做一次「搬运」。V2.2.2 起补上了完全自动的一条:仓库里的 _本地工具/serial-bridge 是一个本地串口桥(Node.js + serialport),它直接 require 本应用的 9 个真源模块复用同一份解析内核——桥解析出的通道值与网页端逐字节一致,不存在两套实现各算各的。桥已封装为 MCP server(Model Context Protocol),接入后任何支持 MCP 的 AI 会话都能直接调用五个工具:
| MCP 工具 | 作用 |
|---|---|
serial_list | 枚举本机可用串口 |
serial_read | 按当前规则采一段数据(可指定时长/波特率/协议预设,产出通道值 + 完整调试包) |
serial_write | 向串口发送指令(HEX 或文本)——危险动作,AI 会先征求你确认 |
serial_parse | 离线解析一段 HEX(不碰硬件):改规则试错、离线重放的主力工具 |
serial_assert | 判据断言:--expect "x>0.5; y.max<=1",退出码 0=通过 / 2=不通过——AI 自动判定「这轮改得对不对」的机器可读出口 |
三步接入(详细命令与参数见 _本地工具/serial-bridge/README.md):
_本地工具/serial-bridge 执行 npm install(Node 18+,仅本地工具目录有依赖,站点本体仍是零依赖);{"command": "node", "args": ["<仓库根>/_本地工具/serial-bridge/bridge.mjs", "mcp"]},路径换成你自己的仓库位置;除了 MCP,还有两条不依赖任何协议的通路:浏览器持续落盘(应用内勾选「持续写入本地文件」,NDJSON 逐行追加,AI 拿文件路径就能读)与 HTTP 收件箱(勾选「HTTP 上报」+ 运行 python _本地工具/serial-inbox.py,数据实时落到 latest.brief.txt 等文件)。AI 拿到导出的数据文件后,可以像操作普通文件一样下载、diff 两轮数据、甚至帮你 git 提交上传 GitHub——这些都不需要额外权限,走的就是普通文件系统。隐私边界:串口数据只在你的本机流转,桥与收件箱没有任何上传代码;AI 能读到什么,取决于你让它读哪个文件。
| 现象 | 先查这里 |
|---|---|
| 点「连接设备」没有任何反应或提示不支持 | 看页面顶部横幅给的具体原因:多半是用了 file:// 或非 Chromium 浏览器 |
| 连上了但一条数据都没有 | 波特率是否与固件一致;是否在「复位等待」窗口内;文本模式下设备是否发送了换行符(没有换行的裸流会等 60ms 静默后按一帧显示) |
| 有数据但通道一直是空的 | 数据形态与解析模式不匹配:文本模式只认 键=值/键:值;二进制帧要切到 HEX 模式并配置字段表 |
| HEX 模式收到的是残帧、校验和一直不匹配 | 逐项核对帧结构:帧头写对了吗?长度字段的偏移是相对「整帧起始(含帧头)」的吗?有校验和时有没有选对类型?长度字段的含义是「载荷长度」还是「整帧长度」? |
| 曲线像一团噪声 | 纵轴量程被固定住了;点图框「编辑」把纵轴上限/下限清空即回到自动量程 |
| 波形被监视器压成一条竖线 / 拉得看不出来 | V2.2.1 起波形面板是固定高度、独立滚动的,不会被监视器拉长。若仍觉得挤:双击中间的分割线复位到 62%,或拖分割线把主区比例调小、拖面板右下角把手把波形调高,也可以点「收起主区」把监视器压成标题条 |
| 时间戳显示的是「多少 s」,不是真实时刻 | 那是「相对秒」口径。切到「显示 → 时间戳口径 → 绝对时刻」即可显示 23:06:40.125(V2.2.1 起默认就是绝对时刻) |
| 点了「暂停刷新」,数据会不会丢 | 不会。暂停只停屏幕重绘,传输、分帧、解析与缓冲照常进行;恢复后数据都在,暂停期间的数据同样能进 AI 调试包、也能被重放 |
| 换了协议、改完规则想验证,要重烧固件吗 | 不用。点「显示 → 按当前规则重放缓存」,用缓存里的原始字节按新规则重新解一遍即可当场看结果 |
| 发送没反应 | 先看底部提示条:未连接、复位等待中、或 HEX 内容不是偶数位十六进制,都会明确提示 |
| 配置丢了 | 换浏览器、清缓存、隐私模式都会导致本地存储不可用;重要配置请用「导出文件」留一份 |