Skip to content

Arduino - Servo Motor

A hobby servo motor is a compact device containing a DC motor, gears, a position feedback potentiometer, and control electronics. It allows you to control the angular position of its output shaft with high precision. Servos are fundamental components in robotics, radio-controlled models, and animatronics.

There are two main types of servos: standard (positional) servos, which rotate over a limited range (typically 0-180 degrees), and continuous rotation servos, which are modified to spin continuously like a regular motor but with easy speed and direction control.

How Servos Work: Pulse Width Modulation (PWM)

Section titled “How Servos Work: Pulse Width Modulation (PWM)”

A servo’s position is not set by a steady voltage, but by the duration (width) of a repeating electrical pulse sent down its signal wire. This control method is called Pulse Width Modulation (PWM). The servo expects a pulse every 20 milliseconds (a frequency of 50 Hz).

  • A pulse of ~1 millisecond (1000 µs) typically corresponds to the 0-degree position.
  • A pulse of ~1.5 milliseconds (1500 µs) corresponds to the 90-degree (neutral) position.
  • A pulse of ~2 milliseconds (2000 µs) corresponds to the 180-degree position.

The Arduino’s Servo.h library handles the generation of these precise pulses for you, making control very simple.

  • 1 × Arduino board (e.g., UNO, Nano, MKR)
  • 1 × Standard hobby servo (e.g., SG90, MG996R)
  • 1 × 10kΩ Potentiometer
  • Jumper Wires
  • (Recommended) An external 5V-6V power supply (e.g., a 4xAA battery pack or a 5V/2A wall adapter)

⚠️ Important Note on Power: A servo can draw significant current, especially under load. Powering it directly from the Arduino’s 5V pin can cause the Arduino to reset or become unstable. While it might work for a single, small servo like an SG90 with no load, the best practice is to power the servo from a separate, external power supply.

Section titled “Recommended Wiring (with External Power Supply)”
  • Servo Power: Connect the servo’s red wire (+V) to the positive (+) terminal of your external 5V/6V supply.
  • Servo Ground: Connect the servo’s brown/black wire (GND) to the negative (-) terminal of your external supply.
  • Common Ground: Connect the negative (-) terminal of the external supply also to a GND pin on the Arduino. This is crucial for the signal to be interpreted correctly.
  • Servo Signal: Connect the servo’s orange/yellow wire (Signal) to a PWM-capable pin on the Arduino (e.g., pin 9, marked with a ~).
  • Potentiometer: Connect its middle pin to Arduino A0. Connect the two outer pins to the Arduino’s 5V and GND pins.

The Servo library simplifies control down to a few key functions:

  • #include <Servo.h>: Includes the library in your sketch.
  • Servo myServo;: Creates a servo object.
  • myServo.attach(pin): Associates the servo object with a physical pin on the Arduino. This must be a PWM pin.
  • myServo.write(angle): Commands the servo to move to a specific angle, from 0 to 180.
  • myServo.writeMicroseconds(us): Provides finer control by specifying the pulse width directly in microseconds (e.g., 1000 to 2000).
  • myServo.detach(): Stops sending pulses to the servo, allowing it to be moved freely and saving power.
/*
Servo Control with a Potentiometer - Modernized
This sketch reads an analog value from a potentiometer and uses it
to control the position of a servo motor.
- Potentiometer connected to pin A0
- Servo signal wire connected to pin 9
- Servo powered by an external 5V supply with a common ground to Arduino
*/
#include <Servo.h>
// Create a servo object to control a servo
Servo myServo;
// Define constants for pins for better readability
const int potPin = A0;
const int servoPin = 9;
void setup() {
// Attach the servo on pin 9 to the servo object
myServo.attach(servoPin);
Serial.begin(9600);
Serial.println("Servo control initialized. Turn the potentiometer.");
}
void loop() {
// Read the raw value from the potentiometer (0 to 1023)
int potValue = analogRead(potPin);
// Scale the potentiometer's range (0-1023) to the servo's angle range (0-180)
int servoAngle = map(potValue, 0, 1023, 0, 180);
// Set the servo position according to the scaled value
myServo.write(servoAngle);
// Print the angle to the serial monitor for debugging
Serial.print("Potentiometer Value: ");
Serial.print(potValue);
Serial.print(", Servo Angle: ");
Serial.println(servoAngle);
// A small delay to allow the servo to reach its position
delay(15);
}
  • Servo is twitching, jittering, or resetting the Arduino: This is almost always a power supply issue. The servo is drawing too much current from the Arduino’s regulator. Use a suitable external power supply.
  • Servo doesn’t move the full 180 degrees: The default pulse width range in the Servo library (typically 544µs to 2400µs) might not match your specific servo’s physical limits. You can calibrate it by using myServo.writeMicroseconds() to find the exact pulse widths that correspond to 0 and 180 degrees for your servo.
  • analogWrite() stops working on certain pins: On some Arduino boards (like the UNO), attaching a servo disables PWM (analogWrite()) on pins 9 and 10. This is due to internal timer conflicts. Be aware of this when designing projects with multiple servos and PWM outputs.

Now that you can control one servo, the next step is to control several. A great mini-project is to build a simple 2 or 3-axis robotic arm. You can use one potentiometer for each servo (e.g., base, shoulder, elbow) to control each joint independently. This teaches you how to manage multiple servos and is a fantastic introduction to robotics.