Control a servo motor with an Arduino and a potentiometer
Beginner
Or see every lesson.
- 505parts on the bench
- 45boards running now
- 1.00xreal time, on every board
A hobby servo is the easiest way to make an Arduino move something to an exact angle: three wires, one signal pin, and a number from 0 to 180. The circuit above is an SG90-style servo on pin 9 of an Arduino Uno, with a slide potentiometer on A0 setting where the horn points. It is running in your browser on a simulated ATmega328P.
Open it in the editor and drag the slider while it runs: the horn walks to the new angle at the speed a real SG90 does, and the serial monitor prints the reading and the angle each time it changes.
What you need
- An Arduino Uno
- An SG90 (or similar) hobby servo
- A 10 k potentiometer (a slide pot here; a rotary one is wired the same way)
- A breadboard and jumper wires
Wiring
| Part and pin | Goes to | Note |
|---|---|---|
| Servo brown wire (GND) | GND | |
| Servo red wire (VCC) | 5 V | Below 4 V the servo does not move at all |
| Servo orange wire (signal) | Pin 9 | Any digital pin works |
| Potentiometer end 1 | 5 V | |
| Potentiometer end 3 | GND | |
| Potentiometer wiper | A0 | Reads 0 to 1023 across the travel |
What a servo actually listens to
The servo’s signal wire does not take PWM in the sense an LED does. The duty cycle means nothing to it. What it measures is the width of each pulse: with the Servo library’s numbers, 544 microseconds puts the horn at one end, 2400 microseconds at the other and 1472 microseconds in the middle, repeated about fifty times a second. The servo holds whatever it was last told and walks there at its own speed, roughly a tenth of a second for sixty degrees.
That is also why you cannot drive a servo with analogWrite() on an Uno. The Uno’s PWM runs at about 490 or 980 hertz, far too fast for a servo to read as a pulse width. The Servo library makes the pulse itself.
The code, explained
The sketch reads the potentiometer four times and averages the readings, so the horn does not twitch on the last, noisy bit of the converter. map() turns 0 to 1023 into 0 to 180 degrees, write() sends the matching pulse, and the loop waits 20 milliseconds, which is the servo’s own frame period. The angle is printed only when it changes, so the serial monitor reads as a sentence rather than a waterfall.
void loop() {
long sum = 0;
for (int i = 0; i < 4; i++) {
sum += analogRead(FADER);
}
int reading = (int)(sum / 4);
int angle = (int)map(reading, 0, 1023, 0, 180);
horn.write(angle);
delay(20);
}The same thing with the Servo library
The built-in example uses Mokxi’s own servo header, but the Arduino Servo library’s calls compile as they stand, on every board that compiles in the browser. The classic sweep sketch below runs unchanged, with the upstream library’s widths: attach(pin) uses 544 to 2400 microseconds, write(90) sends 1472, and attach(pin, min, max) sets another window. One small difference is worth knowing: each write() sends one pulse rather than starting a timer, so a sketch that needs the servo held under load calls refresh() from loop().
For an ESP32 tutorial, ESP32Servo.h is the same class under the name those tutorials use.
#include <Servo.h>
Servo myservo;
void setup() {
myservo.attach(9);
}
void loop() {
for (int pos = 0; pos <= 180; pos++) {
myservo.write(pos);
delay(15);
}
}Open this sketch in the editorThe code alone: the editor places the board and the parts it can read from the sketch.
Try it in the editor
Open the circuit in the editor and change the map() call to map(reading, 0, 1023, 45, 135). The slider now covers only the middle ninety degrees, which is how you give a knob a finer feel over a smaller range.
Then select the servo and look at its properties: min_pulse, max_pulse, range and speed. Set the speed to 60 degrees a second and move the slider quickly; the horn now crawls after it, the way a large, slow servo would. min_pulse and max_pulse are 544 and 2400 by default, the Servo library’s window; a servo set up with attach(pin, 1000, 2000) wants 1000 and 2000 there too.
To drive a second servo, drag another one onto the canvas, wire its signal to pin 10, and add a second Servo object in the sketch.
Common mistakes
Powering the servo from the board and expecting it to be fine. On a real bench an SG90 can pull a quarter of an amp when it stalls, enough to brown out an Uno running from USB, and it is the most common reason a servo project resets itself. The simulator does not model supply current, so a circuit that would sag on your desk runs cleanly here. If you build it for real, give the servo its own 5 volt supply and join the grounds.
Forgetting the common ground. The signal is measured against the servo’s own ground, so if the two supplies share nothing the pulse means nothing.
Asking for angles the servo cannot reach. A pulse past either end of the servo’s window leaves the horn at that end, just as a real SG90 strains against its end stop. If the horn stops short of 0 or 180, check that the window in attach() matches the servo’s min_pulse and max_pulse.
Updating the servo in a tight loop with no delay. Sending pulses faster than every 20 milliseconds gains nothing, because the servo only updates at its own frame rate.
Open this circuit in the editor. Arduino Uno: servo fader, wired as it runs at the top of this page. Change a part or a value and run it again.
Open the circuitQuestions
Which Arduino pins can drive a servo?
Any digital pin. The library makes the pulse in software, so the servo does not need one of the PWM pins marked with a tilde.
Can I drive two servos at once?
Yes. Create two Servo objects on two pins and write to each. Give real servos their own supply once there is more than one, because the current adds up.
Why does my servo jitter?
Usually because the reading it follows is noisy. Averaging a few analogRead() samples, as this sketch does, or ignoring changes of a degree or two, steadies it. On real hardware a sagging supply causes jitter too.
What is the difference between a servo and a stepper motor?
A servo goes to an angle and holds it, with its own feedback inside, usually over 180 degrees. A stepper turns by counted steps, as far as you like, and has no idea where it is unless you count. The stepper tutorial covers the 28BYJ-48.
Keep going
Build this for real
Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.