ESP32 Analog Input and ADC Explained – Potentiometer and LDR Projects

Welcome to Episode 2 of the DigitalLab ESP32 Beginner Series!

In this episode, we will explore how to read analog signals using the ESP32’s built-in Analog-to-Digital Converter (ADC).

Unlike digital inputs, which have only two states (HIGH and LOW), analog inputs can represent a range of voltage levels. The ESP32 can measure these varying voltages and convert them into digital values that can be processed by a program.

To understand this practically, we will build two simple projects:

  1. Potentiometer-based LED Brightness Control
  2. LDR-based Automatic Light Sensor

These projects will help beginners understand ADC, analog voltage, voltage dividers, PWM and sensor-based automation.

What is Analog Input?

An analog signal is a continuously varying electrical signal that can have different voltage levels within a specified range.

For example, a potentiometer can provide a variable voltage between 0V and 3.3V depending on its knob position.

The ESP32 cannot directly process analog voltage as a digital value. It uses an Analog-to-Digital Converter (ADC) to convert the input voltage into a numerical value.

Understanding ADC in ESP32

The ESP32 DevKit V1 supports 12-bit ADC resolution in our experiments.

A 12-bit ADC provides 4096 possible digital values, ranging from:

  • 0 – Minimum reading
  • 2048 – Approximately halfway
  • 4095 – Maximum reading

For our experiments, we will use GPIO34 as the analog input pin.

The Arduino IDE provides the analogRead() function to read analog values from an ESP32 ADC pin.

Stage 1 – Potentiometer and ADC: Controlling LED Brightness

In the first experiment, we will use a 10K potentiometer to generate a variable analog voltage.

The ESP32 reads this voltage through GPIO34 and uses the reading to control the brightness of an LED connected to GPIO25.

Components Required

  • ESP32 DevKit V1 (38-pin)
  • 10K potentiometer
  • LED
  • 220Ω resistor
  • Breadboard
  • Jumper wires

Circuit Connections

Potentiometer connections:

Potentiometer PinESP32 Connection
Outer pin 13.3V
Middle pin (wiper)GPIO34
Outer pin 2GND

The two outer terminals can be interchanged. This only reverses the direction in which the ADC readings increase.

LED connections:

LED ConnectionESP32 Connection
Anode (+)GPIO25 through 220Ω resistor
Cathode (-)GND

The 220Ω resistor limits current through the LED.

Arduino IDE Code – Potentiometer and ADC

// DigitalLab - ESP32 Beginner Series
// EP2: Analog Input and ADC
// Stage 1: Potentiometer-controlled LED brightness

const int POT_PIN = 34;
const int LED_PIN = 25;

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

  analogReadResolution(12);
  analogWriteResolution(LED_PIN, 8);

  pinMode(LED_PIN, OUTPUT);

  Serial.println("DigitalLab - ESP32 ADC Experiment");
}

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

  // Calculate approximate voltage
  float voltage = (adcValue / 4095.0) * 3.3;

  // Convert ADC value into LED brightness
  int brightness = map(adcValue, 0, 4095, 0, 255);
  brightness = constrain(brightness, 0, 255);

  // Control LED brightness
  analogWrite(LED_PIN, brightness);

  // Display readings
  Serial.print("ADC Value: ");
  Serial.print(adcValue);

  Serial.print(" | Voltage (approx): ");
  Serial.print(voltage, 2);
  Serial.print(" V");

  Serial.print(" | LED Brightness: ");
  Serial.println(brightness);

  delay(200);
}

Understanding the Code

1. Reading Analog Values

int adcValue = analogRead(POT_PIN);

This reads the voltage supplied by the potentiometer through GPIO34.

2. Calculating Approximate Voltage

float voltage = (adcValue / 4095.0) * 3.3;

This calculates an approximate voltage based on the ADC reading and the assumed 3.3V reference range.

3. Converting ADC Values into PWM

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

The ADC reading ranges from 0 to 4095, while our LED brightness control uses an 8-bit range of 0 to 255.

The map() function converts one range into another.

4. Controlling LED Brightness

analogWrite(LED_PIN, brightness);

This generates a PWM signal to control the LED brightness.

Expected Output

As you rotate the potentiometer, the ADC readings and LED brightness change.

Potentiometer PositionApprox. ADC ValueLED Brightness
Minimum00
25%102464
50%2048128
75%3072191
Maximum4095255

These are illustrative values. Actual ESP32 ADC readings may vary.

What we learned in Stage 1:

  • Reading analog voltage using ESP32.
  • Understanding 12-bit ADC resolution.
  • Displaying ADC readings in Serial Monitor.
  • Converting ADC readings into approximate voltage.
  • Using PWM to control LED brightness.

<image>

Stage 2 – LDR Light Sensor: Automatic LED Control

In the second experiment, we will use an LDR (Light Dependent Resistor) to detect surrounding light intensity.

An LDR changes its resistance depending on the amount of light falling on its surface.

  • More light: LDR resistance decreases.
  • Less light: LDR resistance increases.

By combining the LDR with a 10K resistor, we can create a voltage divider and read the changing voltage using the ESP32 ADC.

Components Required

  • ESP32 DevKit V1 (38-pin)
  • Small LDR (Light Dependent Resistor)
  • 10K resistor
  • LED
  • 220Ω resistor
  • Breadboard
  • Jumper wires

Circuit Connections

We will connect the LDR and 10K resistor as a voltage divider.

Circuit connections:

ComponentConnection
LDR leg 1ESP32 3.3V
LDR leg 2GPIO34
10K resistor leg 1GPIO34
10K resistor leg 2GND

The junction between the LDR and 10K resistor connects to GPIO34.

The LED uses the same GPIO25 connection as Stage 1, with a 220Ω series resistor.

How the LDR Circuit Works

When more light falls on the LDR, its resistance decreases. This increases the voltage at the junction connected to GPIO34.

When the LDR is covered, its resistance increases and the junction voltage decreases.

The ESP32 reads these voltage changes as ADC values.

With this circuit arrangement:

  • Bright environment → Higher ADC reading.
  • Dark environment → Lower ADC reading.

Arduino IDE Code – LDR Light Sensor

/*
  DigitalLab - ESP32 Beginner Series
  EP2: Analog Input and ADC
  Stage 2: LDR Light Sensor
*/

const int LDR_PIN = 34;
const int LED_PIN = 25;

// Initial threshold - adjust after testing
const int LIGHT_THRESHOLD = 1800;

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

  analogReadResolution(12);

  pinMode(LED_PIN, OUTPUT);

  Serial.println("DigitalLab - LDR Light Sensor");
}

void loop() {

  int ldrValue = analogRead(LDR_PIN);

  Serial.print("LDR ADC Value: ");
  Serial.print(ldrValue);

  if (ldrValue < LIGHT_THRESHOLD) {

    digitalWrite(LED_PIN, HIGH);
    Serial.println(" | Dark - LED ON");

  } else {

    digitalWrite(LED_PIN, LOW);
    Serial.println(" | Bright - LED OFF");

  }

  delay(300);
}

Understanding the Code

1. Reading LDR Values

int ldrValue = analogRead(LDR_PIN);

This reads the analog voltage generated by the LDR voltage divider.

2. Setting a Threshold

const int LIGHT_THRESHOLD = 1800;

This defines the ADC value used to distinguish between bright and dark conditions.

The value 1800 is an initial example. The appropriate threshold depends on the LDR, resistor and surrounding lighting conditions.

3. Automatic LED Control

if (ldrValue < LIGHT_THRESHOLD) {
    digitalWrite(LED_PIN, HIGH);
} else {
    digitalWrite(LED_PIN, LOW);
}

When the ADC reading falls below the threshold, the LED turns ON.

Testing the LDR Sensor

After uploading the code:

  1. Open Serial Monitor at 115200 baud.
  2. Observe the ADC reading under normal room lighting.
  3. Cover the LDR using your finger.
  4. Shine a mobile flashlight on the LDR.
  5. Observe the changes in ADC readings.
  6. Adjust the threshold value and demonstrate how it affects LED switching.

What we learned in Stage 2:

  • Understanding how an LDR works.
  • Building a voltage divider circuit.
  • Reading light intensity using ESP32 ADC.
  • Using conditional statements to control an LED.
  • Adjusting threshold values for automatic light detection.

Important ESP32 Wiring Precautions

Keep these points in mind while building both projects:

  • Use 3.3V for the potentiometer and LDR voltage divider.
  • ESP32 GPIO pins are not 5V tolerant.
  • Never apply 5V to GPIO34.
  • Use a 220Ω resistor in series with the LED.
  • Ensure all circuit grounds are connected to ESP32 GND.
  • GPIO34 is an input-only pin, making it suitable for analog sensor readings.

Watch the EP2 Video:

Conclusion

In this episode of the DigitalLab ESP32 Beginner Series, we explored analog input and ADC using two practical projects.

In Stage 1, we used a potentiometer to generate variable analog voltage and controlled LED brightness using PWM. In Stage 2, we used an LDR to detect surrounding light intensity and automatically switched an LED based on a configurable threshold. These experiments provide a practical introduction to reading analog signals and using sensors with ESP32.

In the next episode, we will explore temperature and humidity measurement using an ESP32 and a digital temperature and humidity sensor.

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.