Использует ли Klipper программный или аппаратный PWM?

TL;DR: Klipper по умолчанию использует программный PWM, но может использовать аппаратный PWM на поддерживаемых MCU, если вы явно включите его в конфигурации.

Программный PWM по умолчанию

Когда вы настраиваете вентилятор, нагреватель или обычный выходной пин в Klipper без специальных флагов, Klipper использует программный PWM. Важно понимать, что бит-бэнгинг выполняется не на стороне хоста/Linux — хост только планирует переключения и отправляет их на MCU. Фактическое переключение GPIO происходит внутри прошивки MCU.

В klippy/mcu.py класс MCU_pwm решает, какой путь использовать. Если hardware_pwm имеет значение False (по умолчанию), он настраивает пин как обычный цифровой выход и отправляет config_digital_out плюс set_digital_out_pwm_cycle на MCU (строки 509-530). Для каждого обновления коэффициента заполнения он отправляет queue_digital_out со значением on_ticks, которое сообщает MCU, сколько тактов часов пин должен оставаться в высоком состоянии в течение цикла PWM.

На стороне MCU src/gpiocmds.c реализует конечный автомат программного PWM:

Таким образом, форма сигнала PWM генерируется планировщиком прерываний таймера MCU, управляемым списком будущих переключений от хоста.

Аппаратный PWM включается опционально

Аппаратный PWM включается для каждого пина с помощью hardware_pwm: True в конфигурации. Когда это установлено, хост отправляет команды config_pwm_out и queue_pwm_out вместо цифровых, и MCU использует периферию PWM платформы.

Диспетчер на стороне MCU находится в src/pwmcmds.c. Платформо-зависимые реализации существуют для нескольких MCU:

Например, реализация для STM32 в gpio_pwm_setup() ищет таймер/канал для запрошенного пина, вычисляет делитель и период счётчика, наилучшим образом соответствующие запрошенному времени цикла, а затем записывает значение коэффициента заполнения в регистр захвата/сравнения таймера.

Документация Klipper явно предупреждает, что “большинство вентиляторов не работают хорошо с аппаратным PWM, поэтому не рекомендуется включать его, если нет электрической необходимости переключения на очень высоких скоростях” (Config_Reference.md).

Что определяет частоту PWM?

Частота просто равна 1 / cycle_time, задаётся в конфигурации:

Для программного 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

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