Embedded Systems

ESP32 Beginner Course #5: Analog Input with a Potentiometer and ADC

Learn how ESP32 analog input works by reading a potentiometer with the ADC, converting raw values to voltage, and using the knob to control LED brightness.

ESP32ADCAnalog InputPotentiometerPWM

Introduction

So far in this ESP32 series, we have mainly worked with digital signals. A digital pin is usually treated as either HIGH or LOW. That is perfect for LEDs, buttons, and simple on/off control, but many real-world signals are not only on or off.

Temperature, light level, battery voltage, joystick position, sound level, and knob position can all vary gradually. To read those changing signals, the ESP32 uses an ADC, or Analog to Digital Converter.

In this lesson, we will read a potentiometer with an ESP32 analog input pin. Then we will convert the raw ADC reading into an approximate voltage and use the knob position to control LED brightness.

What you will learn

By the end of this project, you should understand:

  • What analog input means
  • How analog signals differ from digital signals
  • What an ADC does
  • How a potentiometer works as a voltage divider
  • How to use analogRead()
  • How to estimate voltage from an ADC value
  • How to map analog input to PWM output

Digital vs analog signals

A digital signal has two main states:

  • LOW: close to 0V
  • HIGH: close to 3.3V on the ESP32

An analog signal can be any voltage between those limits. For example, the signal might be 0.4V, 1.2V, 2.6V, or 3.1V.

The ESP32 is still a digital computer internally. It cannot directly store “smooth voltage” as a continuous value. Instead, it measures the voltage and converts it into a number.

That conversion is the job of the ADC.

For a visual model of this conversion, open the interactive lab: ADC and Potentiometer.

What is an ADC?

ADC stands for Analog to Digital Converter.

It converts an input voltage into a digital number that your program can use. On many ESP32 Arduino setups, analogRead() returns a value from 0 to 4095.

For beginner projects, you can think of the range like this:

0V      -> 0
1.65V   -> about 2048
3.3V    -> about 4095

The exact result can vary because ESP32 ADC readings are not perfectly linear, but this model is good enough for learning and for many simple projects.

How a potentiometer works

A potentiometer is a variable resistor with three pins.

When one outer pin is connected to 3.3V and the other outer pin is connected to GND, the middle pin produces a voltage between 0V and 3.3V. Turning the knob changes that middle voltage.

This wiring creates a voltage divider. The ESP32 reads the changing voltage on the middle pin.

Hardware required

  • ESP32 DevKit
  • 10k potentiometer
  • LED
  • 220 ohm resistor
  • Breadboard
  • Jumper wires
  • USB cable

Wiring

Connect the potentiometer like this:

Potentiometer left pin   -> 3.3V
Potentiometer middle pin -> GPIO34
Potentiometer right pin  -> GND

Connect the LED like this:

GPIO2
  |
 LED
  |
220 ohm
  |
 GND

GPIO34 is input-only, which makes it a good beginner choice for analog input.

Read the potentiometer

Start with the simplest possible test. Read the ADC value and print it in Serial Monitor.

const int potPin = 34;

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

void loop()
{
    int adcValue = analogRead(potPin);

    Serial.print("ADC value: ");
    Serial.println(adcValue);

    delay(200);
}

Upload the code, open Serial Monitor at 115200 baud, and rotate the potentiometer.

You should see the number move between low and high values. It may not reach exactly 0 or exactly 4095, and that is normal.

Convert ADC value to voltage

To estimate the voltage, use this formula:

Voltage = ADC value x 3.3 / 4095

In code:

float voltage = adcValue * (3.3 / 4095.0);

Now print both values:

const int potPin = 34;

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

void loop()
{
    int adcValue = analogRead(potPin);
    float voltage = adcValue * (3.3 / 4095.0);

    Serial.print("ADC: ");
    Serial.print(adcValue);
    Serial.print("  Voltage: ");
    Serial.print(voltage);
    Serial.println(" V");

    delay(200);
}

This makes the reading easier to understand because you can connect the number back to the real circuit voltage.

Control LED brightness with the potentiometer

In the PWM lesson, we used duty values from 0 to 255 to control brightness. The ADC gives values from 0 to 4095.

To connect those two ranges, use map():

int brightness = map(adcValue, 0, 4095, 0, 255);

Complete code:

const int potPin = 34;
const int ledPin = 2;

void setup()
{
    Serial.begin(115200);
    ledcAttach(ledPin, 5000, 8);
}

void loop()
{
    int adcValue = analogRead(potPin);
    int brightness = map(adcValue, 0, 4095, 0, 255);

    ledcWrite(ledPin, brightness);

    Serial.print("ADC: ");
    Serial.print(adcValue);
    Serial.print("  Brightness: ");
    Serial.println(brightness);

    delay(50);
}

Now the potentiometer becomes a real control input. Turning the knob changes the PWM duty value, and the LED brightness changes with it.

Common mistakes

If the ADC value does not change:

  • Check that the middle potentiometer pin goes to GPIO34
  • Check that the two outer pins go to 3.3V and GND
  • Make sure Serial Monitor is set to 115200
  • Make sure you are using an ADC-capable pin

If the value changes in the opposite direction, swap the two outer potentiometer pins.

Never connect 5V directly to an ESP32 input pin. ESP32 GPIO pins are generally 3.3V pins.

Real engineering use cases

Analog input is used for:

  • Knobs and control panels
  • Joysticks
  • Battery voltage measurement
  • Light sensors
  • Soil moisture sensors
  • Gas sensors
  • Current and voltage monitoring

The same basic idea appears again and again: a real-world quantity changes a voltage, and the ADC converts that voltage into a number.

Engineering challenge

Add a second LED state:

  • Below 25 percent knob position: LED off
  • Between 25 and 75 percent: LED brightness follows the knob
  • Above 75 percent: LED fully on

This will help you practice combining analog readings with decision logic.

Next lesson

Next, we will focus on Serial Monitor and debugging. Before building bigger projects, it is important to know how to inspect values, find wiring mistakes, and understand what the ESP32 is doing while the program runs.