Klipper 使用 PWM 工具控制激光器与主轴:pwm_tool 配置、M3/M4/M5 宏与 LaserWeb 集成实战
【免费下载链接】klipperKlipper is a 3d-printer firmware项目地址: https://gitcode.com/GitHub_Trending/kl/klipper
导读
本文基于 Klipper 官方文档 docs/Using_PWM_Tools.md 与仓库中的示例配置 config/sample-pwm-tool.cfg,系统讲解如何复用打印头风扇的 PWM 输出来驱动激光器(laser)或主轴(spindle)。你将掌握[pwm_tool]配置段的全部参数含义、M3/M4/M5 宏的实现原理、安全超时的正确设置方法,以及如何在 LaserWeb 等 CAM 工具中无缝集成——最终获得一套可直接复制运行、可安全切换工具头的 PWM 工具控制方案。
工作原理:把风扇 PWM 输出改造成工具控制口
Klipper 打印头风扇原本由 PWM 信号驱动,其输出本质是一路可高速更新的脉宽调制信号。借助这一特性,可以将打印头的风扇 PWM 输出"挪用"为激光器或主轴的控制信号——这在更换式打印头(switchable print heads)场景下尤为实用,例如 E3D toolchanger 或各类 DIY 换头方案。
CNC/CAM 领域通常约定用M3~M5三个 G-code 命令控制主轴与激光器:
| 命令 | 含义 | 参数 |
|---|---|---|
M3 S<value> | 主轴顺时针旋转(Spindle speed CW) | S取值 0~255 |
M4 S<value> | 主轴逆时针旋转(Spindle speed CCW) | S取值 0~255 |
M5 | 停止主轴(Spindle stop) | 无参数,输出回到 shutdown value |
S参数的 0~255 是经典 CNC 的 8 位占空比标度,Klipper 侧通过宏把它归一化映射到 0.0~1.0 的 PWM 占空比(详见下文"M3/M4/M5 宏"一节)。LaserWeb 等工具默认就能以M3 $INTENSITY的形式发送这些命令,因此无需改造切片或 CAM 软件即可接入 Klipper。
安全警告:驱动激光器必须遵守的底线
使用 PWM 工具驱动激光器时,请务必把能想到的安全措施全部落实到位,这一点在原文档中被着重强调:
- 二极管激光器通常是反相的(inverted)。这意味着当 MCU 重启、固件尚未完成初始化时,PWM 引脚处于未定义/默认状态,激光器可能会在 MCU 重新启动的短暂时间内以满功率开启。这是硬件级风险,必须通过外围电路(如常闭联锁继电器)加以兜底。
- 激光通电期间应始终佩戴与激光波长匹配的专用护目镜。
- 不需要使用激光时,请直接断开激光器电源。
- 必须配置安全超时(safety timeout):当主机或 MCU 发生错误时,工具要能自动停止,避免长时间空烧。
安全超时正是[pwm_tool]中maximum_mcu_duration参数的职责,下文会详细展开。
一个隐含但重要的细节:原文档与示例配置反复强调"homing 时工具需要处于默认速度"。因为在归零过程中 Klipper 会执行运动同步,若此时工具占空比非默认值,超时机制可能被误触发或导致意外的 PWM 输出,配置时务必结合下面的超时参数一起考虑。
配置[pwm_tool]:从风扇引脚到可控工具
完整的可运行配置见仓库 config/sample-pwm-tool.cfg,其核心是[pwm_tool]配置段:
[pwm_tool TOOL] pin: !ar9 # 使用你风扇的引脚编号(此处为示例) hardware_pwm: True cycle_time: 0.001 shutdown_value: 0 maximum_mcu_duration: 5 # Default: 0 (disabled) # Amount of time in which the host has to acknowledge # a non-shutdown output value. # Suggested value is around 5 seconds. # Use a value that does not burn up your stock. # Please note that during homing, your tool # needs to be in default speed.[pwm_tool]配置段在 docs/Config_Reference.md(第 3716 行起)中有官方说明,各参数含义与默认值整理如下:
| 参数 | 默认值 | 说明 |
|---|---|---|
pin | 必填 | 要配置为输出的引脚,使用你风扇原来的引脚编号;!前缀表示反相。示例中!ar9是 BigTreeTech 类主板上的 AR9 引脚(反相) |
maximum_mcu_duration | 0(禁用) | MCU 在没有收到主机确认的情况下,最多允许持续输出非 shutdown 值多长时间。若主机无法跟上更新节奏,MCU 将进入 shutdown 并把所有引脚置为各自的 shutdown 值。建议值约 5 秒,具体以不会烧毁你的工件(stock)为准 |
value | 0 | MCU 配置期间引脚初始值(0~1 或 0~scale) |
shutdown_value | 0 | MCU shutdown 事件发生时引脚应置为的值(0~1 或 0~scale)。激光器场景建议设为 0(关闭) |
cycle_time | 0.100 秒 | 每个 PWM 周期的时间(秒)。软件 PWM 建议 10 毫秒或更长;使用硬件 PWM 时实际周期受硬件实现约束,可能与请求值明显不同 |
hardware_pwm | False | 是否使用硬件 PWM 而非软件 PWM |
scale | 1 | 用于改变value/shutdown_value的解析标度,配置为 PWM 引脚控制步进电压参考等场景时可设为等效电流值 |
其中cycle_time: 0.001表示 1 kHz 的 PWM 频率,适合激光器等需要较高调制频率的工具。
版本注意:3 秒上限变更
根据 docs/Config_Changes.md 中20250428条目的记录:[pwm_tool]及类似 PWM 配置段的cycle_time最大值从 5 秒缩减为3 秒,maximum_mcu_duration的上限同样被限制为3 秒。因此在新版本上配置时,maximum_mcu_duration: 5这类取值需要改为不超过 3 秒的值。
为什么需要maximum_mcu_duration
其底层逻辑是"看门狗式"的:正常情况下主机周期性下发新的 PWM 值(例如通过运动队列的刷新回调),MCU 收到后即视为"确认"。若主机卡死、串口中断或发生错误导致长时间没有新指令,MCU 会在超时后将引脚强制置为shutdown_value——对激光器而言就是立刻关断,避免持续高功率输出引发事故。这一点在 pwm_tool.py 中通过_gen_intermediate_updates与_flush_notification机制实现(详见"源码级原理"一节)。
M3/M4/M5 宏:把 0~255 映射成 PWM 占空比
[pwm_tool]本身只提供一个SET_PIN运行时命令,真正的 M3/M4/M5 是通过[gcode_macro]实现的。示例配置中的宏如下:
[gcode_macro M3] gcode: {% set S = params.S|default(0.0)|float %} SET_PIN PIN=TOOL VALUE={S / 255.0} [gcode_macro M4] gcode: {% set S = params.S|default(0.0)|float %} SET_PIN PIN=TOOL VALUE={S / 255.0} [gcode_macro M5] gcode: SET_PIN PIN=TOOL VALUE=0要点解析:
S参数通过 Jinja2 模板读取,params.S|default(0.0)|float保证了未传S时安全回退为 0;- 关键映射是
VALUE={S / 255.0}:把 CNC 惯用的 0~255 标度换算为 Klipper PWM 的 0.0~1.0 占空比。例如M3 S128会执行SET_PIN PIN=TOOL VALUE=0.502; M5直接SET_PIN PIN=TOOL VALUE=0,把输出置回关闭状态。
SET_PIN的语义在 docs/G-Codes.md(第 1071 行起)中有明确定义:PWM 引脚时VALUE应取值 0.0~1.0,若配置了scale则取 0~scale。SET_PIN是面向运动队列的异步命令——它会注册一个 lookahead 回调,在对应的打印时间点才真正改变引脚电平,从而与运动轨迹精确同步,这一点在源码cmd_SET_PIN中可以看到(toolhead.register_lookahead_callback(...))。
LaserWeb 集成配置
LaserWeb 是常见的激光雕刻 CAM 前端。原文档给出了一套经过验证的配置,完整照录如下:
GCODE START: M5 ; Disable Laser G21 ; Set units to mm G90 ; Absolute positioning G0 Z0 F7000 ; Set Non-Cutting speed GCODE END: M5 ; Disable Laser G91 ; relative G0 Z+20 F4000 ; G90 ; absolute GCODE HOMING: M5 ; Disable Laser G28 ; Home all axis TOOL ON: M3 $INTENSITY TOOL OFF: M5 ; Disable Laser LASER INTENSITY: S要点解读:
- 开始/结束/归零时一律先
M5:确保激光在作业前后始终处于关闭状态,属于安全惯例; - TOOL ON 使用
M3 $INTENSITY:LaserWeb 会把当前强度值以S参数形式填充进命令,正好落入上面宏的S/255.0映射; - LASER INTENSITY 填
S:告诉 LaserWeb 强度参数名是S,与 M3/M4 宏的解析方式对应。
可选增强:LCD 菜单控制
示例配置还附带了一段可选的 LCD 菜单控制,便于在打印机屏幕上直接开关工具和调节速度:
[menu __main __control __toolonoff] type: input enable: {'pwm_tool TOOL' in printer} name: Fan: {'ON ' if menu.input else 'OFF'} input: {printer['pwm_tool TOOL'].value} input_min: 0 input_max: 1 input_step: 1 gcode: M3 S{255 if menu.input else 0} [menu __main __control __toolspeed] type: input enable: {'pwm_tool TOOL' in printer} name: Tool speed: {'%3d' % (menu.input*100)}% input: {printer['pwm_tool TOOL'].value} input_min: 0 input_max: 1 input_step: 0.01 gcode: M3 S{'%d' % (menu.input*255)}这里通过printer['pwm_tool TOOL'].value实时读取当前占空比——value状态字段在 docs/Status_Reference.md(第 390 行起)中有定义,表示引脚当前被SET_PIN设置的值。菜单项最终仍复用 M3 宏(S{255 if menu.input else 0}、S{'%d' % (menu.input*255)}),保证 0~255 标度的一致性。
源码级原理:pwm_tool在 Klipper 中如何工作
核心实现在 klippy/extras/pwm_tool.py 中,模块类MCU_queued_pwm承担了全部底层逻辑。PrinterOutputPin.load_config_prefix是配置入口,通过ppins.lookup_pin()解析引脚,然后根据hardware_pwm分支走两套完全不同的 MCU 命令序列:
硬件 PWM 分支:向 MCU 下发config_pwm_out(含cycle_ticks、起始值、default_value、max_duration),随后用queue_pwm_out排入队列;PWM_MAX常量由 MCU 固件提供(如 Atmel 系列的定时器计数上限),占空比换算为value * PWM_MAX的计数值。
软件 PWM 分支:向 MCU 下发config_digital_out与set_digital_out_pwm_cycle,以 GPIO 翻转加周期计数实现软件 PWM。这里有一个硬性约束:软件 PWM 模式下shutdown_value只能是 0.0 或 1.0,否则_build_config会直接抛出配置错误"shutdown value must be 0.0 or 1.0 on soft pwm"。
其他值得注意的实现细节:
- 同步队列(syncemitter):
MCU_queued_pwm从motion_queuing分配一个 syncemitter(alloc_stepcompress=False),PWM 更新通过syncemitter_queue_msg注入运动队列,与步进指令共享时间基准,从而保证占空比切换与打印头运动在时序上严格对齐; - 超时续命机制:
_gen_intermediate_updates会在当前值非默认值时,以duration_ticks为间隔周期性地重发当前值,相当于持续"喂狗";一旦主机停止确认,MCU 侧max_duration即触发 shutdown。这与配置中的maximum_mcu_duration一一对应; - 启动值约束:
_build_config中若设置了max_duration且起始值与 shutdown 值不同,会报错"Pin with max duration must have start value equal to shutdown value"——这正是示例配置中value与shutdown_value都为 0 的原因。
测试用例佐证
仓库测试 test/klippy/pwm.cfg 与 test/klippy/pwm.test 覆盖了pwm_tool的基本行为:测试配置声明了[pwm_tool test_pwm_tool](引脚 PH4),测试脚本依次执行SET_PIN PIN=test_pwm_tool VALUE=0/0.5/0.5/0.25/1,验证重复设置、半占空比与满占空比切换均能正确通过运动队列下发。这套测试同时覆盖硬件 PWM 与软件 PWM 两种分支,可作为修改配置后回归验证的参考。
排查与使用建议
- 激光"失控常亮":优先检查
shutdown_value是否配置为 0,以及maximum_mcu_duration是否按版本上限正确设置;同时确认二极管激光器的反相特性是否已用!引脚前缀或外围电路处理; - 软 PWM 配置报错:报错
shutdown value must be 0.0 or 1.0 on soft pwm时,要么把shutdown_value改为 0 或 1,要么开启hardware_pwm: True; - 超时误触发:若打印过程中工具提前关闭,可适当增大
maximum_mcu_duration(不超过 3 秒上限),并确保归零/换刀等操作期间工具处于默认占空比; - 更换主板:
pin需按新主板风扇引脚改写,可参考 config/example-extras.cfg 中其它输出引脚配置段的写法保持一致风格。
总结
通过[pwm_tool]+ 三个[gcode_macro]宏,Klipper 可以把一路风扇 PWM 输出变成完全可控、带安全超时的激光器/主轴驱动口:M3/M4 S0-255控制占空比、M5安全关断,LaserWeb 开箱即用;maximum_mcu_duration提供主机失联时的硬件级兜底;源码中的 syncemitter 机制保证 PWM 切换与运动时序精确同步。从 config/sample-pwm-tool.cfg 出发,结合本文的参数说明与安全注意点,即可在自己的打印机上安全、可靠地启用 PWM 工具控制。
【免费下载链接】klipperKlipper is a 3d-printer firmware项目地址: https://gitcode.com/GitHub_Trending/kl/klipper
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考