How to Use a Servo Motor with an Arduino

  • #arduino
  • #servo
  • #sg90
  • #tutorial
  • #servo-library

There’s a category of Arduino project where knowing how to control a servo motor unlocks everything: pan-tilt camera mounts, robot grippers, steering mechanisms, animatronic gadgets, anything where you need precise angular positioning. The servo takes care of the hard part — the feedback loop, the driver electronics, the gear reduction — and leaves you with a three-wire interface and a single write() call to point it wherever you want.

This walkthrough uses an SG90 9g micro servo, which is the right place to start for two reasons. First, it’s inexpensive — a five-pack from eBay runs a few dollars, and individual units are similarly cheap from any hobbyist supplier. Second, and more importantly, it’s small enough to power directly from the Arduino. That constraint matters, and we’ll come back to it.

The SG90 and what the three wires mean

The SG90 is a 9-gram micro servo that outputs about 1.8 kg·cm of torque on a 4.8V supply. Its operating range is 0–180°. It draws about 10 mA idle, 100–250 mA when actively moving, and up to 500–700 mA at stall.

The three wires coming off the connector are ground, power, and signal. The color coding on SG90s and their clones is brown-red-orange, but it’s not universal — other brands use black-red-yellow, or black-red-white, or other combinations. The signal wire is usually the lightest color (orange, yellow, or white). If you’re ever unsure, look up the datasheet or the seller listing for your specific servo rather than guessing.

Wire color (SG90)FunctionConnects to
BrownGroundArduino GND
RedPower (5V)Arduino 5V
OrangeSignalArduino digital pin 9

The signal pin doesn’t have to be pin 9. The Arduino Servo library works with any digital pin. The examples use pin 9 by convention.

Wiring

Connect the servo’s brown wire to any GND pin on the Arduino, red to the 5V pin, and orange to digital pin 9. That’s it. No breadboard required for this basic connection — the servo connector can plug onto male header pins directly if you add jumpers from each servo wire to the matching Arduino pin.

The critical rule about power: only power small servos directly from the Arduino’s 5V pin. The SG90 draws around 200 mA when moving — within the roughly 500 mA budget of the Arduino’s 5V pin (less whatever the board itself uses). A larger servo — the MG995, MG996R, or any servo labeled “standard size” or higher torque — can draw 500 mA to 1 A or more, which will overdraw the Arduino’s onboard regulator, cause voltage drops, reset the board, or in bad cases damage it. For anything larger than a micro or mini servo, use an external 5V power supply and share only the ground with the Arduino.

The code: Servo library and the Sweep example

The Arduino IDE ships with the Servo library built in. No installation needed. Find the Sweep example at File → Examples → Servo → Sweep, or copy the code below.

#include <Servo.h>

Servo myServo;   // create a Servo object — name it whatever you like

int pos = 0;     // variable to store the servo position in degrees

void setup() {
  myServo.attach(9);  // attaches the servo to digital pin 9
}

void loop() {
  // sweep from 0° to 180°, one degree at a time
  for (pos = 0; pos <= 180; pos += 1) {
    myServo.write(pos);   // tell servo to go to position 'pos'
    delay(15);            // wait 15ms for the servo to reach the position
  }
  // sweep back from 180° to 0°
  for (pos = 180; pos >= 0; pos -= 1) {
    myServo.write(pos);
    delay(15);
  }
}

Upload it. The servo sweeps back and forth between 0° and 180°, pausing 15 milliseconds between each 1° step.

Tuning the speed

The speed is controlled by two variables: the step size (how many degrees per iteration) and the delay (how long to wait at each position).

Changing the increment from += 1 to += 5 makes the servo move much faster — it jumps 5° per step. The trade-off is that if the delay is too short, the servo doesn’t have time to actually reach the commanded position before the next command arrives, and you’ll see it fall short of 180° before reversing.

// faster but may not complete the full sweep at small delays
for (pos = 0; pos <= 180; pos += 5) {
  myServo.write(pos);
  delay(15);   // may need to increase to 20–30ms if sweep doesn't complete
}

If the servo isn’t reaching the endpoints, increase the delay until it does. The delay() value needed depends on the servo’s speed rating and the load on the output shaft.

Beyond the sweep

The write() command accepts any integer from 0 to 180, so you can point the servo at a specific angle directly:

myServo.write(90);   // center position
myServo.write(0);    // one extreme
myServo.write(180);  // other extreme

For finer control — mapping an analog input like a potentiometer to servo position — use map():

int reading = analogRead(A0);                // 0–1023
int angle = map(reading, 0, 1023, 0, 180);  // scale to 0–180°
myServo.write(angle);

This is the foundation for a manually-controlled servo, a pan-tilt mount driven by joystick inputs, or a steering mechanism in a wheeled robot.

Where this doesn’t apply

This walkthrough covers small servos powered from the Arduino board. Once you move to standard-size servos for more torque — or to more than two or three micro servos running simultaneously — you need an external 5V supply. A dedicated servo tutorial covering external power supply and multiple servos is a separate walkthrough on this channel.

What you’ll need

  • Arduino Uno or compatible
  • SG90 9g micro servo (or similar micro-class servo)
  • Three jumper wires (male-to-female if using the servo’s stock connector)

References and further reading