The Raspberry Pis have two hardware timers capable of generating a PWM signal.
The README in the RPi kernel overlays directory shows the pins where the PWM timers are accessible
...
Name: pwm
Info: Configures a single PWM channel
Legal pin,function combinations for each channel:
PWM0: 12,4(Alt0) 18,2(Alt5) 40,4(Alt0) 52,5(Alt1)
PWM1: 13,4(Alt0) 19,2(Alt5) 41,4(Alt0) 45,4(Alt0) 53,5(Alt1)
N.B.:
1) Pin 18 is the only one available on all platforms, and
it is the one used by the I2S audio interface.
Pins 12 and 13 might be better choices on an A+, B+ or Pi2.
2) The onboard analogue audio output uses both PWM channels.
3) So be careful mixing audio and PWM.
4) Currently the clock must have been enabled and configured
by other means.
...
You can also find this information in the BCM2835 ARM Peripherals datasheet, Section 9.5 Quick Reference.
At the end of Section 9.5 is this note
- PWM clock source and frequency is controlled in CPRMAN
CPRMAN is the Clock Power Reset MANager.
There are two PWM overlays in the default RPi kernels
- pwm.dtbo
- pwm-2chan.dtbo
In the 4.9 kernels, the PWM source clock is always running so you can skip down to the Usage section of this post.
Additional overlays for 4.4 kernels
In the 4.4 kernels, the PWM source clock is not normally enabled in CPRMAN and as a result those overlays are not immediately useful. PWM devices will show up, but you won’t be able to get an output.
There are workarounds, such as playing an audio file before using PWM since audio also uses the PWM clocks and will enable the source clock. But that’s not very convenient.
This mailing list thread describes a device tree solution to enabling the BCM2835_CLOCK_PWM in a dts.
Since it’s easy enough to do, I added two additional PWM overlays
- pwm-with-clk.dtbo
- pwm-2chan-with-clk.dtbo
You can find the source for them here.
If you are using O/S images built from one of the Jumpnowtek repos (Yocto instructions) or (Buildroot instructions) then the custom pwm overlays are already installed for you.
If you are using Raspbian, then you can build the overlays yourself right on the RPi since a device tree compiler should be installed by default.
Download the dts you want to use, for example pwm-with-clk-overlay.dts
and build the binary dtb like this
pi@raspberrypi:~ $ dtc -@ -I dts -O dtb -o pwm-with-clk.dtbo pwm-with-clk-overlay.dts
You’ll get some errors complaining about missing references, but you can safely ignore them. This happens because the compiler doesn’t have access to all the includes referenced in the source.
Then copy the dtbo to the overlays directory
pi@raspberrypi:~ $ sudo cp pwm-with-clk.dtbo /boot/overlays
Usage
Use the standard overlays or the -with-clk overlays the same way.
For example to get a hardware timer on GPIO_18 (pin 12) on any RPi, add this to config.txt
4.9 kernel
dtoverlay=pwm
4.4 kernel
dtoverlay=pwm-with-clk
On RPi boards with 40 pin headers, you can get two channels with this overlay
4.9 kernel
dtoverlay=pwm-2chan
4.4 kernel
dtoverlay=pwm-2chan-with-clk
Without arguments, GPIO_18 is the default pin for PWM0 and GPIO_19 is the default for PWM1.
Suppose you wanted to use GPIO_12 for PWM0 and GPIO_13 for PWM1, then you could provide arguments to the overlay like this
dtoverlay=pwm-2chan,pin=12,func=4,pin2=13,func2=4
When you boot with the pwm overlay loaded, you should see the kernel pwm_bcm2835 driver loaded
root@rpi3:~# lsmod | grep pwm
pwm_bcm2835 2711 0
It’s a standard Linux kernel PWM driver.
Instructions for using the PWM sysfs interface can be found in the Linux documentation pwm.txt.
I have a small Python class that simplifies working with the PWM sysfs interface, but it’s only a convenience and definitely not required to work with the timers.
You can use any language that can do file I/O including the Linux shell.
Here is a quick CLI example with the pwm-2chan-with-clk overlay loaded.
root@rpi3:~# ls /sys/class/pwm
pwmchip0
root@rpi3:~# ls /sys/class/pwm/pwmchip0
device export npwm power subsystem uevent unexport
root@rpi3:~# cd /sys/class/pwm/pwmchip0
There are two PWM channels available
root@rpi3:/sys/class/pwm/pwmchip0# cat npwm
2
Channel 0 is PWM0 and channel 1 is PWM1.
NOTE: For the following echo commands I am assuming a root user to simplify.
On Raspbian you can switch to root like this
pi@raspberrypi:~/overlays $ sudo su -
Prior to using a channel you must export it first
root@rpi3:/sys/class/pwm/pwmchip0# echo 0 > export
That creates a new pwm0
subdirectory
root@rpi3:/sys/class/pwm/pwmchip0# ls
device export npwm power pwm0 subsystem uevent unexport
root@rpi3:/sys/class/pwm/pwmchip0# ls pwm0
duty_cycle enable period polarity power uevent
The period and duty_cycle units are nanoseconds.
Here is a 100 Hz pulse with an 80% duty cycle.
root@rpi3:/sys/class/pwm/pwmchip0# echo 10000000 > pwm0/period
root@rpi3:/sys/class/pwm/pwmchip0# echo 8000000 > pwm0/duty_cycle
root@rpi3:/sys/class/pwm/pwmchip0# echo 1 > pwm0/enable
Here is a servo type signal on PWM1, 20 Hz, 2ms pulse
root@rpi3:/sys/class/pwm/pwmchip0# echo 1 > export
root@rpi3:/sys/class/pwm/pwmchip0# echo 50000000 > pwm1/period
root@rpi3:/sys/class/pwm/pwmchip0# echo 2000000 > pwm1/duty_cycle
root@rpi3:/sys/class/pwm/pwmchip0# echo 1 > pwm1/enable
You can change the values while the timer is running
root@rpi3:/sys/class/pwm/pwmchip0# echo 2500000 > pwm1/duty_cycle
The duty_cycle should obviously not exceed the period.