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:
[fan]
pin: PA8
cycle_time: 0.010
hardware_pwm: False- Default for
[fan]:0.010s → 100 Hz. - Default for
[output_pin]:0.100s → 10 Hz. - Default for
[neopixel]/[dotstar]LED channels:0.010s → 100 Hz.
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:
[extruder]
heater_pin: PA2
pwm_cycle_time: 0.100- Default:
0.100s → 10 Hz. - The documentation notes that “it is not recommended to set this unless there is an electrical requirement to switch the heater faster than 10 times a second” (Config_Reference.md).
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:
[pwm_cycle_time my_pin]
pin: PB0Then at run-time:
SET_PIN PIN=my_pin VALUE=0.5 CYCLE_TIME=0.001This 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:
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:
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
[fan]
pin: PA8
cycle_time: 0.00004
hardware_pwm: True1 / 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
[fan]
pin: PA8
cycle_time: 0.010This is the default and works well with software PWM.
10 Hz heater
[extruder]
heater_pin: PA2
pwm_cycle_time: 0.100Again the default; no need to change it unless your MOSFET/driver needs faster switching.
Summary
- PWM frequency in Klipper is always
1 / cycle_time. - Use
cycle_timefor fans, output pins, and LEDs. - Use
pwm_cycle_timefor heaters. - Software PWM honors the cycle time exactly.
- Hardware PWM may round the cycle time due to MCU timer constraints.