Servo Signaling

This is about how the standard servo signaling protocol works, and how you can debug it if it isn't working.


Servos, continuous rotation servos, and some motor controllers all accept this protocol for their command signaling. Most RC controllers (the control board on the vehicle, not the remote) will output some number of channels of this signaling protocol (to be hooked up to the above listed devices usually). These will be described as actuators (things that receive the signal) and controllers (things that send the signal).


The signal to control a servo is PWM (Pulse Width Modulation), but with special attention paid to the timing of the pulses, not just the duty cycle. Each pulse happens every 20ms (so at 50Hz). The rest state of the signal is at the low voltage, and each pulse is at the nominal high voltage (usually 3.3V or 5V). Each pulse is between 1ms and 2ms in length. When the pulse is 1ms long, the min value is sent to the actuator (so a servo will go to 0 degrees, a continuous rotation servo will go to full reverse). When the pulse is 2ms long, the max value is sent to the actuator (so a servo will go to 180 degrees, a continuous rotation servo will go to full forward). Of course, the middle value of 1.5ms is the middle of the control range (so a servo will be at 90 degrees, and a continuous rotation servo will go to stop).

Newer, digital servos will be able to accept a higher speed version of this protocol, but it behaves essentially the same, but with smaller timings (so it can go faster).



There is a servo library that takes care of the timing to send servo signaling. Once you attach a servo to a pin (which is any actuator that accepts this signal), then you can write either angles (0-180 degrees) to it, or microseconds (of the actual pulse width). Example code is below:

Servo myservo;
myservo.attach(9); // 9 is the pin the servo is attached to
myservo.write(0); // 0 is the min value
myservo.write(90); // 90 is the middle value
myservo.write(180); // 180 is the max value
myservo.writeMicroseconds(1000); // 1000us is the min value
myservo.writeMicroseconds(1500); // 1500us is the middle value
myservo.writeMicroseconds(2000); // 2000us is the max value

Servo control with AVR Timers in C: []


You may need to tune the center point of your servo (particularly if it is a continuous rotation servo, and the center is the stop position). To do this, send different signals to the servo (while keeping track of what you are sending), until you find the point you want. That is your new center.


Sometimes a servo will make an angry sound when you tell it to go to a position, or a motor controller will just refuse to work with you. These are most likely due to small timing errors in either the controller or actuator you are working with. This could be due to the clock on the controller not being perfectly accurate, or manufacturing error in the actuator. The best way to debug is with patience and an oscilloscope. Luckily, this is a fairly straightforward process.

Configure the Scope

Connect your oscilloscope to the line being driven with the servo signal. Set up the scope to measure the period of the wave, and the pulse width. These should both be in microseconds (us) or milliseconds (ms).

Basic debugging

If you send it a servo a 0 degree signal, and it makes an angry sound, try increasing the angle you send to it until it stops growling. Same applies to angry sounds with a 180 degree signal, but decrease the angle instead. Use these new values as your min and max values (and scale appropriately). You may lose a few degrees of total movement, but it will get you going.

How it is wrong, and how to compensate

Sometimes the clock of your controller is off, and therefore when your library tries to send the 0 degree signal, it doesn't actually send a pulse 1000us wide. Or if you try to send a 180 degree signal, the pulse is not 2000us wide. Or the actuator is not accurately measuring the pulses, and is interpreting them incorrectly.

Send values through your library (which you may or may not have written), and adjust the value until you can find what produces a 1000us pulse (as measured on the scope), a 2000us pulse, and a 1500us pulse (these are the three most important ones for most projects). Once this is established, connect the signal line to your actuator, and adjust until you discover where its limits are (it stops changing, or makes angry noises). You have discovered your min, center, and max signal values. Now you have fully calibrated your controller and actuator to work together.