A servo motor rotates its output shaft to a specific angle and holds it there. Unlike a regular DC motor that just spins continuously, you tell a servo "go to 90 degrees" and it moves to exactly that position. The SG90 is a small, inexpensive hobby servo that is perfect for learning -- it shows up in everything from robotic arms to automated plant watering systems. In this guide, you will learn how to wire an SG90 to your ESP32, control its angle from code, and build a smooth sweep effect.
This guide uses the ESP32-WROOM-32 DevKit. Pin labels and GPIO numbers may differ on your board -- always check your board's pinout diagram.
🔗Key Specs
| Parameter | Value |
|---|---|
| Operating voltage | $4.8$ to $6.0\,\text{V}$ |
| Stall current | $\approx 500\,\text{mA}$ (at $4.8\,\text{V}$) |
| Rotation range | $0°$ to $180°$ |
| Signal type | PWM ($50\,\text{Hz}$, pulse width $0.5$ to $2.5\,\text{ms}$) |
| Speed | $\approx 0.12\,\text{s}$ per $60°$ (at $4.8\,\text{V}$) |
| Torque | $1.8\,\text{kg}\cdot\text{cm}$ (at $4.8\,\text{V}$) |
Warning: Do not power the servo from the ESP32's 3.3V pin. The SG90 needs 5V and can draw up to 500 mA under load. The ESP32's onboard regulator cannot supply this. Use the VIN/5V pin (which passes through USB power) or, better yet, an external 5V power supply. Always connect the grounds together.
Which motor type? Servos are for positioning to a specific angle. Need continuous rotation instead? See DC motors. Need precise stepping? See stepper motors. Our motor comparison guide explains the differences.
🔗What You'll Need
| Component | Qty | Notes | Buy |
|---|---|---|---|
| ESP32 dev board | 1 | AliExpress | Amazon.de .co.uk .com | |
| SG90 servo motor | 1 | AliExpress | Amazon.de .co.uk .com | |
| Breadboard | 1 | AliExpress | Amazon.de .co.uk .com | |
| Jumper wires | 3 | AliExpress | Amazon.de .co.uk .com |
Links marked Amazon/AliExpress are affiliate links. We may earn a small commission at no extra cost to you.
🔗Wiring
| SG90 Wire | Connection | Notes |
|---|---|---|
| Red (VCC) | 5V (VIN) | Or external 5V supply |
| Brown (GND) | GND | Shared ground with ESP32 |
| Orange (Signal) | GPIO 13 | PWM signal pin |
Tip: If you are using an external 5V power supply for the servo, make sure to connect its GND to the ESP32's GND. Without a shared ground, the PWM signal has no reference voltage and the servo will not respond.
🔗Required Libraries
Install the ESP32Servo library through the Arduino Library Manager:
- Go to Sketch > Include Library > Manage Libraries...
- Search for ESP32Servo and install it
This library adapts the familiar Arduino Servo interface to work with the ESP32's LEDC hardware.
🔗Code Example: Set Specific Angles
This sketch moves the servo to three positions in sequence.
#include <ESP32Servo.h>
#define SERVO_PIN 13
Servo myservo;
void setup() {
Serial.begin(115200);
myservo.attach(SERVO_PIN);
Serial.println("Servo attached.");
}
void loop() {
myservo.write(0); // Move to 0 degrees
Serial.println("Position: 0°");
delay(1000);
myservo.write(90); // Move to 90 degrees (center)
Serial.println("Position: 90°");
delay(1000);
myservo.write(180); // Move to 180 degrees
Serial.println("Position: 180°");
delay(1000);
}🔗Code Example: Smooth Sweep
This sketch sweeps the servo smoothly from 0 to 180 degrees and back.
#include <ESP32Servo.h>
#define SERVO_PIN 13
Servo myservo;
void setup() {
myservo.attach(SERVO_PIN);
}
void loop() {
// Sweep from 0 to 180
for (int angle = 0; angle <= 180; angle++) {
myservo.write(angle);
delay(15); // Small delay for smooth movement
}
// Sweep from 180 to 0
for (int angle = 180; angle >= 0; angle--) {
myservo.write(angle);
delay(15);
}
}🔗How It Works
A servo motor uses a PWM signal at $50\,\text{Hz}$ (a $20\,\text{ms}$ period) to determine its position. The position is encoded in the pulse width -- the duration of the HIGH portion of each cycle:
| Pulse Width | Angle |
|---|---|
| $0.5\,\text{ms}$ | $0°$ |
| $1.5\,\text{ms}$ | $90°$ (center) |
| $2.5\,\text{ms}$ | $180°$ |
Inside the servo, a small DC motor drives a gear train. A potentiometer attached to the output shaft provides position feedback to a control circuit. The circuit compares the desired position (from the PWM signal) with the actual position (from the potentiometer) and drives the motor until they match. This feedback loop is what lets the servo hold a position even under load.
The ESP32Servo library handles the low-level PWM timing for you, so you can simply call myservo.write(angle) with an angle in degrees.
🔗Troubleshooting
| Problem | Possible Cause | Solution |
|---|---|---|
| Servo does not move | Powered from 3.3V pin | Use 5V (VIN) or external supply |
| Servo jitters or vibrates in place | Insufficient power supply | Use a supply that can deliver at least $1\,\text{A}$; add a $100\,\mu\text{F}$ capacitor across servo power |
| Servo only moves a small range | Wrong pulse width range in library | Try myservo.attach(SERVO_PIN, 500, 2500) to explicitly set min/max pulse widths |
| Servo moves to wrong angles | Signal wire on wrong GPIO | Verify the GPIO number in code matches your wiring |
| ESP32 resets when servo moves | Servo current spike overloading USB | Power the servo from an external 5V supply |
| Buzzing sound at extreme positions | Servo straining against mechanical stop | Avoid commanding angles beyond the servo's physical range (try 5--175 instead of 0--180) |
🔗Next Steps
- Use a potentiometer (analog input) to control the servo angle in real time
- Build a simple pan-tilt mechanism with two servos
- Control the servo over WiFi with a web interface
- Combine with an ultrasonic distance sensor to build a scanning range finder