adc1_example single read

claudea2
Posts: 7
Joined: Tue Apr 06, 2021 8:42 pm

adc1_example single read

Postby claudea2 » Fri Dec 10, 2021 5:43 pm

Hello,
I am looking for an ADC single read example for the ESP32C3. There is a dma example, but it does not use the adc characterization and eFuse stored constants to convert to mV.
The single read example is for the ESP32 and ESP32S2/3.
I was able to add declarations for the attenuation, adc unit, adc channel and bit width but I am not sure about the eFuse checks.
Can I copy the code for the ESP32 and use it for the ESP32C3?

Code: Select all

#if CONFIG_IDF_TARGET_ESP32  // [u]CHANGE TO ESP32C3[/u]
    //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\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");
    }
Thanks

claudea2
Posts: 7
Joined: Tue Apr 06, 2021 8:42 pm

Re: adc1_example single read

Postby claudea2 » Sat Dec 11, 2021 5:52 pm

I believe I have found a bug in the documentation. In the esp32 IDF programming guide for the esp32c3 it states:
"Software Calibration
To convert ADC raw data to calibrated digital data, following steps should be followed:

Check the eFuse to know if the software calibration is supported via esp_adc_cal_check_efuse().

Calculate the ADC calibration characteristics via esp_adc_cal_characterize(). The ADC software calibration characteristics are per ADC module and per attenuation. For example, characteristics of ADC1 channel 0 under 11 dB attenuation are the same as characteristics of ADC1 channel 2 under 11 dB attenuation. But characteristics of ADC1 channel 0 under 11 dB attenuation are different with characteristics of ADC2 channel 0 under 11 dB attenuation. Also characteristics of ADC1 channel 0 under 11 dB attenuation are different with characteristics of ADC1 channel 0 under 6 dB attenuation.

Get the actual voltage value via esp_adc_cal_raw_to_voltage()."

In reality, the esp_adc_cal_characterize() function must be called per ADC, per attenuation and per channel. it sets up the gpio for ADC operation.
The documentation need to be updated.
The output shows that the gpio is updated each time the cal function is called:
termianl output:
eFuse Vref: NOT supported
I (2070296) gpio: GPIO[0]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
Characterized using Two Point Value
Ch:0 Raw: 1773 Voltage: 1248mV
eFuse Two Point: Supported
eFuse Vref: NOT supported
I (2080296) gpio: GPIO[1]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
Characterized using Two Point Value
Ch:1 Raw: 1164 Voltage: 819mV
eFuse Two Point: Supported
eFuse Vref: NOT supported
I (2090296) gpio: GPIO[2]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
Characterized using Two Point Value
Ch:2 Raw: 582 Voltage: 409mV

here is the code:

Code: Select all

/* 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 "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "esp_adc_cal.h"
#define DEFAULT_VREF 1100 //Use adc2_vref_to_gpio() to obtain a better estimate
#define NO_OF_SAMPLES 64 //Multisampling
static esp_adc_cal_characteristics_t *adc_chars;
static const adc_atten_t atten = ADC_ATTEN_DB_11;
static const adc_unit_t unit = ADC_UNIT_1;
static adc_channel_t channel0 = ADC_CHANNEL_0;
//static const adc_channel_t channel1 = ADC_CHANNEL_1;
//static const adc_channel_t channel2 = ADC_CHANNEL_2;
static const adc_bits_width_t width = ADC_WIDTH_BIT_12;
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\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");
}
}
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 app_main(void)
{
int ii=0;
while (1) {
switch (ii){
case 0: channel0 = ADC_CHANNEL_0;
break;
case 1: channel0 = ADC_CHANNEL_1;
break;
case 2: channel0 = ADC_CHANNEL_2;
}
//Check if Two Point or Vref are burned into eFuse
check_efuse();
//Configure ADC
if (unit == ADC_UNIT_1) {
adc1_config_width(width);
adc1_config_channel_atten(channel0, atten);
} else {
adc2_config_channel_atten((adc2_channel_t)channel0, atten);
}
//Characterize ADC
adc_chars = 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);
// sample ADC1 ch 0
uint32_t adc_reading = 0;
//Multisampling
for (int i = 0; i < NO_OF_SAMPLES; i++) {
adc_reading += adc1_get_raw((adc1_channel_t)channel0);
}
adc_reading /= NO_OF_SAMPLES;
//Convert adc_reading to voltage in mV
uint32_t voltage = esp_adc_cal_raw_to_voltage(adc_reading, adc_chars);
printf("Ch:%d\t Raw: %d\tVoltage: %dmV\n",ii, adc_reading, voltage);
vTaskDelay(pdMS_TO_TICKS(10000));
ii++;
if(ii==3){
ii=0;
}
}
}

Who is online

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