Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.

SG90 servo with NodeMCU ESP8266 — wiring and full 0–180° code

Drive an SG90 servo from a NodeMCU ESP8266 on D5 with the core’s Servo library, set to 500–2400 µs so it really turns 0–180°, and power it safely.

Arduino C++Verified — core esp8266 3.1.2, 3 Nov 2026Compile-only

Community draft — report a mistake

An SG90 makes a NodeMCU move things: a door latch, a fish feeder, a pointer on a dashboard. The signal is a 3.3 V pulse from D5; the power must come from VIN or, better, its own 5 V supply.

Unlike the ESP32, the ESP8266 needs no extra library — the Servo that comes with the core works. The catch is its default pulse width, which is why the sketch sets 500–2400 µs explicitly.

Wiring

NodeMCU ESP8266Only the pins used are shown · 3.3 V logicSG90 micro servo (9 g)GNDVIND5SIGVCCGND
Every connection
NodeMCU ESP8266SG90 micro servo (9 g)WireNotes
D5SIGorangeD5 is GPIO14. Orange wire on most SG90s. A 3.3 V signal is enough.
VINVCCredRed wire. One unloaded SG90 on a good USB port only; for anything more use a separate 5 V 1 A supply with its GND joined to the NodeMCU GND.
GNDGNDbrownBrown wire.

4.8–6 V (several hundred mA while moving or stalled) part, 3.3 V board. The signal input is happy with 3.3 V logic, so ESP32 and Pico drive it directly. On ESP32 use the ESP32Servo library — the standard Servo library is for AVR and RP2040.

Board quirks

  • The ESP8266 core ships its own Servo library — don’t install ESP32Servo or the AVR one. Its default pulse range is 1000–2000 µs, which turns an SG90 only about 90°; the sketch calls attach(D5, 500, 2400) for the full sweep.
  • Never power the servo from 3V3. The NodeMCU’s regulator feeds the ESP8266, and a moving servo pulls hundreds of mA — the 3.3 V rail sags and the board resets or the Wi-Fi drops.
  • D0 (GPIO16) can’t generate servo pulses. Avoid D3, D4 and D8 too: the servo’s input can upset the boot levels, and D4 toggles at start-up, which makes the arm twitch every reset.
  • The pulses are made by the core’s software waveform generator, not a hardware timer. Heavy Wi-Fi traffic can add a little jitter; a separate PCA9685 board fixes that for robot arms.

Code

servo-nodemcu.inoArduino C++Open in PlaygroundOpen in PlaygroundFlash
// SG90 micro servo on a NodeMCU (ESP8266), using the Servo library that ships with the core.
// SIG → D5 (GPIO14), VCC → VIN (5 V from USB, one unloaded SG90 only), GND → GND.
#include <Servo.h>

const uint8_t SERVO_PIN = D5;  // GPIO14 — PWM-capable, no boot role (D0 can't do servo pulses)
Servo servo;

void setup() {
  Serial.begin(115200);
  Serial.println();
  // The ESP8266 Servo library defaults to 1000–2000 µs, which only moves an SG90 about 90°.
  // 500–2400 µs gives the full 0–180°. Narrow it if your servo buzzes at the ends.
  servo.attach(SERVO_PIN, 500, 2400);
  Serial.println("Sweeping 0 <-> 180 deg on D5");
}

void loop() {
  for (int a = 0; a <= 180; a += 30) {
    servo.write(a);
    Serial.printf("Angle %d deg\n", a);
    delay(600);
  }
  for (int a = 150; a >= 30; a -= 30) {
    servo.write(a);
    Serial.printf("Angle %d deg\n", a);
    delay(600);
  }
}

Library: Servo (Arduino).

Expected serial output

Serial Monitor · 115200Output
Sweeping 0 <-> 180 deg on D5
Angle 0 deg
Angle 30 deg
Angle 60 deg
Angle 90 deg

Common errors

Servo only turns about half way

You used servo.attach(pin) with the default 1000–2000 µs. Use attach(pin, 500, 2400).

Board resets when the servo moves

The USB supply sags under servo current. Give the servo its own 5 V supply and a 470 µF capacitor across it, with GND shared.

Servo buzzes or jitters at rest

Supply noise or pushing past its end stops. Narrow the range (for example 600–2300 µs). Full fix.

↑↓ to move · Enter to open