Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Pulse Width Modulation

Pulse WIdth Modulation (PWM) is a technique that involves changing the duty dycle of a pulse stream to vary things like the average power delivered to a load, or to operate a servo.

PWM is provided by the type PwmPeriph. Final exposes two header channels, pwm0 and pwm1 (BCM 12 and 13), enabled with the stock pwm-2chan overlay.

Final provides three distinct operating modes for its PwmPeriphs:

  • Raw – you control the pulse interval and on-time manually, in nanoseconds;
  • Linear – used to provide a linear variation in duty cycle from 0 to 1 for the signal whose frequency you specify.
  • Servo – used for controlling hobby-type servos, that have a defined signal characteristic; you can control the servo on a -1..+1 range, where 0 is the null position; or angle from 0 to 180, where 90 is the null position

Both Linear and Servo modes ultimately render your parameters in raw form, but provide a more convenient and less error prone interface.

Here are the parameters you specify, for each mode. Note, that the modal parameters for a mode may only be set if you have selected that mode. This is to prevent conflicting parameter usage. You set/read the properties for each mode on a subobject with the mode name.

Example property accessors, by mode:

  mypwm.raw.periodNs

  mpwn.linear.freq

  mypwm.servo.byRange

PwmPeriph base parameters

ParameterValuesDescription
modePwmPeriph.raw, linear, servoselect the mode

Raw mode

Raw mode is always an available choice, if you want a custom control profile. This mode corresponds to the parameters accepted by the underlying Pi peripheral. The other modes simply layer a more convenient use-case interface upon these raw values.

ParameterValuesDescription
periodNs>0the overall pulse width in nanoseconds
dutyNs< periodNsthe width of the On portion

Linear mode

Linear mode is useful for things like controlling the brightness of LEDs or the power of a heater or other load, using a pulse whose On duty cycle will be the average power delivered into the load. The frequency will typically be on the order of 1 kHz for LEDs, but may be much less for powered loads like heaters. Your hardware and load will determine the appropriate frequency.

ParameterValuesDescription
freq> 0the frequency of the pulse in Hz, eg 1000
duty0.0 to 1.0the on portion of the pulse, def = 0

Servo mode

Servo mode is specifically for the common PWM case of controlling hobby servos, linear actuators, and such. They have a very particular pulse profile, whose design goes back many years to early analog electronics and radios. Today’s devices are digital, but the control system has remained the same, with occasional variations. Make sure you initialize the PwmPeriph to correspond to your device’s actual spec. The peripheral will start up with the control pulse in the neutral/zero position for the actuator, usually what you want. If the device should start up at a different value, set that immediately after setting .enabled true.

ParameterValuesDescription
freq> 0the frequency, default is 50 (for hobby servos)
minUs> 0the minimum pulse width in microseconds, def is 1000 (1 ms)
maxUs> minUsthe maximum pulse width, def is 2000 (2 ms)
setMinMaxmin, maxsetter, for both at once
asAngle0 to 180sets the duty cycle in terms of angle (common for servos), def 90
asRange-1.0 to 1.0sets the duty cycle as a range around 0, def 0 (== 90 degrees)

asAngle and asRange are convenience properties, so you can set/read values in units of your preference; they both have the same effect on the pulse width.