The ESP32C3 does not play well with standard Ardiono anlogRead() and requires special code to provide useful reading.
The ESP32C3 has 2 ADCs, ADC1 and ADC2. ADC2 is shared with the wifi radio adding to the complexity of using it.
These ADCs have special features:
1- Input scaling using attenuation.
You can change the range of the input by changing the attenuation.
2- Factory programmed calibration that can be used to provide increased precision.
ADC2 is a Special Case
You must share it with the WiFi code. If wifi is active, trying to read ADC2 will return a timeout error-code, most of the time. Make sure your code is non blocking. It must not wait indefinetly for a results. Skip the reading if the result is not ESP_OK. This may look like a big drawback but if you are measuring a battery voltage or a temperature, infrequent updates are not a problem.
Test your software thoroughly to ensure there are no adverse effects on the WiFi itself.
3- Calibration
The ESP32 ADCs suffer from an offset that makes raw reading up to 30% off from the real values. Fortunatly Epressif calibrates each unit and store these values in non-volatile memory. They went a step further and provided code to extract the calibration parameters and correct the output values.
4- Noise
Yes noise. You cannot expect a WiFI radio blating electromagnectic waves all over the place not to get into your sensitive ADC. Fortunatly, the solution is simple, just averge 16 or 32 samples. Statically you will eliminate most of the noise.
Here is a code example, without averaging, you can use to explore the ESP32C3 ADC
/* ESP32C3 all 6 channels working including AC2 chan 0 during wifi
single_read example by Claude Arpin CEO Seenov
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <stdlib.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/adc_common.h"
#include "esp_adc_cal.h"
#include <WiFi.h>
#include <WiFiClient.h>
//ADC Channels
#define ADC1_EXAMPLE_CHAN0 ADC1_CHANNEL_0
#define ADC1_EXAMPLE_CHAN1 ADC1_CHANNEL_1
#define ADC1_EXAMPLE_CHAN2 ADC1_CHANNEL_2
#define ADC1_EXAMPLE_CHAN3 ADC1_CHANNEL_3
#define ADC1_EXAMPLE_CHAN4 ADC1_CHANNEL_4
#define ADC2_EXAMPLE_CHAN0 ADC2_CHANNEL_0
static const char *TAG_CH[6][10] = {{"ADC1_CH0"}, {"ADC1_CH2"}, {"ADC1_CH3"}, {"ADC1_CH4"}, {"ADC1_CH5"}, {"ADC2_CH0"} };
//ADC Attenuation
#define ADC_EXAMPLE_ATTEN ADC_ATTEN_DB_11
//ADC Calibration
#define ADC_EXAMPLE_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP
static int adc_raw[2][10];
static const char *TAG = "ADC SINGLE";
static esp_adc_cal_characteristics_t adc1_chars;
static esp_adc_cal_characteristics_t adc2_chars;
byte mac1[6];
static bool adc_calibration_init(void)
{
esp_err_t ret;
bool cali_enable = false;
ret = esp_adc_cal_check_efuse(ADC_EXAMPLE_CALI_SCHEME);
if (ret == ESP_ERR_NOT_SUPPORTED) {
Serial.println( "Calibration scheme not supported, skip software calibration");
} else if (ret == ESP_ERR_INVALID_VERSION) {
Serial.println("eFuse not burnt, skip software calibration");
} else if (ret == ESP_OK) {
cali_enable = true;
esp_adc_cal_characterize(ADC_UNIT_1, ADC_EXAMPLE_ATTEN, ADC_WIDTH_BIT_12, 0, &adc1_chars);
esp_adc_cal_characterize(ADC_UNIT_2, ADC_EXAMPLE_ATTEN, ADC_WIDTH_BIT_12, 0, &adc2_chars);
} else {
Serial.println("Invalid arg");
}
return cali_enable;
}
void setup() {
Serial.begin(115200); //Initialising if(DEBUG)Serial Monitor
delay(1000);
Serial.println("starting");
WiFi.disconnect(); // ensure a clean start
WiFi.begin("Seenov21_2_4", "bandittaichi");
WiFi.mode(WIFI_STA);
WiFi.macAddress(mac1); // returns mac address
char temp = 30; // seconds tying to connect
// wait up to 30 sec for connection
while ((WiFi.status() != WL_CONNECTED) && (temp > 0) )
{
Serial.print("nc"); // no connection
delay(1000);
temp--;
}
// after wait if still not connected launch web for new credentials
if (WiFi.status() == WL_CONNECTED)
{
Serial.println("");
Serial.print("Connected to ");
Serial.print("Seenov21_2_4");
Serial.println(" Successfully");
}
}
void loop() {
esp_err_t ret = ESP_OK;
uint32_t voltage = 0;
bool cali_enable = adc_calibration_init();
//ADC1 config
ESP_ERROR_CHECK(adc1_config_width(ADC_WIDTH_BIT_12));
ESP_ERROR_CHECK(adc1_config_channel_atten(ADC1_EXAMPLE_CHAN0, ADC_EXAMPLE_ATTEN));
ESP_ERROR_CHECK(adc1_config_channel_atten(ADC1_EXAMPLE_CHAN1, ADC_EXAMPLE_ATTEN));
ESP_ERROR_CHECK(adc1_config_channel_atten(ADC1_EXAMPLE_CHAN2, ADC_EXAMPLE_ATTEN));
ESP_ERROR_CHECK(adc1_config_channel_atten(ADC1_EXAMPLE_CHAN3, ADC_EXAMPLE_ATTEN));
ESP_ERROR_CHECK(adc1_config_channel_atten(ADC1_EXAMPLE_CHAN4, ADC_EXAMPLE_ATTEN));
//ADC2 config
ESP_ERROR_CHECK(adc2_config_channel_atten(ADC2_EXAMPLE_CHAN0, ADC_EXAMPLE_ATTEN));
while (1) {
adc_raw[0][0] = adc1_get_raw(ADC1_EXAMPLE_CHAN0);
if (cali_enable) {
voltage = esp_adc_cal_raw_to_voltage(adc_raw[0][0], &adc1_chars);
Serial.print("channel 0= ");
Serial.print(voltage);
}
delay(1000);
//===================================================
adc_raw[0][1] = adc1_get_raw(ADC1_EXAMPLE_CHAN1);
if (cali_enable) {
voltage = esp_adc_cal_raw_to_voltage(adc_raw[0][1], &adc1_chars);
}
delay(1000);
//===================================================
adc_raw[0][2] = adc1_get_raw(ADC1_EXAMPLE_CHAN2);
if (cali_enable) {
voltage = esp_adc_cal_raw_to_voltage(adc_raw[0][2], &adc1_chars);
}
delay(1000);
//===================================================
adc_raw[0][3] = adc1_get_raw(ADC1_EXAMPLE_CHAN3);
if (cali_enable) {
voltage = esp_adc_cal_raw_to_voltage(adc_raw[0][3], &adc1_chars);
}
delay(1000);
//===================================================
adc_raw[0][4] = adc1_get_raw(ADC1_EXAMPLE_CHAN4);
if (cali_enable) {
voltage = esp_adc_cal_raw_to_voltage(adc_raw[0][4], &adc1_chars);
}
delay(1000);
ret = adc2_get_raw(ADC2_EXAMPLE_CHAN0, ADC_WIDTH_BIT_12, &adc_raw[1][0]);
if (cali_enable) {
if(ret == ESP_OK){
voltage = esp_adc_cal_raw_to_voltage(adc_raw[1][0], &adc2_chars);
Serial.print(" ADC2 channel 0= ");
Serial.println(voltage);
}else{
Serial.println(".");
}
}
delay(1000);
}
}
Have fun.