Get to know how to get your ESP32’s ADC up and running through this basic ESP32 ADC programming guide.
Introduction
Your ESP32-S3 has 2 SAR (Successive Approximation Register) ADCs inside them. Knowing how to use them can help you make versatile projects. With these ADCs, you’ll be able to measure analog readings. These readings can be anything from sensor-level data, power supply voltages, or even analog levels from a voltage divider. Here, you’ll learn about basic ESP32 ADC programming.
Above you can see the two ADCs, namely, ADC1 and ADC2. ADC1 is widely used by users. ADC2 has some handicaps because it is also used by the Wi-Fi module. Here we’ll discuss basic configuration and how to use ADC1
USing your ESP32's ADC
Know where your ADC Pins are
Before you can use the ADC, you must know what pins on your ESP32 to use as ADC inputs. Generally speaking, below are the GPIO pins used by both ADC1 and ADC2:
- ADC1: 10 channels (GPIO1 – GPIO10)
- ADC2: 10 channels (GPIO11 – GPIO20)
To be more specific, you can check the ESP32-S3-WROOM datasheet to know which ADC input maps to which I/O pin as seen below:
Setup your Circuit
Setting up your circuit could be as simple as an ESP32-S3 DevKit-C1 wired on a breadboard with a potentiometer as seen below. Note that ADC1_CHANNEL_0 will be used as input which maps to GPIO1.
Creating your Code
Below is a basic guide to get your ESP32-S3 ADC up and running reading a single ADC input pin in one-shot mode. This is the simplest ADC input capture type. One-shot meaning single ADC values are captured by the user. It’s up to him how to initiate and terminate those single-shot ADC capture processes.
Include the necessary Header Files
You’ll want to include the source files below. Some files are necessary to get your ADC capture running. Some are required to output ADC values as string data. You’ll need adc_oneshot.h, adc_cali.h, and adc_cali_scheme.h to successfully configure, calibrate, and capture data with your ADC.
#include
#include
#include
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "soc/soc_caps.h"
#include "esp_adc/adc_oneshot.h"
#include "esp_adc/adc_cali.h"
#include "esp_adc/adc_cali_scheme.h"
Create some Definitions and Variables
ADC_CHANNEL_0 is used for the channel definition while integer variables adc_raw and voltage are used to hold both adc raw and voltage type readings. You’ll see later how an ADC raw reading converts to a voltage type.
#define MY_ADC_CHANNEL ADC_CHANNEL_0
static int adc_raw; // adc raw reading
static int voltage; // adc raw coverted to voltage
Initialize the ADC in one-shot mode
On the main code, initialize the ADC in one-shot mode using the handles and configuration types below. There are two modes you can use, one-shot and continuous. Here, for simplicity’s sake, we’ll concentrate on the simple one-shot mode. ADC1 is ADC_UNIT_1. The ADC is initialized through the adc_oneshot_new_unit()Â API.
// 1 -- Initialize the ADC
adc_oneshot_unit_handle_t adc1_handle;
adc_oneshot_unit_init_cfg_t init_config1 = {
.unit_id = ADC_UNIT_1,
};
adc_oneshot_new_unit(&init_config1, &adc1_handle);
Configure the ADC and the Channel to use
ADC1 is configured to have a maximum bit width (which can go up to 13 bits max) and an attenuation level of 12db. Attenuation levels are important since the ADC reference voltage can go as low as 1.1V. With this, the ADC input pin must be attenuated to some degree if you’re using the VDD pin (3.3V) of the ESP32-S3 as the source voltage for your ADC readings.Â
Below, the adc_oneshot_config_channel() API is used to configure the ADC.
// 2 -- Configure the ADC
adc_oneshot_chan_cfg_t config = {
.bitwidth = ADC_BITWIDTH_DEFAULT,
.atten = ADC_ATTEN_DB_12,
};
adc_oneshot_config_channel(adc1_handle, ADC_CHANNEL_0, &config);
CalibratE the ADC
The ADC reference voltage can swing in small amounts due to internal and external factors. With this, you’ll need some form of calibration to make your ADC readings more precise. Different kinds of calibration schemes are implemented by the ESP-IDF framework. One such scheme is the Curve Fitting Calibration Scheme.
Below is a config type and handle used as parameters for the adc_cali_create_scheme_curve_fitting() API. This calibration API is executed before doing your first ADC reading.
// 3 -- Calibrate the ADC
adc_cali_handle_t adc1_cali_chan0_handle = NULL;
adc_cali_curve_fitting_config_t cali_config = {
.unit_id = ADC_UNIT_1,
.chan = ADC_CHANNEL_0,
.atten = ADC_ATTEN_DB_12,
.bitwidth = ADC_BITWIDTH_DEFAULT,
};
adc_cali_create_scheme_curve_fitting(&cali_config, &adc1_cali_chan0_handle);
Read athe ADC Values
In a loop, you can start reading and displaying the ADC values. Raw data is output by adc_oneshot_read() while adc_cali_raw_to_voltage() converts the value to voltage. Note that the APIÂ adc_cali_raw_to_voltage() is related to the calibration scheme you defined previously.
// 4 -- Read raw ADC value
adc_oneshot_read(adc1_handle, ADC_CHANNEL_0, &adc_raw);
// 5 -- Convert raw to voltage
adc_cali_raw_to_voltage(adc1_cali_chan0_handle, adc_raw, &voltage);
printf("ADC Reading is: %dmV\n", voltage);
Referrence Code
Use the complete reference code below to review basic one shot ESP32 ADC programming on :).
#include
#include
#include
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "soc/soc_caps.h"
#include "esp_adc/adc_oneshot.h"
#include "esp_adc/adc_cali.h"
#include "esp_adc/adc_cali_scheme.h"
#define MY_ADC_CHANNEL ADC_CHANNEL_0
static int adc_raw; // adc raw reading
static int voltage; // adc raw coverted to voltage
void app_main(void)
{
// 1 -- Initialize the ADC
adc_oneshot_unit_handle_t adc1_handle;
adc_oneshot_unit_init_cfg_t init_config1 = {
.unit_id = ADC_UNIT_1,
};
adc_oneshot_new_unit(&init_config1, &adc1_handle);
// 2 -- Configure the ADC
adc_oneshot_chan_cfg_t config = {
.bitwidth = ADC_BITWIDTH_DEFAULT,
.atten = ADC_ATTEN_DB_12,
};
adc_oneshot_config_channel(adc1_handle, ADC_CHANNEL_0, &config);
// 3 -- Calibrate the ADC
adc_cali_handle_t adc1_cali_chan0_handle = NULL;
adc_cali_curve_fitting_config_t cali_config = {
.unit_id = ADC_UNIT_1,
.chan = ADC_CHANNEL_0,
.atten = ADC_ATTEN_DB_12,
.bitwidth = ADC_BITWIDTH_DEFAULT,
};
adc_cali_create_scheme_curve_fitting(&cali_config, &adc1_cali_chan0_handle);
while(1)
{
// 4 -- Read raw ADC value
adc_oneshot_read(adc1_handle, ADC_CHANNEL_0, &adc_raw);
// 5 -- Convert raw to voltage
adc_cali_raw_to_voltage(adc1_cali_chan0_handle, adc_raw, &voltage);
printf("ADC Reading is: %dmV\n", voltage);
vTaskDelay(1000/portTICK_PERIOD_MS);
}
// 6 -- Delete Calibration scheme
adc_cali_delete_scheme_curve_fitting(adc1_cali_chan0_handle);
}
SHOP THIS PROJECT
-
ESP32-CAM WiFi Bluethooth Development Board with OV2640 Camera Module
$31.95Original price was: $31.95.$29.95Current price is: $29.95. Add to cart