Wiring a 10k linear potentiometer (pot) to an Arduino requires exactly three connections: outer lug 1 to 5V, outer lug 2 to GND, and the center wiper to an analog input pin (A0). This guide targets the Arduino Uno R4 Minima (featuring a 14-bit ADC) and the classic Arduino Uno R3 / Nano V3 (10-bit ADC). Below, you will find exact pin mappings, a noise-filtering code block, and a decision tree for debugging the most common analog-to-digital conversion failures.
ADC Resolution & Board Specifications
Before writing code, you must know your board's Analog-to-Digital Converter (ADC) limits. A potentiometer acts as a variable voltage divider, outputting 0V to 5V. The microcontroller translates this voltage into a discrete digital number. If you assume all Arduinos output a maximum value of 1023, your math will break on newer boards.
| Board Variant | ADC Resolution | Max Digital Value | Step Size (at 5V VREF) | Recommended Input Impedance |
|---|---|---|---|---|
| Arduino Uno R3 / Nano V3 | 10-bit | 1023 | 4.88 mV | < 10 kΩ |
| Arduino Uno R4 Minima | 14-bit (Default 10-bit) | 16383 (1023 default) | 0.305 mV (14-bit) | < 50 kΩ |
| ESP32 DevKit V1 | 12-bit (Non-linear) | 4095 | ~0.8 mV (mid-range) | < 10 kΩ (attenuation dependent) |
| Raspberry Pi Pico (RP2040) | 12-bit | 4095 | 0.805 mV (at 3.3V VREF) | < 50 kΩ |
analogRead() function defaults to 10-bit (0-1023) for backward compatibility with R3 code. To access the full 14-bit resolution (0-16383), you must explicitly call analogReadResolution(14); in your setup() loop.
Parts List & Pin Mapping
Do not use an audio-taper (logarithmic) potentiometer for microcontroller position sensing; the non-linear resistance curve will ruin your linear mapping. Always specify a linear taper (marked with a 'B' prefix in Asian naming conventions, e.g., B103, or 'A' prefix in some US conventions).
Required Materials
- Potentiometer: Bourns PTV09A-4015F-B103 (10kΩ, linear, knurled shaft) — approx. $1.50. Avoid $0.10 unbranded clones; their carbon tracks are noisy and cause ADC jitter.
- Microcontroller: Arduino Uno R4 Minima (ABX00080) or Uno R3.
- Wiring: 22 AWG solid-core hook-up wire (Red, Black, Yellow).
- Optional Filter: 100nF (0.1µF) ceramic capacitor for hardware debouncing.
Pin Mapping Table
| Potentiometer Lug | Function | Arduino Uno R4 / R3 Pin | Wire Color |
|---|---|---|---|
| Lug 1 (Left) | VCC (Supply) | 5V | Red |
| Lug 2 (Right) | GND (Ground) | GND | Black |
| Lug 3 (Center/Wiper) | Signal Out | A0 | Yellow |
Note: Swapping Lug 1 and Lug 2 will not damage the board, but it will reverse the direction of the value sweep (clockwise will decrease values instead of increasing them).
Step-by-Step Wiring Procedure
- Identify the Lugs: Hold the pot with the shaft facing you and the lugs pointing down. Left is Lug 1, Center is Wiper, Right is Lug 2.
- Connect Power: Solder or plug the red wire from the Arduino 5V pin to Lug 1.
- Connect Ground: Connect the black wire from Arduino GND to Lug 2. Ensure this ground is shared with the rest of your circuit to avoid ground loop noise.
- Connect the Wiper: Connect the yellow wire from the center lug to Arduino pin A0.
- Add Hardware Filtering (Optional but recommended): If your environment has high EMI, solder a 100nF ceramic capacitor between the Wiper (A0) and GND. This creates a low-pass RC filter that smooths out high-frequency electrical noise before it hits the ADC.
Noise-Filtered Arduino Code
Raw analogRead() values rarely sit perfectly still. Even with a high-quality Bourns pot, thermal noise and ADC quantization error cause the least significant bits to flutter. The code below targets the Arduino Uno R4 Minima (using 14-bit resolution) and implements an Exponential Moving Average (EMA) filter in software to output a rock-solid value.
// Target Board: Arduino Uno R4 Minima (14-bit ADC)
// Fallback compatible with Uno R3 (will just use 10-bit if analogReadResolution is unsupported)
#define POT_PIN A0
#define SERIAL_BAUD 115200
// EMA Filter parameters
const float ALPHA = 0.05; // Lower = smoother but slower response (0.01 to 0.2)
float filteredValue = 0.0;
void setup() {
Serial.begin(SERIAL_BAUD);
// Initialize the filtered value with a raw read to prevent startup jump
// Note: analogReadResolution(14) is specific to R4, Zero, and Due.
// If compiling for Uno R3, comment out the next line.
analogReadResolution(14);
filteredValue = analogRead(POT_PIN);
// Allow ADC to settle
delay(100);
}
void loop() {
// Read raw ADC value (0-16383 on R4, 0-1023 on R3)
int rawValue = analogRead(POT_PIN);
// Error Handling: Check for disconnected wiper (floating pin)
// A floating pin on an Uno will often wildly swing or stick to rails.
// We can't perfectly detect a floating pin via software alone without a pull-down,
// but we can catch out-of-bounds errors if using an external ADC library.
// Apply Exponential Moving Average (EMA) filter
filteredValue = (ALPHA * rawValue) + ((1.0 - ALPHA) * filteredValue);
// Map the 14-bit value (0-16383) to a percentage (0-100)
// If using Uno R3, change 16383.0 to 1023.0
float percentage = (filteredValue / 16383.0) * 100.0;
// Constrain to prevent floating-point overshoot
percentage = constrain(percentage, 0.0, 100.0);
Serial.print("Raw: ");
Serial.print(rawValue);
Serial.print(" | Filtered: ");
Serial.print(filteredValue, 1); // 1 decimal place
Serial.print(" | Percent: ");
Serial.println(percentage, 2);
delay(20); // 50Hz sample rate
}
Debugging: First 3 Things to Check When It Fails
Analog circuits fail differently than digital I2C/SPI buses. When your pot arduino build misbehaves, follow this ranked troubleshooting sequence.
1. Serial Monitor Prints Gibberish (e.g., `???` or `�`)
The Exact Error: You open the Serial Monitor and see a stream of question marks, squares, or unreadable symbols instead of numbers.
The Cause: Baud rate mismatch. The code initializes at 115200, but the Serial Monitor dropdown in the Arduino IDE is set to 9600.
The Fix: Change the Serial Monitor baud rate dropdown to 115200. Alternatively, change #define SERIAL_BAUD 115200 to 9600 in the code if you are using an older serial terminal that caps at lower speeds.
2. ADC Values Jumping Randomly Between 0 and Max
The Exact Error: The potentiometer knob is untouched, but the Serial Monitor shows values violently swinging from 0 to 16383 (or 1023), or the filteredValue drifts continuously upward/downward.
The Cause: A floating wiper pin. The ground wire (Lug 2) has backed out of the breadboard, or the USB cable's ground shield is compromised, leaving the A0 pin without a reference.
The Fix:
- Use your multimeter in continuity mode. Place one probe on Arduino GND and the other on Pot Lug 2. It must read < 1 ohm.
- Check the wiper voltage. Set the multimeter to DC Volts. Probe the center lug while turning the shaft. It should sweep smoothly from 0.00V to 5.00V. If it reads erratic millivolts, the carbon track inside the pot is scratched. Replace the pot.
3. Value Stuck at 1023 (or 16383) Regardless of Knob Position
The Exact Error: Serial monitor reads a constant maximum value. Turning the shaft does nothing.
The Cause: The wiper is shorted to VCC, or the pot is wired backwards and the wiper is disconnected, causing the internal pull-up resistors (if accidentally enabled) or stray capacitance to pull the pin high. More commonly, the jumper wire from the wiper is plugged into the 5V rail instead of A0.
The Fix: Trace the yellow wiper wire. Ensure it is exclusively connected to A0. Verify with a multimeter that the voltage on the yellow wire changes when you turn the knob. If the voltage changes but the Arduino doesn't see it, you may have blown the ADC multiplexer on the ATmega328P/R7FA4M1AB chip by previously feeding >5.5V into A0.
Extending & Simplifying the Build
Once you have a clean, filtered analog reading, you can adapt the circuit for specific applications.
How to Simplify (For Basic LED Dimming)
If you do not need serial logging or high precision, strip out the EMA filter and the 14-bit resolution commands. Use the built-in map() function to convert the analog reading directly to a PWM output for an LED:
int potVal = analogRead(A0);
int ledBrightness = map(potVal, 0, 1023, 0, 255);
analogWrite(9, ledBrightness); // PWM pin 9
How to Extend (HID Media Knob or MIDI CC)
The Arduino Uno R4 Minima and Raspberry Pi Pico feature native USB HID capabilities. You can turn your potentiometer into a volume knob for your PC.
- For Uno R4: Install the
PluggableUSBHIDlibrary. Map the filtered 0-100 percentage to the HID Consumer Control "Volume Increment/Decrement" commands. - For MIDI: Use the
FortySevenEffects MIDIlibrary. Map the 0-16383 value down to the 7-bit MIDI standard (0-127) and send it as a Control Change (CC) message over the hardware UART or USB-MIDI bridge.
For deeper reading on ADC behavior and component selection, refer to the official Arduino analogRead() reference and the Bourns PTV09A series datasheet for mechanical torque and taper specifications.






