11 Servo Motors: Calibration and Applications
11.1 Start With the Decision
A pan-tilt mount turns two servo angles into a camera view. Calibration must remove deadband, offset, and unsafe travel.
11.2 Route Overview
This is part 2 of 2. Review Servo Motors: Position, Motion, and Power for the preceding evidence.
11.3 Learning Objectives
- Calibrate angle limits, centre, and deadband.
- Apply smooth motion to pan-tilt and smart-vent cases.
11.4 Chapter Roadmap
- Pan-Tilt Camera Mount
- Try It: Pan-Tilt Position Simulator
- Knowledge Check
- Deep Dive: Calibration, Deadband, and Servo Control Loops
- Checkpoint: Calibration Closes the Loop
- Summary
- Key Takeaway
- For Kids: Meet the Actuator Crew!
- Smart Vent Zone-Heat Design
- Quiz: Servo Motors
- Beginner Level: Single Servo Sweep
- Intermediate Level: Multi-Servo Choreography
- Advanced Level: Inverse Kinematics for Robotic Arm
- Concept Check: Servo Power Requirements
- Concept Relationships
- See Also
- Common Pitfalls
- 1. Powering Servos from the 3.3V or 5V GPIO Rail
- 2. Commanding Servo Outside Its Physical Range
- 3. Continuous Jitter from Noisy PWM Signal
- 4. Multiple Servos Drawing Simultaneous Stall Current
- What’s Next?
- Label the Diagram
- Code Challenge
11.5 Pan-Tilt Camera Mount
A common IoT application is a pan-tilt camera mount. Read the control path from the bounded pan and tilt variables into the serial-command switch, then into the two servo.write() calls and the echoed position evidence. The software clamps protect the intended 0-180 and 0-90 degree ranges; commissioning must still verify that those limits stay clear of the mechanism’s physical stops.
#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);
}
}
Max’s Motion Check
- Commit: point the camera: pan 0-180, tilt 0-90, starting at pan 90, tilt 45.
- Limits: each 10-degree step is clamped; TILT_MAX 90 stops backward-looking; attach(pin, 500, 2400) bounds pulse width.
- Safe stop: travel ends at software clamps, not hard stops; each move is echoed over serial.
11.6 Knowledge Check
11.7 Deep Dive: Calibration, Deadband, and Servo Control Loops
Before tuning pulse endpoints, inspect Figure 11.1 to locate the closed loop hidden inside a hobby servo. The command is only a target; the driver, motor, gearing, and potentiometer determine whether the shaft reaches and holds it.
Read Figure 11.1 from the microcontroller pulse into the internal controller and motor, then follow potentiometer feedback back to the comparison point. The error drives correction until it falls inside the deadband, connecting pulse calibration to position evidence rather than treating the command as proof of motion.
A hobby servo command is a position pulse, not a motor-power duty cycle. The 20 ms frame repeats the command; the high-pulse width carries the angle. A 1.0 ms pulse in a 20 ms frame is only 5% duty cycle, 1.5 ms is 7.5%, and 2.0 ms is 10%. Sending a 50% duty-cycle signal would hold the line high for 10 ms in each frame, far outside the normal command range.
Calibration is where a bench demo becomes a reliable mechanism. If one servo’s safe travel is 1050 microseconds to 1950 microseconds, the usable span is 900 microseconds. Mapping that to 0-180 degrees gives 900 / 180 = 5 microseconds per degree, so a 45 degree command is approximately 1050 + 45 x 5 = 1275 microseconds. Store the measured endpoints, back off from the hard stops, and map application angles inside that calibrated range instead of assuming every servo accepts a generic 1000-2000 microsecond window.
Torque and current need the same engineering treatment. A 3 kg-cm servo can ideally hold about 3 kg at 1 cm, or 1 kg at 3 cm, before losses. In SI units that is roughly 3 x 9.81 N x 0.01 m = 0.294 N-m. If a vent linkage needs 0.12 N-m, the ideal margin is only 0.294 / 0.12 = 2.45x before friction, off-axis loading, supply-voltage drop, and gear wear. Four servos that can each surge to 700 mA create a 4 x 0.7 A = 2.8 A event if they start together, so staggered movement and a separate servo rail are part of the actuator design, not optional cleanup.
Max’s Motion Check
- Commit: map angles into the measured 1050-1950 microsecond window: 5 microseconds per degree.
- Limits: 3 kg-cm is 0.294 N-m: only 2.45x over a 0.12 N-m linkage.
- Safe stop: back stored endpoints off the hard stops; stagger starts — four 700 mA servos surge 2.8 A.
Inside the package, the controller compares commanded position against feedback from the potentiometer. If the command corresponds to 90 degrees and the feedback reports 84 degrees, the loop sees a +6 degree error and drives the motor in the direction that shrinks the error. If it overshoots to 92 degrees, the sign changes and the driver corrects back. A small deadband prevents constant buzzing: with a 5 microsecond deadband and a 0.18 degree-per-microsecond scale, the no-correction window is about 5 x 0.18 = 0.9 degrees. Too wide a deadband feels sloppy; too narrow a deadband can hunt when the signal is noisy or the linkage is springy.
Industrial servos use the same feedback idea at a tighter scale. They replace the hobby servo’s potentiometer with an encoder or resolver, use a brushless motor plus a dedicated servo drive, and usually close nested torque-current, velocity, and position loops. The current loop controls torque, the velocity loop shapes shaft speed, and the position loop removes final error. The hobby servo hides this behind a three-wire pulse interface; the industrial servo exposes tuning so machine axes can manage stiffness, following error, and response.
Checkpoint: Calibration Closes the Loop
You now know:
- A measured 1050-1950 microsecond window gives a 900 microsecond span, or 5 microseconds per degree across 180 degrees.
- A 3 kg-cm servo is about 0.294 N-m ideally; against a 0.12 N-m linkage, that is only 2.45x margin before losses.
- Deadband is deliberate: 5 microseconds at 0.18 degree per microsecond creates about a 0.9 degree no-correction window that prevents buzz.
11.8 Summary
Servo motors are packaged position actuators: the motor, gearbox, feedback sensor, and controller are integrated so the microcontroller only sends a position command. The main engineering work is not the signal itself; it is power budgeting, mechanical range limits, stall current, and smooth motion between commanded angles.
Servo motors simplify precise angular positioning by packaging a motor, gearbox, feedback sensor, and controller behind a pulse-width command. The hard parts are still engineering problems: calibrated endpoints, enough torque margin, a supply sized for stall current, smooth motion that avoids gear shock, and linkages that do not bind at the ends of travel.
“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 Temperature Terry.
Sam snapped to 45 degrees. “Done!”
“135 degrees!” shouted the LED.
Sam smoothly glided to 135 degrees. “Easy peasy!”
“How do you always know exactly where to point?” asked 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 Temperature Terry 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!” 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!”
11.9 Smart Vent Zone-Heat Design
The summary handled the individual servo. The smart vent scenario combines every earlier decision: angle range, torque margin, noise, cable length, and current spikes.
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 |
| Limited retrofit effort | Prefer a small number of controllers and short servo leads |
Servo Selection:
| Criterion | Micro plastic-gear servo | Micro metal-gear servo | Large metal-gear servo |
|---|---|---|---|
| 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: micro metal-gear servo. A plastic-gear micro servo risks stripped gears under repeated damper spring tension. A large metal-gear servo is overkill (11 kg-cm vs 3 kg-cm needed) and exceeds the local USB power limit. The micro metal-gear option provides metal gears for durability and sufficient torque (2.2 kg-cm at the servo, with a 2:1 linkage trading travel for about 4.4 kg-cm effective torque) within the local power budget.
Architecture Decision: Two ESP32 boards (one per floor, 4 servos each) instead of 8 individual controllers.
| Option | Controller count | Wiring | Complexity |
|---|---|---|---|
| 1 ESP32 per vent | 8 controllers | Minimal (USB each) | 8 devices on Wi-Fi network |
| 1 ESP32 per floor | 2 controllers | 4 servo cables per board (up to 3m each) | 2 devices, cleaner network |
| 1 central ESP32 | 1 controller | 8 long cable runs (up to 10m) | Signal degradation risk |
Decision: 2 ESP32 boards (one per floor). This keeps cable runs under 3 meters for PWM signal integrity and avoids putting 8 separate devices on Wi-Fi.
Parts Plan:
| Component | Qty | Sizing note |
|---|---|---|
| Micro metal-gear servo | 8 | One per vent, torque checked against damper spring |
| ESP32-class controller | 2 | One per floor |
| 5V 3A supply | 2 | One per floor; enough for staggered movement |
| Vent adapter brackets | 8 | Match horn throw to damper travel |
| Servo extension cables | 8 | Keep runs short and strain-relieved |
| Wire, connectors, heat shrink | 1 lot | Common ground and protected power distribution |
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 500 ms delay) to keep peak current under 1A, well within the 3A supply capacity. This also reduces noise.
Expected result: 8 zones can be controlled independently, but validation should focus on actuator reliability and HVAC safety rather than assumed utility outcomes. Confirm that the vents do not bind, the supply does not sag during movement, the controller recovers cleanly after reset, and the HVAC system still has enough airflow when several zones are partially closed.
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.
11.10 Concept Relationships
| Concept | Relates To | Connection Type |
|---|---|---|
| PWM Pulse Width | PWM Control | 1-2 ms 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 |
11.11 See Also
Carry the servo design outward in a deliberate order. Revisit PWM Control for the timing contract, compare Stepper Motors when rotation or open-loop increments change the actuator family, then test coordination in the multi-servo arm, bounded motion in the pan-tilt mount, and physical wiring in the Actuator Labs.
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.
11.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 |
11.13 Continue Your Route
This final part closes the route from Pan-Tilt Camera Mount through Code Challenge. Return to Servo Motors: Position, Motion, and Power or continue from the actuators module index.
