arduino beginner 15 min

Arduino: read a potentiometer and print the value

Wire a 10k potentiometer to an Arduino analog pin and read its position with analogRead. The second project after blink.

Code available for: Arduino CESP32 ArduinoMicroPythonPython
Published Aug 1, 2026

After blink, this is the project that teaches you how the Arduino reads the real world. A potentiometer is a knob that varies its resistance as you turn it. Wire it to an analog pin and the Arduino reports the position as a number from 0 to 1023.

This is the foundation for “dim an LED with a knob,” “control a motor speed with a knob,” and “use a sensor that outputs an analog voltage.”

What you need

  • Arduino (Uno, Nano, etc.)
  • 10k ohm potentiometer (the panel-mount kind with three legs)
  • Three jumper wires

Wiring

A potentiometer has three legs:

   _______
  /       \
 |    o    |   <-- the shaft (the part you turn)
 |    |    |
 1    2    3
  • Pin 1 (left): goes to GND
  • Pin 2 (middle): goes to A0 (analog input)
  • Pin 3 (right): goes to 5V

If the readings go the wrong way when you turn the knob, swap the GND and 5V wires.

The pot I have on my desk right now has the GND and 5V on the outside pins and the wiper on the middle. That is the convention. If yours is different (e.g. a Bourns panel-mount pot), check the datasheet.

The code

Arduino (Uno, Nano, Mega)

void setup() {
  Serial.begin(9600);
}

void loop() {
  int value = analogRead(A0);
  Serial.println(value);
  delay(100);
}

Upload it. Open the Serial Monitor (Tools >> Serial Monitor or Ctrl+Shift+M). Turn the knob. You should see the value change from 0 (all the way one direction) to 1023 (all the way the other direction).

ESP32 (Arduino)

The ESP32’s analog input has a different range (0-4095 instead of 0-1023) and accepts up to 3.3V. Most potentiometers wired to 3.3V work the same way:

void setup() {
  Serial.begin(115200);
}

void loop() {
  int value = analogRead(34);   // GPIO 34 is an ADC-capable input
  Serial.println(value);
  delay(100);
}

The ESP32’s ADC has a known non-linearity, especially at the high and low ends of the range. For a “just turn the knob and read” project, this is fine. For a calibrated sensor readout, average a few samples or use a dedicated ADC chip.

MicroPython (ESP32 or Pico)

The ESP32 and Pico both have ADCs. Same wiring, different pin numbers.

from machine import ADC, Pin
import time

# ESP32: GPIO 34 (ADC1_CH6). Pico: GP26 (ADC0).
pot = ADC(Pin(34))

while True:
    raw = pot.read_u16()      # 0-65535
    print(f'Raw: {raw}')
    time.sleep(0.1)

read_u16() returns a 16-bit value (0-65535). For a “0-100%” mapping, divide by 65535 and multiply by 100.

Raspberry Pi Python

The Raspberry Pi does not have a built-in ADC. To read a potentiometer on a Pi, use an external ADC chip like the MCP3002 (10-bit, SPI) or ADS1115 (16-bit, I2C). The wiring and chip selection are covered in the Pi ADC tutorial.

What you learned

  • analogRead(pin) reads the voltage on an analog pin and returns a value from 0 (0V) to 1023 (5V on a 5V Arduino, 3.3V on a 3.3V Arduino).
  • The Arduino’s ADC (analog-to-digital converter) is 10-bit, which is why the range is 0-1023 instead of 0-255.
  • Reading takes about 100 microseconds. You can read at up to about 10 kHz if you need to.

Mapping the value to something useful

The 0-1023 range is rarely what you want. Use map() to rescale:

int raw = analogRead(A0);
int brightness = map(raw, 0, 1023, 0, 255);
analogWrite(9, brightness);

This maps the raw reading to the PWM range (0-255). Turn the knob and the LED on pin 9 fades up and down.

Smoothing noisy readings

A pot is mechanical. The wiper bounces a little, and the ADC has its own noise. If you are reading a sensor that needs to be steady (e.g. a temperature dial in a UI), average several readings:

int smoothRead(int pin) {
  int total = 0;
  for (int i = 0; i < 16; i++) {
    total += analogRead(pin);
  }
  return total / 16;
}

16 samples is a good default. More samples = smoother but slower to react. For a pot driving a UI, 16 is fine. For a fast-changing sensor signal, fewer samples.

Reading other analog sensors

Anything that outputs 0-5V works on the analog pins. Common ones:

  • Photoresistor (LDR): resistance changes with light. Wire it as a voltage divider with a 10k resistor.
  • Thermistor: resistance changes with temperature. Same voltage divider.
  • Soil moisture sensor: outputs 0-3V depending on wetness.
  • Flex sensor: resistance changes when bent.
  • Microphone breakout (e.g. MAX4466): outputs the audio waveform.

For all of these, the code is the same: analogRead(pin).

When the reading is stuck at 0 or 1023

  • 0: the pot is turned all the way to GND, or the wiper (middle pin) is disconnected.
  • 1023: the pot is turned all the way to 5V, or the wiper is shorted to 5V or GND.
  • Settles at 512: the wiper is disconnected (middle pin not connected).

Double-check the wiring. Potentiometers are easy to wire backwards.

When you need more precision

The Arduino’s 10-bit ADC is fine for most projects. If you need 12-bit or 16-bit, use an external ADC chip:

  • ADS1115: 16-bit, I2C, 4 channels, about $2.
  • MCP3002: 10-bit, SPI, 2 channels.

These are also covered in the book Arduino Sensors.

What to build next

  • A knob-controlled LED dimmer.
  • A knob-controlled servo (rotate a small motor to match the knob).
  • A “meter” display on an OLED that shows the value as a bar.

The knob-controlled servo is in the book Arduino Robotics. The OLED meter is one of the next tutorials on this site.