ESP32-S3 very big ADC error

zazas321
Posts: 231
Joined: Mon Feb 01, 2021 9:41 am

ESP32-S3 very big ADC error

Postby zazas321 » Fri Sep 09, 2022 11:52 am

I am working on a project with ESP32-S3 where we need to measure very small voltage changes via the ADC.

Internal ESP32 12 bit ADC has a 12 bit resolution and assuming that vref is 3.3V, I can calculate the voltage of 1 adc step:
3300/4095 = 0.8mV

I have a few questions:
1.
In the official ESP32 documentation, it says that if attenuation ADC_ATTEN_DB_11 is selected, measurable range is :
150 mV ~ 2450 mV

Does that mean that ESP32 will not be capable of measuring above 2450mV? How is that possible? What if I want to measure across full range (0 - 3300mV)?


2. I have tried to familiarise myself with the ADC and how it works and I flashed very simple program to my CPU:

Code: Select all

/*
 * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/* ADC1 Example

   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.h"
#include "esp_adc_cal.h"



#define ADC1_EXAMPLE_CHAN0              ADC1_CHANNEL_2
//ADC Attenuation
#define ADC_EXAMPLE_ATTEN               ADC_ATTEN_DB_11
#define ADC_EXAMPLE_CALI_SCHEME         ESP_ADC_CAL_VAL_EFUSE_TP_FIT
#define ADC_WIDTH_BIT_DEFAULT           ADC_WIDTH_BIT_12



int adc_raw1;

static esp_adc_cal_characteristics_t adc1_chars;


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) {
        ESP_LOGW("CALIBRATION", "Calibration scheme not supported, skip software calibration");
    } else if (ret == ESP_ERR_INVALID_VERSION) {
        ESP_LOGW("CALIBRATION", "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_DEFAULT, 0, &adc1_chars);


    } else {
        ESP_LOGE("CALIBRATION", "Invalid arg");
    }

    return cali_enable;
}

void app_main(void)
{
    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_DEFAULT));
    ESP_ERROR_CHECK(adc1_config_channel_atten(ADC1_EXAMPLE_CHAN0, ADC_EXAMPLE_ATTEN));


    while (1) {
        adc_raw1 = adc1_get_raw(ADC1_EXAMPLE_CHAN0);
        ESP_LOGI("ADC_RAW", "raw  data: %d", adc_raw1);
        if (cali_enable) {
            voltage = esp_adc_cal_raw_to_voltage(adc_raw1, &adc1_chars);
            ESP_LOGI("ADC_VOLTAGE", "cali data: %d mV", voltage);
        }
        vTaskDelay(pdMS_TO_TICKS(1000));


    }
}


I use labarotory power supply to generate 250mV (also measure this voltage on digital multimeter) and then this voltage and GND is connected to ESP32 ADC configured pin directly.

https://ibb.co/2dqf66c

As you can see from the image above, the LAB power supply is set to 250mV and the digital multimeter is measuring 228mV. So I am expecting to read somewhere in between (250mV and 228mV)

I cannot wrap my head around why the ESP32 ADC measurements fluctuate so much:

Code: Select all

I (653298) ADC_RAW: raw  data: 239
I (653298) ADC_VOLTAGE: cali data: 210 mV
I (654298) ADC_RAW: raw  data: 234
I (654298) ADC_VOLTAGE: cali data: 205 mV
I (655298) ADC_RAW: raw  data: 211
I (655298) ADC_VOLTAGE: cali data: 185 mV
I (656298) ADC_RAW: raw  data: 240
I (656298) ADC_VOLTAGE: cali data: 211 mV
I (657298) ADC_RAW: raw  data: 222
I (657298) ADC_VOLTAGE: cali data: 196 mV
I (658298) ADC_RAW: raw  data: 227
I (658298) ADC_VOLTAGE: cali data: 200 mV
I (659298) ADC_RAW: raw  data: 221
I (659298) ADC_VOLTAGE: cali data: 195 mV
I (660298) ADC_RAW: raw  data: 243
I (660298) ADC_VOLTAGE: cali data: 213 mV
I (661298) ADC_RAW: raw  data: 244
I (661298) ADC_VOLTAGE: cali data: 214 mV
I (662298) ADC_RAW: raw  data: 243
I (662298) ADC_VOLTAGE: cali data: 213 mV
I (663298) ADC_RAW: raw  data: 244
I (663298) ADC_VOLTAGE: cali data: 214 mV
I (664298) ADC_RAW: raw  data: 233
I (664298) ADC_VOLTAGE: cali data: 204 mV
I (665298) ADC_RAW: raw  data: 237
I (665298) ADC_VOLTAGE: cali data: 207 mV
I (666298) ADC_RAW: raw  data: 245
I (666298) ADC_VOLTAGE: cali data: 215 mV
I (667298) ADC_RAW: raw  data: 220
I (667298) ADC_VOLTAGE: cali data: 193 mV
I (668298) ADC_RAW: raw  data: 231
I (668298) ADC_VOLTAGE: cali data: 203 mV
I (669298) ADC_RAW: raw  data: 243
I (669298) ADC_VOLTAGE: cali data: 213 mV
I (670298) ADC_RAW: raw  data: 238
I (670298) ADC_VOLTAGE: cali data: 208 mV
I (671298) ADC_RAW: raw  data: 237
I (671298) ADC_VOLTAGE: cali data: 207 mV
I (672298) ADC_RAW: raw  data: 235
I (672298) ADC_VOLTAGE: cali data: 206 mV
I (673298) ADC_RAW: raw  data: 243
I (673298) ADC_VOLTAGE: cali data: 213 mV
I (674298) ADC_RAW: raw  data: 231
I (674298) ADC_VOLTAGE: cali data: 203 mV
I (675298) ADC_RAW: raw  data: 243
I (675298) ADC_VOLTAGE: cali data: 213 mV
I (676298) ADC_RAW: raw  data: 239
I (676298) ADC_VOLTAGE: cali data: 210 mV
I (677298) ADC_RAW: raw  data: 239
I (677298) ADC_VOLTAGE: cali data: 210 mV
I (678298) ADC_RAW: raw  data: 243
I (678298) ADC_VOLTAGE: cali data: 213 mV
I (679298) ADC_RAW: raw  data: 235
I (679298) ADC_VOLTAGE: cali data: 206 mV
I (680298) ADC_RAW: raw  data: 237
I (680298) ADC_VOLTAGE: cali data: 207 mV
I (681298) ADC_RAW: raw  data: 250
I (681298) ADC_VOLTAGE: cali data: 219 mV
I (682298) ADC_RAW: raw  data: 233
I (682298) ADC_VOLTAGE: cali data: 204 mV
I (683298) ADC_RAW: raw  data: 231
I (683298) ADC_VOLTAGE: cali data: 203 mV
I (684298) ADC_RAW: raw  data: 253
I (684298) ADC_VOLTAGE: cali data: 222 mV
I (685298) ADC_RAW: raw  data: 243
I (685298) ADC_VOLTAGE: cali data: 213 mV
I (686298) ADC_RAW: raw  data: 232
I (686298) ADC_VOLTAGE: cali data: 204 mV
I (687298) ADC_RAW: raw  data: 363
I (687298) ADC_VOLTAGE: cali data: 316 mV
I (688298) ADC_RAW: raw  data: 243
I (688298) ADC_VOLTAGE: cali data: 213 mV
I (689298) ADC_RAW: raw  data: 245
I (689298) ADC_VOLTAGE: cali data: 215 mV
I (690298) ADC_RAW: raw  data: 233
I (690298) ADC_VOLTAGE: cali data: 204 mV
I (691298) ADC_RAW: raw  data: 266
I (691298) ADC_VOLTAGE: cali data: 233 mV
I (692298) ADC_RAW: raw  data: 237
I (692298) ADC_VOLTAGE: cali data: 207 mV
I (693298) ADC_RAW: raw  data: 232
I (693298) ADC_VOLTAGE: cali data: 204 mV
I (694298) ADC_RAW: raw  data: 229
I (694298) ADC_VOLTAGE: cali data: 202 mV
I (695298) ADC_RAW: raw  data: 190
I (695298) ADC_VOLTAGE: cali data: 168 mV
I (696298) ADC_RAW: raw  data: 252
I (696298) ADC_VOLTAGE: cali data: 221 mV
I (697298) ADC_RAW: raw  data: 255
I (697298) ADC_VOLTAGE: cali data: 223 mV
I (698298) ADC_RAW: raw  data: 248
I (698298) ADC_VOLTAGE: cali data: 218 mV
I (699298) ADC_RAW: raw  data: 269
I (699298) ADC_VOLTAGE: cali data: 235 mV
I (700298) ADC_RAW: raw  data: 232
I (700298) ADC_VOLTAGE: cali data: 204 mV
I (701298) ADC_RAW: raw  data: 235
I (701298) ADC_VOLTAGE: cali data: 206 mV
I (702298) ADC_RAW: raw  data: 285
I (702298) ADC_VOLTAGE: cali data: 249 mV
I (703298) ADC_RAW: raw  data: 251
I (703298) ADC_VOLTAGE: cali data: 220 mV
I (704298) ADC_RAW: raw  data: 383
I (704298) ADC_VOLTAGE: cali data: 333 mV
I (705298) ADC_RAW: raw  data: 247
I (705298) ADC_VOLTAGE: cali data: 217 mV
I (706298) ADC_RAW: raw  data: 179
I (706298) ADC_VOLTAGE: cali data: 158 mV
I (707298) ADC_RAW: raw  data: 255
I (707298) ADC_VOLTAGE: cali data: 223 mV
I (708298) ADC_RAW: raw  data: 175
I (708298) ADC_VOLTAGE: cali data: 155 mV
I (709298) ADC_RAW: raw  data: 250
I (709298) ADC_VOLTAGE: cali data: 219 mV
I (710298) ADC_RAW: raw  data: 229
I (710298) ADC_VOLTAGE: cali data: 202 mV
I (711298) ADC_RAW: raw  data: 229
I (711298) ADC_VOLTAGE: cali data: 202 mV
I (712298) ADC_RAW: raw  data: 240
I (712298) ADC_VOLTAGE: cali data: 211 mV
I (713298) ADC_RAW: raw  data: 237
I (713298) ADC_VOLTAGE: cali data: 207 mV
I (714298) ADC_RAW: raw  data: 179
I (714298) ADC_VOLTAGE: cali data: 158 mV
I (715298) ADC_RAW: raw  data: 222
I (715298) ADC_VOLTAGE: cali data: 196 mV
I (716298) ADC_RAW: raw  data: 240
I (716298) ADC_VOLTAGE: cali data: 211 mV
I (717298) ADC_RAW: raw  data: 245
I (717298) ADC_VOLTAGE: cali data: 215 mV
I (718298) ADC_RAW: raw  data: 233
I (718298) ADC_VOLTAGE: cali data: 204 mV
I (719298) ADC_RAW: raw  data: 214
I (719298) ADC_VOLTAGE: cali data: 188 mV
I (720298) ADC_RAW: raw  data: 252
I (720298) ADC_VOLTAGE: cali data: 221 mV
I (721298) ADC_RAW: raw  data: 253
I (721298) ADC_VOLTAGE: cali data: 222 mV
I (722298) ADC_RAW: raw  data: 237
I (722298) ADC_VOLTAGE: cali data: 207 mV
I (723298) ADC_RAW: raw  data: 231
I (723298) ADC_VOLTAGE: cali data: 203 mV
I (724298) ADC_RAW: raw  data: 267
I (724298) ADC_VOLTAGE: cali data: 234 mV
I (725298) ADC_RAW: raw  data: 218
I (725298) ADC_VOLTAGE: cali data: 191 mV
I (726298) ADC_RAW: raw  data: 238
I (726298) ADC_VOLTAGE: cali data: 208 mV
I (727298) ADC_RAW: raw  data: 235
I (727298) ADC_VOLTAGE: cali data: 206 mV
I (728298) ADC_RAW: raw  data: 219
I (728298) ADC_VOLTAGE: cali data: 192 mV
I (729298) ADC_RAW: raw  data: 213
I (729298) ADC_VOLTAGE: cali data: 187 mV
I (730298) ADC_RAW: raw  data: 230
I (730298) ADC_VOLTAGE: cali data: 202 mV
I (731298) ADC_RAW: raw  data: 235
I (731298) ADC_VOLTAGE: cali data: 206 mV
I (732298) ADC_RAW: raw  data: 307
I (732298) ADC_VOLTAGE: cali data: 269 mV
I (733298) ADC_RAW: raw  data: 204
I (733298) ADC_VOLTAGE: cali data: 180 mV
I (734298) ADC_RAW: raw  data: 275
I (734298) ADC_VOLTAGE: cali data: 241 mV
I (735298) ADC_RAW: raw  data: 228
I (735298) ADC_VOLTAGE: cali data: 201 mV
I (736298) ADC_RAW: raw  data: 244
I (736298) ADC_VOLTAGE: cali data: 214 mV
I (737298) ADC_RAW: raw  data: 233
I (737298) ADC_VOLTAGE: cali data: 204 mV
I (738298) ADC_RAW: raw  data: 265
I (738298) ADC_VOLTAGE: cali data: 232 mV
I (739298) ADC_RAW: raw  data: 202
I (739298) ADC_VOLTAGE: cali data: 179 mV
I (740298) ADC_RAW: raw  data: 262
I (740298) ADC_VOLTAGE: cali data: 230 mV
I (741298) ADC_RAW: raw  data: 248
I (741298) ADC_VOLTAGE: cali data: 218 mV
I (742298) ADC_RAW: raw  data: 231
I (742298) ADC_VOLTAGE: cali data: 203 mV
I (743298) ADC_RAW: raw  data: 205
I (743298) ADC_VOLTAGE: cali data: 181 mV
I (744298) ADC_RAW: raw  data: 249
I (744298) ADC_VOLTAGE: cali data: 219 mV
I (745298) ADC_RAW: raw  data: 285
I (745298) ADC_VOLTAGE: cali data: 249 mV
I (746298) ADC_RAW: raw  data: 239
I (746298) ADC_VOLTAGE: cali data: 210 mV
I (747298) ADC_RAW: raw  data: 235
I (747298) ADC_VOLTAGE: cali data: 206 mV
I (748298) ADC_RAW: raw  data: 233
I (748298) ADC_VOLTAGE: cali data: 204 mV
I (749298) ADC_RAW: raw  data: 227
I (749298) ADC_VOLTAGE: cali data: 200 mV
According to the serial logs above you can see that the voltage readings fluctuate from 180mV to over 330mV which is ALOT.

What are the ways to reduce the ADC measuring error? I am expecting to read voltage with +-10mV error if that is possible
Last edited by zazas321 on Wed Sep 14, 2022 11:58 am, edited 1 time in total.

username
Posts: 534
Joined: Thu May 03, 2018 1:18 pm

Re: ESP32-S3 very big ADC error

Postby username » Fri Sep 09, 2022 4:28 pm

There are 2 main things that people dont do when it comes to ADC's

#1) A bypass capacitor right next to the input ADC pin. Even more robust is to use a series resistor then bypass cap to GND right next to the ADC pin.
#2) average the ADC results. You can start taking 100 samples to average them together.

Have to remember that a meter has all these things and more built in. All meters average the sampled input, and have robust filtering on its inputs. Even connecting a wire from your ESP32 adc pin to your power supply will pick up noise from your lights, and other equipment around. So you have to put in measures to deal with filtering that out.

ESP_Sprite
Posts: 9739
Joined: Thu Nov 26, 2015 4:08 am

Re: ESP32-S3 very big ADC error

Postby ESP_Sprite » Sat Sep 10, 2022 12:14 am

Also, Vref is not 3.3V, it's around 1.1V and the input voltage is optionally attenuated before it goes through the ADC, hence the 'strange' limit.

zazas321
Posts: 231
Joined: Mon Feb 01, 2021 9:41 am

Re: ESP32-S3 very big ADC error

Postby zazas321 » Sat Sep 10, 2022 9:40 am

Thank you both for your responses. I will add capacitance and average results next week to see if it is any better.

ESP_Sprite wrote:
Sat Sep 10, 2022 12:14 am
Also, Vref is not 3.3V, it's around 1.1V and the input voltage is optionally attenuated before it goes through the ADC, hence the 'strange' limit.
Please could you help me understand the Vref a little bit more? So by default it is around 1.1V and it is used for calibrating the ADC? If the default Vref is 1.1V, how can I measure above 1.1V ? I assume VREF determines the upper limit of your ADC range?

What if I supply 3.3V to selected GPIO and configure that pin as VREF, then the Vref will become 3.3V right? But what is the difference? Will it be more accurate? Is there any point doing this?


Also, I am mainly concerned about the lower and upper limits of the ADC range, as I have mentioned in the initial post;
In the official ESP32 documentation, it says that if attenuation ADC_ATTEN_DB_11 is selected, measurable range is :
150 mV ~ 2450 mV


Can you just confirm if the ESP32 is capable or not to measure below 150mV and above 2450mV (when ADC_ATTEN_DB_11 is selected) ? Does it make any difference if I use default VREF or my own 3.3V vref?

If the answer to above is that ESP32 cannot measure above 2450mV, is there any ways to improve the range and increase it to 3.2 - 3.3V?

ESP_Sprite
Posts: 9739
Joined: Thu Nov 26, 2015 4:08 am

Re: ESP32-S3 very big ADC error

Postby ESP_Sprite » Sat Sep 10, 2022 11:43 pm

zazas321 wrote:
Sat Sep 10, 2022 9:40 am
Please could you help me understand the Vref a little bit more? So by default it is around 1.1V and it is used for calibrating the ADC? If the default Vref is 1.1V, how can I measure above 1.1V ? I assume VREF determines the upper limit of your ADC range?

What if I supply 3.3V to selected GPIO and configure that pin as VREF, then the Vref will become 3.3V right? But what is the difference? Will it be more accurate? Is there any point doing this?
The default Vref comes from an internal bandgap reference which outputs a voltage of around 1.1V. There is some chip-by-chip variation in this reference voltage, but we record what the specific voltage is in the eFuses of the chip. That is one aspect of what calibration does: compensate for the specific Vref of that chip.

Note that we don't support configuring an external pin of Vref.

Can you just confirm if the ESP32 is capable or not to measure below 150mV and above 2450mV (when ADC_ATTEN_DB_11 is selected) ? Does it make any difference if I use default VREF or my own 3.3V vref?

If the answer to above is that ESP32 cannot measure above 2450mV, is there any ways to improve the range and increase it to 3.2 - 3.3V?
Yep, the ESP32 is not capable of that, to my knowledge. Note that the ESP32-S3 (as in: the later chip) has a somewhat improved ADC; it does not have the issues at the start and end of the range, making it capable of measuring 0 to 3.1V. (Reference here.) If you need to measure all the way up to 3.3V (or higher), it's suggested that you use an external voltage divider.

zazas321
Posts: 231
Joined: Mon Feb 01, 2021 9:41 am

Re: ESP32-S3 very big ADC error

Postby zazas321 » Wed Sep 14, 2022 11:13 am

So what is the accuracy that I should be expecting? Lets assume that I apply very accurate 200mV to one of the ESP32 ADC pins.

What sort of measurements I can expect ? is 210mV or 190mV considered acceptable or not( +- 10mV)?

Since lowest voltage step is 0.8mV ( 4095 steps /3.3V), I would expect to read higher quite accurately

ESP_Sprite
Posts: 9739
Joined: Thu Nov 26, 2015 4:08 am

Re: ESP32-S3 very big ADC error

Postby ESP_Sprite » Thu Sep 15, 2022 2:36 am

It's in the datasheet, table 4-5 and 4-6.

Who is online

Users browsing this forum: Kniroxe and 93 guests