How to control a servo motor with Arduino: the SG90 way
Wire an SG90 servo to an Arduino Uno, move it with three lines of code, and fix the jitter and resets that come from weak power. Wiring, code and checks.
Some links in this guide are affiliate links: if you buy, TechForLive may earn a commission at no extra cost to you. Details.
- Three wires: ground, power and signal, in that order.
- The Servo library does the timing. You only call attach and write.
- A stalling servo can pull far more than USB gives, so give it its own power.
- Centre the servo with a write of 90 before you screw the horn on.
How to control a servo motor with Arduino
A servo motor is a small motor with a brain inside. You tell it an angle, and it turns its shaft to that angle and holds it there. A normal motor just spins. A servo knows where it is pointing, which is why robots use it for arms, grippers, steering and camera mounts.
Most beginners start with the SG90. It weighs 9 grams, costs little, and turns about 180 degrees. Its maker, TowerPro, rates it at 1.8 kg-cm of stall torque at 4.8 V. That means it can hold about 1.8 kg hanging 1 cm from its shaft before it gives up. That is enough for a small gripper or a model steering arm, and not enough for a heavy door.
Control works through pulses. The Arduino sends a short pulse 50 times a second, and the width of the pulse sets the angle. A 1 ms pulse means 0 degrees, a 2 ms pulse means 180 degrees, and 1.5 ms sits in the middle at 90 degrees. You never time these pulses yourself. The Servo library does it for you.
This guide uses an Arduino Uno and one SG90. The same steps work on most Arduino boards, and the same code drives bigger servos too. Bigger servos just need a stronger power supply, which section 4 covers.
| At a glance | Answer |
|---|---|
| Servo used | SG90 micro servo, 9 g |
| Signal pin | Any digital pin, 9 here |
| Angle range | 0 to 180 degrees |
| Supply | 4.8 to 6 V |
| Torque at 4.8 V | 1.8 kg-cm stall |
| Library | Servo, built into the IDE |
What you need, and how the wires go
You need an Arduino Uno, an SG90 servo, a USB cable and three jumper wires. A breadboard helps but is not required. The SG90 comes with a three-wire lead and a small bag of plastic horns. Pick the single-arm horn for your first test, and screw it on only after the servo is centred.
Three wires leave the servo, and each one has a fixed job. Brown is ground, red is power, and orange is the signal. Some clones use black instead of brown, and yellow instead of orange. The order never changes: ground, power, signal, with the signal wire on the outside edge.
Plug the signal wire into any digital pin. Pin 9 is the usual choice because the Servo library examples use it. The red wire goes to 5V and the brown wire to GND. That is the whole circuit for one small servo, and it is enough to test with. The signal runs at 5 V on an Uno. On a 3.3 V board, check that your servo accepts a 3.3 V signal first.
Double-check the red wire before you plug in the USB cable. A servo wired backwards can burn out in seconds. If your servo has a different colour order, read the label on its case.
| Servo wire | Colour | Arduino pin |
|---|---|---|
| Ground | Brown (or black) | GND |
| Power | Red | 5V |
| Signal | Orange (or yellow) | Digital pin 9 |
The code: three lines that move a servo
Servo support comes built into the Arduino IDE, so there is nothing to install. Open the IDE, plug in the Uno, and pick the right board and port from the Tools menu. The code below is the classic sweep example, and it is the fastest way to see your servo alive.
Two lines do the real work. The attach line ties the servo to pin 9, and the write line tells it where to point. The loop then steps the angle from 0 to 180 and back, one degree at a time, with a 15 ms pause at each step. That pause is what makes the sweep smooth instead of a single jump.
Upload the sketch and watch the horn. It should swing slowly from one end to the other and back again. If it only twitches, check the wiring first, then the power. A servo that buzzes without moving is usually starved of current, not broken.
Once the sweep works, try fixed angles. A write of 0 points one way, 90 points to the middle, and 180 points the other way. Those three numbers are your test points for every project after this one. Use them for a gripper that opens and closes, a flag that waves, or a lock that turns.
- Open the Arduino IDE and start a new sketch. Type the code below, or open File, then Examples, then Servo, then Sweep for the same sketch.
- Check the board and port in the Tools menu. Pick Arduino Uno, then the port your board appears on.
- Click Upload. The servo should start sweeping from 0 to 180 degrees and back.
- Change the delay to 50 and upload again. The sweep slows down. Change it to 5 and the sweep speeds up.
Sweep the servo from 0 to 180 degrees and back
#include <Servo.h>
Servo myServo;
int angle = 0;
void setup() {
myServo.attach(9);
}
void loop() {
for (angle = 0; angle <= 180; angle += 1) {
myServo.write(angle);
delay(15);
}
for (angle = 180; angle >= 0; angle -= 1) {
myServo.write(angle);
delay(15);
}
}
Power it right, or it will jitter and reset
Power is where most servo projects fail. A typical PC USB 2.0 port can supply up to 500 mA, and the Arduino shares that current when it runs from USB. A small hobby servo draws tens to a few hundred milliamps while it moves, and several hundred milliamps or more when it stalls. Two servos stalling at once can brown out the board, and the Arduino will reset.
Fix it with a separate supply for the servo. Four AA batteries give about 6 V, which sits inside the SG90 range of 4.8 to 6 V. Connect the battery pack's positive wire to the servo's red wire, and its negative wire to the servo's brown wire and to the Arduino GND. That shared ground is the part people forget, and without it nothing works.
Watch for the warning signs. A servo that jitters, buzzes or twitches at rest is usually underpowered. An Arduino that resets when the servo moves is almost always a power problem. A servo that gets hot is stalled against a load it cannot move, so free the arm or use a stronger servo. Never feed a servo more than 6 V, and never power it from the Arduino Vin pin.
Keep the supply close to the servo. Long thin wires drop voltage. A servo at the end of a metre of jumper wire will behave worse than the same servo on short wires. If the arm must sit far from the board, run the power wires thick and short, and keep only the signal wire long.
Steer it with a knob: a potentiometer in five minutes
A potentiometer is a knob that acts as a voltage divider. Turn it one way and the Arduino reads near 0, turn it the other way and it reads near 1023. The map function turns that reading into an angle, so the servo follows the knob. It is the simplest way to drive a servo by hand.
Wire the knob with three wires, like the servo. The two outer pins go to 5V and GND, and the middle pin goes to analog pin A0. It does not matter which outer pin gets 5V and which gets GND, but swapping them flips the direction the knob turns the servo.
In the code, the knob reading is mapped to an angle and written to the servo. The 15 ms delay keeps the loop from hammering the servo with new commands faster than it can move. Turn the knob slowly and the servo follows smoothly. Turn it fast and the servo lags a little, then catches up.
This knob setup is the core of many real projects. A camera pan mount is a knob on a bigger scale. A robot arm is three knobs, one per joint. Once the knob drives one servo, adding a second servo is just a second object, a second pin and a second map line.
Drive the servo with a potentiometer on A0
#include <Servo.h>
Servo myServo;
int potPin = A0;
int angle = 0;
void setup() {
myServo.attach(9);
}
void loop() {
int reading = analogRead(potPin);
angle = map(reading, 0, 1023, 0, 180);
myServo.write(angle);
delay(15);
}
Common mistakes that make servos jitter, buzz or stall
Powering the servo from the Arduino 5V pin while it carries a load is the most common mistake. It works on the bench with no load, then fails the moment the arm meets resistance. The board resets, the servo twitches, and the code gets blamed. When the bench test passes but the loaded arm fails, power is the first suspect.
Fitting the horn before centring the servo is the second mistake. The servo powers up at its last commanded angle, which is rarely the middle. Centre it first with a write of 90, then fit the horn pointing where you want it.
Asking for angles the servo cannot reach is the third mistake. A standard SG90 turns about 180 degrees, and many clones only reach 160 to 170. Code that writes 0 and 180 will push the arm against its end stops, and the servo will buzz and draw stall current. Test your servo's real limits and stay a few degrees inside them.
Treating a positional servo like a wheel is the last mistake. A normal servo cannot spin all the way round. If your project needs endless rotation, buy a continuous rotation servo instead. Its write command sets speed, not angle, and it never knows where it is pointing.
- Bench test with no load: if it sweeps clean, the code and wiring are fine.
- Jitter at rest: weak power, or a signal wire running beside a motor wire.
- Board resets on movement: the supply cannot keep up with the servo under load.
- Servo buzzes at the ends: the code asks for angles past the real limits.
Quick answers
Can I power an SG90 servo from the Arduino 5V pin?
For a quick test with no load, yes, and many first sketches do exactly that. For real work, no. A stalling servo can draw several hundred milliamps, more than USB power gives the board. Use a separate 4.8 to 6 V supply for the servo.
Which pin should the servo signal wire use?
Any digital pin works, because the Servo library generates the signal in software. Pin 9 is the usual choice, since the library examples use it. On most Arduino boards the library can drive up to 12 servos at once, each on its own pin.
Why does my servo jitter or twitch?
Weak power is the usual cause. Check that the servo supply can give the current the servo wants, and that the ground is shared. A loose signal wire also causes twitching, as does a signal wire running beside a motor or power wire. Short, firm connections fix most of it.
Can a servo spin all the way round?
A standard positional servo cannot. It turns about 180 degrees and stops. For endless rotation, buy a continuous rotation servo. Its write command sets the speed and direction instead of an angle, and it has no sense of position.
How do I make the servo move more slowly?
Move it in small steps with a pause between them. The sweep example steps one degree at a time with a 15 ms delay. Raise the delay to slow the sweep, or lower it to speed it up. A bigger step, such as five degrees, makes the motion visibly jerky.