A servo motor consists of several main parts, the motor and gearbox, a position sensor, an error amplifier and motor driver and a circuit to decode the requested position. Figure 1 contains a block diagram of a typical servo motor unit.
The radio control receiver system (or other controller) generates a pulse of varying length approximately every 20 milliseconds. The pulse is normally between 1 and 2 milliseconds long. The length of the pulse is used by the servo to determine the position it should rotate to.
Figure 1. Servo Motor Block Diagram
Starting from the control pulse we will work though each part of the diagram and explain how it all fits together. Once we have gone through how the servo works we will investigate how the control pulses can be generated with a microcontroller.
Pulse width to voltage converter
The control pulse is feed to a pulse width to voltage converter. This circuit charges a capacitor at a constant rate while the pulse is high. When the pulse goes low the charge on the capacitor is fed to the output via a suitable buffer amplifier. This essentially produces a voltage related to the length of the applied pulse.
The circuit is tuned to produce a useful voltage over a 1ms to 2ms period. The output voltage is buffered and so does not decay significantly between control pulses so the length of time between pulses is not critical.
The current rotational position of the servo motor output shaft is read by a sensor. This is normally a potentiometer (variable resistor) which produces a voltage that is related to the absolute angle of the output shaft.
The position sensor then feeds its current value into the Error Amplifier which compares the current position with the commanded position from the pulse width to voltage converter.
The error amplifier is an operational amplifier with negative feedback. It will always try to minimise the difference between the inverting (negative) and non-inverting (positive) inputs by driving its output is the correct direction.
The output of the error amplifier is either a negative or positive voltage representing the difference between its inputs. The greater the difference the greater the voltage.
The error amplifier output is used to drive the motor; If it is positive the motor will turn in one direction, if negative the other. This allows the error amplifier to reduce the difference between its inputs (thus closing the negative feedback loop) and so make the servo go to the commanded position.
The servo normally contains a single integrated circuit and a hand full of discreet components to implement the entire control system.
Controlling a Servo Motor with a Microcontroller
From the above we can determine that we need to generate a pulse approximately every 20ms although the actual time between pulses is not critical. The pulse width however must be accurate to ensure that we can accurately set the position of the servo.
Many microcontrollers are equipped with PWM generators and most people initially consider using these to generate the control signals. Unfortunately they are not really suitable.
The problem is that we need a relatively accurate short pulse then a long delay; and generally you only have one PWM generator share between several servos which would require switching components outside the microcontroller and complicate the hardware.
The PWM generator is designed to generate an accurate pulse between 0% and 100% duty cycle, but we need something in the order of 5% to 10% duty cycle (1ms/20ms to 2ms/20ms). If a typical PWM generator is 8 or 10 bits say, then we can only use a small fraction of the bits to generate the pulse width we need and so we loose a lot of accuracy.
A more beneficial approach can be implemented with simple timers and software interrupts. The key is realising that we can run a timer at a faster rate and do a single servo at a time, followed by the next and the next etc. Each of the outputs is driven in turn for its required time and then turned off. Once all outputs have been driven, the cycle repeats.
This approach is demonstrated in the PIC servo controller project.
The timer is configured so that we have plenty of accuracy over the 1 to 2 millisecond pulse time. Each servo pin is driven high in turn and the timer configured to interrupt the processor when the pulse should be finished. The interrupt routine then drives the output low.
For simplicity, the output pins can be arranged on a single port and the value zero (0x00) written to the port to turn off all pins at once so that the interrupt routine does not need to know which servo output is currently active.
After the pulse has ended, the microprocessor sets up the next pulse and begins the process again.