Servos
Controlling hobby servos from an ESP32 for cockpit gauges, flap indicators, and other moving parts.
A hobby servo is a self-contained actuator with a DC motor, gearbox, and position-control electronics. It accepts a 50 Hz PWM signal and rotates its output shaft to the corresponding angle (typically 0–180°). Continuous-rotation servos use the same signal but spin indefinitely at variable speed.
| Type | Example | Torque | Cockpit use |
|---|---|---|---|
| Micro (plastic gear) | SG90 | 1.8 kg·cm | Lightweight gauge needles, flap slats |
| Standard (metal gear) | MG996R | 10–13 kg·cm | Throttle feedback, heavier mechanisms |
| High-torque digital | DS3225 | 25 kg·cm | Control column, yoke, rudder pedal |
| Continuous rotation | SG90 CR | — | Motorised knobs, VOR OBS ring |
PWM parameters
| Parameter | Value |
|---|---|
| Signal frequency | 50 Hz (20 ms period) |
| Pulse width — 0° | ~1 000 µs (1 ms) |
| Pulse width — 90° | ~1 500 µs (1.5 ms) |
| Pulse width — 180° | ~2 000 µs (2 ms) |
| Signal voltage | 3.3–5 V (ESP32's 3.3 V output is compatible) |
| Wire colour | Function | Connect to |
|---|---|---|
| Orange / Yellow | Signal (PWM) | GPIO 23 (any PWM-capable pin) |
| Red | VCC | External 5 V supply (+) |
| Brown / Black | GND | Common GND (ESP32 GND + supply GND joined) |
The ESP32Servo library wraps the ESP32's LEDC peripheral and provides the standard Arduino Servo API. Install via Library Manager → search ESP32Servo .
Basic position control
// Library Manager → search "ESP32Servo" by Kevin Harrington
#include <ESP32Servo.h>
Servo myServo;
const int SERVO_PIN = 23;
void setup() {
myServo.attach(SERVO_PIN);
myServo.write(90); // start at center (90°)
}
void loop() {
myServo.write(0); // 0° — full left / closed
delay(1000);
myServo.write(90); // 90° — center
delay(1000);
myServo.write(180); // 180° — full right / open
delay(1000);
}Smooth sweep (gauge needle)
// Smooth sweep — cockpit gauge needle or flap indicator
#include <ESP32Servo.h>
Servo gauge;
void setup() {
// attach(pin, minPulse_µs, maxPulse_µs)
// Calibrate min/max for your specific servo model
gauge.attach(23, 500, 2500);
}
void loop() {
for (int pos = 0; pos <= 180; pos++) {
gauge.write(pos);
delay(8); // ~8 ms per degree ≈ 1.44 s full sweep
}
for (int pos = 180; pos >= 0; pos--) {
gauge.write(pos);
delay(8);
}
}The ESP32's LEDC (LED Control) peripheral generates hardware PWM on any GPIO. This approach requires no extra library and gives precise control over frequency and resolution.
// Raw LEDC — no library (Arduino-ESP32 core 3.x API)
const int SERVO_PIN = 23;
// 50 Hz PWM, 16-bit resolution (65 535 ticks = 20 000 µs period)
// 1 000 µs = 0° → duty ≈ 3 277
// 2 000 µs = 180° → duty ≈ 6 554
void setAngle(int angle) {
int duty = map(angle, 0, 180, 3277, 6554);
ledcWrite(SERVO_PIN, duty);
}
void setup() {
ledcAttach(SERVO_PIN, 50, 16);
setAngle(90);
}
void loop() {
setAngle(0);
delay(1000);
setAngle(180);
delay(1000);
} Pulse-width limits vary by model. Adjust the map() bounds (3277 / 6554) if the servo does not reach its full range.
| Application | Servo type | Notes |
|---|---|---|
| Altimeter / airspeed needle | SG90 micro | Map simulator dataref value to 0–180° in code |
| Flap position indicator | SG90 / MG996R | Drive to fixed angles: 0°, 10°, 20°, 30°, 40° |
| Throttle quadrant lever | MG996R / DS3225 | Needs strong torque to move lever mechanically |
| VOR OBS ring | Continuous rotation | Pair with encoder for absolute position feedback |
| Gear door animation | SG90 / MG996R | Timed to gear retract/extend dataref changes |