BeagleBoard/GSoC/2010 Projects/Pulse Width Modulation

Project: Pulse Width Modulation
Student: Varun Jewalikar

Mentors: Søren Steen Christensen, Cristina Murillo

Repository: http://github.com/neo01124/omap3-pwm

Blog: http://beagleboard-pwm.blogspot.com/

Latest blog entries: http://beagleboard-pwm.blogspot.com/feeds/posts/default|charset=UTF-8|max=3

Abstract
The main aim of this project will be to provide a high level interface for the Pulse Width Modulation output pins of the OMAP3 found on the BeagleBoard. Another aim will be to push this driver upstream(the Linux-OMAP tree). Two applications will be developed to demonstrate the use of this driver:
 * Motor control using PWM signals generated by the BeagleBoard using the PWM driver.
 * Writing a glue layer for ALSA to communicate with the PWM driver and output sound from the PWM output pins.

Build and Run instructions
git clone git://github.com/neo01124/omap3-pwm.git cd omap3-pwm/
 * Clone my git tree for the driver.This can be done using the following commands:

git clone git://github.com/jyore/omap3-pwm.git cd omap3-pwm
 * For newer kernel versions, you can try the fork of the original project (should work with the BeagleBone).


 * A cross compiling environment will be needed for compiling the driver. Instructions below work with OpenEmbedded but can adapted for codesourcery as well.

$ vim beagle-source-me.txt Edit the OETREE path. OETREE should point to the OE folder. For me OETREE= ~/OE.

$ source beagle-source-me.txt This will set the environment variables for cross compilation.

$ make This will generate the requisite pwm.ko kernel module file.


 * Copy the pwm.ko to your target board.

root@beagleboard# ls pwm.ko root@beagleboard# insmod pwm.ko pwm9_enable=1
 * Once on the system, use insmod to load using the optional frequency parameter. The default frequency is 1024 Hz. Use multiples of two with a max of 16384. pwm9_enable,pwm10_enable and pwm11_enable and frequency are load time parameters.

The driver implements a character device interface. When it loads, it will create a /dev/pwm9 entry.

root@beagleboard# insmod pwm.ko pwm9_enable=1 pwm10_enable=1
 * To setup multiple pwm signals on the GPT9/10/11 you should use

This will work similarly for any other (pwm_9/10/11) combinations as well.

Using the sysfs interface (Not advised and fully supported) : Then to issue commands you can use any program that can do file I/O cat and echo will work. root@beagleboard# cat /dev/pwm9 PWM9 Frequency 1024 Hz Stopped root@beagleboard# echo 50 > /dev/pwm9 root@beagleboard:~# cat /dev/pwm9 PWM9 Frequency 1024 Hz Duty Cycle 50% root@beagleboard:~# echo 80 > /dev/pwm9 root@beagleboard:~# cat /dev/pwm9 PWM9 Frequency 1024 Hz Duty Cycle 80% You can put an oscope on pin 28 of the expansion board to see the signal. Use pin 15 for ground. Or you can measure the voltage on pin 28 and you'll see the duty cycle percentage of 1.8v. A fully supported ioctl interface is available and it is advised to prefer this over the above sysfs interface. Sample code to use the ioctl interface: //#define PWM_IOC_MAGIC 0x00 /**/ main {	int fd, status, k, f, sc;
 * There are two ways of modifying the parameters from userland.
 * Using the ioctl calls :
 * 1) include 
 * 2) include 
 * 3) include 
 * 4) include 
 * 5) include 
 * 1) define PWM_SET_DUTYCYCLE 1074003969
 * 2) define PWM_GET_DUTYCYCLE 1074003970
 * 3) define PWM_SET_FREQUENCY 1074003971
 * 4) define PWM_GET_FREQUENCY 1074003972
 * 5) define PWM_ON 1074003973
 * 6) define PWM_OFF 1074003974
 * 7) define PWM_SET_POLARITY 1074003975

fd = open("/dev/pwm9", O_RDWR); scanf("%d", &k); scanf("%d", &f); scanf("%d", &sc);

if (ioctl(fd, PWM_SET_FREQUENCY, f) == -1) printf("TIOCMGET failed: %s\n", strerror(errno));

if (ioctl(fd, PWM_SET_DUTYCYCLE, k) == -1) printf("TIOCMGET failed: %s\n", strerror(errno));

if (ioctl(fd, PWM_SET_POLARITY, sc) == -1) printf("TIOCMGET failed: %s\n", strerror(errno)); printf("%d",ioctl(fd, PWM_GET_FREQUENCY, sc)); printf("\n%d",ioctl(fd, PWM_GET_DUTYCYCLE, sc));

close(fd); }


 * For more information refer to the README file.

Kernel Patch
The kernel config option CONFIG_OMAP_RESET_CLOCKS is enabled in the default beagleboard defconfigs. You'll get an oops using pwm.ko with this enabled. This is a kernel power saving feature. You'll need to disable this config option to use this driver. Below is a sample patch for linux-omap-2.6.32's defconfig. Adjust for the kernel you are using. Gumstix users already have this turned off in default kernels. diff --git a/recipes/linux/linux-omap-2.6.32/beagleboard/defconfig b/recipes/linux/linux-omap-2.6.32/beagleboard/defconfig index cebe1f5..2dad30c 100644 --- a/recipes/linux/linux-omap-2.6.32/beagleboard/defconfig +++ b/recipes/linux/linux-omap-2.6.32/beagleboard/defconfig @@ -241,7 +241,7 @@ CONFIG_ARCH_OMAP3=y # -CONFIG_OMAP_RESET_CLOCKS=y +# CONFIG_OMAP_RESET_CLOCKS is not set CONFIG_OMAP_MCBSP=y CONFIG_OMAP_MBOX_FWK=m
 * 1) CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
 * 2) CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
 * 1) CONFIG_OMAP_MUX is not set

Links

 * More Info about PWM on the beagleboard
 * Demo video using PWM on the beagleboard to control a motor
 * Demo video using PWM on the beagleboard to drive a speaker
 * GUMSTIX: Controlling PWM outputs from an OMAP3 based Linux systems