The SG90 is the 9-gram servo in every robot kit, and the Nano drives it with the standard Arduino Servo library. The signal goes on D9; any digital pin works, but D9 keeps the wiring neat on a breadboard.
Type a number between 0 and 180 in the Serial Monitor (115200 baud, “Newline”) and the horn moves there. For anything heavier than an empty horn, give the servo its own 5 V supply.
Wiring
| Arduino Nano | SG90 micro servo (9 g) | Wire | Notes |
|---|---|---|---|
| D9 | SIG | orange | |
| 5V | VCC | red | One unloaded SG90 only. With a load, or two servos, use a separate 5 V 2 A supply and join its GND to the Nano GND. |
| GND | GND | brown |
4.8–6 V (several hundred mA while moving or stalled) part, 5 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
- On USB the Nano’s 5V pin goes through a diode and the USB port’s current limit. A stalled SG90 can pull 500–700 mA, which resets the Nano or drops the USB port — the classic “servo jitters and the board restarts”.
- The Servo library uses Timer1:
analogWrite()on D9 and D10 stops working once a servo is attached. Use D3, D5, D6 or D11 for PWM LEDs or motors. - SG90 wires: brown = GND, red = 5 V, orange = signal.
attach(pin, 500, 2400)gives the full 0–180° travel on most SG90s; the default 544–2400 µs stops a little short.
Code
// SG90 micro servo on an Arduino Nano, angle set from the Serial Monitor (type 0-180 + Enter).
// SIG → D9, VCC → 5V (one unloaded SG90 only), GND → GND.
// The Servo library takes Timer1, so analogWrite() stops working on D9 and D10.
#include <Servo.h>
const uint8_t SERVO_PIN = 9;
Servo servo;
void setup() {
Serial.begin(115200);
servo.attach(SERVO_PIN, 500, 2400); // SG90 pulse range in microseconds
servo.write(90);
Serial.println(F("Servo at 90. Type an angle 0-180:"));
}
void loop() {
if (Serial.available()) {
long angle = Serial.parseInt();
while (Serial.available()) Serial.read(); // drop the line ending
angle = constrain(angle, 0, 180);
servo.write(angle);
Serial.print(F("Moved to "));
Serial.println(angle);
}
}// SG90 micro servo on an Arduino Nano, angle set from the Serial Monitor (type 0-180 + Enter).
// SIG → D9, VCC → 5V (one unloaded SG90 only), GND → GND.
// The Servo library takes Timer1, so analogWrite() stops working on D9 and D10.
#include <Servo.h>
const uint8_t SERVO_PIN = 9;
Servo servo;
void setup() {
Serial.begin(115200);
servo.attach(SERVO_PIN, 500, 2400); // SG90 pulse range in microseconds
servo.write(90);
Serial.println(F("Servo at 90. Type an angle 0-180:"));
}
void loop() {
if (Serial.available()) {
long angle = Serial.parseInt();
while (Serial.available()) Serial.read(); // drop the line ending
angle = constrain(angle, 0, 180);
servo.write(angle);
Serial.print(F("Moved to "));
Serial.println(angle);
}
}Library: Servo (Arduino) — compiled with Servo 1.3.0.
Expected serial output
Servo at 90. Type an angle 0-180:
Moved to 0
Moved to 180Servo at 90. Type an angle 0-180: Moved to 0 Moved to 180
Common errors
Servo jitters or the Nano keeps resetting
Not enough current from the 5V pin. Use a separate 5 V supply with common GND and a 470 µF capacitor across it. Full fix.
analogWrite on D10 does nothing
The Servo library owns Timer1 (D9/D10). Move the PWM output to D3, D5, D6 or D11.