ESP32 ADC measurement error by 30-40mV

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

ESP32 ADC measurement error by 30-40mV

Postby zazas321 » Fri Oct 15, 2021 6:34 am

Hello. I have been playing with the ESP32 ADC and notice that I always have 30-40mV error in the readings.

For example, I input voltage into my ESP32 from my power supply and compare it with the voltage result from the functions:

Code: Select all

        uint32_t reading =  adc1_get_raw(ADC1_CHANNEL_0); //adc in 5
        uint32_t voltage = esp_adc_cal_raw_to_voltage(reading, adc_chars);
 
voltage returned by the ESP32 is always 30-40mV higher than the actual voltage that I put on the ESP32 pin.


I have calibrated the ESP32 adc as below:

I run the adc info command:

Code: Select all

Connecting........__
Detecting chip type... ESP32
espefuse.py v3.1-dev
ADC VRef calibration: 1114mV
And in the ADC initialization, I change the calibrtion value as following:


Code: Select all


#define DEFAULT_VREF    1114        //Use adc2_vref_to_gpio() to obtain a better estimate
#define NO_OF_SAMPLES   64          //Multisampling

esp_adc_cal_characteristics_t *adc_chars;

static  adc_bits_width_t width = ADC_WIDTH_BIT_12;
static  adc_atten_t atten = ADC_ATTEN_DB_11;
static  adc_unit_t unit = ADC_UNIT_1;


static void check_efuse(void)
{
    //Check if TP is burned into eFuse
    if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) {
        printf("eFuse Two Point: Supported\r\n");
    } else {
        printf("eFuse Two Point: NOT supported\r\n");
    }
    //Check Vref is burned into eFuse
    if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_VREF) == ESP_OK) {
        printf("eFuse Vref: Supported\r\n");
    } else {
        printf("eFuse Vref: NOT supported\r\n");
    }

}


static void print_char_val_type(esp_adc_cal_value_t val_type)
{
    if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
        printf("Characterized using Two Point Value\n");
    } else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
        printf("Characterized using eFuse Vref\n");
    } else {
        printf("Characterized using Default Vref\n");
    }
}

void ADC_Init(void)
{
// ADC config
    adc1_config_width(ADC_WIDTH_BIT_12);
    adc1_config_channel_atten(ADC1_CHANNEL_5,ADC_ATTEN_DB_11); 
    adc1_config_channel_atten(ADC1_CHANNEL_0,ADC_ATTEN_DB_11);
    adc1_config_channel_atten(ADC1_CHANNEL_3,ADC_ATTEN_DB_11);
    adc1_config_channel_atten(ADC1_CHANNEL_6,ADC_ATTEN_DB_11);

    check_efuse();



    //Characterize ADC
    //adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));
    adc_chars = (esp_adc_cal_characteristics_t *)calloc(1, sizeof(esp_adc_cal_characteristics_t));
    esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, width, DEFAULT_VREF, adc_chars);
    print_char_val_type(val_type);

}

Please can someone clarify to me where this 30-40mV error come from and how can I fix this. I do not think that adding an offset of 30mV to every voltage is the most approriate to solve this.

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

Re: ESP32 ADC measurement error by 30-40mV

Postby zazas321 » Fri Oct 15, 2021 6:49 am

I use GPIO36 to measure the ADC
I have attempted to use : adc_vref_to_gpio(ADC_UNIT_1,GPIO_NUM_36);

Code: Select all

void ADC_Init(void)
{
// ADC config


    adc1_config_width(ADC_WIDTH_BIT_12);
    adc1_config_channel_atten(ADC1_CHANNEL_5,ADC_ATTEN_DB_11); 
    adc1_config_channel_atten(ADC1_CHANNEL_0,ADC_ATTEN_DB_11);
    adc1_config_channel_atten(ADC1_CHANNEL_3,ADC_ATTEN_DB_11);
    adc1_config_channel_atten(ADC1_CHANNEL_6,ADC_ATTEN_DB_11);

    check_efuse();



    //Characterize ADC
    //adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));
    adc_chars = (esp_adc_cal_characteristics_t *)calloc(1, sizeof(esp_adc_cal_characteristics_t));
    esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, width, DEFAULT_VREF, adc_chars);
    print_char_val_type(val_type);

    esp_err_t status = adc_vref_to_gpio(ADC_UNIT_1,GPIO_NUM_36);
    if (status == ESP_OK)
    {
        printf("v_ref routed to GPIO36\n");
    }
    else
    {
        printf("failed to route v_ref\n");
    }
    
    vTaskDelay(1000/portTICK_PERIOD_MS);

}
But I am not able to do it for some reason. IT fails to route the v_REF. It seems to be working when I do adc2_vref_to_gpio(GPIO_NUM_25);

mikemoy
Posts: 627
Joined: Fri Jan 12, 2018 9:10 pm

Re: ESP32 ADC measurement error by 30-40mV

Postby mikemoy » Sun Oct 17, 2021 5:14 am

I input voltage into my ESP32 from my power supply
Are you verifying the voltage at the ESP32 pin with a decent meter, or are you just using your power supply's display?

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

Re: ESP32 ADC measurement error by 30-40mV

Postby zazas321 » Mon Oct 18, 2021 5:47 am

Thanks for the reply. I am verifying with the meter and I can confirm that this 30-40mV persists throughout the whole ADC range ( 0 - 3V+)
At the moment I do:

Code: Select all

	int ADC_OFFSET = 40;
        uint32_t reading =  adc1_get_raw(ADC1_CHANNEL_0); //adc in 5
        uint32_t voltage = esp_adc_cal_raw_to_voltage(reading, adc_chars);
        printf("voltage = %u \n",voltage-ADC_OFFSET);
But as I have mentioned, this is not the proper solution and I am concerned that this may not be 40mV for other ESP32 devices just this particular one.

So is there any way to "calibrate" this in software ?

mikemoy
Posts: 627
Joined: Fri Jan 12, 2018 9:10 pm

Re: ESP32 ADC measurement error by 30-40mV

Postby mikemoy » Tue Oct 19, 2021 1:54 am


Who is online

Users browsing this forum: Dennie and 121 guests