Hello,
I have perfomed some other test on different samples of ESP32_WROOM_32D modules.
I noted some differences between the efuse Vref value and the one measured on GPIO26. This results in error of measured voltage. I report here my results on 6 samples:
Vapplied is the voltage applied to AD1_CHANNEL_6
Vmeasured is what esp32 reports after calling "esp_adc_cal_raw_to_voltage" (see below my source code).
Code: Select all
Sample #1:
Vref efuse: 1114mV
Vref to GPIO26: 1100mV
Vapplied Vmeasured Error %
388mV 398mV 2.5%
558mV 571mV 2.2%
733mV 750mV 2.2%
Sample #2:
Vref efuse: 1121mV
Vref to GPIO26: 1116mV
Vapplied Vmeasured Error %
343mV 347mV 1.15%
532mV 535mV 0.56%
827mV 834mV 0.84%
Sample #3:
Vref efuse: 1128mV
Vref to GPIO26: 1121mV
Vapplied Vmeasured Error %
316mV 321mV 1.5%
532mV 538mV 1.1%
832mV 843mV 1.3%
Sample #4:
Vref efuse: 1121mV
Vref to GPIO26: 1119mV
Vapplied Vmeasured Error %
310mV 309mV 0.32%
564mV 564mV 0%
827mV 829mV 0,24%
Sample #5:
Vref efuse: 1072mV
Vref to GPIO26: 1069mV
Vapplied Vmeasured Error %
301mV 305mV 1.3%
510mV 515mV 0,97%
833mV 838mV 0,59%
Sample #6:
Vref efuse: 1079mV
Vref to GPIO26: 1073mV
Vapplied Vmeasured Error %
302mV 314mV 3.8%
476mV 488mV 2.4%
867mV 882mV 1,7%
I also report the source code of my test. I have obviously enabled CONFIG_ADC_CAL_EFUSE_VREF_ENABLE in sdkconfig.
Code: Select all
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "esp_adc_cal.h"
#include "esp_log.h"
#define DEFAULT_VREF 1100 //Use adc2_vref_to_gpio() to obtain a better estimate
#define NO_OF_SAMPLES 16 //Multisampling
void app_main()
{
static esp_adc_cal_characteristics_t *adc_chars;
//Check TP is burned into eFuse
if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) {
printf("eFuse Two Point: Supported\n");
} else {
printf("eFuse Two Point: NOT supported\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\n");
} else {
printf("eFuse Vref: NOT supported\n");
}
//Route Vref to GPIO26
esp_err_t status = adc2_vref_to_gpio(GPIO_NUM_26);
if (status == ESP_OK) {
printf("v_ref routed to GPIO\n");
} else {
printf("failed to route v_ref\n");
}
//ADC1 bit and attenuation
adc1_config_width(ADC_WIDTH_BIT_10);
adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_0);
//Characterize ADC
adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));
memset(adc_chars, 0x0, sizeof(esp_adc_cal_characteristics_t));
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_0, ADC_WIDTH_BIT_10, DEFAULT_VREF, adc_chars);
//Check type of characterization
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");
}
//Continuously sample ADC1
while (1)
{
uint32_t adc_reading = 0;
//Multisampling
for (int i = 0; i < NO_OF_SAMPLES; i++) {
int value = adc1_get_raw(ADC1_CHANNEL_6);
adc_reading += value;
vTaskDelay(pdMS_TO_TICKS(10));
}
adc_reading /= NO_OF_SAMPLES;
printf( "adc_reading fin:%d\n", adc_reading);
//Convert adc_reading to voltage in mV
uint32_t voltage = esp_adc_cal_raw_to_voltage(adc_reading, adc_chars);
printf("Voltage: %dmV\n", voltage);
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
Is there any hint you can give me?
I have also a side question related to ATTENUATION: how is this attenuation obtained inside the chip? Can attenuation introduce another spread variation from chip to chip which is not accounted by adc_calibration?
The test i have performed are with attenuation_0_dB but in our application we need to use 6dB attenuation.
Thanks