ESP32 UNO - Potentiometer Servo Motor

Want to move a servo with a simple knob? Connect a potentiometer and a servo motor to the ESP32 Uno form board, and the servo arm follows your hand from 0° to 180°. Here is how to wire it and program it in the Arduino IDE.

By the end, you can:

  1. Connect a knob and a hobby servo to the ESP32 Uno header pins
  2. Read the knob position with analogRead()
  3. Turn the 0–4095 reading into a servo angle with map()
  4. Drive the servo with the ESP32Servo library
ESP32 Uno potentiometer servo motor

Components You Need

1×ESP32 Uno-form Board
1×USB Cable Type-A to Type-C (for USB-A PC)
1×USB Cable Type-C to Type-C (for USB-C PC)
1×Servo Motor
1×Potentiometer
1×Alternatively, 10k Ohm Trimmer Potentiometer
1×Alternatively, Potentiometer Kit
1×Alternatively, Potentiometer Module with Knob
1×Breadboard
1×Jumper Wires

Or you can buy the following kits:

1×DIYables Sensor Kit (18 sensors/displays)
Disclosure: Some of the links provided in this section are Amazon affiliate links. We may receive a commission for any purchases made through these links at no additional cost to you.
Additionally, some of these links are for products from our own brand, DIYables .

Buy Note: For controlling multiple servo motors, use the PCA9685 16 Channel PWM Servo Driver Module to save MCU pins and simplify wiring.

Servo and Potentiometer Basics

Goal: know what each part does before you join them.

Part Role in This Project Signal
Potentiometer Knob that gives a changing voltage 0V to 3.3V on the wiper
Servo motor Holds an arm at a chosen angle PWM pulse on the signal wire

If either part is new to you, read its own guide first:

ESP32 Uno Pinout

Each Uno header pin on the ESP32 Uno form board maps to one GPIO number, and your code uses that GPIO number. Check the diagram below to match them before you connect any wire.

ESP32 Uno pinout diagram

How to Connect

Goal: finish the circuit in two signal wires. Knob output to A0, servo signal to D9. A classic three-pin part and a knob module connect in the same way.

Classic potentiometer

The wiring diagram between ESP32 Uno Servo Motor Potentiometer

This image is created using Fritzing. Click to enlarge image

Potentiometer module

The wiring diagram between ESP32 Uno Servo Motor Potentiometer module

This image is created using Fritzing. Click to enlarge image

Component Pin ESP32 Uno Pin
Potentiometer VCC 3.3V
Potentiometer GND GND
Potentiometer Output A0 (GPIO2)
Servo VCC (red) 5V
Servo GND wire (brown or black) GND
Servo Signal wire (orange or yellow) D9 (GPIO13)

Good to know: ESP32 Uno pins are not 5V tolerant. Feed the potentiometer from 3.3V so the wiper never goes above 3.3V. The servo can still take 5V power, because its signal wire only receives the 3.3V pulse from the board.

WARNING

A0 (GPIO2) is a boot strapping pin. The chip reads it at startup to pick the boot mode. A potentiometer wiper is usually harmless here, but if the board does not boot or upload with the knob connected, unplug the wiper wire, upload the code, then plug it back in.

How It Works

Goal: see the three steps that repeat in the loop.

Step 1 — Read the knob

The 12-bit ADC gives a number from 0 to 4095. A0 is GPIO2.

int analogValue = analogRead(2);

Step 2 — Scale it to an angle

Squeeze the 0–4095 range into 0–180 degrees.

int angle = map(analogValue, 0, 4095, 0, 180);

Step 3 — Move the servo

Send the angle to the servo.

myServo.write(angle);

Code

The sketch reads A0 (GPIO2) every 100 ms, moves the servo on D9 (GPIO13), and prints the value and the angle.

/* * This ESP32 Uno code was developed by newbiely.com * * This ESP32 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-uno/esp32-uno-potentiometer-servo-motor */ #include <ESP32Servo.h> #define POT_PIN 2 // A0 (GPIO2) reads the potentiometer wiper #define SERVO_PIN 13 // D9 (GPIO13) sends the control signal to the servo Servo myServo; // servo object that drives the motor void setup() { // open the Serial Monitor link at 9600 baud Serial.begin(9600); // set the ADC attenuation to 11 dB (up to ~3.3V input) analogSetAttenuation(ADC_11db); // tie the servo object to D9 (GPIO13) myServo.attach(SERVO_PIN); } void loop() { // raw knob reading, 0 to 4095 on the 12-bit ADC int analogValue = analogRead(POT_PIN); // convert the reading into a servo angle from 0 to 180 int angle = map(analogValue, 0, 4095, 0, 180); // move the servo arm to that angle myServo.write(angle); // show both numbers in the Serial Monitor Serial.print("Potentiometer's Value: "); Serial.print(analogValue); Serial.print(" => Servo Motor's Angle: "); Serial.println(angle); delay(100); }
Code Part What It Does
#include Loads the servo library made for the ESP32 core
analogSetAttenuation(ADC_11db) Opens the ADC range to about 3.3V
analogRead(POT_PIN) Reads the knob as 0–4095
map(...) Converts the reading to 0–180 degrees
myServo.write(angle) Moves the servo arm

The servo follows the knob, and the Serial Monitor shows the numbers.

Good to know: the 11 dB attenuation lets the ESP32 Uno analog pin read the full range, from 0V up to about 3.3V. With a narrow range the number tops out early, so the arm hits 180° while the knob still has travel left.

Upload and Test

  1. First time with this board? Set it up with ESP32 Uno - Getting Started before you continue.
  2. Build the circuit by following the wiring table above.
  3. Plug in the USB Type-C cable between the ESP32 Uno and your computer.
  4. Select the board in Arduino IDE: pick ESP32 Dev Module and the COM port of the board (CH340).
  5. Add the servo library: in Library Manager, type ESP32Servo and press Install on the entry from Kevin Harrington.
  6. Copy the code above into the Arduino IDE.
  7. Click Upload to send the sketch to the board.
  8. Start the Serial Monitor and choose 9600 baud.
  9. Turn the knob slowly from one end to the other and watch the servo arm.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32 Dev Module
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32 Dev Module' on 'COM15')
New Line
9600 baud
Potentiometer's Value: 0 => Servo Motor's Angle: 0 Potentiometer's Value: 213 => Servo Motor's Angle: 9 Potentiometer's Value: 655 => Servo Motor's Angle: 28 Potentiometer's Value: 1022 => Servo Motor's Angle: 44 Potentiometer's Value: 1390 => Servo Motor's Angle: 61 Potentiometer's Value: 1873 => Servo Motor's Angle: 82 Potentiometer's Value: 2301 => Servo Motor's Angle: 101 Potentiometer's Value: 2748 => Servo Motor's Angle: 120 Potentiometer's Value: 3166 => Servo Motor's Angle: 139 Potentiometer's Value: 3590 => Servo Motor's Angle: 157 Potentiometer's Value: 4095 => Servo Motor's Angle: 180
Ln 11, Col 1
ESP32 Dev Module on COM15
2
  1. Pro tip: Mark the knob at the middle. The servo arm should then sit near 90°, so you can check the setup in one look.

Video Tutorial

See the ESP32 Uno build in action in the video below.

Code Explanation

Goal: understand how setup() and loop() share the work.

Part What It Does
setup() Starts Serial, sets the ADC range, and attaches the servo to GPIO13
loop() Reads, maps, writes, prints, then waits 100 ms
POT_PIN GPIO2, the A0 header
SERVO_PIN GPIO13, the D9 header

Every line in the code also has a short comment. Read them from top to bottom to follow the flow.

ESP32 Uno vs UNO R4 for This Project

Goal: know what changes when you move this project from the UNO R4 to the ESP32 Uno.

Item Arduino UNO R4 ESP32 Uno
Logic voltage 5V 3.3V
Potentiometer pin A0 A0 (GPIO2)
Servo pin D9 D9 (GPIO13)
ADC range 0–1023 0–4095
Servo library Servo.h ESP32Servo.h
Extra code line none analogSetAttenuation(ADC_11db)
Arduino IDE board Arduino UNO R4 WiFi ESP32 Dev Module

The wiring uses the same Uno header positions, so you do not move any wire. Just power the potentiometer from 3.3V and update the map() range to 4095.

Go Wireless: Control the Servo from Your Phone

Goal: move the same servo without touching the knob.

The ESP32 Uno has WiFi and Bluetooth. You can add a slider on a web page or in a phone app, and use its value as the servo angle in place of the potentiometer reading. Or send the knob angle to a page to watch it live.

Try These Next

  • Add a second servo on D10 or another PWM pin and move both with one knob.
  • Use constrain() to limit the servo to 30°–150°.
  • Average five readings to remove jitter.

Troubleshooting

Problem Possible Cause Solution
No COM port in Arduino IDE CH340 driver missing or charge-only cable Install the CH340 driver and use a USB cable that carries data
Failed to connect or Waiting for download Board is not in upload mode Hold the BOOT button while the upload starts
Board does not boot or upload with the knob connected A0 (GPIO2) is a boot strapping pin pulled the wrong way Unplug the wiper wire while uploading, then plug it back in
Error Servo.h not found or does not compile Servo.h is built for AVR boards Swap it for ESP32Servo.h and install that library
Servo hits 180 before the knob ends ADC range too small or knob powered from 5V Keep analogSetAttenuation(ADC_11db) and power the knob from 3.3V
Servo does not move Signal wire on the wrong pin or no shared ground Check the signal wire is on D9 and servo GND is joined to board GND
Board resets when the servo moves Servo draws too much current Use an external 5V supply and share GND with the board
Servo shakes while the knob is still ADC noise on the wiper Put 100 nF between A0 and GND, or average a few samples
Garbled Serial Monitor text Wrong baud rate Set the Serial Monitor to 9600

FAQ

How does a potentiometer control a servo?

The potentiometer works as a voltage divider. Its wiper voltage changes with the knob. The code reads that voltage as a number and maps it to an angle for the servo.

What range does analogRead() give on the ESP32 Uno?

It gives 0 to 4095, because the ADC is 12-bit. The UNO R4 sketch uses 0 to 1023 by default, so the map() call here uses 4095 as the top value.

Which supply voltage should the knob use?

Use 3.3V. ESP32 Uno pins are not 5V tolerant, so a knob on 5V could send up to 5V into A0 and damage it.

Can the ESP32 Uno 5V pin power the servo?

A small servo like the SG90 usually works on USB power. Big servos pull more current than USB can give, and the board may restart. Use an external 5V supply and join its GND to the board GND.

Does the standard Servo library work here?

Not on this board. Add the ESP32Servo library (author Kevin Harrington) and put #include at the top. After that, attach(), write() and read() behave as you know them.

What is analogSetAttenuation(ADC_11db) for in this sketch?

It sets the ESP32 Uno ADC input range to about 0–3.3V, so the full knob signal maps to 0–4095. With a smaller range, readings saturate early. The UNO R4 does not need this line, it is ESP32-only. Keep the knob output at 3.3V or less.

Is A0 safe to use as an analog input?

A0 is GPIO2, an ADC2 pin and a boot strapping pin. It works fine here because this sketch does not use WiFi. If you add WiFi, analogRead() on ADC2 stops working, so move the knob to A2 (GPIO35) and change POT_PIN in the code.

Can I use the UNO shields or the same wiring as the UNO R4?

The Uno header positions are the same, so the wiring stays. Check the 3.3V logic and the GPIO numbers in the pin table, because the code uses GPIO numbers and not A0 or D9.

Can I show the knob angle on a web page?

Yes. The ESP32 Uno has WiFi and Bluetooth, so you can send the angle to a web page or phone app. See the Go Wireless section for ready tutorials.

What if my project needs more pins than the Uno headers give?

The ESP32 Uno has a few extra holes near the power header: GPIO32 and GPIO33 (I/O, PWM, analog on ADC1, so they also work while WiFi is on) and GPIO15 (I/O, PWM, analog on ADC2). Add pin headers by soldering, then use the plain GPIO number in your sketch. For this project, a second potentiometer fits GPIO32 or GPIO33, and a second servo fits GPIO33. Two warnings: (1) GPIO15 and GPIO0 (the IO0 pin at the unused Uno NC position) are boot strapping pins, and a wrong connection can stop the board from booting or uploading code, so use GPIO32 and GPIO33 first; (2) never use the six holes under the digital header (SD0–SD3, CMD, CLK = GPIO6–GPIO11), because they are wired to the flash chip and using them crashes the board.

※ OUR MESSAGES

  • As freelancers, We are AVAILABLE for HIRE. See how to outsource your project to us
  • Please feel free to share the link of this tutorial. However, Please do not use our content on any other websites. We invested a lot of effort and time to create the content, please respect our work!