自制工业控制系统:G代码与3B解析实战——模态状态机、象限重建与段表生成
Contents
起因
机床界面篇定了编程屏和仿真屏,两块屏吃的是同一样东西:段表——直线和圆弧排成的几何清单,仿真渲染它,插补执行它,运行屏显示"当前执行第几段"查的还是它。段表从哪儿来,就是这篇的事:把程序文本变成段表。
程序文本有两代,都得吃。老厂里流通的存量几乎全是 3B——HF 时代三十年攒下来的程序,老师傅图纸柜里的 U 盘拷出来的全是它;新 CAD/CAM 后处理吐出来的又是 G 代码。只吃一样,机器要么接不上行业存量,要么对不上新工具。这两代语言各自的来历——3B 为什么五个字段全无符号、G 代码的模态为什么存在——单独开了一篇:G代码与3B代码详解。解析器还是应用篇里少数不依赖运动控制卡手册就能动工的模块:输入文本、输出段表,纯函数,没有硬件依赖——顺手把它做成全系统第一个能在开发机上跑 cargo test 的模块,测试向量当回归资产攒起来。
一、先定段表:解析器的输出契约
先把输出定死,再写解析。段表是编程、仿真、插补三方的契约,它的形态比任何一方的代码都稳定:
|
|
三条设计决定:
- 绝对 µm 一口径。G 代码的 I J 是相对起点、3B 的坐标是"相对起点或圆心"还无符号——这些方言差异全部在解析器内部归一成绝对坐标。下游的仿真和插补不应该知道程序原来是什么格式
- 补偿和锥度只记录、不展开。G41/G42 的转接拐角、G51 的 UV 联动量是几何变换,归插补和补偿篇做。解析器忠实记录"从这段起补偿左、D03"就够——层次混了,解析器会变成半个插补器,两头都不好改
- ue/ve 做成 Option。AutoCut 系的方言用 XYUV 四坐标直接编锥度,普通程序没有 UV,Option 表达"这一段带不带锥度联动",不带就是平面切割
二、G 代码:词法、模态与我们的方言
先说丑话:G 代码没有强制标准,每家控制器的方言都不一样。所以第一件事是把我们自己的子集定义清楚,子集之外的东西一律显式报"不支持的代码",不静默忽略——静默忽略等于给碰撞和废件埋雷。
词法简单:一行一个块,块里是"字母+有符号数"的词序列。(括号注释)、;行注释、行首 N 号(解析后丢弃,只保留行号)、/ 块删除开关(界面上一键切换跳过)。词法之前先过一遍全角字符检查——中文输入法敲出来的G和X是全角,肉眼分不出来,词法直接报"全角字符",错误信息里把行列出来。
真正要当心的是模态(续效)。G01 之后连续十行只有坐标,运动方式还是 G01——解析器是个状态机,每个模态组各自记住当前值:
| 组 | 代码 | 语义 |
|---|---|---|
| 运动 | G00/G01/G02/G03 | 快速定位/直线/顺圆/逆圆,续效 |
| 距离 | G90/G91 | 绝对/增量,续效 |
| 平面 | G17 | 只支持 XY 平面;G18/G19 报不支持 |
| 补偿 | G40/G41/G42 | 丝径补偿关/左/右 + D 号 |
| 锥度 | G50/G51/G52 | 锥度关/左/右 + A 角度(毫度存) |
| 坐标系 | G54–G59 | 工件坐标系偏置,值在参数区 |
| 暂停 | G04 X/P 毫秒 | 非续效,只在本块有效 |
| 辅助 | M00/M01/M02 | 程序停/选择停/结束 |
坑:数值不用 f64,手工解析成定点 µm。 0.1 在二进制里是无穷小数,f64 累加几千段能漂出 1µm——对 0.005mm 精度目标的机器这是白送的系统误差。手工解析:整数部分 ×1000,小数逐位 ×10^(2−i),一步到位是 i64。配套两条纪律:小数超过 3 位(mm 的 µm 分辨率)报错不截断——静默吃掉 0.0004 的差值,闭环里永远查不出来;遇到 , 报"疑似德语区小数点"的专用错误码——德语区 CAM 导出的 X12,345 真实存在,解析成 12 和 345 两个字就是废件(CSV 分隔符同一个坑,国际化篇)。
圆弧两种写法都收,但偏爱 I J:G02 X Y I J 圆心是起点相对增量,几何无歧义;G02 X Y R 半径格式一个 R 对应两个圆心,按惯例正 R 取小圆弧(≤180°)、负 R 取大圆弧,弦长大于 2|R| 报错。R 格式解析完同样折算成绝对圆心进段表。
I J 格式自带一个白捡的校验——起点半径和终点半径必须一致:
|
|
整圆是 I J 的专属能力:X Y 省略(等于起点)加 I J 就是一个 360°——3B 表达不了整圆,这是两代格式的能力差,导入 3B 时整圆必然是四段,段数对不上要心里有数。
F 字段解析了、存了,但它在线切割里的含义和普通 CNC 不一样:实际进给速度由放电状态反馈调节——放电 ISR 统计的平均电流和短路率实时调插补步频(HF 时代叫"变频"),F 只是初值和上限。把 F 当恒速用,切割效率直接掉一半,这是线切割和铣削 CNC 的思维方式差异,调度篇的放电反馈环就是为它建的。
三、3B:五字段、无符号与象限
3B 一行一段,格式是 B X B Y B J G Z,五个字段全是没有符号的整数(µm):
| 字段 | 含义 |
|---|---|
| X Y | 直线:终点相对起点的坐标绝对值;圆弧:起点相对圆心的坐标绝对值 |
| J | 计数长度:该段在计数方向轴上投影的总和,µm |
| G | 计数方向:GX / GY |
| Z | 加工指令:直线 L1–L4(终点所在象限);圆弧 SR1–4(顺)、NR1–4(逆),数字是起点所在象限 |
符号信息全藏在 Z 里,这是 3B 时代给硬件省掉的麻烦,现在全成了解析器的活。
直线的重建最省事:L1–L4 给出终点相对起点的象限,符号一挂,终点 = 起点 + (±X, ±Y)。计数方向对直线的规则是终点坐标绝对值大的轴(|X|>|Y| 取 GX),J 等于那个大数——解析器重算一遍和纸面对数,抄错的 X Y 直接现形。
圆弧是 3B 解析的硬骨头,一步一步来。关键是先接受一个事实:3B 的圆弧不直接给终点——逐点比较法的机器拿圆心定位、拿计数器判终,终点是插补走出来的。解析器要把这个过程用几何重建出来:
|
|
第 6 步是 3B 的 J 天生该当的角色:校验和。纸面 J 是人抄的,几何是机器算的,两边对不上必有一边错。老程序库里 J 抄错一位数是真实发生率最高的错误,靠这一步在导入时就抓住,而不是切到一半轨迹合不拢。
三个坑,都真踩过的人才知道疼:
- 圆弧 X Y 的口径分歧:主流教材和 HF 系机器是"起点对圆心",个别老教材写成终点对圆心。机器逻辑站在起点这边——逐点比较法要的是圆心加判终计数,终点本来就是走出来的。拿不准的历史程序,两种解释都按上面流程跑一遍,能通过 J 复核且轮廓闭合的那种解释是对的
- 起点恰在坐标轴上的象限归属:约定俗成是"算即将进入的象限",但各家老控制器的习惯不统一。导入器留一个开关(轴上起点按进入象限/按离开象限),默认前者,配合闭合校验用
- 4B/5B 别当 3B 硬啃:4B 在 3B 尾上多了补偿符号和半径,直接按 3B 解析会在第 6 步 J 复核大面积报错——报错信息里提示"疑似 4B 格式",导入器单独走 4B 路径
四、两种文本一个骨架:全局校验
单段级的检查(J 复核、半径一致、弦长 2R)抓的是抄写错误。还有一类错误单段看不出来,得整条轨迹一起看:
- 轮廓闭合:线切割程序绝大多数是封闭轮廓(凹模型腔、外形),末段终点必须回到首段起点,容差给 2µm。3B 圆弧任何一个字段抄错,最后多半在闭合这一步现形——上一节两个"拿不准"的开关,最终裁决也是它
- 软限位:段表整体对轴行程包络检查一遍,越界段标出(机床界面篇仿真屏的三项预检之一,数据在这一步备好)
- 补偿/锥度状态配对:G41 之后没有 G40 就 M02、G51 挂着没 G52——状态机的收尾检查,漏关的补偿会在下一次加工时带着上一次的偏移量,这是废件制造机
- 首段防呆:程序一上来就 G02——没有前一段建立位置上下文,模态坐标机状态没初始化,直接报"程序必须以定位或直线段开始"
错误报告的形态照编程界面(机床界面篇)的闭环设计:错误码用报警码体系的程序段,信息带行号 + 字段 + 两个数(纸面值 vs 重算值)。“第 47 行 J 与几何不符:纸面 3400,重算 3410"比"解析失败"值钱一百倍——前者老师傅自己就能把程序改了,后者只能打电话。
五、容量、归属与测试
工程账三笔:
- 内存归属:段表是变长的、程序有多大有多大,只能上堆——堆只有 Core1 合法(架构红线),解析跑在协作层 Core1,正好。每行 Row 加 Seg 按 48B 算,十万段约 5MB,给段表设显式上限并在编程界面显示余量,别让一个异常程序把服务核的堆吃穿
- 性能不用操心:词法是逐字符状态机,十万段毫秒量级,“保存即查"毫无压力。真正慢的是人找错,所以第 4 节的错误信息质量比解析速度重要一个数量级
- 测试是这个模块最大的红利:解析器纯函数、无硬件依赖,是全系统第一个能在开发机上
cargo test的模块。golden 文件攒起来——矩形件、带圆角的凸模、锥度口沿、老师傅的历史程序各存一份,连同期望段表一起进仓库。以后改解析器,先跑测试再上机,半夜不用蹲车间
总结
实战清单:绝对 µm 段表契约(Seg/Row、src_line 溯源、Option 承载 XYUV);G 代码模态状态机 + 方言子集表(不支持显式报错)+ 定点解析(拒 f64、3 位小数封顶、德语逗号专用码)+ I J/R 双格式与半径一致性校验 + 整圆;3B 五字段与象限指令、圆心重建六步(含 J 累加规则与复核)+ 三个坑(口径分歧用 J 与闭合裁决、轴上起点开关、4B 识别);全局校验四件套(闭合 2µm、软限位、状态配对、首段防呆)+ 错误信息带行号字段双数值;Core1 堆归属 + 48B/段容量账 + host 侧 cargo test 与 golden 集。跑通标志:老师傅的历史 3B 程序库成批导入,J 复核和闭合校验双零误报;故意篡改一个 J、一个 I、删一个 G40,三种坏程序都被对应检查抓住且错误信息能直接指导改程序;仿真屏把解析出的段表画出完整轨迹;G 和 3B 两份等价程序解析出的段表逐字节一致。
下一篇先补两代语言的来龙去脉:G代码与3B代码详解——两代线切割程序语言的来历、格式与方言——格式为什么长这样,线切割的编程和铣床差在哪。执行侧的插补紧随其后。
参考链接
- LinuxCNC G 代码文档——最详尽的开放 G 代码方言参考,模态分组和 I J/R 语义对照用
- NIST RS274NGC 解释器标准——G 代码解释器设计的经典文献,状态机分组的思路来源
- 本系列:机床界面实战(编程/仿真屏与错误闭环)、中断驱动的硬实时层与协作式主循环(放电反馈调节进给的通路)、国际化实战(德语区小数点与注释转码边界)、参数系统与断电恢复实战(D 号补偿值与坐标系偏置的存取)
Author 软件开发大郭
LastMod 2026-09-11