3、G-code语法与格式规范:行结构、词地址(字母+数字)、注释格式、参数单位与精度要求

G-code是3D打印机最底层的运动控制指令集,解析器能否正确、高效、鲁棒地处理G-code文本,直接决定了打印质量与设备安全。本章从语法规范出发,系统拆解G-code的行结构、词地址(Word Address)构成、注释规则、参数单位与精度要求,并给出解析器设计时应遵循的工程约束。理解这些规范,是后续实现词法分析器、语法检查器与运动规划器的基础。

G-code 语法结构总览 行结构 [行号] 词地址序列 ; 注释 N10 G1 X10.5 Y20.3 F1800 N20 G28 X Y ; Home 每行一条指令,可含多个词 词地址(字母+数字) G → 准备功能(G0/G1/G28) M → 辅助功能(M104/M106) X/Y/Z → 坐标轴目标位置 F/S/E → 速度/温度/挤出量 注释格式 ; 分号注释(行尾) ( 圆括号注释 ) /* 块注释 */(部分固件) 解析器应剥离注释再处理 参数单位与精度 G20(英寸)/ G21(毫米) 默认毫米,解析器需跟踪单位状态 精度:整数/小数混合,建议浮点+容差 典型精度:0.001mm(切片器输出) 解析器处理链路 行读取 → 注释剥离 → 词法切分 → 语法校验 → 单位换算 → 语义执行 → 运动规划 → 步进电机驱动 错误处理:跳过/报警/急停 规范先行 → 解析稳健 → 打印精准

3.1 行结构:从物理行到逻辑指令

3.1.1 核心原理:行的边界与语义

G-code文件本质上是文本流,每一行(Line)代表一条完整的指令。行结构由三个可选部分组成:行号(N)、词地址序列和注释。行号在早期数控系统中用于跳转和排序,现代3D打印机固件(如Marlin、Klipper)通常忽略行号,但解析器仍需兼容。词地址序列是行的核心,由一个或多个“字母+数字”对组成,例如 G1 X10.5 Y20.3 F1800 包含四个词:G1、X10.5、Y20.3、F1800。注释以分号(;)或圆括号(())开头,解析器应在词法分析前剥离注释,避免干扰数值解析。

3.1.2 判断方法与操作流程:行解析的工程步骤

解析器处理一行的标准流程如下:

  1. 读取原始行:按换行符(\n)或回车换行(\r\n)切分文件,注意处理文件末尾无换行符的情况。
  2. 去除首尾空白:使用 trim() 或等价操作,避免空格/Tab干扰。
  3. 剥离注释:先查找分号(;),若存在则截断;再查找圆括号对,删除括号内内容。注意:圆括号可能跨行(不推荐,但需兼容)。
  4. 空行检查:若剥离注释后为空,则跳过该行,不产生任何动作。
  5. 词法切分:按空格或Tab将剩余文本拆分为词(Token)。
  6. 语法校验:每个词必须匹配“字母+数字”模式,字母为A-Z(大小写不敏感),数字可为整数或小数,允许正负号。
示例:原始行 N10 G1 X10.5 Y20.3 F1800 ; move to start
剥离注释后:N10 G1 X10.5 Y20.3 F1800
切分结果:["N10", "G1", "X10.5", "Y20.3", "F1800"]
解析器应忽略N10(行号),提取G1、X、Y、F的值。

3.1.3 案例拆解:多词行与连续行处理

考虑以下切片器输出的典型片段:

G0 Z0.3
G1 X10.5 Y20.3 F1800
G1 X11.2 Y21.0 E0.042
M104 S200
; layer 2
G1 Z0.6 F300

解析器逐行处理:第一行 G0 Z0.3 表示快速移动到Z=0.3mm;第二行 G1 X10.5 Y20.3 F1800 设置进给率1800mm/min并移动到目标点;第三行增加E参数表示挤出量0.042mm;第四行M104设置喷嘴温度200°C;第五行是纯注释,直接跳过;第六行再次移动Z轴。注意:G0和G1都是运动指令,但G0不挤出,G1可挤出,解析器需区分。

3.1.4 常见误区与总结

  • 误区1:忽略行号导致错误——某些固件用N号做缓冲管理,解析器应提取但不必执行。
  • 误区2:注释剥离不彻底——分号出现在字符串中(极少见)或圆括号未闭合,应做防御性处理。
  • 误区3:大小写敏感——G和g应视为相同,统一转为大写。
风险提示:若行内出现非法字符(如中文、特殊符号),解析器应记录错误行号并跳过,而不是崩溃。建议采用“容错跳过+错误日志”策略。

3.2 词地址:字母+数字的语义映射

3.2.1 核心原理:地址字母的分类

词地址由一个大写字母(A-Z)后跟一个数值组成。字母决定语义类别,数值是该类别的参数。常见地址分类如下:

地址含义典型范围/示例
G准备功能(运动模式)G0/G1/G28/G90/G91
M辅助功能(机器控制)M104/M106/M140/M190
X/Y/Z线性轴目标坐标(mm)X10.5, Y-3.2, Z0.3
E挤出量(mm或mm³)E0.042, E-0.01
F进给率(mm/min)F1800, F300
S温度/速度/亮度等S200(温度), S255(风扇)
P参数/时间/索引P0(等待温度), P1(PID)
I/J圆弧中心偏移(相对起点)I5.0 J0.0
R圆弧半径或温度回退R10.0
T工具/挤出机选择T0, T1

3.2.2 判断方法与操作流程:词法解析规则

解析词地址时,需遵循以下规则:

  1. 字母提取:取词的首字符,转为大写,判断是否为A-Z。
  2. 数值提取:剩余部分必须为合法数字,支持科学计数法(如 1.5e3)但建议禁用,因为切片器不输出。
  3. 重复地址处理:同一行中同一字母出现多次(如 X10 X20),按规范应报错,但部分固件取最后一个值。解析器应选择“报错并跳过”或“取最后值”策略,并在文档中说明。
  4. 未知地址:遇到未定义的字母(如 Q),应忽略并记录警告,不应中断解析。
经验:建议将词地址解析结果存入结构体 GCodeWord { char letter; double value; },便于后续语义分析。

3.2.3 案例拆解:圆弧指令的I/J/R解析

圆弧插补指令 G2 X10 Y10 I5 J0 中,I和J表示圆心相对于起点的偏移量。解析器需同时处理X/Y目标坐标和I/J偏移,并计算圆心绝对坐标。若使用R格式 G2 X10 Y10 R5,则需根据起点、终点和半径计算圆心(存在两解,需根据G2/G3方向选择)。解析器应提供两种模式的转换接口,供运动规划模块调用。

3.2.4 常见误区与总结

  • 误区1:将G和M混淆——G控制运动模式,M控制机器状态(如温度、风扇),语义完全不同。
  • 误区2:忽略E值的正负——负E值表示回抽(Retraction),解析器必须保留符号。
  • 误区3:F值单位错误——F的单位是mm/min,不是mm/s,换算时需除以60。

3.3 注释格式:剥离策略与边界情况

3.3.1 核心原理:三种注释风格

G-code注释有三种常见格式:

  • 分号注释(;):从分号到行尾全部忽略,最常用。
  • 圆括号注释(()):括号内内容忽略,可跨行(不推荐)。
  • 块注释(/* */):部分固件支持,类似C语言风格。

解析器应优先支持分号和圆括号,块注释可选。注释内可能包含任意字符(包括数字和字母),剥离时必须完整删除,不能残留。

3.3.2 操作流程:注释剥离算法

function stripComments(line):
    # 先处理圆括号(可能跨行,需状态机)
    while line contains '(':
        start = line.indexOf('(')
        end = line.indexOf(')', start)
        if end == -1:  # 未闭合,删除到行尾
            line = line.substring(0, start)
            break
        line = line.substring(0, start) + line.substring(end+1)
    # 再处理分号
    semi = line.indexOf(';')
    if semi != -1:
        line = line.substring(0, semi)
    return line.trim()
注意:圆括号注释可能跨行,解析器需维护“是否在注释中”的状态标志。若文件在注释中结束,应报告错误。

3.3.3 案例拆解:复杂注释行

输入行:G1 X10 ; move X (this is a comment) Y20
剥离分号后:G1 X10 ,圆括号内容已被分号截断,因此Y20被忽略。若先剥离圆括号:G1 X10 ; move X Y20,再剥离分号:G1 X10 。两种顺序结果相同,但若圆括号在分号前:G1 X10 (comment ; still comment) Y20,先剥离圆括号得 G1 X10 Y20,先剥离分号得 G1 X10 (comment ,导致错误。因此必须先剥离圆括号,再剥离分号。

3.3.4 常见误区与总结

  • 误区1:注释嵌套——G-code不支持嵌套注释,遇到 (;) 应视为普通字符。
  • 误区2:注释中的引号——注释内出现引号不改变注释语义,无需特殊处理。
  • 误区3:性能问题——逐字符扫描注释会降低解析速度,建议使用正则表达式或状态机优化。

3.4 参数单位与精度要求:毫米、英寸与浮点容差

3.4.1 核心原理:单位制与精度标准

3D打印G-code默认使用毫米(mm)作为长度单位,进给率单位为毫米/分钟(mm/min),温度单位为摄氏度(°C)。但G20指令可切换为英寸(inch),解析器必须跟踪当前单位状态。精度方面,切片器(如Cura、PrusaSlicer)通常输出3位小数(0.001mm),但解析器应支持更高精度(如6位小数),并采用双精度浮点(double)存储,避免累积误差。

3.4.2 判断方法与操作流程:单位换算与容差处理

  1. 单位状态跟踪:解析器维护一个全局变量 unitMode(0=毫米,1=英寸),遇到G20/G21时切换。
  2. 换算公式:1英寸 = 25.4mm。解析时,若当前为英寸模式,所有坐标值乘以25.4转换为毫米;F值也需换算(1 inch/min = 25.4 mm/min)。
  3. 精度容差:由于浮点运算误差,比较两个坐标是否相等时,应使用 abs(a-b) < 1e-6 作为容差,而非 ==。
  4. 整数与小数:词地址的数值部分允许整数(如 X10)和小数(如 X10.5),解析器应统一转为double。
示例:若当前为英寸模式,指令 G1 X2.5 F100 应转换为 X=2.5*25.4=63.5mm,F=100*25.4=2540mm/min。

3.4.3 案例拆解:精度对打印质量的影响

假设切片器输出 G1 X100.123 Y50.456 E0.789,解析器若使用单精度浮点(float),有效位数约7位,100.123可能存储为100.12299,导致0.00001mm的误差。虽然单层误差微小,但累积数千层后可能产生可见偏差。因此,解析器必须使用double类型,并在运动规划中采用增量式累加,避免重复计算起点到终点的绝对坐标。

3.4.4 常见误区与总结

  • 误区1:忽略G20/G21切换——若切片器在文件开头输出G21,解析器未处理,后续坐标全部错误。
  • 误区2:F值单位混淆——部分固件支持F值单位为mm/s(如Klipper的 F 实际为mm/s),解析器需根据固件配置调整。
  • 误区3:负零问题——-0.0 与 0.0 在浮点中不同,应统一归零。
最佳实践:在解析器初始化时,强制设置默认单位为毫米(G21),并在每次G20/G21后打印日志,便于调试。

3.5 综合案例:从原始G-code到运动指令的完整解析

下面通过一个完整案例,串联本章所有知识点。假设输入文件 test.gcode 内容如下:

; generated by Cura 5.0
G21 ; set units to mm
G90 ; absolute positioning
M104 S200 ; set nozzle temp
G28 X Y ; home X and Y
G1 Z0.3 F300 ; move Z to 0.3mm
G1 X10.5 Y20.3 F1800 ; move to start point
G1 X11.2 Y21.0 E0.042 ; extrude 0.042mm
M106 S255 ; fan on full
G1 X12.0 Y22.0 E0.084
M104 S0 ; turn off nozzle
M140 S0 ; turn off bed
M107 ; fan off
M84 ; disable motors

解析过程:

  1. 逐行读取,剥离注释(分号后内容删除)。
  2. 第一行 G21 设置单位为毫米;第二行 G90 设置绝对定位。
  3. M104 S200 设置喷嘴温度200°C,解析器将温度值存入状态变量。
  4. G28 X Y 触发回原点,解析器应标记X和Y轴需要归零。
  5. G1 Z0.3 F300 设置Z轴目标0.3mm,进给率300mm/min。
  6. G1 X10.5 Y20.3 F1800 设置X/Y目标,F更新为1800。
  7. G1 X11.2 Y21.0 E0.042 增加E值,解析器需计算挤出增量(0.042-0=0.042)。
  8. 后续行类似,直到 M84 禁用电机。

结果对比:解析器输出结构化指令序列,每个运动指令包含目标坐标、进给率、挤出量,以及温度/风扇等辅助指令。若解析器未处理G21,则所有坐标被误认为英寸,实际移动距离放大25.4倍,导致打印尺寸严重错误。

风险与代价:单位错误是3D打印最常见的事故之一,轻则打印失败,重则撞机损坏热床。因此,解析器必须在文件开头检测单位指令,并在每次切换时输出警告。

复盘经验:建议在解析器测试套件中加入“单位切换”和“注释剥离”的边界测试用例,例如:G20 G1 X1 ; comment、(multi\nline) G1 X2 等。

3.6 本章总结与工程清单

G-code语法规范是解析器设计的基石。本章核心要点如下:

模块关键规范解析器要求
行结构行号可选,词地址序列+注释剥离注释,忽略行号,容错空行
词地址字母+数字,大小写不敏感提取字母和数值,处理重复/未知地址
注释分号、圆括号、块注释先剥离圆括号,再剥离分号
单位G20英寸/G21毫米,默认毫米跟踪单位状态,换算坐标和F值
精度双精度浮点,容差1e-6使用double,避免累积误差
工程提醒:解析器应输出结构化日志(行号、词列表、单位状态、错误信息),便于固件调试和用户排障。建议实现 --strict 模式,在严格模式下任何语法错误都停止打印,在宽松模式下跳过错误行并继续。