embedded

Working with PWM on a BeagleBone Black

I recently figured out how to enable and set PWM pins on a BlackBone Black rev. C running debian with a test image dated 2014/12/19. I got the image from here. The debain version is 3.8.13-bone68. All instruction are from the command line of a ssh session. I work on a MacBook Pro, so beaglebone.local works with Bonjour, so I don’t need to know the IP address for the board.

I started by updating and installing the universal io device tree overlays, whose source is in the folder /opt/source/beaglebone-universal-io. This folder contains the github source, so I made sure it was up to date by typing,

git pull origin master

, then to install I typed

make install

In my detective work on this subject, there a two parts to setting up a pin,

  1. Set the pin multiplexing for the mode/function (gpio, pwm, I2C …), which the universal IO device tree overlays allow you to do.
  2. Setup the peripheral for the pin function.

To start, I needed to load the universal IO device tree overlay with following command,

root@beaglebone:~# echo cape-universaln > /sys/devices/bone_capemgr.*/slots

This created files in the /sys/devices/ocp.* folder for the expansion header pins (the files have a “pinmux” extension), which can be used to for pin multiplexing. I have four motors that I control with motor drivers, which I have PWM outputs connected to P9.14, P9.16, P9.21, and P9.22. So, I can look at the multiplexing modes for each pin like this,

root@beaglebone:~# config-pin -l P9.14
default gpio gpio_pu gpio_pd pwm

“pwm” is what I want, so I multiplex the pin by typing

root@beaglebone:~# config-pin P9.14 pwm

I can check pinmux state using the pinmux file in the ocp folder like this,

root@beaglebone:~# cat /sys/devices/ocp.*/P9_14_pinmux.*/state
pwm

Note that the state can be set like this,

root@beaglebone:~# echo pwm > /sys/devices/ocp.*/P9_14_pinmux.*/state

This is useful to know when coding in C/C++.

Now, I’m ready to enable and setup the PWM peripherals. With some detective work by searching, reading blogs, and going through some forum discussions, I pieced together the following. So, the pwm system files are in the folder /sys/class/pwm. This is the listing I got.

root@beaglebone:~# ls -l /sys/class/pwm/
total 0
--w------- 1 root root 4096 Dec 31 1999 export
lrwxrwxrwx 1 root root 0 Jan 6 17:56 pwmchip0 -> ../../devices/ocp.3/48300000.epwmss/48300200.ehrpwm/pwm/pwmchip0
lrwxrwxrwx 1 root root 0 Jan 6 17:56 pwmchip2 -> ../../devices/ocp.3/48300000.epwmss/48300100.ecap/pwm/pwmchip2
lrwxrwxrwx 1 root root 0 Jan 6 17:56 pwmchip3 -> ../../devices/ocp.3/48302000.epwmss/48302200.ehrpwm/pwm/pwmchip3
lrwxrwxrwx 1 root root 0 Jan 6 17:56 pwmchip5 -> ../../devices/ocp.3/48304000.epwmss/48304200.ehrpwm/pwm/pwmchip5
lrwxrwxrwx 1 root root 0 Jan 6 17:56 pwmchip7 -> ../../devices/ocp.3/48304000.epwmss/48304100.ecap/pwm/pwmchip7
--w------- 1 root root 4096 Dec 31 1999 unexport

So, there is a lot to be learned from this listing. I read in a forum post that you export 0 thru 7 to enable the 8 available PWM channels, but that didn’t tell me which pin they corresponded to. So, I noticed that the files “pwmchip#” are links to another folder, and they range from 0 to 7. Looking at the paths there are two numbers that look like memory addresses. So, the next clues can be found in the “AM335x Sitara Processors, Technical Reference Manual” which can be found here.
Looking for address 48300000 in the memory map, I found this was in the L4_PER block, and this was listed as the “PWM subsystem 0”, and 48300200 was the EHR0 PWM channel and 48300100 the eCAP0 PWM. Also, address 4830200 is the “PWM subsystem 1”, and address 4830400 is the “PWM subsystem 2”.  Awesome, I’m on the right track to figuring this out. Now, using the pin names found from the “BeagleBoard.org – bone101” page served from the board, and deductive reasoning. I came up with the following maping of pin to export number.

export number pin name pins
0 EHRPWM0A P9.22,P9.31
1 EHRPWM0B P9.21,P9.29
2 ECAPPWM0 P9.42
3 EHRPWM1A P9.14,P8.36
4 EHRPWM1B P9.16,P8.34
5 EHRPWM2A P8.19,P8.45
6 EHRPWM2B P8.13,P8.46
7 ECAPPWM2 P9.28

Awesome!! So, I’m now ready to setup the PWM to control the speed of my motors. P9.14 was one of the PWM pins I connected, so it is EHRPWM1A with export number 3. So, to enable the peripheral I can type the following,

root@beaglebone:~# echo 3 > /sys/class/pwm/export

Listing the contents of the pwm folder I see this,

root@beaglebone:~# ls /sys/class/pwm/
export pwm3 pwmchip0 pwmchip2 pwmchip3 pwmchip5 pwmchip7 unexport

So, a folder named “pwm3” showed which means that the export worked. Next, I want to look inside this folder,

root@beaglebone:~# ls /sys/class/pwm/pwm3/
device duty_ns period_ns polarity power run subsystem uevent

Perfect, I can configure the PWM, but what do I set these to? I found a link to “Linux Core PWM User’s Guide, however, some of it is wrong, but it gave me enough to understand how to configure the PWM. The duty cycle and period are in nanoseconds, and “run” will enable the output. So, I can check and set things as follows,

root@beaglebone:~# cat /sys/class/pwm/pwm3/duty_ns
0
root@beaglebone:~# echo 500000 > /sys/class/pwm/pwm3/duty_ns
root@beaglebone:~# cat /sys/class/pwm/pwm3/duty_ns
500000

I was able run my motors and change the speed using the command line. The next step would be to code this in C/C++ using the open(), write(), and close() functions. So, that was my adventure in getting the PWM output working in my project.

Standard

14 thoughts on “Working with PWM on a BeagleBone Black

  1. Pingback: Working With PWM On A #BeagleBoneBlack @TXInstruments @BeagleBoardOrg « adafruit industries blog

  2. Pingback: Making Catchup: 6502 home computer, Trinket Mouse, Beaglebone IO, Manga Screen and piCore Linux | Codescaling

  3. Hello, I am currently trying to follow your tutorial, but when I execute “echo 3 > /sys/class/export” I get this error “-bash: echo: write error: No such device”. What should I do?

    Like

  4. Bob says:

    root@beaglebone:~# more /sys/devices/bone_capemgr.*/slots
    0: 54:PF—
    1: 55:PF—
    2: 56:PF—
    3: 57:PF—
    4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G
    5: ff:P-O-L Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI
    7: ff:P-O-L Override Board Name,00A0,Override Manuf,bone_pwm_P8_13
    8: ff:P-O-L Override Board Name,00A0,Override Manuf,bone_pwm_P9_14
    9: ff:P-O-L Override Board Name,00A0,Override Manuf,bone_pwm_P9_21
    10: ff:P-O-L Override Board Name,00A0,Override Manuf,bone_pwm_P9_42
    root@beaglebone:~# echo 6 > /sys/class/pwm/export
    -bash: echo: write error: No such device
    root@beaglebone:~# echo 3 > /sys/class/pwm/export
    -bash: echo: write error: No such device

    Like

  5. Bob says:

    Above problem was the old Angstrom way of doing pwm, after rebooting and following the authors directions the problem went away. This article is EXCELLENT!

    Like

  6. Marcelo Gobetti says:

    Hello! Thanks a lot for sharing your great discovers. This method actually proved to activate the PWMs more precisely than using the “config-pin” utility – don’t ask me why, I haven’t discovered it yet, but the pin output looks a lot like a charging-discharging capacitor, while your method outputs pretty square waves with only a 10 nanosecond oscillation at its borders. So, as your method is the one I use for my work, I would like to add this post as a reference to it. Would you mind sharing your name so that I can give you proper credit? Thank you very much.

    Like

  7. Hugo says:

    Great Work!!! I have follow this instructions and its working!! Have you made the code with the C/C++ functions ? Can you send me??

    Like

  8. dean_sh says:

    Hi there. This tutorial was excellent. I managed to get PWM out working without a problem.

    How would I go about reading a PWM from another device?

    Like

  9. Chris says:

    Awesome! Great explanations, effective and to the point. Very similar stuff is working on the 4.1 kernel. Some items have been moved around slightly in the directory structure, but this post was what got me on track. Thanks!

    Like

Leave a comment