How to define PWM frequency in Klipper?

TL;DR: In Klipper the PWM frequency is set indirectly through a cycle time parameter. The frequency is 1 / cycle_time. The exact config option depends on what you are controlling.

Which config parameter to use

Klipper does not have a single pwm_frequency option. Instead you configure the period of one PWM cycle, and Klipper derives the frequency from that.

Fans and output pins: cycle_time

For fans, generic output pins, LED channels, and similar, use cycle_time:

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

The parameter is documented in docs/Config_Reference.md for [fan] (lines 3239-3242) and [output_pin] (lines 3678-3681).

Heaters: pwm_cycle_time

For heaters (extruder, heated bed, etc.) the parameter is called pwm_cycle_time:

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

Run-time configurable cycle time: [pwm_cycle_time]

If you need to change the PWM cycle time at run-time via G-code, use the [pwm_cycle_time] section:

example.ini
[pwm_cycle_time my_pin]
pin: PB0

Then at run-time:

example.txt
SET_PIN PIN=my_pin VALUE=0.5 CYCLE_TIME=0.001

This is documented in docs/Config_Reference.md and implemented in klippy/extras/pwm_cycle_time.py.

How the value is used internally

In klippy/mcu.py, the MCU_pwm class converts the cycle time into MCU clock ticks:

example.py
cycle_ticks = self._mcu.seconds_to_clock(self._cycle_time)

For software PWM this becomes the cycle_ticks argument of set_digital_out_pwm_cycle (line 488), and the on-time within each cycle is scheduled in the same tick units. For hardware PWM the same cycle_ticks value is passed to the platform-specific gpio_pwm_setup(), which then chooses a timer prescaler and period that best matches it.

Hardware PWM caveat: the actual frequency may differ

When hardware_pwm: True is set, the frequency you request is only a target. The MCU timer peripheral must pick a prescaler and counter period that fit within its hardware limits, so the real frequency may be slightly different.

For example, the STM32 implementation in src/stm32/hard_pwm.c computes the closest achievable hwpwm_ticks and prescaler values (lines 328-348). The final frequency on STM32 is approximately:

example.txt
frequency = CLOCK_FREQ / (prescaler * hwpwm_ticks * pclock_div)

If two hardware PWM pins share the same timer, they must also use the same frequency; otherwise Klipper shuts down with “PWM already programmed at different speed” (line 356).

Practical examples

25 kHz fan for 4-wire PWM control

example.ini
[fan]
pin: PA8
cycle_time: 0.00004
hardware_pwm: True

1 / 0.00004 = 25,000 Hz. Because this is outside the reliable range of software PWM, hardware_pwm: True is required.

Standard 100 Hz part cooling fan

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

This is the default and works well with software PWM.

10 Hz heater

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

Again the default; no need to change it unless your MOSFET/driver needs faster switching.

Summary


Check out similar posts by category: Klipper, 3D Printing