How Potentiometers Work and How to Use Them with Arduino

1. What Is a Potentiometer?

A potentiometer — often shortened to pot — is a variable resistor with three terminals. Inside the housing sits a resistive track (commonly carbon or cermet) with a fixed resistance between its two outer pins. A third pin, called the wiper, slides along that track when you rotate the shaft. Depending on where the wiper sits, the resistance between the wiper and each outer pin changes.

The most common form factor for hobbyist projects is the through-hole rotary pot with a 15 mm knurled shaft, a nut, and a washer — exactly like the WH148 linear potentiometer available here. These are rated by their total resistance — typically 10 kΩ or 100 kΩ — and by their taper, which we will cover in detail later.

Key physical facts to remember:

  • Three pins: left terminal, wiper (middle), right terminal.
  • Total resistance between the two outer pins stays constant.
  • Rotating the shaft moves the wiper, splitting that resistance into two parts that always sum to the total.
  • 10 kΩ pots are ideal for Arduino — low enough to give a stable reading, high enough not to waste current.

2. The Voltage Divider — How Rotation Maps to Voltage

The reason a potentiometer is so useful with a microcontroller is that it acts as a voltage divider. Connect one outer pin to 5 V and the other to GND, and the wiper will output a voltage somewhere between those two extremes — proportional to the shaft’s rotation.

The voltage divider formula is:

V_out = V_in × (R2 / (R1 + R2))

In a potentiometer, R1 is the resistance from the top of the track to the wiper, and R2 is from the wiper to the bottom. As you turn the shaft:

  • Shaft at minimum → wiper is at the GND end → R2 ≈ 0 → V_out ≈ 0 V
  • Shaft at centre → R1 = R2 → V_out = 2.5 V
  • Shaft at maximum → wiper is at the 5 V end → R2 ≈ total resistance → V_out ≈ 5 V

This is why a potentiometer must be connected to an analogue input on your Arduino — not a digital pin. Digital pins only distinguish HIGH (5 V) from LOW (0 V). You would lose all the information in between. The analogue pins convert that continuously varying voltage into a number your code can use.

3. Wiring a Potentiometer to Arduino

You will need an Arduino Uno, a solderless breadboard, a 10 kΩ potentiometer, and three jumper wires. The wiring is straightforward:

  • Left outer pin → Arduino 5V
  • Wiper (middle pin) → Arduino A0 (or any analogue pin)
  • Right outer pin → Arduino GND

Swapping the 5 V and GND connections simply reverses the direction of the reading — useful if your physical knob feels backwards. There is no wrong orientation electrically; it is just a matter of preference.

A breadboard makes this connection tool-free and reconfigurable. Insert the three pot pins spanning the centre gap of the breadboard, then run wires from the power rails to the outer pins and from the middle pin to A0 on the Arduino.

4. Reading the Potentiometer with analogRead()

The Arduino Uno’s ATmega328P contains a 10-bit Analogue-to-Digital Converter (ADC). When you call analogRead(A0), the ADC samples the voltage on that pin and converts it to an integer between 0 and 1023 — that is 2¹⁰ = 1024 possible steps. 0 represents 0 V, 1023 represents the reference voltage (5 V by default).

The simplest possible sketch:

void setup() {
  Serial.begin(9600);
}
 
void loop() {
  int rawValue = analogRead(A0);
  Serial.println(rawValue);
  delay(100);
}

Open the Serial Monitor (Ctrl + Shift + M) at 9600 baud and turn the knob. You will see numbers sweeping from 0 to 1023. That raw range is the foundation for everything else in this guide.

One important detail: analogRead() takes roughly 100 microseconds. If you are calling it in a tight loop with no delay, you will be making about 10,000 reads per second, which is more than enough for any human-controlled input.

5. Mapping the ADC Range to Useful Values

Rarely will you want a raw 0–1023 value. You almost always need to translate it into something meaningful — a percentage, an angle, a frequency, a delay time. Arduino provides the map() function for exactly this purpose.

long map(long value, long fromLow, long fromHigh, long toLow, long toHigh);

It performs a linear interpolation:

// Map pot to a percentage (0–100)
int percent = map(rawValue, 0, 1023, 0, 100);
 
// Map pot to servo angle (0–180 degrees)
int angle = map(rawValue, 0, 1023, 0, 180);
 
// Map pot to LED brightness (0–255 for PWM)
int brightness = map(rawValue, 0, 1023, 0, 255);
 
// Map pot to a delay time (100 ms to 2000 ms)
int delayTime = map(rawValue, 0, 1023, 100, 2000);

Important caveat: map() works with integers and truncates decimals. It also does not clamp the output — if your raw value somehow exceeds 1023 due to noise, the mapped value can exceed your expected range. Use constrain() to guard against this:

int angle = map(rawValue, 0, 1023, 0, 180);
angle = constrain(angle, 0, 180);

6. Smoothing Noisy Readings

Real potentiometers are mechanical components. The resistive track is not perfectly uniform, the wiper contact is not perfectly clean, and wires picking up electromagnetic interference add further jitter. If you print raw readings to the Serial Monitor while holding the knob perfectly still, you may see values flickering by ±2 or ±3 counts. In most applications that is harmless, but it can cause a servo to jitter, an LED to flicker, or a threshold check to trigger spuriously.

The most practical fix is a rolling average (also called a moving average):

const int NUM_SAMPLES = 10;
int samples[NUM_SAMPLES];
int sampleIndex = 0;
long sampleTotal = 0;
 
void setup() {
  Serial.begin(9600);
  // Initialise array with first reading
  for (int i = 0; i < NUM_SAMPLES; i++) {
    samples[i] = analogRead(A0);
    sampleTotal += samples[i];
  }
}
 
void loop() {
  // Subtract the oldest sample, replace it, add the new one
  sampleTotal -= samples[sampleIndex];
  samples[sampleIndex] = analogRead(A0);
  sampleTotal += samples[sampleIndex];
  sampleIndex = (sampleIndex + 1) % NUM_SAMPLES;
 
  int smoothed = sampleTotal / NUM_SAMPLES;
  Serial.println(smoothed);
  delay(10);
}

This circular buffer approach is efficient — it avoids re-summing the whole array every loop. Increasing NUM_SAMPLES gives smoother output but adds latency. Ten samples is a good starting point for most UI-driven inputs.

An alternative is exponential smoothing, which uses less memory and responds faster to genuine changes:

float smoothed = 0;
const float alpha = 0.1; // 0 = no change, 1 = no smoothing
 
void loop() {
  int raw = analogRead(A0);
  smoothed = alpha * raw + (1 - alpha) * smoothed;
  Serial.println((int)smoothed);
  delay(10);
}

Lower alpha values respond more slowly but reject more noise. A value of 0.05–0.15 works well for potentiometers.

7. Practical Projects

Control a Servo Motor Angle

This is the classic potentiometer project. Wire the servo signal pin to pin 9 on the Arduino (a PWM-capable pin), include the Servo library, and map the pot reading to degrees:

#include <Servo.h>
 
Servo myServo;
 
void setup() {
  myServo.attach(9);
}
 
void loop() {
  int raw = analogRead(A0);
  int angle = map(raw, 0, 1023, 0, 180);
  myServo.write(angle);
  delay(15);
}

Turn the knob and the servo horn follows in real time. This pattern is the foundation of manual robot arm control, camera pan-tilt rigs, and RC prototyping.

Dim an LED with PWM

Connect an LED (with a 220 Ω resistor in series) to pin 9. Use analogWrite() to set its brightness:

void setup() {
  pinMode(9, OUTPUT);
}
 
void loop() {
  int raw = analogRead(A0);
  int brightness = map(raw, 0, 1023, 0, 255);
  analogWrite(9, brightness);
}

analogWrite() on the Uno outputs a PWM signal at ~490 Hz on most pins (980 Hz on pins 5 and 6). The ratio of on-time to off-time — the duty cycle — controls perceived brightness.

Set a Threshold for a Sensor

Potentiometers are excellent for setting adjustable thresholds at runtime, avoiding the need to recompile code every time you want to tweak a trigger point:

void loop() {
  int threshold = analogRead(A0);         // Pot sets the threshold
  int sensorValue = analogRead(A1);       // Another sensor (LDR, temp, etc.)
 
  if (sensorValue > threshold) {
    digitalWrite(LED_BUILTIN, HIGH);      // Trigger when sensor exceeds threshold
  } else {
    digitalWrite(LED_BUILTIN, LOW);
  }
}

This technique is widely used in light-triggered alarms, motor cutoffs, and any system where the trigger point needs to be fine-tuned in the field without a laptop.

8. Linear vs Logarithmic Taper

Not all potentiometers behave the same way as you rotate them, even with identical physical resistance ratings. The taper describes how resistance changes relative to shaft rotation.

Linear Taper (Type B)

At 50% rotation, you get exactly 50% of the total resistance. The relationship between angle and resistance is a straight line. This is what the WH148 potentiometer uses, and it is correct for most electronics and Arduino projects — motor speed control, position sensing, threshold adjustment, and anything where you want equal physical movement to produce equal change in output.

Logarithmic Taper (Type A / Audio Taper)

At 50% rotation, you only get roughly 10–20% of total resistance. The remaining 80–90% is packed into the upper half of the travel. This mirrors how human hearing perceives volume: the ear responds logarithmically, so a logarithmic pot makes a volume knob feel linear to the listener. You will find audio taper pots in amplifiers, mixing desks, and audio equipment.

If you connect an audio taper pot to an Arduino and map it linearly, most of the useful range will be crammed into the final quarter-turn. For robotics, LED dimming, and general sensing, always choose a linear taper pot.

Markings vary by manufacturer, but a common convention is: B for linear, A for logarithmic. Always check the datasheet if precision matters.

Closing Thoughts

The potentiometer is one of those deceptively simple components that rewards deeper understanding. Once you grasp the voltage divider principle, the significance of the ADC range, and how map() bridges the two, you have a transferable mental model that applies to every analogue sensor you will ever use — thermistors, LDRs, joysticks, force sensors, and beyond.

Start with the basics: wire up a 10 kΩ linear pot on a breadboard, connect it to your Arduino Uno, and watch raw numbers appear in the Serial Monitor. From there, add smoothing, add mapping, and then connect it to something that moves or lights up. The physical feedback of turning a knob and seeing an immediate real-world response is what makes potentiometers one of the most satisfying entry points into the world of electronics.

Leave a Reply

Your email address will not be published. Required fields are marked *