Servo motors
What you’ll learn
- How a servo holds an exact angle
- How to control one with the Servo library
- How to power several servos safely
Inside a servo
A hobby servo (like the SG90) contains a small DC motor, a gearbox, a potentiometer that measures the output angle, and a control circuit. You tell it an angle; it drives the motor until the potentiometer says it’s there, then holds. That’s closed-loop control in one small box.
The signal
Servos read a pulse sent about 50 times a second. The pulse width sets the angle: roughly 1 ms → one end, 1.5 ms → middle, 2 ms → other end (many servos accept about 0.5–2.5 ms for their full 0–180° travel). The Servo library makes the pulses for you:
#include <Servo.h>Servo s;s.attach(9); // signal on pin 9s.write(90); // go to 90°Wires
| Wire colour (usual) | Connect to |
|---|---|
| Brown or black | GND |
| Red | 5 V (servo power) |
| Orange or yellow | Signal pin |
Power
One small SG90 can run from the Arduino’s 5V pin when it isn’t loaded. Several servos, or larger ones, need their own 5–6 V supply (with grounds connected), or the Arduino will reset when they move.
Continuous rotation servos
Some servos are modified to spin all the way round. For these, write(90) means stop, lower values spin one way and higher values the other.
Example: a slow sweep
#include <Servo.h>Servo s;
void setup() { s.attach(9); }
void loop() { for (int a = 0; a <= 180; a++) { s.write(a); delay(10); } for (int a = 180; a >= 0; a--) { s.write(a); delay(10); }}Example: a radar scanner
Mount an ultrasonic sensor on a servo, sweep it, and record the distance at each angle. The robot can then turn towards the most open direction.
Try it in the virtual Arduino
Press Start simulator, replace diagram.json with the wiring below, paste the sketch and press ▶. Turn the knob and the servo follows. If Wokwi says a library is missing, click its Install button and press ▶ again.
{ "version": 1, "author": "RoboLearn", "editor": "wokwi", "parts": [ { "type": "wokwi-arduino-uno", "id": "uno", "top": 0, "left": 0, "attrs": {} }, { "type": "wokwi-servo", "id": "servo1", "top": -100, "left": 180, "attrs": {} }, { "type": "wokwi-potentiometer", "id": "pot1", "top": -90, "left": 40, "attrs": {} } ], "connections": [ [ "servo1:GND", "uno:GND.1", "black", [] ], [ "servo1:V+", "uno:5V", "red", [] ], [ "servo1:PWM", "uno:9", "orange", [] ], [ "pot1:GND", "uno:GND.2", "black", [] ], [ "pot1:VCC", "uno:5V", "red", [] ], [ "pot1:SIG", "uno:A0", "green", [] ] ], "dependencies": {}}#include <Servo.h>
Servo arm;
void setup() { arm.attach(9);}
void loop() { int angle = map(analogRead(A0), 0, 1023, 0, 180); arm.write(angle); delay(15);}Runs on Wokwi, free, no account needed.
Three positionsEasy
Replace the knob code so the servo goes to 0°, 90° and 180°, pausing 1 s at each.
In loop(): arm.write(0); delay(1000); arm.write(90); delay(1000); arm.write(180); delay(1000);
Limit the rangeMedium
Your gripper breaks if the servo goes past 120°. Make the knob control only 30–120°.
int angle = map(analogRead(A0), 0, 1023, 30, 120);
Smooth followerHard
Make the servo move towards the knob’s angle smoothly, at most 2° per step, instead of jumping.
Show an answer
int current = 90;void loop() { int target = map(analogRead(A0), 0, 1023, 0, 180); if (current < target) current += min(2, target - current); if (current > target) current -= min(2, current - target); arm.write(current); delay(15);}Quick check
Finished this lesson?