ESP32 ADC calibration tips

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

ESP32 ADC calibration tips

Postby zazas321 » Tue Feb 08, 2022 5:50 am

Hello. I would like to know how can I perform ADC calibration to achieve the best results. We are using resistance temperature sensor.

To read the resistance temperature value, we use voltage divider (See the image link below for the schematic screenshot):
https://ibb.co/hYrJ4fD


The adc is setup as following:

Code: Select all

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) {
        ESP_LOGI(ADC_TAG,"eFuse Two Point: Supported");
    } else {
        ESP_LOGI(ADC_TAG,"eFuse Two Point: NOT supported");
    }
    //Check Vref is burned into eFuse
    if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_VREF) == ESP_OK) {
        ESP_LOGI(ADC_TAG,"eFuse Vref: Supported");
    } else {
        ESP_LOGI(ADC_TAG,"eFuse Vref: NOT supported");
    }

}


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

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);

    vTaskDelay(1000/portTICK_PERIOD_MS);
}

I have noticed across multiple devices that the error between the temperature that I can measure on the ADC pin with the multimeter and the voltage that ESP32 returns using esp_adc_cal_raw_to_voltage has about 30-40 mv error which is not ideal for our product.

I have a variable resistance box to simulare my resistance sensor. For example, when I set it to 20kOhm the voltage output should be 1.57V but the ESP32 returns 1.6V using esp_adc_cal_raw_to_voltage.

Can someone suggest me what is the best way to setup and calibrate adc?

vanBassum
Posts: 68
Joined: Sun Jan 17, 2021 11:59 am

Re: ESP32 ADC calibration tips

Postby vanBassum » Tue Feb 08, 2022 3:06 pm

I have read that the ADC from de ESP itself isnt the most acurate one. Maybe an external reference could help. I'm not sure if just a calibration will help your case.

User avatar
Vader_Mester
Posts: 300
Joined: Tue Dec 05, 2017 8:28 pm
Location: Hungary
Contact:

Re: ESP32 ADC calibration tips

Postby Vader_Mester » Tue Feb 08, 2022 4:44 pm

zazas321 wrote:
Tue Feb 08, 2022 5:50 am
Hello. I would like to know how can I perform ADC calibration to achieve the best results. We are using resistance temperature sensor.

To read the resistance temperature value, we use voltage divider (See the image link below for the schematic screenshot):
https://ibb.co/hYrJ4fD

I have noticed across multiple devices that the error between the temperature that I can measure on the ADC pin with the multimeter and the voltage that ESP32 returns using esp_adc_cal_raw_to_voltage has about 30-40 mv error which is not ideal for our product.

I have a variable resistance box to simulare my resistance sensor. For example, when I set it to 20kOhm the voltage output should be 1.57V but the ESP32 returns 1.6V using esp_adc_cal_raw_to_voltage.

Can someone suggest me what is the best way to setup and calibrate adc?
When you say error, do you mean an actual error (+/-) or an offset in a fixed direction?

If you have a fixed offset, you can easily calibrate it out, by saving the offset value in flash (like using NVS).
You can even save it on millivolts not ADC values, so getting the final result is easier.
You can also set one of the eFuse location that is free to be used by the application, to store this offset.
Either way you have it persistently stored that stays there between boots.
Then when you boot up, you read it out to a variable and use it in every ADC calculation.

If it is an actuall error, meaning that the value swings by this much in both directions from sample to sample, that is probably a hardware or circuitry issue, which you need to fix yourself. Can be power supply stability problem, or noise.

Code: Select all

task_t coffeeTask()
{
	while(atWork){
		if(!xStreamBufferIsEmpty(mug)){
			coffeeDrink(mug);
		} else {
			xTaskCreate(sBrew, "brew", 9000, &mug, 1, NULL);
			xSemaphoreTake(sCoffeeRdy, portMAX_DELAY);
		}
	}
	vTaskDelete(NULL);
}

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

Re: ESP32 ADC calibration tips

Postby zazas321 » Wed Feb 09, 2022 5:18 am

When I say error I mean slight deviation from the actual voltage and the voltage that the ESP32 reads. Adding an offset to flash is not a problem for a single device. All device will have slightly different offsets and there will be thousands of them. I wont be able to calibrate all of them by hand. I need a software method so the devices can calibrate themselves accordingly.


I dont think there could be an issue with hardware. I have tested with various ESP32 devkit boards and they all have same issues. They all have ADC error. I can use signal generator or apply some known voltage on the ADC pin. For example I can provide 1.5V on the ADC pin and the ESP32 will not measure 1.5V. My particular device would measure 1.52V. So the ESP32 has a measuring error of 0.02V at 1.5V . Is that normal error for the ESP32 adc or there is something wrong with my ESP32?

vanBassum
Posts: 68
Joined: Sun Jan 17, 2021 11:59 am

Re: ESP32 ADC calibration tips

Postby vanBassum » Wed Feb 09, 2022 3:10 pm

Sounds like a reference problem. If all the devices had the same error a linear calibration (Ax+B) would be sufficient. In that case the calibration would be the same for all devices. Since all devices have a different error, you can't get away with this.

An ADC has to have a known voltage as reference, if this reference is different for each device so will be the measured value. Let me aks you this, how does the device know what voltage is applied to a pin without some kind of reference?

User avatar
Vader_Mester
Posts: 300
Joined: Tue Dec 05, 2017 8:28 pm
Location: Hungary
Contact:

Re: ESP32 ADC calibration tips

Postby Vader_Mester » Thu Feb 10, 2022 11:21 am

zazas321 wrote:
Wed Feb 09, 2022 5:18 am
When I say error I mean slight deviation from the actual voltage and the voltage that the ESP32 reads. Adding an offset to flash is not a problem for a single device. All device will have slightly different offsets and there will be thousands of them. I wont be able to calibrate all of them by hand. I need a software method so the devices can calibrate themselves accordingly.


I dont think there could be an issue with hardware. I have tested with various ESP32 devkit boards and they all have same issues. They all have ADC error. I can use signal generator or apply some known voltage on the ADC pin. For example I can provide 1.5V on the ADC pin and the ESP32 will not measure 1.5V. My particular device would measure 1.52V. So the ESP32 has a measuring error of 0.02V at 1.5V . Is that normal error for the ESP32 adc or there is something wrong with my ESP32?
If you add a voltage reference, like a Microchip LM4030-2.5, this is an extremely precise voltage reference. Just add it to the product. Since you know, that you need to measure 2.5V exactly, you can pretty much use this to self calibrate your ADC measurements.

Code: Select all

task_t coffeeTask()
{
	while(atWork){
		if(!xStreamBufferIsEmpty(mug)){
			coffeeDrink(mug);
		} else {
			xTaskCreate(sBrew, "brew", 9000, &mug, 1, NULL);
			xSemaphoreTake(sCoffeeRdy, portMAX_DELAY);
		}
	}
	vTaskDelete(NULL);
}

vanBassum
Posts: 68
Joined: Sun Jan 17, 2021 11:59 am

Re: ESP32 ADC calibration tips

Postby vanBassum » Thu Feb 10, 2022 3:53 pm

Yes that is a possibility, altough i would advice you to add this as a reference. Because of things like drift, temp coëfficiënt ect. A calibration doens't account for these things unless you want to do a calibration before each measurement.

FirstFreeLogin
Posts: 3
Joined: Thu Feb 10, 2022 12:02 pm

Re: ESP32 ADC calibration tips

Postby FirstFreeLogin » Thu Feb 10, 2022 10:47 pm

@zazas321 You no need external Vref to calibration. At some production stage (e.g programing) you can calibrate it by precision resistor connected instead your temperature sensor. Now you will know what count ADC must back and you can cancel different.
I place pcb on special tool with spring needle where I burn finish firmware. Also in this firmware I have test and calibration procedure (it run only if a tool is detected)

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

Re: ESP32 ADC calibration tips

Postby zazas321 » Tue Jun 14, 2022 4:39 am

Thank you all for suggestions :)

Who is online

Users browsing this forum: Google [Bot] and 74 guests