6  Servo Motors

In 60 Seconds

Servo motors provide precise angular positioning (typically 0-180 degrees) using PWM pulse width signals at 50 Hz, where 1ms = 0 degrees and 2ms = 180 degrees. They integrate a DC motor, gear reduction, potentiometer feedback, and control circuit into one package, making them ideal for IoT applications like robotic arms, smart vents, and pan-tilt camera mounts.

Key Concepts
  • RC Servo Motor: A self-contained motor system integrating a DC motor, gearbox, position feedback potentiometer, and control electronics; position is commanded by a 50 Hz PWM signal where pulse width (1-2 ms) maps to 0-180 degree output angle
  • Servo Pulse Width Protocol: Standard servo control: 50 Hz PWM (20 ms period); pulse width 1.0 ms = minimum angle (~0 degrees), 1.5 ms = center (~90 degrees), 2.0 ms = maximum (~180 degrees); exact angles vary by servo model and require calibration
  • Servo Torque Ratings: Specified in kg.cm or N.cm at a defined voltage; represents the force x distance at the output horn; a 2 kg.cm servo can lift 2 kg at 1 cm from the servo axis, or 0.2 kg at 10 cm; torque drops significantly when operating below rated voltage
  • Continuous Rotation Servo: A servo modified (or designed) to rotate continuously rather than position to an angle; pulse width controls speed and direction: 1.5 ms = stop, <1.5 ms = one direction, >1.5 ms = other direction; used for wheeled robot drive systems
  • Servo Deadband: A small range of pulse widths (typically +-5 us) around the current position where the servo does not respond; prevents jitter from small PWM timing variations; a servo with a wide deadband appears sluggish in fine position control
  • Stall Torque vs. No-Load Speed: Stall torque is the maximum torque at zero speed; no-load speed is the maximum RPM with no load; real operating points lie between these extremes on the torque-speed curve; operating near stall continuously overheats the motor
  • Servo Horn and Mounting: The output hub that connects the servo shaft to the mechanical linkage; plastic horns are included with servos; metal horns are available for higher-torque applications; improper linkage geometry causes binding and reduces effective servo range
  • Servo Library (Arduino/ESP32): The Arduino Servo.h library abstracts pulse width calculation; Servo::attach(pin) starts 50 Hz PWM; Servo::write(angle) converts degrees to microseconds automatically; Servo::writeMicroseconds(us) provides direct microsecond control for precision calibration

Learning Objectives

After completing this chapter, you will be able to:

  • Explain servo motor construction and closed-loop operating principles
  • Control servo position using PWM pulse width mapping
  • Interface single and multiple servos with ESP32
  • Implement smooth motion profiles using interpolation
  • Build coordinated multi-servo systems (robotic arms, pan-tilt)
  • Evaluate tradeoffs between servo and stepper motors for positioning applications

A servo motor is like a precise pointing finger – you tell it exactly what angle to point to, and it moves there and holds that position. Unlike a regular motor that just spins continuously, a servo can rotate to a specific angle (say 90 degrees) and stay there. This makes servos perfect for things like robotic arms, camera mounts that need to pan and tilt, or smart vents that open to a precise position.

How It Works: Servo Motor Internal Feedback Loop

A servo motor is like a self-driving car for rotation - you give it a destination (angle), and it figures out how to get there.

Inside every servo:

  1. DC motor: Provides the actual rotation force
  2. Gear reduction: Trades speed for torque (makes it strong but slow)
  3. Potentiometer: A sensor that measures the current shaft angle
  4. Control circuit: The “brain” that compares where you want to be vs where you actually are

The closed-loop magic:

  • You send a PWM pulse: “Go to 90 degrees”
  • The servo reads its potentiometer: “I’m currently at 45 degrees”
  • The control circuit calculates: “I need to turn 45 degrees clockwise”
  • It drives the motor until the potentiometer reads 90 degrees
  • It then holds that position, fighting any external force that tries to move it

Why this matters: Unlike a DC motor (which you must monitor with an external encoder), the servo is self-contained. Send the pulse, and it handles everything else. This is why hobby servos are perfect for beginners - one pin, one library call, instant position control.

6.1 Servo Motor Fundamentals

Servo motors provide precise angular positioning (typically 0-180 degrees) using PWM signals. Unlike DC motors that spin continuously, servos move to specific angles and hold position.

Characteristics:

  • Precise position control
  • Built-in feedback loop
  • Limited rotation range (standard servos: 0-180 degrees)
  • Easy to control with PWM
  • Self-correcting (closed-loop)

6.1.1 Internal Components

Servo motors integrate a complete feedback control system in a compact package:

  1. DC Motor Core: Provides rotational force
  2. Gear Reduction System: Amplifies torque, reduces speed
  3. Potentiometer: Position feedback sensor
  4. Control Circuit: Compares commanded vs actual position

The internal potentiometer continuously measures shaft position, and the control circuit compares this to the commanded position from the PWM signal. This closed-loop design maintains position accuracy even under varying loads.

6.1.2 PWM Position Control

Servo motors use pulse width (not duty cycle) to determine position:

Servo motor PWM timing diagram showing three waveforms: 1ms pulse width for 0 degrees, 1.5ms pulse width for 90 degrees center position, and 2ms pulse width for 180 degrees maximum rotation, all at 50Hz frequency with 20ms period
Figure 6.1: Servo Motor Position Control: Pulse Width Determines Angle (50Hz)

Key parameters:

  • 50 Hz frequency (20ms period) - Standard for hobby servos
  • 1ms pulse = 0 degrees (5% duty cycle)
  • 1.5ms pulse = 90 degrees (7.5% duty cycle, center position)
  • 2ms pulse = 180 degrees (10% duty cycle, maximum rotation)

At 50 Hz, the period is \(T = 1/50 = 20\) ms. A 1.5ms pulse for 90° means duty cycle \(D = 1.5/20 = 0.075 = 7.5\%\). To command 45°, interpolate: pulse width \(t = 1 + (45/180) \times (2-1) = 1.25\) ms. For smooth motion from 0° to 180° over 1 second at 50 Hz, you send 50 commands with angular step \(\Delta\theta = 180/50 = 3.6°\) per frame. Current draw spikes during motion (500mA) but drops to holding current (~100mA) once positioned, so energy per 2-second actuation is \(E \approx (0.5 \text{ A} \times 5 \text{ V} \times 1 \text{ s}) + (0.1 \text{ A} \times 5 \text{ V} \times 1 \text{ s}) = 2.5 + 0.5 = 3\) joules (0.00083 Wh).

Interactive Calculator: Angle to Pulse Width

Important: Servo libraries handle the timing. You just write servo.write(90) for 90 degrees!

6.2 Servo vs Stepper Comparison

Tradeoff: Servo Motor vs. Stepper Motor for Positioning

Option A: Servo motor (SG90/MG996R): Range 0-180 degrees, resolution ~1 degree, holding torque 1.8-10 kg-cm, power 5V @ 100-500mA active, cost $2-15, closed-loop feedback maintains position under load, simple PWM control (1 GPIO pin)

Option B: Stepper motor (NEMA17): Range unlimited rotation, resolution 1.8 degrees/step (200 steps/rev), micro-stepping achieves 0.05 degrees, holding torque 40+ kg-cm, power 12V @ 400mA-2A, cost $8-25, open-loop control requires calibration/homing, requires driver board + 2-4 GPIO pins

Decision Factors: For IoT applications needing simple angular positioning within 180 degrees (smart vents, valve actuators, pan-tilt cameras), servos win on simplicity and cost. For continuous rotation, high precision (<0.1 degree), or high torque (3D printer axes, CNC, telescope mounts), steppers are mandatory. Servos consume power only when moving; steppers draw holding current continuously. For battery IoT, this makes servos 5-10x more energy efficient for intermittent positioning tasks.

6.3 Basic Servo Control

6.3.1 Single Servo Control

#include <ESP32Servo.h>

Servo myServo;

#define SERVO_PIN 18

void setup() {
  Serial.begin(115200);

  // Attach servo (ESP32 uses different timers)
  myServo.attach(SERVO_PIN, 500, 2400);  // Min/max pulse width in microseconds

  Serial.println("Servo Controller Ready");
}

void loop() {
  // Sweep from 0 to 180 degrees
  for (int pos = 0; pos <= 180; pos++) {
    myServo.write(pos);
    Serial.print("Position: ");
    Serial.println(pos);
    delay(15);
  }

  delay(1000);

  // Sweep back from 180 to 0 degrees
  for (int pos = 180; pos >= 0; pos--) {
    myServo.write(pos);
    Serial.print("Position: ");
    Serial.println(pos);
    delay(15);
  }

  delay(1000);
}
Try It: Servo Sweep Simulator

6.3.2 Multi-Servo Robotic Arm

#include <ESP32Servo.h>

Servo baseServo, shoulderServo, elbowServo, gripperServo;

struct RobotPosition { int base, shoulder, elbow, gripper; };

RobotPosition homePos  = {90, 90, 90, 90};
RobotPosition pickPos  = {45, 45, 45, 90};
RobotPosition placePos = {135, 45, 45, 45};

void setup() {
  Serial.begin(115200);
  baseServo.attach(18, 500, 2400);
  shoulderServo.attach(19, 500, 2400);
  elbowServo.attach(21, 500, 2400);
  gripperServo.attach(22, 500, 2400);
  moveToPosition(homePos, 1000);
  Serial.println("Commands: h=home, p=pick, l=place, s=sequence");
}

void loop() {
  if (Serial.available()) {
    switch(Serial.read()) {
      case 'h': moveToPosition(homePos, 1500); break;
      case 'p': moveToPosition(pickPos, 1500); break;
      case 'l': moveToPosition(placePos, 1500); break;
      case 's': pickAndPlaceSequence(); break;
    }
  }
}

// Smooth interpolated motion — all joints move simultaneously
void moveToPosition(RobotPosition target, int duration) {
  int cB = baseServo.read(), cS = shoulderServo.read();
  int cE = elbowServo.read(), cG = gripperServo.read();
  int steps = duration / 20;
  for (int i = 0; i <= steps; i++) {
    float p = (float)i / steps;
    baseServo.write(cB + (target.base - cB) * p);
    shoulderServo.write(cS + (target.shoulder - cS) * p);
    elbowServo.write(cE + (target.elbow - cE) * p);
    gripperServo.write(cG + (target.gripper - cG) * p);
    delay(20);
  }
}

void pickAndPlaceSequence() {
  moveToPosition(pickPos, 1500);   delay(500);  // Move to pick
  gripperServo.write(45);          delay(500);  // Close gripper
  moveToPosition(placePos, 2000);  delay(500);  // Move to place
  gripperServo.write(90);          delay(500);  // Open gripper
  moveToPosition(homePos, 1500);                // Return home
}

6.4 Smooth Motion with Interpolation

For professional-quality motion, use smooth acceleration/deceleration profiles:

// Ease-in-out interpolation for smooth motion
float easeInOut(float t) {
  return t < 0.5 ? 2 * t * t : 1 - pow(-2 * t + 2, 2) / 2;
}

void smoothMove(Servo& servo, int startPos, int endPos, int duration) {
  int steps = duration / 20;

  for (int i = 0; i <= steps; i++) {
    float t = (float)i / (float)steps;
    float easedT = easeInOut(t);

    int pos = startPos + (endPos - startPos) * easedT;
    servo.write(pos);
    delay(20);
  }
}
Try It: Easing Curve Explorer

6.5 Interactive Lab: Servo Control

Try It Yourself: Control a Servo Motor

What you’ll do: Control a servo motor’s position using buttons and potentiometer.

What you’ll learn:

  • How PWM pulse width controls servo position
  • Smooth motion using delay and interpolation
  • Reading analog input to control servo

Estimated time: 10 minutes

Interactive Challenges:

  1. Potentiometer Control: Use a potentiometer to control servo position (0-180 degrees)
  2. Button Presets: Add buttons for preset positions (0, 45, 90, 135, 180 degrees)
  3. Smooth Sweep: Implement smooth back-and-forth sweeping motion

6.6 Common Servo Specifications

Model Voltage Torque Speed Weight Use Case
SG90 4.8-6V 1.8 kg-cm 0.1s/60 deg 9g Light loads, prototyping
MG90S 4.8-6V 2.2 kg-cm 0.1s/60 deg 13.4g Metal gears, higher torque
MG996R 4.8-7.2V 11 kg-cm 0.17s/60 deg 55g Robotic arms, heavy loads
DS3218 4.8-6.8V 21 kg-cm 0.16s/60 deg 60g Industrial, waterproof
Power Supply Warning

Do NOT power multiple servos from the ESP32 5V pin! Use an external 5V 2A power supply. Connect ESP32 GND to power supply GND (common ground).

SG90: Up to 600mA stall current each MG996R: Up to 2.5A stall current each

A 3-servo arm with MG996R servos may need 5V @ 5A or more!

Try It: Servo Power Budget Calculator

6.7 Pan-Tilt Camera Mount

A common IoT application is a pan-tilt camera mount:

#include <ESP32Servo.h>

Servo panServo;   // Horizontal rotation
Servo tiltServo;  // Vertical rotation

#define PAN_PIN 18
#define TILT_PIN 19

// Position limits
#define PAN_MIN 0
#define PAN_MAX 180
#define TILT_MIN 0
#define TILT_MAX 90  // Limit tilt to prevent looking backward

int panPos = 90;   // Start center
int tiltPos = 45;  // Start mid-height

void setup() {
  Serial.begin(115200);

  panServo.attach(PAN_PIN, 500, 2400);
  tiltServo.attach(TILT_PIN, 500, 2400);

  panServo.write(panPos);
  tiltServo.write(tiltPos);

  Serial.println("Pan-Tilt Camera Ready");
  Serial.println("Commands: w=up, s=down, a=left, d=right, c=center");
}

void loop() {
  if (Serial.available()) {
    char cmd = Serial.read();

    switch(cmd) {
      case 'w':  // Tilt up
        tiltPos = min(tiltPos + 10, TILT_MAX);
        break;
      case 's':  // Tilt down
        tiltPos = max(tiltPos - 10, TILT_MIN);
        break;
      case 'a':  // Pan left
        panPos = min(panPos + 10, PAN_MAX);
        break;
      case 'd':  // Pan right
        panPos = max(panPos - 10, PAN_MIN);
        break;
      case 'c':  // Center
        panPos = 90;
        tiltPos = 45;
        break;
    }

    panServo.write(panPos);
    tiltServo.write(tiltPos);

    Serial.print("Pan: ");
    Serial.print(panPos);
    Serial.print(" Tilt: ");
    Serial.println(tiltPos);
  }
}
Try It: Pan-Tilt Position Simulator

6.8 Knowledge Check

    1. 0 degrees (minimum position)
    1. 90 degrees (center position)
    1. 180 degrees (maximum position)
    1. The servo will not move because 1.5ms is outside the valid range

Answer: B) 90 degrees (center position). Standard servo timing maps pulse width to angle: 1ms = 0 degrees, 1.5ms = 90 degrees (center), 2ms = 180 degrees. The 1.5ms pulse places the servo at the midpoint of its range. The 50 Hz frequency gives a 20ms period, and the servo reads the pulse width within each period.

    1. It uses less power than constant-speed movement
    1. It prevents mechanical stress by gradually accelerating and decelerating, producing natural-looking motion
    1. Servos cannot move at constant speed
    1. It makes the code simpler to write

Answer: B) It prevents mechanical stress by gradually accelerating and decelerating, producing natural-looking motion. Ease-in-out interpolation starts slowly, accelerates in the middle, and decelerates at the end. This reduces mechanical shock on gears and joints, prevents sudden jerks that could destabilize a robot arm, and produces smooth, professional-quality motion similar to how humans naturally move.

    1. 2.5A
    1. 5A
    1. 7.5A
    1. 1A

Answer: C) 7.5A. In the worst case, all three servos could stall simultaneously (e.g., when holding a heavy load or reaching mechanical limits). Each draws 2.5A at stall, so 3 x 2.5A = 7.5A total. In practice, you might use a slightly larger supply (8-10A) for safety margin. Never power multiple servos from the ESP32’s 5V pin, which provides only about 500mA.

Key Takeaway

Servo motors are the simplest path to precise angular positioning in IoT, integrating a DC motor, gear reduction, position feedback, and control circuit in one package. Control is as easy as writing servo.write(90). For multi-servo systems, always use external power supplies, implement smooth interpolation for professional-quality motion, and remember that servos consume power only when actively moving, making them energy-efficient for intermittent positioning tasks.

“Hey everyone, watch me point!” said Servo Sam, swinging his arm to exactly 90 degrees. “Tell me any angle and I’ll nail it!”

“45 degrees!” called Sammy the Sensor.

Sam snapped to 45 degrees. “Done!”

“135 degrees!” shouted Lila the LED.

Sam smoothly glided to 135 degrees. “Easy peasy!”

“How do you always know exactly where to point?” asked Bella the Battery.

“I have a secret inside me,” Servo Sam explained, opening a tiny door to show his insides. “See this little knob? It’s called a potentiometer – it’s like a tiny Sammy the Sensor living inside me! As my arm turns, this knob turns too, and it tells my brain exactly what angle I’m at.”

“So you’re like a sensor AND an actuator combined?” gasped Sammy.

“Exactly! Max sends me a special pulse signal – a short blink means ‘go to 0 degrees,’ a medium blink means ‘go to 90 degrees,’ and a long blink means ‘go to 180 degrees.’ My internal brain compares where Max wants me to be with where I actually am, and adjusts until they match!”

“That’s called a feedback loop!” Max the Microcontroller added proudly. “It’s why Servo Sam is so reliable. Even if you push his arm, he fights back to stay at the right angle!”

“Just remember,” Bella warned, “Sam and his friends drink a LOT of power when they’re pushing hard. Always give them their own power supply – don’t make Max share his!”

6.9 Worked Example: Designing a Smart Vent System for Zone Heating

Scenario: A homeowner wants to retrofit 8 HVAC vents across a 2-story house with servo-controlled dampers to create heating/cooling zones. Each vent damper opens 0-90 degrees to control airflow. The system should integrate with a smart thermostat via Wi-Fi and run on mains power (USB adapter at each vent).

Requirements Analysis:

Requirement Implication
8 vents, 0-90 deg each 8 servos with 90+ deg range
Spring-loaded dampers ~3 kg-cm torque per damper
Quiet (bedrooms) Low buzz at hold position
USB-powered per vent 500mA per port limit
Wi-Fi integration ESP32 per vent or per floor
Budget Under $200 total

Servo Selection:

Criterion SG90 ($2) MG90S ($4) MG996R ($8)
Torque 1.8 kg-cm 2.2 kg-cm 11 kg-cm
Stall current 600 mA 700 mA 2.5 A
Weight 9 g 13 g 55 g
Gears Plastic Metal Metal
Noise Low Low Moderate
USB-powered? Yes (500mA limit OK for 1) Borderline No (needs external supply)

Decision: MG90S. The SG90’s plastic gears would strip under continuous damper spring tension within months. The MG996R is overkill (11 kg-cm vs 3 kg-cm needed) and exceeds USB power limits. The MG90S provides metal gears for durability and sufficient torque (2.2 kg-cm > damper resistance when using a 2:1 lever arm = 4.4 kg-cm effective) within USB power budget.

Architecture Decision: Two ESP32 boards (one per floor, 4 servos each) instead of 8 individual controllers.

Option Hardware Cost Wiring Complexity
1 ESP32 per vent (8 total) 8 x $5 = $40 Minimal (USB each) 8 devices on Wi-Fi network
1 ESP32 per floor (2 total) 2 x $5 = $10 4 servo cables per board (up to 3m each) 2 devices, cleaner network
1 central ESP32 1 x $5 = $5 8 long cable runs (up to 10m) Signal degradation risk

Decision: 2 ESP32 boards (one per floor). Saves $30 vs per-vent approach, keeps cable runs under 3 meters (PWM signal integrity), and only 2 devices on Wi-Fi.

Bill of Materials:

Component Qty Unit Cost Total
MG90S servo 8 $4 $32
ESP32 DevKit 2 $5 $10
5V 3A USB-C power supply 2 $8 $16
3D-printed vent adapter brackets 8 $2 (filament) $16
Servo extension cables (1m) 8 $1 $8
Wire, connectors, heat shrink 1 lot $10 $10
Total $92

Power Budget per ESP32 (4 servos):

State Current Draw Duration
All servos holding position 4 x 10 mA = 40 mA 99% of time
1 servo moving (others holding) 700 mA + 30 mA = 730 mA Brief transitions
2 servos moving simultaneously 1.4 A + 20 mA = 1.42 A Rare (stagger moves in code)
ESP32 Wi-Fi active 240 mA During commands

Design decision: Stagger servo movements in firmware (move one servo at a time with 500ms delay) to keep peak current under 1A, well within the 3A supply capacity. This also reduces noise.

Result after 3 months: 8 zones independently controlled, average heating bill reduced 22% ($45/month savings) by closing vents in unoccupied rooms during the day. Payback period: 2 months. Zero servo failures (metal gears holding up to daily cycling).

Goal: Make a servo sweep smoothly from 0° to 180° and back, like a radar dish scanning.

Hardware: SG90 servo + ESP32

Code pattern:

for (int angle = 0; angle <= 180; angle++) {
  myServo.write(angle);  // Move to angle
  delay(15);             // Small delay for smooth motion
}

What to observe: The servo sweeps smoothly. Try changing delay(15) to delay(100) - notice the difference in sweep speed.

Goal: Control 3 servos (base, arm, gripper) to perform a pick-and-place sequence.

Challenge: All servos must move simultaneously and arrive at target positions at the same time.

Technique: Linear interpolation across all axes

// Calculate steps needed
int steps = duration / 20;  // 20ms per step (50 Hz servo rate)

// Move all servos proportionally
for (int i = 0; i <= steps; i++) {
  float progress = (float)i / steps;
  baseServo.write(startBase + (targetBase - startBase) * progress);
  armServo.write(startArm + (targetArm - startArm) * progress);
  delay(20);
}

What to observe: All servos start and finish together. Without interpolation, fast-moving axes would finish early, causing jerky motion.

Goal: Tell a 2-DOF arm “move gripper to X,Y coordinates” and have it calculate the required joint angles.

Math: Given gripper position (x, y), calculate shoulder and elbow angles using geometry:

float distance = sqrt(x*x + y*y);
float angle1 = atan2(y, x);  // Base angle to target
float angle2 = acos((L1*L1 + distance*distance - L2*L2) / (2*L1*distance));
int shoulderAngle = (angle1 + angle2) * RAD_TO_DEG;
int elbowAngle = ... // Second calculation

Why it’s hard: Multiple solutions exist (elbow up vs elbow down). Must handle singularities (unreachable points). Requires linear algebra for 3+ DOF arms.

Result: Type “move to (10, 15)” and the arm calculates and executes the motion automatically.

6.10 Concept Relationships

Concept Relates To Connection Type
PWM Pulse Width PWM Control 1-2ms pulse determines angle, not duty cycle
Closed-Loop Control Sensor Fundamentals Internal potentiometer provides position feedback
Power Requirements Actuator Safety Multiple servos need external power supply
Servo vs Stepper Actuator Classifications Choose based on rotation range and precision needs

6.11 See Also

Common Pitfalls

Servo motors draw 100-500 mA at rest and up to 1-2 A at stall. Powering even a single servo from the microcontroller’s onboard 3.3 V or 5 V regulator (typically rated 300-500 mA total) causes voltage sag that resets the MCU. Always power servos from a separate supply (a dedicated BEC or battery pack) and only share a common ground with the microcontroller.

Writing angles of 0 or 180 degrees to the servo library may command pulse widths that exceed the servo’s mechanical travel, forcing it against the mechanical stop. This draws continuous high stall current, overheats the motor, and can strip gears. Determine the actual minimum and maximum pulse widths for your specific servo model by testing, then software-limit commands to within that range.

PWM signal noise, especially from long wires near motor drivers, causes the servo to hunt constantly around its target position, consuming power and wearing gears. Keep servo signal wires short (<30 cm), route them away from motor power cables, and add a 100 nF decoupling capacitor between servo signal and ground close to the servo connector.

A robot with 6 servos can draw up to 12 A simultaneously at stall. Designing for the single-servo current times the number of servos assumes they never all stall simultaneously — which happens whenever the robot encounters resistance or is manually restrained. Size the power supply for simultaneous stall, or implement current monitoring with firmware soft-limit on commanded torque.

6.12 What’s Next?

Topic Chapter Why It’s Relevant
Stepper Motors Stepper Motors When you need more than 180° of rotation or sub-degree precision
PWM Control PWM Control Deep dive into 50 Hz timing, duty cycle, and hardware timers
Actuator Classifications Actuator Classifications Compare servo, stepper, DC, and solenoid actuators
Actuator Safety Actuator Safety Power supply rules, overcurrent protection, and wiring safety
Hands-on Labs Actuator Labs Build a servo gripper and pan-tilt camera mount