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()):
// 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():
#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
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