Difference between revisions of "EBC Exercise 13 Pulse Width Modulation"

From eLinux.org
Jump to: navigation, search
m (Added Analytics)
m
(34 intermediate revisions by 3 users not shown)
Line 1: Line 1:
 
[[Category:EmbeddedBeagleClass]]
 
[[Category:EmbeddedBeagleClass]]
 
[[Category:ECE497]]
 
[[Category:ECE497]]
<analytics uacct="UA-119847-6" ></analytics>
+
{{YoderHead}}
 +
{{EBC3.8}}This is for the 3.8 kernel.  [[EBC Exercise 13 Pulse Width Modulation 3.2]] is for the 3.2 kernel.
  
In a previous exercise ([[EBC Exercise 03 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 a previous exercise ([[EBC Exercise 11 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 we will learn how to use the Beagle's pulse width modulation (pwm) hardware by writing directly to the registers that control it and also learn about pin multiplexing (pin mux) on the way.
+
In this exercise you will learn how to use the Beagle's pulse width modulation (pwm) hardware using the sysfs interface.
  
=== PWM and pin MUXing ===
+
== PWM on the Bone ==
  
The DM3730 has 11 general purpose timers, 4 of which (gpt8-gpt11) can be brought out of the chip and used for pulse width modulation ([http://focus.ti.com/docs/prod/folders/print/dm3730.html DM3730 TRM page 2689]). The problem is the DM3730 has more internal lines than hardware I/O pins.  The solution is that I/O pins run though a MUX that selects which internal lines appear on I/O pins.  A given pin can have one from as many as eight lines assigned to it. 
+
(Note: The pwm interface seems to changing. Some of this may not apply in the future.)
  
These MUXes are set at boot time, and must be set when the kernel boots, or in u-boot. I couldn't set them during kernel boot with the 2.6.32 kernel, so I used u-boot.  [[BeagleBoardPinMux]] is a good place to learn about the pin MUXing. The u-boot details are [[BeagleBoardPinMux#Setting_Mux_Through_u-boot | here]].
+
The Bone has a PWM interface at <code>/sys/class/pwm/</code>. You can see what's there by:
  
[[BeagleBoardPWM]] is a nice overview of how to do PWM on the BeagleThe version of the kernel and u-boot that I've given you should already be configured to access the PWM pins. If it isn't you'll have to recompile the Kernel and u-boot.
+
beagle$ '''cd /sys/class/pwm'''
 +
beagle$ '''ls -F'''
 +
export  unexport
 +
Hmmm, there isn't much there.  We have to run a command to make something appearTry
 +
beagle$ '''SLOTS=/sys/devices/bone_capemgr.*/slots'''
 +
beagle$ '''PINS=/sys/kernel/debug/pinctrl/44e10800.pinmux/pins'''
 +
beagle$ '''echo am33xx_pwm > $SLOTS'''
 +
beagle$ '''ls -F'''
 +
export  pwmchip0@  pwmchip2@  pwmchip3@  pwmchip5@  pwmchip7@  unexport
 +
Now we need to run another command to say which pwm pin we want to use. I'm using P9_21.
 +
beagle$ '''echo bone_pwm_P9_21 > $SLOTS
 +
Now you can export a pwm much list you export a gpio port
 +
beagle$ '''echo 1 > export'''
 +
beagle$ '''cd pwm1'''
 +
beagle$ '''ls -F'''
 +
device@  duty_ns  period_ns  polarity  power/  run  subsystem@  uevent
 +
Try a 1kHz frequency with a 25% duty cycle
 +
beagle$ '''echo 1000000 > period_ns'''
 +
beagle$ '''echo  250000 > duty_ns'''
 +
beagle$ '''echo 1 > run'''
 +
If you have an oscilloscope try probing pin P9_21. I'm getting a nice clean 1kHz 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 standard way to interface with the outside world in Linux is through Kernel Drivers. Currently there are no standard PWM driver for the Beagle, though couple have been proposed ([https://groups.google.com/d/topic/beagleboard/RI3qTxn68bY/discussion], [http://git.billgatliff.com/pwm.git/?p=pwm.git;a=commit;h=a49cbfff0fa09bff40d328f8985a0a7a7b951d6f] and [http://git.pengutronix.de/?p=imx/linux-2.6.git;a=commit;h=137654cde98a2ffe548f47f02e7fde512bc2091c]). [[BeagleBoardPWM]] takes a more traditional MCU approach by accessing the memory mapped PWD registers directly using '''mmap''' in a C program. Although this approach works, it is really transitional until a standard can be established. 
 
  
You could even do PWM from a shell command by using [http://esdw.wordpress.com/2010/03/25/a-useful-tool-devmem2/ devmem2] to write to the memory mapped registers from a command line.
+
The [http://processors.wiki.ti.com/index.php/AM335x_PWM_Driver's_Guide AM335x PWM Driver's Guide] details what eCAP and eHRPWM are and gives some examples.
  
== Assignment ==
+
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?
  
Updated pwd files are [http://www.rose-hulman.edu/~yoder/Beagle/exercises/ here]. 
+
Stick a scope on the pin and see if the frequency and duty cycle are right.  What's the highest frequency you can get? What's the lowest?
# Copy the '''dm3730-demo''' directory to your Beagle.
+
# Look at the file to see what they are doing.
+
# Run '''make''', then '''pwd-demo'''.   
+
# Hook up a oscilloscope.  (See Table 22 of the [http://beagleboard.org/static/BBxMSRM_latest.pdf Beagle System Reference manual] to see where to probe.) Are the pwd outputs doing what you expected?
+
# What's the highest frequency you can generate? What's the lowest?
+
# Create a new C program, based on pwm-demo, that take 3 parameters, the <pwm to use>, <frequency> and <duty cycle>.
+
# Create a shell file that will call your new program and set up the three pwm's that appear on the expansion header and program them to do something interesting.
+
# Write a shell file that will do the pin MUXing using '''devmem2'''.
+
# Rewrite '''pwm-demo''' as a shell file that uses '''devmem2'''.
+
  
== Resources ==
+
{{YoderFoot}}
 
+
# [[BeagleBoardPWM]] from ECE597
+
# [[BeagleBoard/GSoC/2010_Projects/Pulse_Width_Modulation]]  Google SoC project
+
# [[BeagleBoardPinMux]], how to set the pin mux.
+

Revision as of 16:34, 31 May 2013

thumb‎ Embedded Linux Class by Mark A. Yoder


3.8 Kernel

This is for the 3.8 kernel. EBC Exercise 13 Pulse Width Modulation 3.2 is for the 3.2 kernel.

In a previous exercise (EBC Exercise 11 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.

PWM on the Bone

(Note: The pwm interface seems to changing. Some of this may not apply in the future.)

The Bone has a PWM interface at /sys/class/pwm/. You can see what's there by:

beagle$ cd /sys/class/pwm
beagle$ ls -F
export  unexport

Hmmm, there isn't much there. We have to run a command to make something appear. Try

beagle$ SLOTS=/sys/devices/bone_capemgr.*/slots
beagle$ PINS=/sys/kernel/debug/pinctrl/44e10800.pinmux/pins
beagle$ echo am33xx_pwm > $SLOTS
beagle$ ls -F
export  pwmchip0@  pwmchip2@  pwmchip3@  pwmchip5@  pwmchip7@  unexport

Now we need to run another command to say which pwm pin we want to use. I'm using P9_21.

beagle$ echo bone_pwm_P9_21 > $SLOTS

Now you can export a pwm much list you export a gpio port

beagle$ echo 1 > export
beagle$ cd pwm1
beagle$ ls -F
device@  duty_ns  period_ns  polarity  power/  run  subsystem@  uevent

Try a 1kHz frequency with a 25% duty cycle

beagle$ echo 1000000 > period_ns
beagle$ echo  250000 > duty_ns
beagle$ echo 1 > run

If you have an oscilloscope try probing pin P9_21. I'm getting a nice clean 1kHz 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.

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?

Stick a scope on the pin and see if the frequency and duty cycle are right. What's the highest frequency you can get? What's the lowest?




thumb‎ Embedded Linux Class by Mark A. Yoder