Control 6 R/C servos using your MAVRIC-IIB, MAVRIC-II, or MAVRIC
This program demonstrates how to control up to 6 standard R/C servo using the ATmega128's PWM facility which is capable of precise timing for rock steady control and also consumes very little CPU time since most of the servo pulse generation is done in the background by the on-boad PWM facility.
In this example, the servo positions are commanded by setting their positions using a simple command-line interace which runs over the first UART, UART0 running at 9600 N81. Commands are provided to display and set the servo positions.
Wire the servo signal pins to PORTE3, PORTE4, PORTE5, PORTB5, PORTB6, and PORTB7. These drive servos SERVO1, SERVO2, SERVO3, SERVO4, SERVO5, and SERVO6 respectively. Be sure and use a seperate power supply for the MAVRIC board from the servo power, otherwise the power supply may brown-out due to the heavy current draw of the servos and cause the CPU to reset. Also, be sure and use a good power supply for the servos because they tend to be jittery if their power supply is not strong enough.
For each servo, the pulse width is set as follows corresponding to the output compare register:
The nominal servo center position is 1.5 ms. This is achieved by setting up timers 1 and 3 to run in normal mode with a prescale of 8 and generate an interrupt on overflow, which at 16 MHz external clock, interrupts about 30 times per second - standard servos want the pulse repeated 20 - 50 times per second, so the prescale was chosen to be within this range so that the timer overflows approximately 30 times per second. When the timer overflow occurs, the servo signal pin is set high by the timer overflow interrupt handler. This starts the servo pulse. When the output compare match occurs as defined by the current timer counter value and the content of the servo's output compare register (one for each servo), then the hardware automatically sets the servo signal pin low precisely ending the servo pulse. The timer continues to count until overflow occurs and the cycle repeats.
This all happens in the background - once configured, your program never needs to initiate a pulse. To change a servo's position, just assign a new value to that servo's output compare register. For convenience, these are alias'd to the names SERVO1 ... SERVO6 in the sample program. Since the hardware PWM facilities performs all the time critical portions of the servo pulse generation in the background, your program expends very little overhead on the servo control task. Thus, nearly all CPU cycles are still available to your application.
Sample program is here.