If you need a physical dial for an embedded project, the default choice is a 10kΩ linear taper (B10K) cermet potentiometer. Specifically, buy the Bourns 3386P-1-103LF (roughly $1.80 each). Wire the outer legs to 5V and GND, and the middle wiper pin to your microcontroller's analog input. This specific 10k value provides the ideal source impedance to charge the ATmega328P's internal sample-and-hold capacitor without drawing excessive current, while the linear taper ensures a 1:1 physical-to-digital mapping.
This guide covers the exact hardware selection, a noise-filtered code implementation, and the specific debugging steps for when your analog readings refuse to stabilize.
The Decision Path: Which Arduino Pot Taper and Resistance?
Walking into an electronics store or browsing Mouser yields hundreds of potentiometer variants. The wrong choice leads to non-linear UI behavior or excessive ADC jitter. Use this decision matrix to lock in your part number.
| Application | Required Taper | Resistance | Material | Concrete Pick (Part Number) |
|---|---|---|---|---|
| UI Dials, Motor Speed, LED Dimming | Linear (B) | 10kΩ | Cermet | Bourns 3386P-1-103LF |
| Volume Control (Audio signals) | Logarithmic (A) | 10kΩ - 50kΩ | Carbon / Conductive Plastic | Alps RK09L1140A0P |
| High-Precision Calibration / Lab Gear | Linear (Multi-turn) | 1kΩ - 5kΩ | Wirewound | Bourns 3296W-1-102LF |
| Battery-powered / Low-quiescent current | Linear (B) | 100kΩ | Cermet | Bourns 3386P-1-104LF |
Parts List & Spec-Sheet Pin Mapping
This build targets the Arduino Nano v3 (ATmega328P, 5V logic, 10-bit ADC). The Nano is chosen over the Uno R3 for breadboard compatibility, and over the ESP32 because the ESP32's ADC is notoriously non-linear and requires a completely different software calibration approach.
Bill of Materials
- Microcontroller: Arduino Nano v3 (ATmega328P variant, e.g., Elegoo or official Arduino)
- Potentiometer: Bourns 3386P-1-103LF (10kΩ, Linear, 10% tolerance, PC pins)
- Wiring: 22 AWG solid core hookup wire (pre-cut jumper kit)
- Decoupling Capacitor: 100nF (0.1µF) ceramic capacitor (X7R dielectric)
Pin Mapping Table
| Potentiometer Pin | Physical Location | Wired To | Function |
|---|---|---|---|
| Pin 1 (CCW) | Left outer leg | Nano GND | Low reference (0V) |
| Pin 2 (Wiper) | Center leg | Nano A0 | Variable voltage output (0V - 5V) |
| Pin 3 (CW) | Right outer leg | Nano 5V | High reference (5V) |
| N/A (Capacitor) | Across A0 and GND | Nano A0 & GND | Hardware low-pass filter (cuts high-freq noise) |
Wiring Steps and the "Floating Wiper" Trap
- Seat the Nano: Press the Arduino Nano v3 into the center trench of a standard 830-point solderless breadboard. Ensure all 15 pins on each side are fully seated.
- Install the Pot: Push the Bourns 3386P into the breadboard. If the pins are splayed, gently squeeze them parallel with needle-nose pliers first.
- Wire the Reference Rails: Run a jumper from the Nano's
5Vpin to the right outer leg of the pot. Run a jumper from the Nano'sGNDpin to the left outer leg. - Wire the Wiper: Connect the center leg (wiper) directly to the Nano's
A0pin. - Add Hardware Filtering: Insert the 100nF ceramic capacitor with one leg in the same row as the A0 jumper, and the other leg in the GND rail. This creates a passive RC low-pass filter that physically blocks electromagnetic interference (EMI) before it hits the ADC.
- Verify with a DMM: Before plugging in USB, set your multimeter to continuity mode. Probe the wiper and the GND leg. Turn the knob fully counter-clockwise. You should read near 0 ohms. Turn it fully clockwise; you should read exactly 10kΩ (±10%).
Compilable Code: Moving Average ADC Filter
Even with perfect wiring, the ATmega328P's 10-bit ADC will exhibit ±2 to ±5 counts of jitter at rest due to internal thermal noise and USB power ripple. Raw analogRead() values will make downstream PID loops or PWM outputs twitch. The code below implements a ring-buffer moving average filter to smooth the output without introducing the lag of a standard delay().
// Target Board: Arduino Nano v3 (ATmega328P, 5V logic, 10-bit ADC)
// Library Dependencies: None (Standard Arduino Core)
#define POT_PIN A0
#define LED_PIN 13 // Built-in Nano LED for visual feedback
#define SAMPLE_SIZE 16 // Must be a power of 2 for fast division (optional bitwise shift)
int readings[SAMPLE_SIZE];
int readIndex = 0;
long total = 0;
int average = 0;
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
// Initialize the ring buffer to zero to prevent startup spikes
for (int i = 0; i < SAMPLE_SIZE; i++) {
readings[i] = 0;
}
// Allow ADC reference voltage to stabilize
delay(100);
analogRead(POT_PIN); // Dummy read to set internal MUX
}
void loop() {
// 1. Subtract the oldest reading from the total
total = total - readings[readIndex];
// 2. Read the new value
int currentRead = analogRead(POT_PIN);
// 3. Error Handling: Clamp out-of-bounds values
// If a 3.3V pot is accidentally wired to a 5V reference, or noise causes a negative spike
if (currentRead < 0) currentRead = 0;
if (currentRead > 1023) currentRead = 1023;
// 4. Add new reading to buffer and total
readings[readIndex] = currentRead;
total = total + readings[readIndex];
// 5. Advance the index, wrapping around using modulo
readIndex = (readIndex + 1) % SAMPLE_SIZE;
// 6. Calculate the smoothed average
average = total / SAMPLE_SIZE;
// 7. Map to 8-bit PWM for LED dimming
// Note: map() truncates integers. For high-precision, use float math.
int pwmOut = map(average, 0, 1023, 0, 255);
analogWrite(LED_PIN, pwmOut);
// 8. Telemetry
Serial.print("Raw: "); Serial.print(currentRead);
Serial.print(" | Avg: "); Serial.print(average);
Serial.print(" | PWM: "); Serial.println(pwmOut);
// Delay sets the sampling rate. 20ms = 50Hz update rate.
delay(20);
}
Debugging: "analogRead Values Jumping Randomly"
The most common failure mode when integrating an Arduino pot is erratic serial output.
Exact Symptom: The Serial Monitor outputs stable data like Raw: 512 | Avg: 512 | PWM: 128, but intermittently spikes to Raw: 1023 or Raw: 0 when the knob is completely untouched. Alternatively, the reading fluctuates by ±15 counts continuously at rest.
The First 3 Things to Check
- Check the 5V Rail Sag (Power Integrity): The Arduino Nano's ADC uses the 5V USB rail as its default voltage reference (
DEFAULT). If your USB cable is thin or the PC port is underpowered, the 5V pin might drop to 4.6V under load. Because the ADC measures the ratio of the wiper voltage to the 5V reference, a sagging reference causes massive calculation errors. Fix: Measure the Nano's 5V pin to GND with a DMM. It must read between 4.8V and 5.2V. Switch to a high-quality, short USB data cable. - Check Wiper Continuity (Mechanical Failure): If the spike is exactly 0 or 1023, the wiper has lost contact with the resistive track, causing the pin to float and hit the internal protection diodes. Fix: Unplug power. Set DMM to resistance. Probe the wiper and an outer leg. Turn the knob slowly. If the resistance jumps to "OL" (Open Loop) at any point, the pot is physically destroyed. Replace it.
- Check Source Impedance (ADC Starvation): If you ignored the decision tree and used a 100kΩ or 1MΩ pot, the internal 14pF sampling capacitor cannot fully charge during the 1.5 ADC clock cycles allocated for acquisition. This results in the reading being "pulled" toward the previous channel's voltage. Fix: Replace the pot with a 10kΩ variant, or add a 100nF capacitor directly across the wiper and GND pins to act as an external charge reservoir (Microchip ATmega328P Datasheet, Section 28.6.2).
Extending and Simplifying the Build
Once the baseline circuit is stable, you will inevitably need to adapt it for production or simpler prototypes.
How to Simplify (The Fixed Voltage Divider)
If you only need to detect two or three specific threshold states (e.g., a "mode select" switch that reads Low, Medium, or High) and don't need continuous rotation, delete the potentiometer entirely. Replace it with a fixed voltage divider using two 10kΩ resistors to feed a static 2.5V (ADC reading ~512) into the pin, and use physical pushbuttons to short the line to 5V or GND. This eliminates mechanical wear and ADC jitter entirely.
How to Extend (I2C Digital Potentiometers)
If your project requires the microcontroller to remember the knob position after a power cycle, or if you need to mount the dial more than 6 inches away from the Nano (which turns the analog wire into an EMI antenna), switch to an I2C digital potentiometer like the Microchip MCP4131-103.
By moving the ADC conversion inside the digital pot's silicon and sending the data over the I2C bus, you eliminate analog noise entirely. The tradeoff is a loss of infinite resolution (the MCP4131 offers 129 steps compared to the ATmega's 1024 steps) and the requirement to implement the Wire.h library. For UI dials, 129 steps is indistinguishable to the human hand, making the digital pot the superior choice for robust, noise-immune embedded systems.






