Welcome to our second blog in this series, which covers controlling a servo with a potentiometer! We will explore Arduino and learn how a potentiometer can control a servo’s motion. A servo is a motor designed for precise position control. In this project we use an MG90S metal gear servo motor, known for its reliability and precision.
Using a potentiometer, which is a variable resistor, we can vary a voltage and control the servo shaft’s movement. Turning the potentiometer moves the shaft accordingly, opening up creative possibilities for interactive mechanical motion and robotics.
Let’s combine hardware and software to create dynamic projects. We will explore how to build our own servo-controlled structures using Arduino!
Components Used in the Project
| Arduino UNO |
| Servo Motor |
| Potentiometer |
| Jumper wires |
| Breadboard |
-
Arduino UNO: Arduino UNO is the heart of this project: a microcontroller-based device acting as our programmable brain. It lets us connect and control different electronic components and perform various tasks.
-
Servo Motor: A servo motor is designed for precise movement. In this project we control an “MG90S metal gear servo motor”. It receives Arduino commands and turns to a specified angle, enabling precise positioning and motion.
-
Potentiometer: The potentiometer is a variable resistor. Its knob adjusts resistance. We use it to control the servo’s motion by changing the angle it turns to.
-
Jumper wires: Short wires with connectors at each end link the components. They are flexible and easy to use for connecting Arduino, servo, potentiometer and breadboard.
- Breadboard: A breadboard is useful for temporary electronic circuit prototypes. It connects components without permanent soldering. Insert components into its holes and link them using jumper wires.
Let’s take a closer look at the servo motor.
SG-90 Servo Motor

The SG-90 is a small, compact servo for precise movement of mechanical parts, common in hobby projects, robotics and remote-controlled devices. This overview describes SG-90; the project also names MG90S, so check the specifications of the exact servo supplied.
Key Points about the SG-90 Servo:
-
Control: The SG-90 uses closed-loop position control. It moves within a limited angular range, often described as 180 degrees; the actual safe travel and pulse limits depend on the exact model.
-
Torque: SG-90 has relatively low torque compared with larger servos, but enough for many light to medium projects and small mechanical parts.
-
Voltage: Check the exact servo’s voltage and current ratings; 4.8 V to 6 V is a commonly stated range for these hobby servos, not a universal guarantee. Use a regulated external supply rated for starting/stall current and connect its ground to Arduino ground. Do not assume the UNO 5V output can power the servo reliably.
-
Signal Control: The servo receives position-control pulses whose width specifies the requested angle. This is commonly called servo PWM; it is not the same as using Arduino analogWrite() for ordinary duty-cycle control.
-
Connection: The servo typically has three wires—red (Vcc/+) , black (GND/-) and orange (signal). Colours can vary, so check the servo documentation. Power and ground supply the motor; the signal wire receives position-control pulses.
The Project Circuit
Having built our first circuit, we now have room for a few metaphors in the explanation. Let’s go...
In this circuit, where our servo dances to the potentiometer’s tune, we return to our faithful breadboard. This time our special guest is the “MG90S metal gear servo motor”, known for its precision, joined by lively jumper wires and the charming potentiometer that gives us control.
First, power the servo from a suitable external regulated supply, here nominally 5V within its documented rating, and connect the supply’s GND to both servo ground and Arduino ground. Do not connect the external positive supply to UNO’s 5V rail while it is USB-powered. Connect the servo signal to GPIO pin 9, where it receives commands and turns them into graceful motion. Now the potentiometer takes the stage.
Our potentiometer joins the electrical party too. Connect its two outer terminals to 5V and GND on Arduino, then connect its wiper to analogue pin A0, where it reports its current position.
With the circuit assembled and components ready for ACTION, it is time for the code. We will use Arduino code to control the servo and potentiometer and create an elegant sequence of movements. Let’s explore how programming brings the components into harmony with our desired motion.
The Code
This code introduces libraries in Arduino IDE!
Arduino libraries give us ready-made code developed by other skilled people. They make it easier to implement complex functions and control components without writing everything from scratch. Libraries contain predefined functions, constants and definitions, making Arduino programming more efficient and accessible.
Think of libraries as programs we can download to take valid shortcuts in programming.
To install a library using Arduino IDE:
- Open Arduino IDE on your computer.
- Open Library Manager from the sidebar, or choose Sketch > Include Library > Manage Libraries.
- Search for the required library, here Servo.
- Select the matching library and check its author and board compatibility.
- Click Install.
- Arduino IDE downloads and installs the library.
- Once installation finishes, it is ready to use.
In the code, we use the library “Servo”. As mentioned, a library is a collection of predefined functions and code for working with specific components or features. Here the Servo library controls the servo motor.
Here Is the Project Code
#include <Servo.h> // Tilføj servo-biblioteket
Servo myservo; // Opret servo-objekt til at styre en servo
int potpin = 0; // Analog pin brugt til at forbinde potentiometeret
int val; // Variabel til at læse værdien fra den analoge pin
void setup() {
myservo.attach(9); // Tilslut servoen på pin 9 til servo-objektet
}
void loop() {
val = analogRead(potpin); // Læser værdien fra potentiometeret (værdi mellem 0 og 1023)
val = map(val, 0, 1023, 0, 180); // Skalér værdien til brug med servoen (værdi mellem 0 og 180)
myservo.write(val); // Indstil servoen til den skalerede værdi
delay(15); // Vent på at servoen når den ønskede position
Throughout this series, we use links to Arduino documentation to introduce programming concepts. Click the links and read the descriptions if anything is confusing. It may seem overwhelming at first, but patience and willingness to learn will help you master it!
Start by including the Servo library with “#include <Servo.h>”. This makes its useful functions and commands available.
Next create an object called myservo using “Servo myservo;”. This object controls the servo.
Define potpin and assign 0. It identifies analogue input 0, where the potentiometer is connected.
In setup, use “myservo.attach(9);” to attach the servo motor to pin 9 on Arduino.
In loop, read the potentiometer with “val = analogRead(potpin);”.
analogRead() resembles digitalRead(), introduced in the first blog in this series: Light & Sound.
analogRead reads analogue input values. Unlike digitalRead, which returns HIGH (1) or LOW (0), analogRead returns a range of values representing voltage levels.
An Arduino UNO has 6 analogue inputs labelled A0 to A5. On the classic UNO, analogRead normally returns 0–1023 from its 10-bit ADC. This represents the input relative to the selected reference voltage, normally nominally 5 V; resolution is not a guarantee of absolute accuracy.
Next use “map” to scale 0–1023 to 0–180 in the example. Check the servo’s safe mechanical travel and pulse limits and restrict the range if needed.
Use “myservo.write(val);” to set the servo position from the scaled value.
Finally use “delay(15);” to wait 15 milliseconds before repeating loop.
Upload the Code
To upload and test, connect Arduino to the computer with a USB cable and follow these steps.
- Open Arduino IDE.
- Click Verify in the toolbar. This compiles the code and checks for compilation errors; it does not verify the physical wiring or all behaviour.
- If compilation succeeds, the IDE reports success.
- Select the correct Arduino board and port under Tools.
- Click Upload in the toolbar to compile and transfer the code to Arduino.
- If successful, the IDE reports that uploading is complete.
- Now test whether the project behaves as expected.
We have now explored projects with a sound sensor and servo motor. You have learned to build circuits, program Arduino and see your creations take shape. But there is more!
If you want more electronics, here is a bonus project combining both: the servo from blog 2 and the sound sensor from blog 1 in an interactive sound-controlled movement project.
BONUS PROJECT
This bonus combines the servo from blog 2 and the sound sensor from blog 1 for a unique, fun, interactive sound-controlled movement project.
We will program Arduino to respond to sounds, specifically finger snaps. One snap moves the servo in one direction and lights the green LED; two snaps move it the other way and light the red LED instead. Combining sound and motion gives you a new way to interact with the project.
Now for the exciting part: test your own skills! Build the circuit and implement the code to make the sound-controlled movement project work.
Take Arduino, the servo and the sound sensor, and connect them on the breadboard using jumper wires. Follow the external servo-supply guidance above; power the other modules at their rated voltage, here 5V, and connect all GND points together.
Open Arduino IDE and copy the supplied code into a new sketch.
#include <Servo.h>
Servo myservo;
int soundSensor = 2; // Lydsensor er tilsluttet pin 2
int greenLED = 5; // Grøn LED er tilsluttet pin 5
int redLED = 4; // Rød LED er tilsluttet pin 4
boolean greenLEDStatus = false; // Status for grøn LED
boolean redLEDStatus = false; // Status for rød LED
unsigned long greenLEDTimestamp = 0; // Tidsstempel for grøn LED
unsigned long redLEDTimestamp = 0; // Tidsstempel for rød LED
int doubleSnapDelay = 2000; // Juster denne værdi efter behov
void setup() {
myservo.attach(9);
pinMode(soundSensor, INPUT);
pinMode(greenLED, OUTPUT);
pinMode(redLED, OUTPUT);
myservo.write(0); // Indstil servoens position til 0 grader
delay(1000); // Vent et øjeblik for at servo nå den indledende position
}
void loop() {
int SensorData = digitalRead(soundSensor);
if (SensorData == 1) {
unsigned long currentTime = millis();
// Tjek om der er gået nok tid siden grøn LED sidst blev tændt
if (currentTime - greenLEDTimestamp >= doubleSnapDelay) {
greenLEDStatus = false;
digitalWrite(greenLED, LOW);
}
// Tjek om der er gået nok tid siden rød LED sidst blev tændt
if (currentTime - redLEDTimestamp >= doubleSnapDelay) {
redLEDStatus = false;
digitalWrite(redLED, LOW);
}
if (greenLEDStatus == false && redLEDStatus == false) {
greenLEDStatus = true;
digitalWrite(greenLED, HIGH);
// Ét knips registreret, drej servo fra 0 til 180 grader
myservo.write(180);
delay(700); // Juster forsinkelsen om nødvendigt
// Opdater tidsstempel for grøn LED
greenLEDTimestamp = millis();
} else if (greenLEDStatus == true && redLEDStatus == false) {
unsigned long snapTime = millis();
int numSnaps = 0;
boolean doubleSnapDetected = false;
while (millis() - snapTime <= doubleSnapDelay) {
int SensorData = digitalRead(soundSensor);
if (SensorData == 1) {
numSnaps++;
delay(100); // Forsinkelse for at undgå flere knips-detektioner
if (numSnaps > 1) {
doubleSnapDetected = true;
break;
}
}
}
if (doubleSnapDetected) {
// To knips registreret, tænd rød LED
redLEDStatus = true;
digitalWrite(redLED, HIGH);
// Drej servo fra 180 til 0 grader
myservo.write(0);
delay(700); // Juster forsinkelsen om nødvendigt
}
// Opdater tidsstempel for rød LED
redLEDTimestamp = millis();
// Sluk grøn LED
greenLEDStatus = false;
digitalWrite(greenLED, LOW);
}
}
}
Psst! Here is a little help to get started.
This code introduces a new function called millis().
It returns the number of milliseconds since Arduino started or reset.
We use millis() to track time since a snap was detected. Store the timestamp in a variable and compare elapsed time with the required delay to decide when to act.
The LED timestamps use the type unsigned long, matching millis() on the classic UNO. A “unsigned long” stores non-negative integers over a larger range than the UNO’s signed int.
Using unsigned long does not eliminate overflow: millis() wraps to zero after about 49.7 days on the classic UNO.
For elapsed-time checks, use unsigned subtraction, such as now - previous >= interval, with suitable interval bounds. An ordinary 16-bit int is unsuitable for storing millis() timestamps. Rollover-safe arithmetic matters as well as the type.
Now try reading the code to infer the circuit connections. For example, “int soundSensor = 2;” tells us to connect the sound sensor signal to pin 2. Can you identify the other connections?
Remember current-limiting resistors (about 1k ohm) for the LEDs. Connect the low-current components to their appropriate supply (5V from Arduino) and ground (Arduino GND). Follow the separate servo-supply guidance above. Now put your knowledge into practice and see the bonus project in action!