Klipper使用软件PWM还是硬件PWM?

简而言之: Klipper默认使用软件PWM,但如果你在配置中明确启用,它可以在支持的MCU上使用硬件PWM。

软件PWM是默认选项

当你在Klipper中配置风扇、加热器或通用输出引脚而不使用任何特殊标志时,Klipper运行软件PWM。需要理解的重要一点是,位操作不是在主机/Linux端完成的——主机只调度转换并将其发送到MCU。实际的GPIO切换发生在MCU固件内部。

在 klippy/mcu.py 中,MCU_pwm 类决定采用哪条路径。如果 hardware_pwm 为 False(默认值),它将引脚配置为普通数字输出,并向MCU发送 config_digital_out 和 set_digital_out_pwm_cycle(第509-530行)。对于每次占空比更新,它发送 queue_digital_out 和一个 on_ticks 值,告诉MCU在PWM周期内引脚应保持高电平多少个时钟滴答。

在MCU端,src/gpiocmds.c 实现了软PWM状态机:

  • digital_load_event() 读取下一个排队更新,设置初始引脚状态,并计算引脚是否需要切换。
  • digital_toggle_event() 切换引脚并为周期内的导通持续时间或关断持续时间重新调度自身。

因此,PWM波形由MCU的定时器中断调度器生成,由主机的未来转换列表驱动。

硬件PWM是可选的

硬件PWM通过配置中的 hardware_pwm: True 按引脚启用。设置此项后,主机改为发送 config_pwm_out 和 queue_pwm_out 命令,MCU使用平台的PWM外设。

MCU端的调度在 src/pwmcmds.c 中。多个MCU有特定平台的实现:

例如,gpio_pwm_setup() 中的STM32实现查找请求引脚对应的定时器/通道,计算最匹配请求周期时间的预分频器和计数器周期,然后将占空比值写入定时器的捕获/比较寄存器。

Klipper文档明确警告*“大多数风扇在硬件PWM下工作效果不佳,因此除非有电气要求需要以非常高的速度切换,否则不建议启用此项”*(Config_Reference.md)。

什么定义了PWM频率?

频率就是 1 / cycle_time,在配置中设置:

  • [fan]:cycle_time: 0.010 → 100 Hz(默认)。
  • [output_pin]:cycle_time: 0.100 → 10 Hz(默认)。
  • [extruder] / [heater_bed]:pwm_cycle_time: 0.100 → 10 Hz(默认)。

对于软件PWM,这是MCU切换的实际频率。对于硬件PWM,这是请求的频率,但由于预分频器/计数器限制,MCU定时器硬件可能会将其取整到最接近的可实现值。此外,共享同一定时器的多个硬件PWM引脚必须以相同频率运行;否则Klipper会报错"PWM already programmed at different speed"。

配置示例

使用软件PWM的风扇(默认)

example.ini
[fan]
pin: PA8
cycle_time: 0.010
hardware_pwm: False

使用硬件PWM的输出引脚

example.ini
[output_pin my_pwm]
pin: PB0
pwm: True
cycle_time: 0.001
hardware_pwm: True

加热器PWM周期

example.ini
[extruder]
heater_pin: PA2
pwm_cycle_time: 0.100

按类别查看类似文章: Klipper 3D打印