class PWM – pulse-width modulation

The PWM class outputs a pulse-width-modulated signal on a Pin. It is the modern, cross-port API for PWM; on STM32 OpenMV cams it wraps the underlying pyb.Timer channel machinery, so each PWM instance ties up one timer channel.

Example usage:

from machine import PWM, Pin

# 50 Hz PWM on a header pin with a 12.5 % duty.
pwm = PWM(Pin("P7"), freq=50, duty_u16=8192)

pwm.duty_u16(32768)            # change duty to 50 %
pwm.init(freq=5000, duty_ns=5000)  # re-init at 5 kHz, 5 us pulse
pwm.duty_ns(3000)              # 3 us pulse

pwm.deinit()

Constructors

class machine.PWM(dest: Pin | int, *, freq: int | None = None, duty_u16: int | None = None, duty_ns: int | None = None, invert: bool = False)

Construct a PWM object driving dest (a Pin on OpenMV cams). The keyword arguments are equivalent to calling init() immediately after construction:

  • freq – PWM frequency in Hz.

  • duty_u16 – duty cycle as a ratio duty_u16 / 65535.

  • duty_ns – pulse width in nanoseconds.

  • invert – if True, invert the output polarity.

At most one of duty_u16 / duty_ns may be passed at a time. Setting freq may affect other PWM instances that share the same underlying timer (true on STM32 – every channel of a given TIM runs at the same frequency).

Methods

init(*, freq: int | None = None, duty_u16: int | None = None, duty_ns: int | None = None) None

Reconfigure the PWM output. Only arguments supplied are updated; the others retain their previous values. See the constructor for the meaning of each argument.

deinit() None

Disable the PWM output and release the timer channel it occupied.

freq() int
freq(value: int, /) None

Get or set the PWM frequency.

With no argument, return the current frequency in Hz.

With a single value argument, set the frequency to that value in Hz. May raise ValueError if the frequency is outside the range achievable by the underlying timer.

duty_u16() int
duty_u16(value: int, /) None

Get or set the duty cycle as an unsigned 16-bit value in the range 065535.

With no argument, return the current duty.

With a single value argument, set the duty cycle to value / 65535 of the period. 0 is always low, 65535 is always high.

duty_ns() int
duty_ns(value: int, /) None

Get or set the pulse width directly in nanoseconds.

With no argument, return the current pulse width.

With a single value argument, set the high-time of each cycle to value nanoseconds. Useful for servo-style outputs where the pulse width is the meaningful quantity rather than the duty ratio.

Limitations

  • PWM frequency and duty resolution are interdependent on every hardware timer: at high frequencies, fewer counter steps fit in a period and so fewer low bits of duty_u16 are meaningful.

  • The achievable PWM frequency depends on the timer’s clock source and prescaler. STM32 TIM2 / TIM5 are 32-bit on most parts (and TIM3 / TIM4 as well on the STM32N6), giving wider frequency and duty ranges; the remaining timers are 16-bit. See the relevant MCU reference manual for the exact ranges.

  • On STM32 multiple PWM channels on the same TIM share a frequency. Setting freq() on one instance changes the output of every other channel attached to that TIM.