EBC Pulse Width Modulation

In a previous exercise (EBC gpio Polling and Interrupts) you saw how to use the gpio to produce a square wave out using a C program and sysfs. I was able to get a 1.5kHz square wave out; however we can do much better using some built in hardware on the Beagle.

In this exercise you will learn how to use the Beagle's pulse width modulation (PWM) hardware using the sysfs interface.

On Chip Peripherals (OCP)
BeagleBone Black has a large number on on chip peripherals. You can see a list with these commands. bone$ SLOTS=/sys/devices/bone_capemgr.*/slots bone$ cd /sys/devices/ocp.* bone$ ls 44e07000.gpio    48046000.timer                 49000000.edma      nop-phy.6 44e09000.serial  48048000.timer                 4a100000.ethernet  nop-phy.7 44e0b000.i2c     4804a000.timer                 53100000.sham      power 44e10448.bandgap 4804c000.gpio                  53500000.aes       rstctl.4 44e35000.wdt     4819c000.i2c                   56000000.sgx       subsystem 44e3e000.rtc     481ac000.gpio                  gpio-leds.8        uevent 47400000.usb     481ae000.gpio                  mmc.11 48042000.timer   48200000.interrupt-controller  mmc.5

The hex numbers are the physical address for the peripheral. Initially the PWM interface doesn't appear.

Pulse Width Modulation
(Note: The PWM interface seems to changing. Some of this may not apply in the future.)

Here's how to see the PWM interface.

bone$ echo am33xx_pwm > $SLOTS bone$ ls 44e07000.gpio    48046000.timer                 48302000.epwmss    mmc.11 44e09000.serial  48048000.timer                 48304000.epwmss    mmc.5 44e0b000.i2c     4804a000.timer                 48310000.rng       modalias 44e10448.bandgap 4804c000.gpio                  49000000.edma      nop-phy.6 44e35000.wdt     4819c000.i2c                   4a100000.ethernet  nop-phy.7 44e3e000.rtc     481ac000.gpio                  53100000.sham      power 47400000.usb     481ae000.gpio                  53500000.aes       rstctl.4 48042000.timer   48200000.interrupt-controller  56000000.sgx       subsystem 48044000.timer   48300000.epwmss                gpio-leds.8        uevent

Three PWM controllers have appeared. Now, to use PWM on P9_21:

bone$ echo bone_pwm_P9_21 > $SLOTS bone$ cd /sys/devices/ocp.*/pwm_test_P9_21.* bone$ ls driver duty  modalias  period  polarity  power  run  subsystem  uevent

The units are in ns. Try a 1Hz frequency with a 25% duty cycle bone$ echo 1000000000 > period bone$ echo 250000000 > duty bone$ echo 1 > run

Connect the LED from and watch it flash. Try changing the frequency and duty cycle. You may have to set the duty cycle to 0 to change the frequency. Can you guess why?

Challenge
Combine the analog in and the PWM by having the pot control the frequency or the duty cycle of the LED.

If you have an oscilloscope try probing pin P9_21. I'm getting a nice clean 1Hz signal, with no variation. Let's try a higher frequency, like 10 MHz. beagle$ echo 50 > duty_ns beagle$ echo 100 > period_ns I'm getting a 9 MHz signal that has lots of ringing. The timer in the bone must be off a bit.

The AM335x PWM Driver's Guide details what eCAP and eHRPWM are and gives some examples.