6 Servo Motors
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
For Beginners: Servo Motors
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:
- DC motor: Provides the actual rotation force
- Gear reduction: Trades speed for torque (makes it strong but slow)
- Potentiometer: A sensor that measures the current shaft angle
- 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:
- DC Motor Core: Provides rotational force
- Gear Reduction System: Amplifies torque, reduces speed
- Potentiometer: Position feedback sensor
- 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:
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)
Putting Numbers to It
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);
}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);
}
}6.5 Interactive Lab: Servo Control
Interactive Challenges:
- Potentiometer Control: Use a potentiometer to control servo position (0-180 degrees)
- Button Presets: Add buttons for preset positions (0, 45, 90, 135, 180 degrees)
- 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!
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);
}
}6.8 Knowledge Check
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.
For Kids: Meet the Sensor Squad!
“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).
Beginner Level: Single Servo Sweep
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.
Intermediate Level: Multi-Servo Choreography
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.
Advanced Level: Inverse Kinematics for Robotic Arm
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 calculationWhy 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
- Stepper Motors - When you need >180° rotation or higher precision
- PWM Control - Understanding 50 Hz servo timing
- Multi-Servo Robotic Arm Example - Coordinated motion code above
- Pan-Tilt Camera Mount - Practical 2-servo project
- Actuator Labs - Hands-on servo gripper project
Common Pitfalls
1. Powering Servos from the 3.3V or 5V GPIO Rail
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.
2. Commanding Servo Outside Its Physical Range
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.
3. Continuous Jitter from Noisy PWM Signal
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.
4. Multiple Servos Drawing Simultaneous Stall Current
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 |