Skip to contents

Pulse Width Modulation on the Raspberry Pi

Hardware PWM vs Software PWM

The Raspberry Pi exposes two PWM channels from the Broadcom chip. These appear on lines which also supply GPIO connections and so the Broadcom ALT functions need to be called.

  • PWM0 appears on board pins 12 (GPIO18) and 32 (GPIO12).

  • PWM1 appears on board pins 33 (GPIO13) and 35 (GPIO19).

This causes a confusing situation in two ways:

  • Don’t confuse board pin 12 with GPIO12 (board pin 32). Both are connected to BCM PWM0
  • If you want to use two PWM channels, there are only certain combinations of pins that will provide the two channels. These combinations are board pins (12,33), (32,33), (12,35), or (32,35)

rpi_pwm() handles these issues. If you stick to board pin numbers, it will all work out. If you go astray, rpi_pwm() will stop and warn you.

The Raspberry Pi analog audio output uses both PWM channels. You can’t use hardware PWM and audio output at the same time.

Although it is possible to create software PWM, this isn’t advised due to latency of linux and R. rpigpior does not supply any software PWM channels.

Enabling hardware PWM on the Raspberry Pi

Raspberry Pi OS uses the device tree to enable hardware PWM. You’ll need to do a bit of behind-the-scenes editing to set this up.

To do this, edit /boot/config.txt as root.

  1. On the Raspberry Pi, open a terminal window

  2. Use the command sudo nano /boot/config.txt. This will open the nano text editor and display the contents of /boot/config.txt.

  3. Add the dtoverlay command at the end of the file. The easiest way to determine the command to add to /boot/config.txt is to ask rpi_pwm() for help. Set pwm_debug=TRUE then select the pins you want to use. If they aren’t enabled, rpi_pwm() will stop and provide you with the correct dtoverlay string. This looks something like dtoverlay=pwm,pin18,func-2 but will change depending on the pins you have chosen.

    If you want to do the math yourself, there is an excellent guide available at github.com/dotnet. There is also linux documentation that discusses Enabling one PWM channel or Enabling a dual pwm channel

  4. Use control-o to write the file, then control-x to exit nano

  5. Reboot your Raspberry Pi to enact this change.

Note that if you rebuild your SD card or reinstall Raspberry Pi OS on the OS card, you’ll need to repeat this step.

How to use rpi_pwm()

Here’s an example:

rpi_pwm(c(12, 33), pwm_period = 50000, pwm_dutycycle = 25000)

# This will enable PWM0 and PWM1 with a period (frequency) of 50000 and a duty cycle of 25000. That is to say, 50% power.

Or…

rpi_pwm(12, pwm_period = 50000, pwm_dutycycle = 10000)

# This will turn PWM0 down to 20%

Handling Errors:

If you set pwm_debug = TRUE then rpi_pwm() will run diagnostics as it goes.

rpi_pwm(12, pwm_period = 50000, pwm_dutycycle = 10000, pwm_debug = TRUE)

Invalid PWM pin:

You’ve called rpi_pwm(pin_number) where the pin (or pins) specified don’t supply hardware Pulse Width Modulation. On the Raspberry Pi, this is only board pins 12, 32, 33, or 35. Keep in mind rpi_pwm() only specifies pins as board pins - not GPIO or BCM pins. Lots of documentation will refer to these other pin numbering schemes.

Invalid PWM pin combination:

As you know by now, the Raspberry Pi only has two hardware PWM channels, but each channel is connected to two pins:

  • PWM0 appears on board pins 12 (GPIO18) and 32 (GPIO12).

  • PWM1 appears on board pins 33 (GPIO13) and 35 (GPIO19).

So…if you are going to use two PWM channels, you need to use pins connected to different channels. Since board pin 12 and 32 are both connected to PWM0, it would be nonsense to use rpi_pwm(pin_number = c(12,32). Instead, these are the valid combinations:

  • rpi_pwm(pin_number = c(12,33)
  • rpi_pwm(pin_number = c(12,35)
  • rpi_pwm(pin_number = c(32,33)
  • rpi_pwm(pin_number = c(32,35)

If you try to select an invalid combination and pwm_debut = TRUE you will receive an error.

PWM not enabled:

The PWM channel (or channels) you have selected are not yet enabled. Enabling PWM is described in the above section titled Enabling hardware PWM on the Raspberry Pi . The error message from rpi_pwm supplies the string you’ll need to paste into /boot/config.txt.

Notes:

The Linux driver implementer’s API guide has a chapter on PWM : https://www.kernel.org/doc/html/v5.10/driver-api/pwm.html