Component Guide

Actuators Beginner

SG90 Micro Servo: External Power and ESP32 Pulses

Control a positional SG90-class servo using Arduino-ESP32 3.x LEDC. Use a documented external supply, common ground and a buffered control signal; begin with small unloaded movements.

BeginnerDifficulty Classic ESP32Compatible
Share
Product-style illustration of SG90 Micro Servo; not a verified module pinout
Jump to a section

Before you start

Board and software
Classic ESP32-WROOM-32/32E DevKit with these GPIOs exposed and unused. Arduino IDE 2.x; esp32 by Espressif Systems 3.x (API review baseline 3.3.2, not a latest-version claim). Select the exact board or ESP32 Dev Module for a generic WROOM board. Other ESP32 families need their own pin map. Serial Monitor: 115200 baud.
Hardware assumption
A positional SG90-class servo documented for 4.8 V supply and a 50 Hz RC control signal accepting 1400–1600 µs pulses. Tower Pro lists 4.8 V for its SG90 Digital; clones/different revisions are not assumed identical. Use a standard 14-pin SN74AHCT125 powered from the same regulated 4.8 V rail.
Prerequisites and parts
First complete Arduino IDE setup and Blink. Servo without mechanical load, regulated external 4.8 V supply sized for its actual starting/stall current, SN74AHCT125, 100 nF buffer decoupling and suitable supply wiring.
Expected result
The servo starts near its pulse-defined center, then alternates between two nearby positions. No angle, torque or travel is promised for an unidentified variant.
Verification status
Reviewed against the technical references below. Not compiled for an ESP32 or tested on hardware in this update. The approved product-style illustration identifies the family; follow documented terminal labels and the logical wiring diagram, not its rendered pin positions.

Overview

A positional servo uses repeated control pulses to choose a position; it is not powered from the signal wire. The motor can draw a surge when starting or blocked, so its supply must be independent of the ESP32 3.3 V rail.

Tower Pro lists 4.8 V and external adapter power for its SG90 Digital. This example uses that nominal rail; do not infer a universal 5–6 V rating from the SG90 name. A 5 V supply is acceptable only if the exact servo documentation permits it. Share ground with the USB-powered ESP32, not independent positive rails.

Technical Specifications

Arduino library: No additional servo library; Arduino-ESP32 3.x LEDC API

SpecificationValueWhy it matters
Servo type Positional SG90-class Continuous-rotation conversions behave differently; no universal travel/torque claim.
Power Documented external 4.8 V supply Size for actual peak/stall current; stop if buzzing or blocked.
Control 50 Hz (20 ms period) Assumed standard RC positional control; verify actual servo.
Example pulse width 1500 µs start; 1400 / 1600 µs movement Small initial range, not universal angles or endpoints.
LEDC GPIO25, 16-bit resolution on classic ESP32 Uses ledcAttach and pin-based ledcWrite in Arduino-ESP32 3.x; other families may have lower resolution limits.

Pinout

  • Servo positive Motor/electronics supply External regulated 4.8 V Common red convention is not proof: verify connector wiring.
  • Servo ground Return Supply minus + ESP32 GND + buffer pin7 Use supply wiring sized for motor current; no motor current through GPIO.
  • Servo signal RC pulse input GPIO25 → buffer 1A pin2 / 1Y pin3 → signal Buffer VCC pin14 to 4.8 V; OE pin1 LOW; 100 nF between supply/ground.
  • Unused buffer channels Defined unused state OE pins4/10/13 HIGH; A pins5/9/12 LOW Outputs6/8/11 unconnected; verify standard 14-pin package. Do not substitute plain HC125 without checking input thresholds.

Wiring Diagram

External regulated 4.8 V powers the documented servo and SN74AHCT125; all grounds join. GPIO25 controls buffer channel1, whose output drives the identified servo signal lead.

Component terminalESP32 / circuit connectionPurpose and qualification
Servo positiveExternal regulated 4.8 VCommon red convention is not proof: verify connector wiring.
Servo groundSupply minus + ESP32 GND + buffer pin7Use supply wiring sized for motor current; no motor current through GPIO.
Servo signalGPIO25 → buffer 1A pin2 / 1Y pin3 → signalBuffer VCC pin14 to 4.8 V; OE pin1 LOW; 100 nF between supply/ground.
Unused buffer channelsOE pins4/10/13 HIGH; A pins5/9/12 LOWOutputs6/8/11 unconnected; verify standard 14-pin package. Do not substitute plain HC125 without checking input thresholds.
Logical connections for SG90 Micro Servo: External Power and ESP32 Pulses; see the accompanying wiring table for terminal details

Open wiring diagram at full size (new tab)

  1. 1

    Disconnect USB and servo power. Verify the exact servo supply range, signal lead and allowed pulses. Remove the horn/load for first movement.

  2. 2

    Wire buffer channel1, enables, decoupling and unused inputs as shown. Share ground but do not join external positive to USB/3V3.

  3. 3

    Upload the sketch with Arduino-ESP32 3.x, then power the verified servo circuit. Keep fingers and loose wires away from motion.

  4. 4

    Start with the narrow pulse range. Disconnect power if the servo strains; do not force the shaft or widen endpoints blindly.

Wiring and matching Arduino code

Narrow-range positional pulse test

External regulated 4.8 V powers the documented servo and SN74AHCT125; all grounds join. GPIO25 controls buffer channel1, whose output drives the identified servo signal lead.

sg90_micro_servo_esp32.ino
#include <Arduino.h>
constexpr uint8_t SERVO_PIN = 25;
constexpr uint8_t RESOLUTION = 16; // Classic ESP32 supports this at 50 Hz.
constexpr uint32_t PERIOD_US = 20000;
bool ready = false;
bool nextHigh = false;
bool writePulse(uint32_t pulseUs) {
  uint32_t duty = (pulseUs * (1UL << RESOLUTION) + PERIOD_US / 2) / PERIOD_US;
  return ledcWrite(SERVO_PIN, duty); // 3.x uses the pin, not a channel number.
}
void setup() {
  Serial.begin(115200);
  ready = ledcAttach(SERVO_PIN, 50, RESOLUTION);
  if (ready) ready = writePulse(1500);
  if (!ready) { Serial.println("LEDC configuration failed."); return; }
  Serial.println("Start at 1500 us; next pulses are 1400 and 1600 us.");
  delay(2000);
}
void loop() {
  if (!ready) { delay(1000); return; }
  uint32_t pulseUs = nextHigh ? 1600 : 1400;
  nextHigh = !nextHigh;
  ready = writePulse(pulseUs);
  if (!ready) { Serial.println("LEDC write failed."); return; }
  Serial.printf("Pulse: %lu us\n", static_cast<unsigned long>(pulseUs));
  delay(2000);
}

Pulse duty equals pulse duration divided by the 20 ms period, scaled to 2^16. Hardware LEDC maintains pulses during delay(). This is positional control, not speed control; a successful API return does not verify a connected servo.

Expected Output

After the initial 1500 µs pulse, the sketch sends 1400 and 1600 µs alternately every two seconds. A compatible unloaded positional servo should move between nearby positions. Exact angles depend on the model; continuous rotation, buzzing, hard stops or resets call for stopping and checking hardware.

How it works

Pulse width requests position. Increasing supply voltage does not select an angle. The buffer provides a documented logic interface instead of assuming every servo accepts ESP32 3.3 V HIGH. External supply capacity and a common reference remain necessary even when code and pulse timing are correct.

Troubleshooting

ProblemPossible causeSolution
ESP32 resets when the servo moves Supply droop or motor current in ESP32 power wiring. Use separate rated servo power and common ground; check actual surge current, wiring and supply decoupling.
No movement Wrong connector, disabled buffer, unsupported pulse input or no servo power. Check vendor lead order, 4.8 V-compatible supply, shared ground, buffer OE and pulses; USB alone is not servo power.
Buzzing or hard stop Load, mechanical obstruction or unsuitable pulse range. Disconnect power, remove the load and verify the model/pulse range. Do not force the shaft.
ledcAttach is missing Arduino-ESP32 2.x or wrong board/core. Select Arduino-ESP32 3.x and the classic WROOM board. Do not mix channel-based legacy calls with this pin-based example.

Where you use it

  • Small indicator pointer
  • Unloaded servo learning experiment
  • Documented low-load robot joint

Continue learning

Related projects

FAQ

Technical references

Downloads

Official manufacturer PDF for teachers and advanced builders.

No separate datasheet is needed for this beginner guide.