By Imogen Tasker Fact-checked by Hugo Lindgren Published
A potentiometer at half rotation on an Arduino Uno R3 should read about 511, and the same pot on a Raspberry Pi Pico reads about 32768. The knob hasn’t changed. Only the ADC behind it has. This page lists the readings you should expect on four common boards, shows how to turn them into volts, percent or ohms, explains why they jitter, and walks through checking whether the pot itself is faulty.
Key takeaways
- Connect the wiper to an analog pin. The reading is the wiper voltage divided by the reference voltage, multiplied by the ADC’s maximum count.
- Expect 0-1023 on an Uno R3, up to 0-16383 on a UNO R4 at 14-bit, 0-4095 on an ESP32 and 0-65535 on a Pico.
- On the ESP32 and Pico, power the pot from 3.3 V only. On the ESP32, use analogReadMilliVolts() when you need real volts.
- Fix jitter in hardware first (a 10-100 nF capacitor from wiper to GND), then add a running average and hysteresis in code.
- A “10k” pot that measures 8.5k can be perfectly healthy. Bourns rates common pots at ±20%.
Fact-checked
We checked these key facts against the sources named, on November 14, 2026:
- Bourns rates the PDB18 series at ±20% and the PDA24 at ±15% (source: bourns.com)
- If USB delivers 4.85 V and not 5.00 V, the pot at 50% still reads about 511 (source: docs.arduino.cc)
- Give motors their own supply and connect only the grounds together. :::tip Maker tip Fit the 10-100 nF capacitor between the wiper and GND before you write any filter code (source: learn.adafruit.com)
- On an Arduino Forum thread, an ESP32-C3 user saw 4095 at about 2.8 V and fixed the voltage readout by switching to analogReadMilliVolts(), because plain analogRead() doesn’t use the factory calibration (source: docs.espressif.com)
Potentiometer readings at a glance
Connect the pot’s outer pins to the board’s supply and GND, and its middle pin (the wiper) to an analog input. The number you get back is the wiper’s share of the reference voltage, scaled to the ADC’s full count. That means 0-1023 on an Uno R3, up to 0-16383 on a UNO R4 at 14-bit, 0-4095 on an ESP32 and 0-65535 on a Pico.
The one formula you need
The ADC compares the wiper voltage with a reference voltage and returns a whole number:
reading = (Vwiper ÷ Vref) × (2^bits − 1)
Work it backwards to get volts: Vwiper = reading × Vref ÷ (2^bits − 1).
Here’s a worked example. On an Uno R3 with Vref = 5 V and 10 bits, a reading of 768 gives 768 × 5 ÷ 1023 ≈ 3.75 V. That puts the wiper about 75% of the way toward the 5 V end. (The ATmega328P datasheet uses 1024 in its formula, not 1023. The difference is under 0.1% and doesn’t matter for a knob.)
There’s a useful consequence here. The pot and the ADC reference share the same 5 V rail, so the raw count is ratiometric. If USB delivers 4.85 V and not 5.00 V, the pot at 50% still reads about 511. Only the conversion to volts changes. So measure your real 5 V pin with a multimeter only when you need absolute volts. You don’t need to for knob position.
Expected readings table by board
Assume a linear (B) pot with no noise. Real boards land within a few counts of these values.
| Wiper position | Volts at 5 V | Uno R3 (10-bit) | UNO R4 (14-bit) | Volts at 3.3 V | ESP32 12-bit (ideal) | Pico read_u16 |
|---|---|---|---|---|---|---|
| 0% | 0.00 V | 0 | 0 | 0.00 V | 0 | 0 (small offset typical) |
| 25% | 1.25 V | ~256 | ~4096 | 0.83 V | ~1024 | ~16384 |
| 50% | 2.50 V | ~511 | ~8191 | 1.65 V | ~2048 | ~32768 |
| 75% | 3.75 V | ~767 | ~12287 | 2.48 V | ~3071 | ~49151 |
| 100% | 5.00 V | 1023 | 16383 | 3.30 V | 4095 (often reached early) | 65535 |
The ESP32 column is labelled “ideal” on purpose. Its raw ADC is nonlinear, so real raw counts bend away from this line, especially near the top. The ESP32 section below covers the fix.
Board ADC cheat sheet
| Board | Max reading | Default resolution | Reference voltage | Gotcha |
|---|---|---|---|---|
| Arduino Uno R3 (ATmega328P) | 1023 | 10-bit | 5 V | Best with source impedance of 10 kΩ or less |
| Arduino UNO R4 Minima / UNO R4 WiFi | 16383 at 14-bit | 10-bit | 5 V | Asking for 16-bit pads 2 zero bits |
| ESP32 / ESP32-C3 / ESP32-S3 | 4095 | 12-bit | ~3.3 V range set by attenuation | Raw analogRead() is uncalibrated and nonlinear |
| Raspberry Pi Pico (RP2040) | 65535 | 12-bit ADC scaled to 16-bit | 3.3 V | Inputs must stay between 0 and 3.3 V |
| Raspberry Pi 4 / Pi 5 | None | No ADC | n/a | Needs an external ADC chip |
How a pot turns rotation into a number
A potentiometer is a resistive track with a sliding contact. Wired as a voltage divider, it gives out a voltage that moves in step with the knob. The resistance between the two outer pins never changes. Turning the knob only moves the wiper along the track, which splits that fixed resistance into two parts.
Take a 10k pot with its outer pins on 5 V and GND. At 25% rotation the wiper sits 2.5 kΩ from the GND end and 7.5 kΩ from the 5 V end. The divider output is 5 V × 2.5k ÷ 10k = 1.25 V. That’s the 25% row of the table above, and it reads about 256 on an Uno.
Voltage divider vs variable resistor wiring
You can use the same part in two ways, and each answers a different question.
- Divider wiring (three pins): outer pins to supply and GND, wiper to the analog pin. You read a voltage that tracks position. Use this for knobs, joysticks and setpoints.
- Variable resistor wiring (two pins): one outer pin plus the wiper. The pot becomes a variable resistance, sometimes called a rheostat. A microcontroller can’t read resistance directly, so you add a fixed resistor to build a divider, or you measure it with a multimeter.
To estimate ohms from a divider reading, use R(wiper to GND end) ≈ R(total) × reading ÷ 1023 on an Uno. A reading of 300 on a pot that measures 9.6k end to end means about 2.8 kΩ between the wiper and the GND end.
Which pin is which
On most rotary pots, the middle pin is the wiper. With the shaft facing you and the pins pointing down, the left and right pins are the two ends of the track. They’re interchangeable electrically. Swapping them only reverses direction, so if clockwise makes the number go down, swap the 5 V and GND wires.
Don’t confuse a pot with a rotary encoder. A pot has end stops and outputs an analog voltage. An encoder spins forever and outputs digital pulses that you count on digital pins. If your “pot” has five pins and turns endlessly, it’s an encoder.
Reading a potentiometer on Arduino Uno R3 and UNO R4
Wire the wiper to A0, call analogRead(A0), and print the result. On an Uno R3 the reading runs from 0 to 1023 against 5 V. On a UNO R4 it does the same by default, and you can raise it to 14 bits with analogReadResolution(14).
| From (pot) | To (Arduino) | Purpose |
|---|---|---|
| Left outer pin | 5V header pin | Top of the divider |
| Middle pin (wiper) | A0 | Analog signal |
| Right outer pin | GND header pin | Bottom of the divider |
Uno R3: 0-1023 at 5 V
This sketch compiles for the Uno R3 and the UNO R4. It prints labelled values that the Arduino IDE Serial Plotter draws as separate lines.
const int POT_PIN = A0; // wiper
const int LED_PIN = 9; // PWM-capable pin on Uno R3 and UNO R4
void setup() {
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
}
void loop() {
int raw = analogRead(POT_PIN); // 0-1023
float volts = raw * 5.0 / 1023.0; // float math, not integer
int percent = map(raw, 0, 1023, 0, 100); // 0-100 %
int pwm = map(raw, 0, 1023, 0, 255); // 0-255 for analogWrite
analogWrite(LED_PIN, pwm);
Serial.print("raw:");
Serial.print(raw);
Serial.print(",percent:");
Serial.print(percent);
Serial.print(",volts:");
Serial.println(volts, 2);
delay(50);
}
Maker tip
Open Tools > Serial Plotter in place of the Serial Monitor. Jitter shows up as a fuzzy line, and a log-taper pot shows up as a curve where you expected a straight ramp.
UNO R4: 10, 12 or 14 bits
The Arduino UNO R4 Minima and UNO R4 WiFi default to 10-bit, so old sketches behave the same. Arduino’s ADC resolution tutorial lists 10, 12 and 14 bits as supported. Add one line to setup() and change the divisor:
void setup() {
Serial.begin(9600);
analogReadResolution(14); // 0-16383 on UNO R4
}
void loop() {
int raw = analogRead(A0);
float volts = raw * 5.0 / 16383.0;
Serial.print("raw:");
Serial.print(raw);
Serial.print(",volts:");
Serial.println(volts, 3);
delay(50);
}
Fourteen bits gives you finer steps (about 0.3 mV each at 5 V), not better accuracy. A hand-turned knob doesn’t need 16,384 positions. The extra bits mostly show noise in more detail.
Did you know?
According to Arduino’s analogReadResolution() reference, calling analogReadResolution(16) on a UNO R4 returns an approximated 16-bit number. The first 14 bits are the real reading and the last 2 bits are padded with zeros, so you gain no precision.
Readers on the Arduino Forum have reported a UNO R4 WiFi reading a different value from an Uno R3 on the same circuit at 10, 12 and 14 bits. That’s an anecdotal community report, not a documented defect. The two boards use different chips and different analog front ends, so small offsets between them are expected. If your project needs exact volts, calibrate each board against a multimeter. Don’t assume they match.
Converting to volts, percent and PWM
Most conversion bugs come from integer math. Arduino evaluates analogRead(A0) * 5 / 1023 with integer operations, so the fractional part is thrown away: at the default 10-bit resolution the result can only be 0 through 5 and never 2.47. Writing 5.0 and 1023.0 forces float math.
Maker tip
Do volt math in float: analogRead(A0) * 5.0 / 1023.0. Integer division throws away everything after the decimal point.
Two more map() traps catch people. map() uses integer math and truncates, so map(1022, 0, 1023, 0, 100) returns 99, not 100. If the top of the range matters, map from 0-1024 or clamp the result. map() also doesn’t constrain its output. If you map from a calibrated range such as 20-1000 and the pot reads 5, you get a negative number unless you wrap the result in constrain().
Reading a potentiometer on ESP32
On an ESP32, power the pot from 3.3 V, put the wiper on an ADC1 pin, and read it with analogReadMilliVolts() whenever you need real voltage. The plain analogRead() value is raw and uncalibrated, so it isn’t a reliable measure of volts.
Power check
ESP32 and Pico analog pins are 3.3 V inputs. Connecting the pot’s top pin to 5 V can put 5 V on the pin at full rotation and damage it.
| From (pot) | To (ESP32 DevKit) | Purpose |
|---|---|---|
| Left outer pin | 3V3 pin | Top of the divider |
| Middle pin (wiper) | GPIO34 (ADC1_CH6) | Analog signal |
| Right outer pin | GND pin | Bottom of the divider |
Pick an ADC1 pin like GPIO34 on the classic ESP32. ADC2 pins clash with Wi-Fi on that chip, so readings on them fail while Wi-Fi is running.
Raw counts vs calibrated millivolts
The arduino-esp32 core documentation says analogRead() returns a raw value with no calibration applied, while analogReadMilliVolts() returns a calibrated result in millivolts. The default attenuation is ADC_11db, which gives the widest input range.
const int POT_PIN = 34; // ADC1_CH6 on classic ESP32 DevKit
void setup() {
Serial.begin(115200);
analogReadResolution(12); // 0-4095
analogSetPinAttenuation(POT_PIN, ADC_11db); // widest range (default)
}
void loop() {
int raw = analogRead(POT_PIN);
uint32_t mv = analogReadMilliVolts(POT_PIN);
Serial.printf("raw:%d,mV:%lu\n", raw, (unsigned long)mv);
delay(50);
}
Plot both lines and the difference is obvious. The millivolt line tracks the knob more evenly, while the raw line bends. The Waveshare ESP-IDF ADC tutorial explains why. Simple line-fitting calibration can’t remove the nonlinear error at the extremes of the range. The curve-fitting scheme on the ESP32-S3, ESP32-C3 and newer chips corrects the bend in the mid-to-high range better.
Fixing “stuck at 4095” and dead zones
If an ESP32 hits 4095 before the knob reaches its end stop, the top of the pot’s range is above what the ADC can measure at that attenuation. On an Arduino Forum thread, an ESP32-C3 user saw 4095 at about 2.8 V and fixed the voltage readout by switching to analogReadMilliVolts(), because plain analogRead() doesn’t use the factory calibration. That’s a single community report, but it fits Espressif’s own documentation.
Work through the fixes in this order:
- Confirm the attenuation is ADC_11db (the widest setting).
- Switch to analogReadMilliVolts() and map position from millivolts, not raw counts.
- Turn the pot slowly end to end and record the real minimum and maximum. Then map() from those values, not from 0-4095.
- If you need every degree of rotation, add a fixed resistor between 3V3 and the pot’s top pin. That keeps the full-rotation voltage inside the ADC’s linear range.
“Same pot reads steady on Uno but wanders on ESP32. Why?” The ESP32’s ADC is noisier, its 3.3 V rail carries Wi-Fi current spikes, and it has four times as many counts per volt as the Uno’s 10-bit scale. The same millivolt of noise therefore shows up as more counts. The filters below fix it.
Reading a potentiometer on Raspberry Pi Pico (and why a regular Pi needs an ADC)
The Raspberry Pi Pico’s RP2040 has analog inputs on GP26, GP27 and GP28. In MicroPython, ADC.read_u16() returns 0-65535. To convert that to volts, multiply by the board’s actual ADC input range (about 3.3 V on a standard Pico, ideally checked against a multimeter) and divide by 65535. A Raspberry Pi 4 or Pi 5 has no analog inputs at all.
MicroPython example
| From (pot) | To (Pico) | Purpose |
|---|---|---|
| Left outer pin | 3V3(OUT), physical pin 36 | Top of the divider |
| Middle pin (wiper) | GP26 / ADC0, physical pin 31 | Analog signal |
| Right outer pin | AGND, physical pin 33 (or any GND) | Bottom of the divider |
from machine import ADC
import time pot = ADC(26) # GP26 = ADC0 while True:
raw = pot.read_u16() # 0-65535
volts = raw * 3.3 / 65535
percent = raw * 100 // 65535
print(raw, round(volts, 2), percent)
time.sleep(0.05)
The RP2040’s converter is 12-bit. MicroPython scales its result up to the 16-bit range, so consecutive readings move in steps of about 16, not 1. Expect a small non-zero value at the GND end. That’s offset, not a fault.
Raspberry Pi 4/5: add an external ADC
The 40-pin header on a Raspberry Pi 4 or Pi 5 is digital only. To read a pot, add an ADC chip, which is an integrated circuit that does the conversion and sends the result over a bus. The common choices are the MCP3008 (10-bit, eight channels, SPI) and the ADS1115 (16-bit, four channels, I2C). Power the pot and the chip from 3.3 V so nothing above 3.3 V reaches the Pi’s GPIO.
Why your potentiometer readings jump around (and how to fix it)
A reading that wobbles by 1-2 counts while nobody touches the knob is normal ADC noise. Jumps of tens or hundreds of counts point to a wiring, power or pot problem. Fix the hardware first, then filter in software.
| Symptom | Likely cause | Fix |
|---|---|---|
| ±1-3 counts flicker, knob untouched | Normal ADC noise | Running average plus hysteresis |
| Large random jumps while still | Loose breadboard contact or floating wiper | Reseat the pot, use short wires, check the wiper wire |
| Values swing when a servo moves | SG-90 servo current dragging the 5 V rail down | Separate servo supply, shared ground, capacitor on the wiper |
| Noise rises when an LCD backlight or Wi-Fi is on | Load or RF noise on the supply | Decouple, shorten leads, use ADC1 on the ESP32 |
| Reading drops to 0 or spikes mid-turn | Worn or dirty track | Test the pot (see below), clean or replace |
| Most of the change happens in one end of the rotation | Audio (A) taper pot | Use a B (linear) pot |
| ESP32 sticks at 4095 early | Range limit and nonlinearity | analogReadMilliVolts(), calibrate the endpoints |
| Reading sits mid-scale whatever you do | Analog pin not connected to the wiper | Check the pin number in code and on the board |
Hardware fixes
“Is it a loose contact on the breadboard causing the small fluctuations?” Sometimes. The legs on cheap pots are short and thin, and they rock in breadboard sockets. Press the pot down and watch the plotter. If the noise changes, the contact is the cause. Solder header pins to the pot, or use a pot made for breadboards.
- Add a 10-100 nF ceramic capacitor from the wiper to GND, mounted at the board. An Arduino Forum user cut the fluctuation by adding a 10 nF capacitor there, then added a hysteresis threshold so the leftover jitter stopped triggering actions.
- Keep the pot wires short and twist the three together if they run more than about 30 cm.
- Give everything one common ground. A pot grounded at a different point from the board picks up the voltage drop along the ground wire.
- Power heavy loads separately. An SG-90 servo, a solenoid valve or an LCD backlight pulls current pulses that sag the shared rail. Give motors their own supply and connect only the grounds together.
Maker tip
Fit the 10-100 nF capacitor between the wiper and GND before you write any filter code. It often removes most of the flicker on its own.
Running average done right
A running average keeps the last N readings in a circular buffer and updates the total one sample at a time. It doesn’t refill the whole array on every call. This version compiles for AVR, UNO R4 and ESP32 boards:
const int POT_PIN = A0; // use 34 on a classic ESP32
const int NUM_SAMPLES = 16;
int samples[NUM_SAMPLES];
int sampleIndex = 0;
long total = 0;
int readSmoothed() {
total -= samples[sampleIndex]; // drop the oldest
samples[sampleIndex] = analogRead(POT_PIN); // take the newest
total += samples[sampleIndex];
sampleIndex = (sampleIndex + 1) % NUM_SAMPLES;
return total / NUM_SAMPLES;
}
void setup() {
Serial.begin(9600);
int first = analogRead(POT_PIN); // pre-fill so it starts correct
for (int i = 0; i < NUM_SAMPLES; i++) {
samples[i] = first;
total += first;
}
}
void loop() {
Serial.print("smoothed:");
Serial.println(readSmoothed());
delay(10);
}
Sixteen samples at 10 ms means the output lags the knob by roughly 0.16 s. If that feels sluggish, use fewer samples. An exponential filter uses less memory and needs only one variable:
float smoothed = 0;
const float ALPHA = 0.1; // 0.05 = smoother, 0.3 = snappier
void setup() {
Serial.begin(9600);
smoothed = analogRead(A0);
}
void loop() {
int raw = analogRead(A0);
smoothed += ALPHA * (raw - smoothed);
Serial.println((int)smoothed);
delay(10);
}
Hysteresis so values stop flickering
Averaging shrinks noise, but a value that sits on a boundary still toggles between two numbers, say 511 and 512. A deadband only accepts a new value when it moves more than a set number of counts. The end snaps let the value still reach the true 0 and maximum.
const int POT_PIN = A0;
const int MAX_READING = 1023; // 4095 on ESP32, 16383 on UNO R4 at 14-bit
const int DEADBAND = 4; // counts of change to ignore
int stableValue = -1;
int readStable() {
int raw = analogRead(POT_PIN);
if (raw <= DEADBAND) {
stableValue = 0; // snap to the bottom end
} else if (raw >= MAX_READING - DEADBAND) {
stableValue = MAX_READING; // snap to the top end
} else if (stableValue < 0 || abs(raw - stableValue) > DEADBAND) {
stableValue = raw; // real movement
}
return stableValue;
}
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.print("stable:");
Serial.println(readStable());
delay(20);
}
The deadband costs you resolution. A 4-count deadband on a 1023 scale still leaves more than 200 usable steps, which is plenty for a volume or speed knob. For a precision setpoint, use a running average with a smaller deadband.
Why pot value matters: 10k vs 100k
Pick 10 kΩ for the Uno R3 and you’re inside the ADC’s design limit. The ATmega328P datasheet says its ADC is optimised for sources with an output impedance of about 10 kΩ or less. Above that, the internal sample capacitor charges more slowly and the result is less accurate.
The source impedance of a pot peaks at mid rotation, at a quarter of its total value. A 10k pot never exceeds 2.5 kΩ, which is comfortably inside the limit. A 100k pot reaches 25 kΩ, so its readings get less accurate, especially when you switch between analog channels. Going lower isn’t free either. A 1k pot across 5 V draws 5 mA all the time, while a 10k draws 0.5 mA.
Did you know?
The Microchip ATmega328P datasheet says the ADC is optimised for sources of about 10 kΩ or less. That limit, more than habit, is why kits ship with 10k pots.
Reading the markings: A vs B, 103, B10K and tolerance
The letter on a pot gives the taper, and the number gives the end-to-end resistance. On Bourns parts, A means audio (logarithmic) taper and B means linear taper. So B10K is a 10 kΩ linear pot, the right choice for microcontroller knobs.
What A and B mean
The Bourns PTA slide pot datasheet defines A as audio taper and B as linear taper in its ordering code, and most current hobby pots follow the same convention. Older or regional parts haven’t always used this lettering, so check the datasheet when a part’s behaviour doesn’t match its label.
You can spot a log pot from its readings. On a linear pot, the halfway position reads about half-scale (around 511 on an Uno). On an A pot, it reads well under half, and the plotter line stays low for most of the turn before climbing steeply near the end. If your potentiometer readings bunch up at one end, check for an A on the body before you blame the code.
What the numbers mean
| Marking | Meaning | Example |
|---|---|---|
| B10K | Linear taper, 10 kΩ | Standard Arduino knob |
| A10K | Audio/log taper, 10 kΩ | Volume control |
| 102 | 10 × 10² = 1 kΩ | Trimmer |
| 103 | 10 × 10³ = 10 kΩ | Bourns 3309W trimmer code |
| 503 | 50 × 10³ = 50 kΩ | Trimmer |
| 104 | 10 × 10⁴ = 100 kΩ | Higher-impedance pot |
In the three-digit code, the first two digits are the value and the third digit is the number of zeros. So 103 = 10,000 Ω. Bourns lists the 10,000 Ω version of its 3309W trimmer as resistance code 103.
“My pot is labelled p103 and 520B. What do the other labels mean?” The 103 is the value: 10 kΩ. Markings that don’t fit the three-digit pattern are generally the maker’s own series, batch or date codes, so they need the datasheet. The Bourns 3303W datasheet shows that even the value can appear as a short body marking code (such as 14) and not the 103 printed in the ordering code.
How many ohms is a 10k pot really
A 10k pot measures 10,000 Ω between its outer pins, give or take its tolerance. Bourns rates the PDB18 series at ±20% and the PDA24 at ±15%. A “B10K” that reads 9.2 kΩ on your meter is well inside spec. So is one at 8.5 kΩ or 11.6 kΩ. Divider readings don’t depend on the exact total, only on the ratio, which is another reason the wiring works so well.
How to test if a potentiometer is bad
A healthy pot has a steady end-to-end resistance near its rating, and the wiper resistance changes smoothly as you turn it. An open reading, a near-zero reading, or a wiper value that skips or drops to zero mid-turn means the pot is faulty.
Multimeter test
Build steps
- Disconnect the pot from the circuit and set the multimeter to resistance (20 kΩ range for a 10k).
- Measure between the two outer pins. Expect the rating ±20%.
- Treat no reading as an open track or broken terminal, and near zero as a short.
- Move one probe to the wiper and turn the shaft slowly from stop to stop.
- Watch for a smooth rise or fall with no skips, jumps or drops to zero.
- Repeat from the wiper to the other outer pin. The two values should add up to the end-to-end reading.
Spectra Symbol’s test guide adds a third outcome: an end-to-end reading far above the rating points to a damaged track. If you’re new to meter work, the same probe technique shows up in testing continuity with a multimeter.
Arduino sweep test
Your board can act as a logging meter. This sketch records the minimum, maximum and biggest single jump during a 10-second sweep:
const int POT_PIN = A0;
const unsigned long SWEEP_MS = 10000UL;
int minVal = 32767;
int maxVal = -1;
int lastVal = -1;
int biggestJump = 0;
unsigned long startMs;
bool done = false;
void setup() {
Serial.begin(9600);
Serial.println("Turn the knob slowly from stop to stop for 10 seconds");
startMs = millis();
}
void loop() {
if (done) return;
if (millis() - startMs < SWEEP_MS) {
int v = analogRead(POT_PIN);
if (v < minVal) minVal = v;
if (v > maxVal) maxVal = v;
if (lastVal >= 0 && abs(v - lastVal) > biggestJump) {
biggestJump = abs(v - lastVal);
}
lastVal = v;
delay(5);
} else {
Serial.print("min: "); Serial.println(minVal);
Serial.print("max: "); Serial.println(maxVal);
Serial.print("biggest jump: "); Serial.println(biggestJump);
done = true;
}
}
On an Uno, a good pot swept slowly shows a minimum near 0, a maximum near 1023 and a biggest jump of only a few counts. A jump of 50 or more on a slow sweep, or a dip to 0 partway through, matches the worn or dirty wiper that a multimeter sweep would catch. If max never gets near 1023 on a linear pot, check the 5 V connection to the top pin.
Clean or replace?
A scratchy pot, one that crackles or jumps only at certain spots, often has dust or oxidation on the track. Contact cleaner sprayed into the opening and worked in by turning the shaft fully several times can restore it. Replace the pot if it reads open, if it’s shorted, or if the jumps come back after cleaning. A new 10k linear pot costs less than the time spent nursing a worn one. If you need a part that lasts through endless turning, a rotary encoder has no resistive track to wear out.
FAQ
What do the A and B stand for on potentiometers?
On Bourns and most current parts, A means audio (logarithmic) taper and B means linear taper. Use B for microcontroller knobs so equal rotation gives equal change in the reading.
How to test if a potentiometer is bad?
Measure the outer pins with a multimeter, expecting the rating ±20%. Then sweep the wiper and watch for a smooth change. Open circuits, shorts, jumps or drops to zero mean the pot is faulty.
How many ohms is a 10k potentiometer?
It’s 10,000 Ω between the outer pins, within tolerance. Common Bourns pots are ±20%, so anywhere from 8 kΩ to 12 kΩ is normal.
What do the numbers mean on a potentiometer?
A three-digit code gives the value: two digits followed by a multiplier, so 103 is 10 kΩ and 104 is 100 kΩ. A label like B10K spells out the taper and value directly.
Why does my potentiometer never read exactly 0 or 1023?
The wiper never quite touches the end terminals, and every ADC has small offset errors. Readings of 2 or 1020 at the stops are normal. Use the end snaps in the hysteresis code if your project needs exact endpoints.
How do I convert potentiometer readings to voltage?
Multiply the reading by the reference voltage and divide by the maximum count for the API and resolution you’re using, in float: reading × 5.0 ÷ 1023.0 on an Uno at its default 10-bit setting. On a Pico, MicroPython’s read_u16() scales readings to 0-65535 while the Pico SDK returns 12-bit values (0-4095), so use the matching divisor and the board’s actual reference voltage. On an ESP32, call analogReadMilliVolts().
Why are my potentiometer readings fluctuating when I’m not touching it?
Some ADC noise of 1-3 counts is normal. Larger swings usually come from loose breadboard contacts, long wires, a missing common ground, or loads like servos and backlights on the same rail. Add a 10-100 nF capacitor from wiper to GND, then a running average and a deadband.
Why does my ESP32 read 4095 before the pot is fully turned?
The raw ESP32 ADC saturates below 3.3 V, and its response bends near the top of the range. Check that attenuation is ADC_11db, switch to analogReadMilliVolts(), and map from the real minimum and maximum you measured.
Can I connect a potentiometer to a Raspberry Pi?
Yes, a Pico can read it directly on GP26-GP28. A Raspberry Pi 4 or Pi 5 has no analog inputs and needs an external ADC such as an MCP3008 or ADS1115, with everything powered from 3.3 V.
What potentiometer value should I use with Arduino?
Use 10 kΩ linear (B10K). It stays within the ATmega328P’s guideline of 10 kΩ or less for source impedance and draws only 0.5 mA at 5 V.
Once your readings are stable, the next build is a calibrated knob: record the real min and max with the sweep test, map() between them, and pass the result to a servo, an LED or a menu on a display. A knob that reads 0 to 100% cleanly is a better base for the rest of the project than any extra bits of resolution.
Notes on this article
- Fact-checked by Hugo Lindgren against the sources listed below before publication.
- Published
Fact-checking
- Researched from 8 sources, listed below.
- Every claim is checked by Hugo Lindgren; anything we cannot confirm is corrected, labelled or removed.
Sources (8)
- Arduino UNO R4 WiFi ADC Resolution (docs.arduino.cc)
- analogReadResolution() – Arduino Language Reference (docs.arduino.cc)
- Arduino UNO R4 Minima Cheat Sheet (docs.arduino.cc)
- Incorrect ADC readings on Arduino Uno R4 WiFi compared to Uno R3 (forum.arduino.cc)
- arduino-esp32 ADC API (docs.espressif.com)
- ESP32-C3 ADC issue – reading 4095 at 2.8V (forum.arduino.cc)
- Waveshare ESP-IDF Tutorial: ADC Analog Input (docs.waveshare.com)
- Raspberry Pi Pico ADC Tutorial (microcontrollerslab.com)









