2、G代码基础:G代码与M代码的语法、坐标系统、单位、进给率、温度与运动命令的解析

在Klipper固件环境中,G代码(RS-274)是3D打印机最底层的控制语言。无论是切片软件生成的打印文件,还是通过终端手动发送的调试指令,最终都会以G代码行的形式被Klipper解析并转化为步进电机的脉冲、加热棒的PWM占空比以及风扇的转速。理解G代码的语法结构、坐标系统、单位制以及关键命令的语义,是编写宏指令、排查打印异常、优化运动控制参数的先决条件。本章将系统拆解G代码的核心要素,并重点说明Klipper与标准Marlin固件在解析上的细微差异。

G代码解析链路与坐标系统 G代码行解析 G1 X10.5 Y20.3 E1.5 F1800 G1 → 运动模式(线性插补) X/Y → 目标坐标(/相对) E → 挤出量(mm³ 或 mm) F → 进给率(mm/min) 注释:分号 ; 后内容被忽略 坐标系统 • 机床坐标系(MCS) • 坐标 G90 / 相对坐标 G91 • 工作偏置 G54 / G92 设置 • 单位:G21 (mm) / G20 (inch) • 软限位与运动学映射 Klipper 使用笛卡尔坐标映射到步进 运动与温度命令 G0/G1 → 快速/线性移动 G28 → 回原点 G29 → 自动调平 M104/M140 → 设置温度 M109/M190 → 等待温度 M106/M107 → 风扇控制 Klipper 对 G 代码的特殊处理 • 运动前瞻(Lookahead):G1 命令被缓冲到轨迹队列,Klipper 根据最大加速度和拐角速度进行规划。 • 挤出量单位:Klipper 默认将 E 值解释为 mm³(若配置了挤出机截面积),否则为 mm。 • 温度等待:M109 在 Klipper 中会阻塞解析线程,但运动缓冲仍可继续执行,需注意宏中的时序。 常见误区与排障 • 误区1:G91 后忘记切换回 G90,导致后续坐标偏移。 • 误区2:F 值在 Klipper 中默认单位是 mm/min,但切片软件可能输出 mm/s,需在切片机中统一。 • 误区3:M104 只设置温度不等待,若立即发送 G1 挤出,冷挤出保护会触发。

2.1 G代码语法结构与解析规则

核心原理:词法单元与地址字

每一行G代码由若干地址字(Address Word)组成,每个地址字由一个英文字母(A-Z)后跟一个数值(可带正负号和小数点)构成。字母代表命令类型或参数类型,数值代表该参数的值。例如 G1 X10.5 Y20.3 E1.5 F1800 中,G 是准备功能(Preparatory Function),1 表示线性插补;X、Y 是目标坐标轴;E 是挤出轴;F 是进给率。Klipper 的解析器会从左到右扫描,忽略大小写,并将分号(;)之后的内容视为注释。与 Marlin 不同,Klipper 对未定义的地址字会直接报错,而不是静默忽略,这有助于提前发现切片配置错误。

判断方法:命令分类与模态/非模态

G代码命令分为模态命令(Modal)和非模态命令(Non-modal)。模态命令一旦执行,其效果会持续到被同组的另一个命令替换为止。例如 G90(定位)和 G91(相对定位)属于同一模态组,发送 G91 后,后续所有坐标解释都变为相对模式,直到发送 G90。非模态命令如 G28(回原点)只影响当前行。Klipper 的宏系统([gcode_macro])允许你自定义命令,但必须遵循同样的词法规则。在编写宏时,建议显式声明模态状态,避免依赖上一次执行留下的状态。

经验提醒:在Klipper中,G0 和 G1 在运动控制上完全等价(均使用最大加速度和速度规划),但在语义上 G0 通常用于非挤出移动。切片软件有时会交替使用,Klipper 不会区分,但宏中建议保持语义清晰。

案例拆解:解析一行实际打印命令

假设切片软件输出以下命令:

G1 X127.2 Y104.8 E0.762 F2400 ; 外壁移动

解析过程如下:

  • G1:线性插补,目标点为 (127.2, 104.8)。
  • E0.762:挤出量增加 0.762mm(若配置了挤出机截面积,则为 0.762mm³)。
  • F2400:进给率 2400 mm/min(即 40 mm/s)。
  • Klipper 会将此命令加入运动队列,并根据 max_accel 和 max_velocity 计算实际运动曲线。

若在终端手动发送 G1 X127.2 Y104.8 E0.762 F2400,但当前挤出机温度低于冷挤出保护阈值(默认 min_extrude_temp),Klipper 会拒绝执行并报错 Heater extruder not hot enough。这是常见的初学者困惑点。

常见误区与总结

  • 误区:认为 G0 比 G1 快。实际上在Klipper中两者速度规划完全一致。
  • 误区:忽略注释中的分号。分号后的内容不会被解析,但若分号出现在字符串中(如 M117 Hello;World),Klipper 会截断为 M117 Hello。
  • 复盘:在宏中尽量使用 G90 和 G21 开头,确保坐标和单位状态可预测。

2.2 坐标系统与单位制

核心原理:机床坐标、工作坐标与相对坐标

3D打印机的坐标系统分为三层:机床坐标系(Machine Coordinate System, MCS) 是物理原点(通常由限位开关决定);工作坐标系(Work Coordinate System, WCS) 是切片软件设定的打印起点,通过 G54 或 G92 偏移实现;相对坐标 则是以当前点为原点。Klipper 默认使用坐标(G90),但切片软件可能在首层使用 G91 进行相对移动(如 G91 G1 Z0.2 抬升0.2mm)。单位制方面,G21 设置毫米,G20 设置英寸。Klipper 的配置文件 [printer] 段中的 kinematics 选项决定了坐标如何映射到步进电机(如 cartesian、corexy、delta)。

操作流程:设置工作偏置与原点

  1. 开机后执行 G28 回原点,建立机床坐标系。
  2. 若使用探针(BLTouch),执行 G29 或 BED_MESH_CALIBRATE 生成网格补偿。
  3. 切片软件通常在 G 代码开头发送 G92 E0 将挤出轴清零,然后 G1 Z0.2 F300 移动到首层高度。
  4. 若需手动调整Z偏移,使用 SET_GCODE_OFFSET Z=0.05 或 G92 Z0.1 临时修改。

案例拆解:首层坐标偏移问题

某用户打印时发现模型整体向X轴正方向偏移5mm。检查切片G代码开头:

G28 ; 回原点
G1 Z5 F3000 ; 抬升
G92 E0 ; 清零挤出
G1 X5 Y5 F3000 ; 移动到起点

问题在于 G1 X5 Y5 是坐标,但用户之前手动发送过 G91 且未切换回 G90。Klipper 保留了模态状态,导致该命令被解释为相对移动。解决方法是切片软件开头强制添加 G90。此案例说明模态命令的“粘性”是排障时首要检查项。

常见误区与总结

  • 误区:混淆 G92 与 G54。G92 是临时偏移,重启后失效;G54 是持久工作偏置,需在配置中定义。
  • 误区:在Klipper中使用 M206(Marlin的坐标偏移)无效,应使用 SET_GCODE_OFFSET。
  • 总结:单位制错误会导致打印尺寸偏差10倍(毫米/英寸混淆),务必在切片机中设置公制输出。

2.3 进给率与运动命令解析

核心原理:F值的含义与运动规划

进给率 F 的单位是 mm/min(毫米/分钟),但切片软件常以 mm/s 表示速度。Klipper 内部将 F 值转换为 mm/s 用于运动规划。例如 F1800 等于 30 mm/s。运动命令 G1 会触发Klipper的轨迹前瞻(Lookahead)机制:它不会立即执行,而是进入缓冲区,由运动控制器根据 max_accel、max_velocity 和 square_corner_velocity 计算平滑的速度曲线。这意味着即使你发送 G1 F3000,实际最高速度也可能被 max_velocity 限制。

判断方法:区分速度限制与加速度限制

当打印出现“ ringing ”(振纹)时,通常不是 F 值过高,而是加速度 max_accel 设置过大。Klipper 的 TUNING_TOWER 命令可以辅助测试不同加速度。另外,G1 命令中的 F 值只影响当前运动段,若后续命令未指定 F,则沿用上一次的 F 值(模态)。在宏中,建议每次运动都显式指定 F,避免速度突变。

案例拆解:高速打印时的挤出不足

用户设置 F6000(100 mm/s)打印,但出现层间挤出不足。分析:Klipper 的 max_extrude_only_velocity 和 max_extrude_only_accel 限制了纯挤出移动的速度。若切片软件在非挤出移动(如 G0)中设置了高 F,但挤出移动(G1)的 F 值较低,则不会触发限制。然而,若用户手动发送 G1 E10 F6000,Klipper 会报错 Extrude only move too fast。解决方法是调整配置:

[extruder]
max_extrude_only_velocity: 50  # mm/s
max_extrude_only_accel: 500    # mm/s²

此案例说明,理解Klipper的运动学限制比单纯调高 F 值更重要。

常见误区与总结

  • 误区:认为 F 值越大越好。实际上,加速度限制和电机扭矩决定了实际可达速度。
  • 误区:在宏中使用 G4 P200(暂停200ms)时,Klipper 会阻塞解析线程,但运动缓冲仍会执行完之前的命令,可能导致暂停位置不精确。
  • 复盘:使用 SET_VELOCITY_LIMIT 命令可在运行时动态调整速度限制,适合打印不同特征(如薄壁 vs 填充)时切换。

2.4 温度命令与等待机制

核心原理:M104/M109 vs M140/M190

温度命令分为两组:挤出机(M104 设置,M109 设置并等待)和热床(M140 设置,M190 设置并等待)。Klipper 对 M109 的处理与 Marlin 不同:Marlin 会阻塞所有命令直到温度到达,而 Klipper 的 M109 会阻塞宏解析线程,但运动队列中的命令仍会执行。这意味着如果你在宏中写 M109 S200 后立即 G1 E10,挤出命令可能先于温度到达执行,导致冷挤出。正确做法是使用 TEMPERATURE_WAIT 命令或确保宏中温度等待后无运动命令。

操作流程:安全的温度控制宏

[gcode_macro START_PRINT]
gcode:
  # 设置目标温度但不等待
  M104 S{params.TEMP}
  M140 S{params.BED}
  # 等待热床到达
  M190 S{params.BED}
  # 等待挤出机到达
  M109 S{params.TEMP}
  # 此时才允许挤出
  G92 E0
  G1 Z5 F300

注意:M190 在Klipper中会等待热床到达目标温度,但若目标温度低于当前温度,它会立即返回(不降温)。若需降温等待,需使用 TEMPERATURE_WAIT SENSOR=heater_bed MINIMUM=50。

案例拆解:宏中温度等待导致的热失控

用户编写宏:

M104 S210
M109 S210
G1 E5 F300

在Klipper中,M109 阻塞了解析线程,但运动队列为空,所以实际上没有命令执行。然而,如果之前有未完成的运动命令(如 G1 X100),它们会在等待期间执行。若挤出机温度未到,G1 E5 会触发冷挤出保护。更隐蔽的问题是:如果 M109 等待时间过长,加热棒持续全功率加热,可能触发 heater_timeout 保护。Klipper 默认 heater_timeout 为 30 秒,若温度在30秒内未变化,会报错。解决方法是使用 M109 S210 前先检查当前温度,或使用 SET_HEATER_TEMPERATURE 配合 TEMPERATURE_WAIT。

常见误区与总结

  • 误区:在Klipper中使用 M109 后立即发送 G28,回原点命令会等待温度,导致打印启动缓慢。
  • 误区:忽略 min_extrude_temp 设置。默认值为 170°C,若打印PLA设置190°C,冷挤出保护不会触发,但若设置160°C,则必须等待。
  • 总结:推荐在宏中使用 M190 等待热床,使用 M109 等待挤出机,但务必确保等待期间无运动命令。

2.5 知识结构总览与实战复盘

命令类别 典型命令 Klipper 特有行为 常见错误
运动 G0, G1, G28, G29 G0/G1 等价;G29 需配置探针 未指定 F 导致速度突变
坐标 G90, G91, G92, G54 G92 临时偏移;G54 需配置 模态状态未重置
单位 G20, G21 默认 G21,配置中可强制 英寸/毫米混淆
温度 M104, M109, M140, M190 M109 阻塞解析但运动队列继续 冷挤出保护触发
风扇 M106, M107 M106 S0 关闭,S255 全速 PWM 频率不匹配
风险提示:在Klipper中,M112(紧急停止)会立即切断步进使能,但不会关闭加热器。若发生热失控,应使用 FIRMWARE_RESTART 或物理断电。切勿在宏中依赖 M112 作为温度保护手段。

本章从语法、坐标、单位、进给率和温度五个维度拆解了G代码的核心机制。Klipper 的解析器严格且高效,但模态命令的“记忆性”和运动队列的异步执行是初学者最容易踩坑的地方。建议在编写宏时,始终以 G90 和 G21 开头,显式设置 F 值,并使用 TEMPERATURE_WAIT 替代 M109 实现更精细的温度控制。下一阶段,我们将深入 Klipper 的宏语法(gcode_macro)与变量系统,将本章的命令知识转化为可复用的自动化逻辑。