Index
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.
- Install the Arduino IDE: Download and install the Arduino IDE from here.
- 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 code
https://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)
andanalogRead(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).