linux 3.8 PWM guide?

4,130 views
Skip to first unread message

joseph yarborough

unread,
Jun 6, 2013, 11:12:10 PM6/6/13
to beagl...@googlegroups.com
I'm having a real time trying to figure out how to enable PWM on the BBB.

Apparently in 3.8 you need to use "device trees" which require compiling code to go into /boot/dtbs/.

I'm completely confused on the hows and whys. Everything I read seems to suggest that I not only need some custom version of the kernel, but also a custom version of dtc. Can this be true? It seems kinda nuts, but maybe that's the state of affairs.

I can use the /sys filesystem to enable pwm's and enable P8_13, but it's apparently not muxed (to mode 4?) so none of my changes to the period_ns/duty_ns files seem to do anything.

If anyone has a guide that shows a newbie like me, step by step, what is going on, I would so very greatly appreciate it!

-JNY

Jacek Radzikowski

unread,
Jun 6, 2013, 11:24:12 PM6/6/13
to beagl...@googlegroups.com
It's simpler that you could think:

modprobe pwm_test
echo am33xx_pwm > /sys/devices/bone_capemgr.9/slots
echo bone_pwm_P9_14 > /sys/devices/bone_capemgr.9/slots
echo 500 > /sys/devices/ocp.2/pwm_test_P9_14.*/period
echo 250 > /sys/devices/ocp.2/pwm_test_P9_14.*/duty

This will connect PWM to pin P9_14 and generate on the pin ~2MHz
waveform with 50% duty.

j.
> --
> For more options, visit http://beagleboard.org/discuss
> ---
> You received this message because you are subscribed to the Google Groups
> "BeagleBoard" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to beagleboard...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>



--
Given a choice between two theories, take the one which is funnier

joseph yarborough

unread,
Jun 6, 2013, 11:29:00 PM6/6/13
to beagl...@googlegroups.com
pwm_test not found. I thought that was the code from pwm_test.c, which was the kernal patch I was told I didn't need to use because of magical device trees.

Jacek Radzikowski

unread,
Jun 6, 2013, 11:35:27 PM6/6/13
to beagl...@googlegroups.com
install kernel-module-pwm-test package.

j.


On Thu, Jun 6, 2013 at 11:29 PM, joseph yarborough

joseph yarborough

unread,
Jun 6, 2013, 11:50:17 PM6/6/13
to beagl...@googlegroups.com
I'm guessing on angstrom? Or will ubuntu work? Which version?

I usually prefer arch, but support on the BBB seems weak on arch. I'm currently flashing the latest angstrom to attempt this method, but would it work on ubuntu as well? Ubuntu has support for JDK7, where I want to do my development.

Thanks big time,
-JNY

Jacek Radzikowski

unread,
Jun 6, 2013, 11:53:01 PM6/6/13
to beagl...@googlegroups.com
I'm using angstrom. Unfortunately I can't help you with ubuntu, but
this may give you some ideas:
http://hipstercircuits.com/enable-pwm-on-beaglebone-with-device-tree-overlays/

j.


On Thu, Jun 6, 2013 at 11:50 PM, joseph yarborough

joseph yarborough

unread,
Jun 6, 2013, 11:58:07 PM6/6/13
to beagl...@googlegroups.com
I've read that 20 times to no avail. haha.

I'm installing angstrom. If I can get it working in any distro, I can figure out how to bring in my tools.

Thank you very much for your time.

-JNY

joseph yarborough

unread,
Jun 7, 2013, 12:04:18 AM6/7/13
to beagl...@googlegroups.com
What version of the kernel / angstrom are you using? It didn't work on my fresh install of the latest angstrom.

joseph yarborough

unread,
Jun 7, 2013, 12:07:19 AM6/7/13
to beagl...@googlegroups.com
root@beaglebone:/sys/devices/bone_capemgr.8# echo am33xx_pwm > slots
-sh: echo: write error: No such file or directory

Jacek Radzikowski

unread,
Jun 7, 2013, 12:08:27 AM6/7/13
to beagl...@googlegroups.com
Install angstrom from the latest flasher from
http://beagleboard.org/latest-images. Everything worked for me OOTB.

j.

Jacek Radzikowski

unread,
Jun 7, 2013, 12:09:49 AM6/7/13
to beagl...@googlegroups.com
What image did you use?

j.

joseph yarborough

unread,
Jun 7, 2013, 12:11:25 AM6/7/13
to beagl...@googlegroups.com
I am absolutely using this file:

demo_beaglebone_BBB-eMMC-flasher-2013.05.27.xz

I uncompress it to it's 4gB of glory, then dd it onto my flash card.

Then I put it in and boot (my onboard flash has no image, so it's definately booting from sdcard)

Then I use those commands and it fails when I try to inable am33xx_pwm


# cat slots
...
 6: ff:P-O-- Override Board Name,00A0,Override Manuf,am33xx_pwm

Jacek Radzikowski

unread,
Jun 7, 2013, 12:14:50 AM6/7/13
to beagl...@googlegroups.com
Did you flash the image, or are you trying to configure PWM on system
running from the SD card?

j.


On Fri, Jun 7, 2013 at 12:11 AM, joseph yarborough

joseph yarborough

unread,
Jun 7, 2013, 12:20:08 AM6/7/13
to beagl...@googlegroups.com
I dd if=[file] of=/dev/sdd and boot it up.

Should I be doing something else after that to get the system live?

Jacek Radzikowski

unread,
Jun 7, 2013, 12:21:52 AM6/7/13
to beagl...@googlegroups.com
Boot from SD card, go for a long walk and after the flashed finishes
work remove the SD card and boot the system from the on-board flash.

j.


On Fri, Jun 7, 2013 at 12:20 AM, joseph yarborough

joseph yarborough

unread,
Jun 7, 2013, 12:24:56 AM6/7/13
to beagl...@googlegroups.com
I am ashamed...

I didn't read the last paragraph of the instructions because it all looked to be identical to every other RPi/BB distro I've ever used.

I had no idea it was meant to upgrade the eMMC rather than run live from the SD card.

Thanks.

joseph yarborough

unread,
Jun 7, 2013, 8:23:00 AM6/7/13
to beagl...@googlegroups.com
Thanks much for your help good sir. I rebooted this morning and it works beautifully I think. I say I think because this microservo from radioshak just moves to max out when I do a period of 20000000 and any duty cycle between 1666666-6666666 (which should be moving twards the middle.

It just maxes out but I think it could be because it is expecting a higher voltage signal? I'm not sure because if I set it too low the motor stops maxing out.

KurtE

unread,
Jun 7, 2013, 10:24:45 AM6/7/13
to beagl...@googlegroups.com
I have been playing around with  Saad Ahmad c++ library code mentioned in the thread:

https://groups.google.com/forum/embed/?place=forum/beagleboard&showsearch=true&showpopout=true&showtabs=true&hideforumtitle=true&parenturl=http%3A%2F%2Fbeagleboard.org%2FCommunity%2FForums%3Futm_expid%3D6702460-6%26utm_referrer%3Dhttp%253A%252F%252Fbeagleboard.org%252FSupport%252FHardware%252520Support#!category-topic/beagleboard/C2tzvRYk1Wg

Plus when I was first playing with these commands, I also found that the pulse was wrong for servos, as the polarity was wrong so for example when I was trying to create a 1500us pulse it was actually creating a 20000-1500us pulse.  You can change this by updating the polarity variable/file of the test.  For your Duty I would expect the valid ranges in us to within the 500-2500us range or maybe tighter (750-2250us).  Obviously need to multiple by 1000 to get to ns.

I did an update to his test program that now looks like;
#include "PWM.h"
#include <ctime>
#include <string>
#include <unistd.h>
int main()
{
   
const int delayMS = 50;
   
const long periodNS = 20 * MILLISECONDS_TO_NANOSECONDS;

    PWM
::Pin pinA("P8_13", periodNS); // Since both pins share the same channel, they're periods must be the same
    std
::cout << "P8_13 created" << std::endl;

    PWM
::Pin pinB("P8_19", periodNS);
    std
::cout << "P8_19 created" << std::endl;

   
int slot = PWM::GetCapeManagerSlot("P8_13");
    std
::stringstream ss;
    ss
<< slot;
    std
::cout << "Found: " << ss.str() << std::endl;


   
// Enable both only after we have set the periods properly.
   
// Otherwise we will have conflicts since each pin will try to set its own period and conflict with the others
    std
::cout << "Before PinA enable" << std::endl;
    pinA
.Enable();
    std
::cout << "Before PinB enable" << std::endl;
    pinB
.Enable();
    std
::cout << "Pins Setup and ready to go!" << std::endl;

   
// I want to do a sweep of the two servos from 500us to 2500us
   
for (int pw = 500; pw < 2500; pw+=100)
   
{
        pinA
.SetDutyUS(pw);
        pinB
.SetDutyUS(3000-pw);    // reverse this one.
        usleep
(100 * 1000);        // delay for a bit maybe 5 pulses per pw
   
}
   
// Tell both pins to stop.
    pinA
.Disable();
    pinB
.Disable();

    std
::cout << "Done everything. Quiting now!" << std::endl;
}



I have my Saleae logic analyzer hooked up to these pins and have verified that I am now generating what appears to be very good servo like output.  The only interesting thing was figuring out the best way to end the pulses.  If I set the duty to zero, it created some strange outputs on one of the pins, likewise if I just let the objects get destroyed, one channel generated maybe 6 more pulses... Disable did it cleanly.

Note: I went through the complete steps to rebuild the test_pwm object plus create the SC_PWM overlays like he spelled out in his write up.

Kurt

Message has been deleted

Saad Ahmad

unread,
Jun 7, 2013, 11:15:33 AM6/7/13
to beagl...@googlegroups.com
@Kurt, 
For cleanup could you describe the strange outputs? If its because of the 6 extra pulses I believe the issue is because I have a delay in the UnloadDeviceTreeModule function which would cause the second pin to  output for at least 100ms after the first pin is destroyed. I added that in because I was having some issues with timing when I loading the module into the cape_manager. If you want you can try removing the usleep(MODULE_DELAY_TIME_US); and see if you have any issues. I didn't seem to have any issues with it when I removed the delay but better safe then. If also ends up working fine I can remove it from the code. I would say that disable is also good. 

@Joseph,
If you want you can try to used the compiled dtbo and pwm_test files instead of having to compile it yourself. I believe the SC_PWM overlays you can just the compiled ones as I dont really see much related to the kernel itself in it. The pwm_test kernel module you may need to compile as the compiled one I provided was for 3.8.13

Saad 

KurtE

unread,
Jun 7, 2013, 11:45:39 AM6/7/13
to beagl...@googlegroups.com
As you mentioned without doing anything, with the test program, it is probably fine as it simply output the 2nd one during your delay.  Will try later to see if removing it helps, but again it probably does not hurt anything for it to output a few extra pulses.

The 2nd test I did of setting the duty to 0, is something I wanted to check out as with my robot, I may wish to issue a command (over the XBee) to tell the motors to relax.  So wanted to see if that would do it cleanly... What I found is setting them both to zero, one or both of these channels would output a full 20ms pulse and then every 20ms (my Frame rate), they both output a very short pulse in the nature of .25us.  Could be smaller, I have my LA set for 8mhz sample rate.   Again not a big deal as setting the enable cleans up nicely.

Thanks again
Kurt

joseph yarborough

unread,
Jun 7, 2013, 12:43:21 PM6/7/13
to beagl...@googlegroups.com
I figured it out! I was thinking of the duty cycles backwards it seems. I needed to give it numbers close to the high end, rather than the low end.

Perhaps this is the "reverse polarity" stuff people were talking about in relation to duty cycles?

I have a driver working now. Thank you very much.

mic...@bondoandersen.dk

unread,
Oct 30, 2013, 8:39:22 PM10/30/13
to beagl...@googlegroups.com
Just a short comment:
 
Using Beagleboard bone, and ubuntu 3.8 with kernel:
-  Linux ubuntu-armhf 3.8.13-bone28: pwm IS working
-  Linux ubuntu-armhf 3.8.13-bone20: pwm is NOT working
 
Probably because the driver (pwm_test.ko) is not included
 
- MBA
 

Robert Nelson

unread,
Oct 30, 2013, 8:44:33 PM10/30/13
to Beagle Board
On Wed, Oct 30, 2013 at 7:39 PM, <mic...@bondoandersen.dk> wrote:
> Just a short comment:
>
> Using Beagleboard bone, and ubuntu 3.8 with kernel:
> - Linux ubuntu-armhf 3.8.13-bone28: pwm IS working
> - Linux ubuntu-armhf 3.8.13-bone20: pwm is NOT working

and for some reason, users seem to not want to upgrade from bone20 to
bone28... Not sure why. ;)

Regards,

--
Robert Nelson
http://www.rcn-ee.com/

Giuseppe Iellamo

unread,
Oct 31, 2013, 6:28:55 AM10/31/13
to beagl...@googlegroups.com
Just my two cent,

after some struggling with the eQep support

I'm currently using BBB with 3.8.13-bone28 xenomai patched and both of PWM and encoder reading are working well.

lmm...@gmail.com

unread,
Nov 14, 2013, 2:12:56 PM11/14/13
to beagl...@googlegroups.com
what did you do to get it to work on the new kernel? did you simply follow the steps here:

  modprobe pwm_test 
  echo am33xx_pwm > /sys/devices/bone_capemgr.9/slots 
  echo bone_pwm_P9_14 > /sys/devices/bone_capemgr.9/slots 
  echo 500 > /sys/devices/ocp.2/pwm_test_P9_14.*/period 
  echo 250 > /sys/devices/ocp.2/pwm_test_P9_14.*/duty 

?

lmm...@gmail.com

unread,
Nov 14, 2013, 2:15:39 PM11/14/13
to beagl...@googlegroups.com
Was this using Ubuntu?

Giuseppe Iellamo

unread,
Nov 16, 2013, 2:00:29 AM11/16/13
to beagl...@googlegroups.com, lmm...@gmail.com
Yes I'm using Ubuntu 13.04 as my userland.

It is working faily well but sometimes (once in a second) I have latancies that approaces 1 ms... I'm reasoning about writing a xenomai kernel space driver for PWM/eqep....

long...@gmail.com

unread,
Mar 29, 2014, 1:00:47 PM3/29/14
to beagl...@googlegroups.com, lmm...@gmail.com
Is it because of the pwm_test.c that kind of thing?
I'm just don't know what's the connection between the device overlay tree and c/cpp driver?
Reply all
Reply to author
Forward
0 new messages