Page 1 of 1
PWM output
Posted: Thu Jan 27, 2011 7:39 pm
by hayedid
Hi. I have a mod5282. I've been reading up on the PWM functionality -- I don't really understand it yet and I don't have an oscilloscope to see the output. The code I've been playing with from one of the manuals is below. I am trying to send PWM output to control a servo. As I understand it, these servos generally function between 20 and 50 Hz. A 1ms pulse puts the servo at 0 degrees, 1.5 at 90 degrees, and a 2ms pulse puts it at 180 degrees. Does anyone know how to do this? Any help would be appreciated.
Thank you very much.
void InitThreePhasePWM(int GPT_num, int pwm_resolution, int p0, int p1, int p2)
{
sim.gpt[GPT_num].scr1=0; // Turn the time system off
sim.gpt[GPT_num].ios=0x0f; // Turn on output compare for all four channels
sim.gpt[GPT_num].oc3m=0x07; // Set up the condition for ch 3 output compare
sim.gpt[GPT_num].oc3d=0x07; // Set up the condition for ch 3 output compare
sim.gpt[GPT_num].tov=0; // No toggle on overflow
sim.gpt[GPT_num].ctl1=0xAA; // Set output to 0 on output compare
sim.gpt[GPT_num].ctl2=0x00; // No input capture
sim.gpt[GPT_num].scr2=0x08; // Enable ch 3 reset with sys clk prescale of 1
sim.gpt[GPT_num].tie=0x00; // No interrupts
sim.gpt[GPT_num].c0=p0; // Set up the initial compare values
sim.gpt[GPT_num].c1=p1;
sim.gpt[GPT_num].c2=p2;
sim.gpt[GPT_num].c3=pwm_resolution;
sim.gpt[GPT_num].ddr=0x0f; // Set all four channel pins as outputs
sim.gpt[GPT_num].scr1=0x90; // enable the timer
}
Re: PWM output
Posted: Fri Jan 28, 2011 1:15 am
by nirias999
You would set a period of 20 mSecs for 50 hz and use a duty cycle that varied from 1ms to 2ms.
I havent run that type of servo off a 5282 but this approach should do the trick:
In order to get such a long period you need to use a timer prescaler of 16, which will slow the timer clock to 2073600 hz. At that timer frequency, your output channel 3 output compare would be 2073600/50 = 41472 to get the 20 mSec period.
For a 1 mSec pulse you would set channel 0 output compare to 2074 and for a 2mSec pulse to 4147. Interpolate linearly between those endpoints for other servo positions.
If you have two more servos you can set their values on channels 1 and 2
To do the prescaler at 16 vs the 1:1 shown in the example code, use sim.gpt[GPT_num].scr2=0x0C; See Table 20-14 in the Freescale manual for the full description of this control register.
Note: I've done PWM to servos with other microcontrollers and have noticed that some servos can be run faster than 50hz. I have also noticed that endpoints of 1ms and 2ms are more like guidelines than a rigid specification. So your actual limits of travel might be 1.1mS to 1.9mS. They might also be 0.9 mS to 2.1mS. If you need things to be exact you will need to calibrate the endpoints to work with your specific servos.
Re: PWM output
Posted: Fri Jan 28, 2011 4:52 am
by Ridgeglider
Take a look at the pin level controls too and the OCxM bits that define how those levels are controlled upon completion of an output compare. Each GPT module (A and B) contain 4 servo channels. I's setup a 20 mSec servo period using channel 3. To start, set the timer count to 0,
and outputs for the other three channels (0, 1, & 2) high. Next, output compares are configured for those channels and they are configured to set their outputs low upon a successful compare. Finally, Channel 3 is configured to return the Ch 1, 2, and 3 outputs high after a successful compare, ie after 20 mSecs. The result is that users can modify the output
pulsewidth of Channels 1, 2, & 3 simply by writing appropriate count values into the compare registers for each of the timer channels. Like the ch3 pulse, the periods of those pulses could be up to 20 msec, although for RC servos, the typical minimum pulse width is 1.0 mSec, and the max pulsewidth is ~2 to 2.5 mSecs. Set up some min and max pulsewidth values for
Channels 0-2 of 1 and 2 mSec respectively, with 2073 possible steps between the two limits. Interrupts are NOT required or used.
You can also use the DMA timers to do this, but on the 5282, the GPTs are great. Note that on most of the NB demo boards, the 5282 GPT pins are alos used by the LEDs so be careful using the putleds() call at the same time as this kind of servo code.
rnirias999 had close to the right PWMperiod value for 20 msec.
#define PWMperiod (41471) // The 5282 system clock is 66,355,200Hz. This
// signal is divided by 2 and presented to the
// input of the GPT timer system as a 33,177,600Hz signal. We need to
// specify the number of counts required to produce a 20 mSec period. IN
// ADDITION, this count MUST fit in the 16 bit GPTA Channel Register,
// (GPTC3) and therefore must be <= 65535. The formula is:
//
// (TimerInputClk / DivisorSpecdByGPTSCR2_PR)
//OutputCompareValue= ----------------------------------------- - 1
// ( 1 / DesiredPulseWidthInSecs)
//
// In the setup function, InitThreePhasePWM, we've spec'd the Divisor
// for the timer input clock as 16 by setting GPTSCR2 PR bits (bit2-0)
// to 100. Therefore, the formula is:
//
// (33,177,600 / 16) 2,073,600
// Output Compare Value = ------------------ - 1 = --------- - 1 so:
// (1 / 0.020) 50
//
// Output Compare Value = 41471. (Note we adjusted the PR divisor
// from 1 down to 16 until the calc'd
// value was <= 65535, the largest
// value to fit in the 16 bit register.
For the 1-2ms pulses, you might try:
#define PWM_MIN (PWMperiod/20) //2074
#define PWM_MAX (PWMmin * 2) //4147
#define PWM_ZERO (PWMmin + (( PWMmax - PWMmin) / 2)) //3110
Re: PWM output
Posted: Fri Jan 28, 2011 6:54 pm
by hayedid
Thank you for your feedback and suggestions.
I'm sorry. I must be missing something that's not clicking yet. Doing google searches on 3 channel PWM's seems to indicate that you would tie each channel to a different pin, but the demo function ties all these channels to the same pin, correct? In what situation would this be done?
It's been a rough week. Perhaps a good nights rest will help.
Re: PWM output
Posted: Sun Jan 30, 2011 4:59 pm
by Ridgeglider
Skip the google searches and pull out chapter 20 (GPT) of the Freescale reference manual for the 5282: C:\nburn\docs\FreescaleManuals\MCF5282UM.pdf and MCF5282UMAD.pdf.
With regard to the pins, yes, there is one pin per servo, however the pin is controlled by two timers. One of the GPT timers, say GPT3, controls the 20 msec interval. The other three timers (GPT0-2) control the 1-2msec intervals, one timer for each of the servo channels. Init all timer pins high. Disable the timer while you init it by clearing the GPTEN and TFFCA bits in GPTSCR1. Turn on ouput compare for all four timers (IOSn=1) in the GPTIOS register. Now that you have spec'd that you want the timers to control pins, specify how they should control pins upon succesful OC3 compare (ie when the 20msec is up). I think you want to load the GPTOC3M register OC3M bit with 0x07 so that a successful output compare will affect the timer 0, 1, & 2 pins, but not the Timer 3 pin. Next, load GPTOC3D register OC3D bit with 0x07 so that the Timer 0,1, & 2 bits go hi w/ succesful compare. Next, load the GPT1CTL OMx/OLx bits wit 0xAA, (ie Omx/OLx = 0b10 = 2). These bits determine what happens to the 3 servo pins when Timers 0, 1, 2 have successful compares. With a value 0f 0xAA, the pin outputs go lo. Eliminate any input captures on pins by writting a 0x00 to GPTCTL2. Set the timer divisor by loading GPTSCR2 with 0x0c, enable TCRE ch 3 reset, and sysclk prescale = so timer divisor is 16. Load 0 into GPTTIE so there are no interrupts. Load The appropriate 1-2 msec pulse width value into Ch0,1& 2 compare registers. Load the number of ticks req'd for 20 mSec intot he Timer 3 control register. Now that the timers are configured, let 'em rip: Write 0x90 to the GPTSCR1 register. This enables the timers with fast clears.
Re: PWM output
Posted: Mon Jan 31, 2011 10:50 am
by greengene