New ESP32-S3 development board is now available → /products
</>OceanLabz
Beginner1 Feb 2024 · 6 min read

ESP32 ADC

### What is an ADC? **_Analog-to-Digital Conversion (ADC)_** **is the process of converting an analog voltage signal into a digital value that can be processed by a microcontroller. The ESP32's ADC allows it to interface with various analog sensors, converting their continuous signals into digital v

ESP32 ADC

#What is an ADC?

Analog-to-Digital Conversion (ADC) is the process of converting an analog voltage signal into a digital value that can be processed by a microcontroller. The ESP32's ADC allows it to interface with various analog sensors, converting their continuous signals into digital values ranging from 0 to a specified resolution (e.g., 12-bit resolution gives a range of 0 to 4095).

Imagine you have a dimmer switch at home that lets you control the brightness of a light bulb. When you twist the knob, you’re adjusting how much electricity flows to the bulb, making it brighter or dimmer. Now, what if you wanted to tell a computer exactly how bright the light is? This is where something called an Analog-to-Digital Converter (ADC) comes in.

In simple terms, an ADC is like a translator for your computer or microcontroller (like the ESP32). It takes an analog signal—something that can have any value within a range, like the voltage coming from your dimmer switch—and converts it into a digital number that the computer can understand.

For example, let’s say you have a sensor that measures temperature, and it outputs a varying voltage based on the temperature it senses. The ADC in the ESP32 reads this voltage and converts it into a number between 0 and 4095. The exact number depends on how high or low the voltage is, giving your ESP32 a way to understand and process the temperature data.

#Introduction to ADC on ESP32

The ESP32 is equipped with two ADCs: ADC1 and ADC2, each having multiple channels. These ADCs can read analog voltages on the GPIO pins and convert them into a digital value ranging from 0 to 4095, corresponding to the input voltage (typically 0 to 3.3V). However, the ADC2 is shared with other peripherals like Wi-Fi, so it’s generally recommended to use ADC1 to avoid conflicts.

#Hardware and Requirements

  • ESP32 Development Board
  • Potentiometer (e.g., 10kΩ)
  • Breadboard and Jumper Wires
  • Power Supply or USB Cable

#Setting Up the Development Environment

Before diving into the code, ensure that you have the Arduino IDE installed along with the ESP32 board package.

  1. Install the Arduino IDE: Download and install the Arduino IDE from here.
  2. Install the ESP32 Board Package:
    • Open the Arduino IDE.
    • Go to File -> Preferences.
    • In the "Additional Board Manager URLs" field, enter the following URL : arduino Copy codehttps://dl.espressif.com/dl/package_esp32_index.json
    • Go to Tools -> Board -> Boards Manager and search for "ESP32".
    • Install the "ESP32 by Espressif Systems" package.

#Understanding the ADC on ESP32

The ESP32 features multiple ADC channels, each capable of reading analog signals. Here are key points to understand:

  • ADC Channels: The ESP32 has 18 ADC channels, divided between two ADC modules (ADC1 and ADC2). ADC1 is typically preferred for general use as ADC2 shares pins with Wi-Fi functions, potentially causing conflicts.
  • Resolution: The default resolution is 12 bits, but it can be configured between 9 and 12 bits. A higher resolution gives more precise readings but increases the time required for conversion.
  • Voltage Reference: The ESP32's ADC reads input voltages between 0 and 3.3V. The resolution divides this range into equal intervals.

#Reading Analog Values with ADC

Let’s start with a simple example where we read the value from a potentiometer connected to one of the ADC pins.

Wiring:

  • Connect the middle pin of the potentiometer to GPIO 34 (ADC1 Channel 6).
  • Connect one of the outer pins to 3.3V.
  • Connect the other outer pin to GND.

// Sample Code is Written By OceanLabz.in

const int potPin = 34; // GPIO 34 (ADC1 Channel)

void setup() { Serial.begin(115200); // Initialize serial communication at 115200 baud }

void loop() { int potValue = analogRead(potPin); // Read the analog value Serial.println(potValue); // Print the value to the Serial Monitor delay(500); // Delay for stability }

Explanation:

  • analogRead(potPin): This function reads the analog value from GPIO 34.
  • The ADC converts the voltage from the potentiometer into a value between 0 and 4095.
  • The value is printed to the Serial Monitor every 500 milliseconds.

#Scaling and Calibration

To convert the raw ADC readings into meaningful values (e.g., voltage), you may need to scale and calibrate the output.

Example: Converting the ADC value to voltage.

const float voltageMax = 3.3; // Maximum voltage const int adcMax = 4095; // Maximum ADC value (12-bit resolution)

void loop() { int potValue = analogRead(potPin); float voltage = (potValue * voltageMax) / adcMax; // Convert to voltage Serial.println(voltage); // Print the voltage delay(500); }

#Advanced ADC Applications

#Reading a Temperature Sensor

Analog temperature sensors like the LM35 provide a voltage output proportional to the temperature. You can use the ADC to read this voltage and convert it to a temperature value.

Example: Reading temperature from an LM35 sensor.

//

const int tempPin = 34; // GPIO 34 const float voltageRef = 3.3; // Reference voltage

void loop() { int adcValue = analogRead(tempPin); float voltage = (adcValue * voltageRef) / 4095.0; float temperatureC = voltage * 100.0; // LM35 gives 10mV/°C Serial.print("Temperature: "); Serial.print(temperatureC); Serial.println(" °C"); delay(1000); }

#Using Multiple ADC Channels

The ESP32 allows you to read from multiple ADC channels simultaneously. Here’s how you can monitor two analog sensors (e.g., a potentiometer and a photoresistor).

Wiring:

  • Potentiometer middle pin to GPIO 34.
  • Photoresistor (LDR) connected in series with a 10kΩ resistor between 3.3V and GND. The junction of the LDR and resistor connects to GPIO 35 (ADC1 Channel 7).

// Sample Code is Written By OceanLabz.in

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

void loop() { int potValue = analogRead(34); // Read potentiometer int ldrValue = analogRead(35); // Read LDR

Serial.print("Potentiometer: "); Serial.print(potValue); Serial.print(" | LDR: "); Serial.println(ldrValue);

delay(500); }

Explanation:

  • analogRead(34) and analogRead(35) are used to read from two different ADC channels.
  • The readings are printed side by side to the Serial Monitor.

#Troubleshooting and Tips

  • Floating Inputs: Unused ADC pins can float, leading to unstable readings. To prevent this, connect unused ADC pins to ground through a pull-down resistor.
  • ADC Accuracy: The ESP32’s ADC is not perfect and might have some non-linearity or noise. Consider averaging multiple readings for more stable results.
  • Wi-Fi Interference: When using ADC2, avoid using Wi-Fi simultaneously, as it can cause ADC readings to be inaccurate.

#Other Functions

  • analogReadResolution(resolution):
    • Set the sample bits and resolution between 9 to 12 bits.
    • Default is 12-bit resolution.
  • analogSetWidth(width):
    • Similar to analogReadResolution(), set sample bits and resolution.
    • Default is 12-bit resolution.
  • analogSetCycles(cycles):
    • Set the number of cycles per sample.
    • Default is 8, range: 1 to 255.
  • analogSetSamples(samples):
    • Set the number of samples in the range, affecting sensitivity.
    • Default is 1 sample.
  • analogSetClockDiv(attenuation):
    • Set the divider for the ADC clock.
    • Default is 1, range: 1 to 255.
  • analogSetAttenuation(attenuation):
    • Set input attenuation for all ADC pins.
    • Default is ADC_11db.
    • Accepted values:
      • ADC_0db: No attenuation (measures up to approximately 800 mV).
      • ADC_2_5db: Attenuated input, measuring up to approx. 1100 mV.
      • ADC_6db: Attenuated input, measuring up to approx. 1350 mV.
      • ADC_11db: Attenuated input, measuring up to approx. 2600 mV.
  • analogSetPinAttenuation(pin, attenuation):
    • Set the input attenuation for a specified pin.
  • adcAttachPin(pin):
    • Attach a pin to ADC, clearing any other analog mode.
    • Returns TRUE or FALSE result.
  • adcStart(pin), adcBusy(pin), and adcEnd(pin):
    • Start an ADC conversion on the attached pin’s bus.
    • Check if conversion on the pin’s ADC bus is running (returns TRUE or FALSE).
    • Get the result of the conversion (returns a 16-bit integer).