Society of Robots - Robot Forum

Software => Software => Topic started by: cybcode on August 24, 2007, 12:42:31 PM

Title: Accurate servo control - "Phase and Frequency Correct PWM mode" (ATmega8)
Post by: cybcode on August 24, 2007, 12:42:31 PM
Hi,

I've just discovered "Phase and Frequency Correct PWM mode" and I'd like to share it with those who don't already know it. I've searched the forums and I don't think this has been posted before.
If I understood correctly, it's the best way to control 1 or 2 servos. It's much more precise than delay_cycles and more comfortable because it doesn't take any CPU time.

This is what you have to do (will work only with ATmega8 running at 1MHz):

1. Call the following setup function before entering the main loop (before the while(1) in main()):

Code: [Select]
void run_servos_pwm()
{
// Set PB1 and PB2 as outputs
DDRB |= (1 << 1) | (1 << 2);

// Ask for 50Hz (20ms) PWM signal (ms count should be halved)
ICR1 = 20000/2 ;

// Center both servos
OCR1A = 1500/2 ;
OCR1B = 1500/2 ;

// Ask for non-inverted PWM on OC1A and OC1B
TCCR1A = (1 << COM1A1) | (1 << COM1B1);

// Configure timer 1 for Phase and Frequency Correct PWM mode, with no prescaling
TCCR1B = (1 << WGM13) | (1 << CS10);
}

2. When you want to set a servo's position/speed somewhere in the main loop, use the following macros, instead of servo_left() and servo_right():

Code: [Select]
#define SERVO_PWM_LEFT(_us)    OCR1A=_us/2
#define SERVO_PWM_RIGHT(_us)   OCR1B=_us/2

(the valid range for the PWM signal's width is 900us to 2100us with 1500us at the center, according to Hitec's documentation)

or just do

Code: [Select]
OCR1A = integer_between_450_and_1050 ; //for the left servo
OCR1B = integer_between_450_and_1050 ; //for the right servo

3. Instead of connecting the signal wires of the servos to pins 2 and 3, connect the left one to pin 15 (PB1, bottom right) and the right one to pin 16 (PB2, right above PB1).

My servos move much more smoothly this way, and the resolution is much better (450-1050 instead of 21-49). This should be particularly useful if you use fuzzy logic to set the positions/speeds.

Note: setting OCR1A and OCR1B takes no CPU time, unlike servo_left() and servo_right(). This may affect your program's timing.

Here's a page that helped me understand this stuff:
http://mil.ufl.edu/~achamber/servoPWMfaq.html
Title: Re: Accurate servo control - "Phase and Frequency Correct PWM mode" (ATmega8)
Post by: reefat on September 07, 2008, 11:11:55 AM
I just used your code and is working fine with 4MHz Crystal too. Even if I take the Cryatal out, it works. I used 900 for left and 2100 for right rotation.

Got a quick question for you. I have a Continuous Rotations servo. How can I use this piece of code to drive that servo? What part should I modify?
Title: Re: Accurate servo control - "Phase and Frequency Correct PWM mode" (ATmega8)
Post by: Strikeskids on August 24, 2009, 04:58:50 AM
Just use 1500 +- 200 (forwards, backwards) as the _us in the code.
Title: Re: Accurate servo control - "Phase and Frequency Correct PWM mode" (ATmega8)
Post by: SmAsH on August 24, 2009, 05:19:03 AM
This topic was dead...
and besides, the standard for servos is 1000, 1500 and 2000
Title: Re: Accurate servo control - "Phase and Frequency Correct PWM mode" (ATmega8)
Post by: Webbot on August 24, 2009, 05:21:01 AM
I've covered most of this in my PWM tutorial at http://www.societyofrobots.com/member_tutorials/node/228 (http://www.societyofrobots.com/member_tutorials/node/228)

Incidentally: Phase and Frequency Correct mode is really aimed at DC motors and, although it will still work fine, you can also use Fast PWM mode for servos.
Title: Re: Accurate servo control - "Phase and Frequency Correct PWM mode" (ATmega8)
Post by: Razor Concepts on August 24, 2009, 10:11:48 AM
Just a question for webbot - what else would need to be changed if it is running at 16mhz?
Title: Re: Accurate servo control - "Phase and Frequency Correct PWM mode" (ATmega8)
Post by: Webbot on August 24, 2009, 01:03:46 PM
Do you mean for my member tutorial - or for the code originally posted on this thread?
Title: Re: Accurate servo control - "Phase and Frequency Correct PWM mode" (ATmega8)
Post by: Razor Concepts on August 24, 2009, 02:54:34 PM
For your member tutorial. I put ICR1 as 39999 and kept the 8mhz prescaler(cs11). Flashed it on my roboduino board but no luck... probably some stupid mistake somewhere.
Title: Re: Accurate servo control - "Phase and Frequency Correct PWM mode" (ATmega8)
Post by: Webbot on August 24, 2009, 05:21:12 PM
Its exactly for this kinda scenario that I created my library - (see my signature) - rather than having to come up with different code for different platforms, CPU speed etc etc I created a lib where you could say 'I got a servo on pin xx - please control it with PWM' - and it just does it.

But hey ho - back to the details....

Send me your code and I'll have a look. Roboduino=ATMega168 and F_CPU=16Mhz, right?
Title: Re: Accurate servo control - "Phase and Frequency Correct PWM mode" (ATmega8)
Post by: Razor Concepts on August 24, 2009, 05:33:21 PM
Yup. Here is the code below.
Title: Re: Accurate servo control - "Phase and Frequency Correct PWM mode" (ATmega8)
Post by: Chendro on October 01, 2009, 04:14:28 PM

Incidentally: Phase and Frequency Correct mode is really aimed at DC motors and, although it will still work fine, you can also use Fast PWM mode for servos.


Phase and frequency correct mode is indeed used for DC motors, but it can also be used for many other applications that require PWM. As far as I know, the main advantage of the phase and frequency corrected PWM is the fact that the pulses are always positioned in the middle of the period. Therefore the signal will be more symmetric, which results in less harmonic distortion in the device you are driving (like a DC motor or some voltage converter coil). For a DC motor this means a decrease in torque ripple, fewer losses due to eddy currents and less stress on the motor magnets (if it has any).

When you are a hobbyist, this might not be the most useful or necessary thing to consider using, but for some more advances control it could be something to look in to. And of course, you can also use it to control servos but they will not benefit from the 'positioned' pulse.
Title: Re: Accurate servo control - "Phase and Frequency Correct PWM mode" (ATmega8)
Post by: RoboGeek on October 02, 2009, 10:27:43 PM
Correct, there is no benefit using that mode with RC servos. The analog servo's internal driver chip uses sample and hold based on the HI pulse width only. They are specifically designed to completely tolerant to phasing, to LO period and to frequency, provided the LO period is less than the timeout period.

I did testing of Hitec and Futaba analog servos deliberately introducing large period and frequency errors( +/- 10% and worse) including random jitter per pulse, and it made no noticable difference to servo performance.

The only thing you need to get right is the period of the HI pulse, and to send pulses often enough so it doesn't shut down.