You've got a robot arm that needs to wave, a camera gimbal that needs to pan smoothly, or a little animatronic puppet that needs to nod its head. The component that makes this precise, angular motion possible is the humble servo motor. But if you've ever plugged one in and watched it twitch erratically or refuse to move, you know there's a gap between buying a servo and actually controlling it reliably. I've been there, frying my share of cheap servos by misunderstanding their power needs. Let's bridge that gap.

This guide cuts through the noise. We'll start with the absolute fundamentals of what a servo is and how it interprets commands, then move straight into practical code for Arduino and Raspberry Pi. More importantly, we'll cover the setup mistakes that cause jitter, burnout, and frustration—things most tutorials gloss over.

What Exactly is a Servo Motor?

Forget the complex definitions. A servo motor is a packaged unit containing three things: a small DC motor, a set of gears to reduce speed and increase torque, and a control circuit with a feedback sensor (usually a potentiometer). This last part is key. The sensor tells the control circuit the motor's current position. When you send a command saying "go to 90 degrees," the circuit compares that target to the current position and powers the motor until they match. It's a closed-loop system.

This is fundamentally different from a standard DC motor, which just spins when you apply power. A servo gives you positional control. The most common type is the 180-degree rotary servo, like the ubiquitous SG90 or MG90S. It moves its output shaft to a specific angle between 0 and 180 degrees. There are also continuous rotation servos (which act like speed-controllable gearmotors) and high-torque or digital servos for more demanding jobs.

Quick Anatomy: A typical hobby servo has three wires: Power (Red/VCC), Ground (Brown/Black), and Signal (Yellow/Orange/White). The color coding isn't universal, so always check your datasheet. The signal wire is where you send the control pulses.

How Servo Motors Work: The PWM Signal Explained

You don't send a servo a number like "90". You send it a pulse. This is the core concept everyone needs to grasp. The language a servo understands is called Pulse Width Modulation (PWM).

Imagine you're rapidly flipping a light switch on and off. The servo expects a new "on" pulse every 20 milliseconds (50 times per second). The magic is in the duration of that "on" pulse, or the pulse width.

  • A pulse width of 1.5 milliseconds typically tells the servo to move to its neutral position (90 degrees).
  • A pulse width of 1.0 milliseconds commands it to go to 0 degrees.
  • A pulse width of 2.0 milliseconds commands it to go to 180 degrees.

The control circuit inside the servo measures the length of each incoming pulse and drives the motor to the corresponding position. If the pulses stop, most servos will simply hold their last position (or go limp, depending on the model).

The Big Misconception About Voltage

Here's a subtle point that causes endless trouble. The PWM signal on the signal wire is about timing, not power. It's usually a 5V or 3.3V logic pulse from your microcontroller. However, the servo's motor needs a separate, more robust power source. A tiny micro-servo might run on 5V from your Arduino's USB port for testing, but the moment it meets any resistance, it will draw more current than the Arduino's voltage regulator can supply. This causes the Arduino to brown out, reset, or the servo to behave erratically.

Rule of thumb: Always power your servos from a dedicated power supply (like a 5V or 6V battery pack or bench supply) and connect its ground to your microcontroller's ground. The signal wire is the only connection needed from the MCU.

How to Control a Servo with Arduino

Arduino makes servo control almost trivial, which is why it's the perfect starting point. It has a dedicated Servo library that handles the precise timing of the PWM pulses for you.

Basic Wiring and Sweep Example

Let's control an SG90 servo. You'll need an external 5V power source (like a 4xAA battery holder or a USB power bank).

Wiring:
- Servo Red Wire -> 5V on your external supply.
- Servo Brown/Black Wire -> GND on your external supply and GND on Arduino.
- Servo Yellow/Orange Wire -> Pin 9 on Arduino.
- Connect the GND of your external supply to an Arduino GND pin. This creates a common ground.

Now, the code. This makes the servo sweep back and forth.

#include

Servo myServo; // Create a servo object
int servoPin = 9;

void setup() {
myServo.attach(servoPin); // Attach the servo to pin 9
}

void loop() {
myServo.write(0); // Command to 0 degrees
delay(1000); // Wait 1 second
myServo.write(90); // Command to 90 degrees
delay(1000);
myServo.write(180); // Command to 180 degrees
delay(1000);
}

The myServo.write(angle) function is the magic. You give it an angle from 0 to 180, and the library converts it to the correct pulse width. Couldn't be simpler.

Controlling Multiple Servos

The standard Servo library can control up to 12 servos on most Arduino boards. Just create more Servo objects. However, there's a catch: using delay() in your code will freeze everything. For a robot with multiple moving parts, you need non-blocking code. This is where millis()-based timing or more advanced libraries like ESP32Servo (for ESP32 boards) come in.

Controlling Servos with a Raspberry Pi

On the Raspberry Pi, servo control is different. The Pi's hardware PWM pins are limited (only GPIO12, GPIO13, GPIO18, GPIO19 on a Pi 4). For reliable, jitter-free control, you should use a dedicated servo hat or an external PCA9685 PWM driver, which communicates via I2C. But for a single servo test, we can use software PWM with the GPIO Zero library, keeping in mind it may have slight jitter.

from gpiozero import Servo from time import sleep # Adjust the min_pulse_width and max_pulse_width if your servo doesn't move fully. # SG90 typical values are 1ms and 2ms. my_servo = Servo(17, min_pulse_width=0.0005, max_pulse_width=0.0025) try: while True: my_servo.min() # Move to 0 degrees sleep(1) my_servo.mid() # Move to 90 degrees sleep(1) my_servo.max() # Move to 180 degrees sleep(1) except KeyboardInterrupt: print("Program stopped") my_servo.detach() # This stops sending pulses, allowing the servo to be moved freely

For any serious multi-servo project on a Pi, I strongly recommend the PCA9685 breakout board. It's cheap, handles 16 servos independently, and offloads the timing work from the Pi's CPU, giving you rock-solid performance.

How to Choose the Right Servo Motor for Your Project

Not all servos are created equal. Picking the wrong one leads to stripped gears or a mechanism that just can't move. Look at these three specs:

Servo TypeTorque (kg-cm)Speed (sec/60°)Best ForPrice Range
Micro Servo (SG90)1.2 - 2.50.10 - 0.15Small robot joints, lightweight flags, pan/tilt for tiny cameras.$3 - $5
Standard Servo (MG90S)2.0 - 3.00.10 - 0.14RC car steering, medium-duty robot arms, larger pan/tilt mechanisms.$5 - $10
High-Torque Servo (MG996R)10 - 130.17 - 0.20Heavy-duty robot arms, combat robot weapons, large animatronics.$10 - $20
Digital ServoVaries (often high)Very Fast (0.06-0.08)Precision robotics, drones (gimbals), competition RC where holding strength and speed are critical.$20+

Torque is the rotational force. If you're lifting an arm with a weight at the end, you need high torque. Speed is how fast it moves. A fast, weak servo is useless for lifting; a strong, slow servo is bad for quick movements.

My advice: For a first project, buy a 3-pack of MG90S servos. They're metal-geared (more durable than SG90's plastic gears), strong enough for most small to medium projects, and very affordable. Avoid the absolute cheapest no-name servos—their calibration and consistency are terrible.

Advanced Control and Common Problems Solved

Fixing Servo Jitter and Buzzing

This is the #1 complaint. The servo buzzes or shakes when it should be still. 95% of the time, it's a power supply issue. The servo isn't getting clean, sufficient current. The fix: Use a dedicated regulator (like a 5V UBEC) or a high-current battery pack. Never power multiple servos from a microcontroller's 5V pin.

The other 5% is electrical noise or a poor signal connection. Keep signal wires away from power wires. Use a capacitor (100-470µF) across the servo's power and ground leads, right at the servo connector. This smooths out sudden current draws.

Achieving Smoother Movement

The write() function makes an immediate jump. For a graceful sweep, you need to move in small steps. Here's a better Arduino loop:

void loop() { // Smooth sweep from 0 to 180 for (int pos = 0; pos = 0; pos -= 1) { myServo.write(pos); delay(15); } }

Controlling a Continuous Rotation Servo

These servos are rewired internally. A 1.5ms pulse means "stop." 1.0ms means "full speed clockwise," and 2.0ms means "full speed counter-clockwise." You control speed and direction, not position. They're great for simple wheeled robots. The Arduino Servo library still works—you use write() with 0 as full speed one way, 180 as full speed the other, and 90 to stop. The values in between control speed.

Your Servo Control Questions Answered

Why is my servo motor jittering or buzzing even when I'm not sending a command?
It's almost certainly a power problem. The servo is trying to hold its position but the voltage is dipping, causing the internal circuit to constantly correct. This creates the buzz. First, disconnect the servo's power (red wire) from your Arduino/development board and connect it to a separate 5V power source that can supply at least 1A per servo. Connect the grounds together. If the jitter persists, add a 100µF electrolytic capacitor between the servo's power and ground pins, as close to the servo as possible.
Can I control a servo directly with a 9V battery?
No. Most hobby servos are designed for 4.8V to 6.6V (typically 5V or 6V). Applying 9V directly will almost instantly destroy the control circuitry. You need a voltage regulator to step the 9V down to 5V or 6V. A simple 7805 linear regulator with a heatsink can work for low-current applications, but a switching UBEC (Universal Battery Eliminator Circuit) is far more efficient and won't overheat.
What's the difference between analog and digital servos?
Analog servos (the cheap ones) check their position and adjust the motor about 50 times per second. Digital servos have a faster microprocessor and can update at 300 Hz or more. This means a digital servo reacts faster, holds its position with more force (it "pushes back" against resistance more frequently), and is generally more precise. The downside is they draw more current. For a simple project, analog is fine. For anything requiring high performance or precision, go digital.
How many servos can I run from one Arduino?
The Servo library says up to 12, but that's only about the software's ability to generate signals. The real limit is electrical. Even if you power them externally, all those servos switching on and off create massive electrical noise on the common ground, which can reset the Arduino. For more than 2-3 servos, use a separate PWM driver board like the PCA9685, which isolates the control logic from the motor power.
My servo only turns about 170 degrees, not 180. Is it broken?
Probably not. There's manufacturing variance. The standard 1.0-2.0ms pulse range is a guideline. Your specific servo might need a 0.8ms pulse for 0 degrees and a 2.2ms pulse for 180 degrees. Most libraries let you adjust this. In Arduino, use myServo.attach(pin, minPulse, maxPulse). In the Raspberry Pi GPIO Zero example above, you saw the min_pulse_width and max_pulse_width parameters. Tweak these values to get the full range of motion.