Page 1 of 1

Is there anything to do to make the adc2_vref_to_gpio () function work?

Posted: Mon Aug 31, 2020 4:56 pm
by jhmluna
Hello.
I am testing some ESP32 modules using VSCode + PlatformIO in Arduino framework.
My experiment involves putting some values in the output of DAC2 (GPIO26) and reading that value with ADC1_CHANNEL_6 (GPIO34).
My output values on DAC2 are updated via serial, transmitting values between 0 and 255.
The part that is puzzling me is related to the adc2_vref_to_gpio () function;
I'm using it this way:
  1.  // Routing ADC reference voltage to GPIO, so it can be manually measured (for Default Vref):
  2.     esp_err_t status = adc2_vref_to_gpio(GPIO_NUM_25);
  3.     if (status == ESP_OK)
  4.     {
  5.         printf("v_ref routed to GPIO25\n");
  6.     }
  7.     else
  8.     {
  9.         printf("failed to route v_ref\n");
  10.     }
I have already programmed three ESP32 modules using GPIO_NUM_26 and GPIO_NUM_27 as a parameter of the adc2_vref_to_gpio () function and in neither case did it work.
My question is whether I need to do anything else for the adc2_vref_to_gpio function to work.
I already tested it with an example of the ESP-IDF framework and it worked, I can read the reference voltage on the pin for the GPIO25, but if I use this function in the Arduino Framework, no GPIO produces the reference voltage.
Can someone help me?

The complete code is below.
  1. #include <Arduino.h>
  2. #include <esp_adc_cal.h>
  3. #include <esp_efuse.h>
  4.  
  5. #define DEFAULT_VREF 1100 // Use adc2_vref_to_gpio() to obtain a better estimate
  6. #define NO_OF_SAMPLES 1  // Multisampling
  7.  
  8.  
  9. static esp_adc_cal_characteristics_t *adc_chars;
  10. static const adc1_channel_t channel = ADC1_CHANNEL_6; //GPIO34 if ADC1, GPIO14 if ADC2
  11. static const adc_bits_width_t width = ADC_WIDTH_BIT_12;
  12. static const adc_atten_t atten = ADC_ATTEN_DB_11;
  13. static const adc_unit_t unit = ADC_UNIT_1;
  14.  
  15. static void check_efuse(void)
  16. {
  17.     //Check if TP is burned into eFuse
  18.     if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK)
  19.     {
  20.         printf("eFuse Two Point: Supported\n");
  21.     }
  22.     else
  23.     {
  24.         printf("eFuse Two Point: NOT supported\n");
  25.     }
  26.     //Check Vref is burned into eFuse
  27.     if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_VREF) == ESP_OK)
  28.     {
  29.         printf("eFuse Vref: Supported\n");
  30.     }
  31.     else
  32.     {
  33.         printf("eFuse Vref: NOT supported\n");
  34.     }
  35.  
  36.     uint8_t chip_ver = esp_efuse_get_chip_ver();
  37.     printf("Chip version is: %d\n", chip_ver);
  38.  
  39. }
  40.  
  41. static void print_char_val_type(esp_adc_cal_value_t val_type)
  42. {
  43.     if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP)
  44.     {
  45.         printf("Characterized using Two Point Value\n");
  46.     }
  47.     else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF)
  48.     {
  49.         printf("Characterized using eFuse Vref\n");
  50.     }
  51.     else
  52.     {
  53.         printf("Characterized using Default Vref\n");
  54.     }
  55. }
  56.  
  57. void setup()
  58. {  
  59.     Serial.begin(115200);
  60.  
  61.     // Set GPIO High in order to measure HIGH value voltage.
  62.     pinMode(GPIO_NUM_17, OUTPUT);
  63.     digitalWrite(GPIO_NUM_17, HIGH);
  64.  
  65.     //Check if Two Point or Vref are burned into eFuse
  66.     check_efuse();
  67.  
  68.     //Characterize ADC at particular atten
  69.     adc_chars = (esp_adc_cal_characteristics_t *)calloc(1, sizeof(esp_adc_cal_characteristics_t));
  70.     esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, width, DEFAULT_VREF, adc_chars);
  71.     print_char_val_type(val_type);
  72.  
  73.     // Routing ADC reference voltage to GPIO, so it can be manually measured (for Default Vref):
  74.     esp_err_t status = adc2_vref_to_gpio(GPIO_NUM_25);
  75.     if (status == ESP_OK)
  76.     {
  77.         printf("v_ref routed to GPIO25\n");
  78.     }
  79.     else
  80.     {
  81.         printf("failed to route v_ref\n");
  82.     }
  83.  
  84. }
  85.  
  86. void loop()
  87. {
  88.     uint32_t adc_reading = 0;
  89.     static int16_t dac_counter = 0;
  90.     uint32_t voltage = 0;
  91.     int Buffer = 0;  // Serial buffer
  92.  
  93.  
  94.     // Read serial input to update DAC value
  95.     if(Serial.available() > 0)
  96.     {
  97.         Buffer =  Serial.parseInt();
  98.         if ((Buffer < 0) || (Buffer > 255)){
  99.             Serial.println("Input number is invalid.");
  100.         }
  101.         else{
  102.             Serial.print("Number is: ");
  103.             Serial.println(Buffer);
  104.             dac_counter = Buffer;
  105.         }
  106.     }
  107.  
  108.     // write dac value
  109.     dacWrite(GPIO_NUM_26, dac_counter);
  110.  
  111.    
  112.     // Reading ADC value
  113.     unsigned long adc_conv_time = micros();
  114.     for (int i = 0; i < NO_OF_SAMPLES; i++)
  115.         {
  116.             adc_reading += analogRead(GPIO_NUM_34);
  117.         }
  118.     // Calcualate mean value
  119.     unsigned long adc_conv_time1 = micros() - adc_conv_time;
  120.     adc_reading /= NO_OF_SAMPLES;
  121.     voltage = esp_adc_cal_raw_to_voltage(adc_reading, adc_chars);
  122.     unsigned long adc_conv_time2 = micros() - adc_conv_time;
  123.    
  124.     // Print values
  125.     Serial.print("DAC: ");
  126.     Serial.print(dac_counter);
  127.     Serial.print("  Raw voltage: ");
  128.     Serial.print(adc_reading);
  129.     Serial.print("  Voltage: ");
  130.     Serial.print(voltage);
  131.     Serial.print("  Time adc: ");
  132.     Serial.print(adc_conv_time1);
  133.     Serial.print("  Time calculus: ");
  134.     Serial.println(adc_conv_time2);
  135.    
  136.     delay(1000);
  137.  
  138. }

Re: Is there anything to do to make the adc2_vref_to_gpio () function work?

Posted: Tue Sep 01, 2020 1:52 am
by lbernstone
This code works for me, and gives me a pretty consistent reading at 1113mV.

Code: Select all

#include <driver/adc.h>
gpio_num_t ref_pin = (gpio_num_t) 25;
void setup() {adc2_vref_to_gpio(ref_pin);}
void loop() {}

Re: Is there anything to do to make the adc2_vref_to_gpio () function work?

Posted: Tue Sep 01, 2020 1:07 pm
by jhmluna
lbernstone wrote: This code works for me, and gives me a pretty consistent reading at 1113mV.

Code: Select all

#include <driver/adc.h>
gpio_num_t ref_pin = (gpio_num_t) 25;
void setup() {adc2_vref_to_gpio(ref_pin);}
void loop() {}
Hello.
It is basically the same code I used.
If I write only your code it works, but if I use the adc2_vref_to_gpio() function in the same way in my code, it will stop working.
So, I think there is some incompatibility between the adc2_vref_to_gpio() function and some of the resources that I am using. Perhaps ADC1 or DAC2. I dont know...

Re: Is there anything to do to make the adc2_vref_to_gpio () function work?

Posted: Tue Sep 01, 2020 2:59 pm
by lbernstone
If you want a consistent voltage on the pin, calibrate during setup with the vref, then use the dac to recreate that signal.

Re: Is there anything to do to make the adc2_vref_to_gpio () function work?

Posted: Tue Sep 01, 2020 3:40 pm
by jhmluna
Hello @lbernstone
Thank you for your attention.
As for my application, I was able to get around this problem, so it is no longer a problem for me.
However, I decided to post because I think this is a bug in the Arduino framework.
I hope someone from the Espressif development takes a look at the post and gives an opinion.

Re: Is there anything to do to make the adc2_vref_to_gpio () function work?

Posted: Mon Jan 25, 2021 4:34 pm
by bikerbill
Hi, i was testing this too and i was able to run your code (thanks for posting, it helped educate me). I don't think this is a bug, if you add a 10sec delay after esp_err_t status = adc2_vref_to_gpio(GPIO_NUM_25) before you do anything else with the ADC2 then it works fine. i read my Vref as 1.115v. as you said, something later on in your code seems to be disturbing this setup but the function itself appears to work ok.
regards bikerbill.