Get efuse vref value in code, "espefuse.py --port [PORT] adc_info" equivalent in onboard code?
Get efuse vref value in code, "espefuse.py --port [PORT] adc_info" equivalent in onboard code?
Hi there,
Anyone know if I can get the value of the reference voltage (vref) burned in efuse through a built in esp-idf function?
I know I can get it "outside of the board" with espefuse.py --port [PORT] adc_info, but I like to use and display the vref value per board. Mostly out of curiosity
Anyone know if I can get the value of the reference voltage (vref) burned in efuse through a built in esp-idf function?
I know I can get it "outside of the board" with espefuse.py --port [PORT] adc_info, but I like to use and display the vref value per board. Mostly out of curiosity
Re: Get efuse vref value in code, "espefuse.py --port [PORT] adc_info" equivalent in onboard code?
Alright. I found a way of getting my vref value and for example the mac address in code. I think there should be a way of using esp_efuse_read_field_blob for the vref too... And probably multiple other ways as well. But I wasn't able to adapt it for the vref register yet... perhaps someone else knows? I ended up copying the code that was in esp_adc_cal.c with the function: read_efuse_vref :
Code: Select all
#include "esp_efuse.h"
#include "soc/efuse_reg.h"
#include "esp_efuse_table.h"
#include "soc/efuse_periph.h"
#include "esp_err.h"
#include "esp_adc_cal.h"
#define VREF_FORMAT 0
#define VREF_REG EFUSE_BLK0_RDATA4_REG
#define VREF_MASK 0x1F
#define VREF_STEP_SIZE 7
#define VREF_OFFSET 1100
static inline int decode_reg_bits(uint32_t bits, uint32_t mask, bool is_twos_compl)
{
int ret;
if (bits & (~(mask >> 1) & mask)) { //Check sign bit (MSB of mask)
//Negative
if (is_twos_compl) {
ret = -(((~bits) + 1) & (mask >> 1)); //2's complement
} else {
ret = -(bits & (mask >> 1)); //Sign-magnitude
}
} else {
//Positive
ret = bits & (mask >> 1);
}
return ret;
}
static uint32_t read_efuse_vref_reg(void)
{
//eFuse stores deviation from ideal reference voltage
uint32_t ret = VREF_OFFSET; //Ideal vref
uint32_t bits = REG_GET_FIELD(VREF_REG, EFUSE_ADC_VREF);
ret += decode_reg_bits(bits, VREF_MASK, VREF_FORMAT) * VREF_STEP_SIZE;
return ret; //ADC Vref in mV
}
void read_efuse_values(){
uint8_t mac[6];
ESP_ERROR_CHECK(esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, &mac, sizeof(mac) * 8));
printf("1. read MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
uint32_t efuse_vref = read_efuse_vref_reg();
printf("2. ADC_VREF from eFuse: %u mV\n", efuse_vref);
}
Re: Get efuse vref value in code, "espefuse.py --port [PORT] adc_info" equivalent in onboard code?
@oldndumb, I love your sketch, but do not yet understand how it works. Could you maybe explain? Below what I was using to read Vref:
Below one return value that different for each device:
The return for one of the device:
Code: Select all
#include "esp_adc_cal.h"
void setup() {
Serial.begin(115200);
while (!Serial) {}
//Read eFuse Voltage Refference
esp_adc_cal_characteristics_t adc_chars; //declaring ADC calibration variable adc_chars
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, 1100, &adc_chars); //characterizing the ADC calibration function ADC_UNIT_1 or ADC_UNIT_2
Serial.println(); Serial.print("eFuse-Vref:"); Serial.print(adc_chars.vref); Serial.println(); //reading the actual internal refference voltage
}
void loop() {
}
And for the MAC, I was reading registers before I found your code:eFuse-Vref:1086
Code: Select all
#include <soc/efuse_reg.h>
void setup() {
Serial.begin(115200);
while (!Serial) {}
//Read all registers of eFuse Block 0
uint32_t blk0reg0 = REG_READ(EFUSE_BLK0_RDATA0_REG), blk0reg1 = REG_READ(EFUSE_BLK0_RDATA1_REG), blk0reg2 = REG_READ(EFUSE_BLK0_RDATA2_REG), blk0reg3 = REG_READ(EFUSE_BLK0_RDATA3_REG),
blk0reg4 = REG_READ(EFUSE_BLK0_RDATA4_REG), blk0reg5 = REG_READ(EFUSE_BLK0_RDATA5_REG), blk0reg6 = REG_READ(EFUSE_BLK0_RDATA6_REG); //blk0reg7 = REG_READ(EFUSE_BLK0_RDATA7_REG) did not work
//Print all registers of eFuse Block 0
Serial.println(); Serial.println();
Serial.print("Block 0 non HEX: "); Serial.print(blk0reg0); Serial.print(blk0reg1); Serial.print(blk0reg2);
Serial.print(blk0reg3); Serial.print(blk0reg4); Serial.print(blk0reg5); Serial.print(blk0reg6); Serial.println(); //Serial.print(blk0reg7)
//HEX Print all registers of eFuse Block 0
Serial.println("Block 0 HEX:");
Serial.print("Block 0, Register 0: "); Serial.println(blk0reg0, HEX);
Serial.print("Block 0, Register 1: "); Serial.println(blk0reg1, HEX);
Serial.print("Block 0, Register 2: "); Serial.println(blk0reg2, HEX);
Serial.print("Block 0, Register 3: "); Serial.println(blk0reg3, HEX);
Serial.print("Block 0, Register 4: "); Serial.println(blk0reg4, HEX);
Serial.print("Block 0, Register 5: "); Serial.println(blk0reg5, HEX);
Serial.print("Block 0, Register 6: "); Serial.println(blk0reg6, HEX);
//Serial.print("Block 0, Register 7: "); Serial.println(blk0reg7, HEX);
}
void loop() {
}
Whereby the last 4 digits of Block 0, Register 2 (first one or two is the checksum) + Register 1 is the MAC 30C6F71DD3B8. And I also could not read the last Resister 7 for some reason. Also have lost time with esp_efuse_read_field_blob and could not find a working sample sketch.Block 0, Register 0: 0
Block 0, Register 1: F71DD3B8
Block 0, Register 2: 330C6
Block 0, Register 3: A000
Block 0, Register 4: 1236
Block 0, Register 5: 100000
Block 0, Register 6: 4
Re: Get efuse vref value in code, "espefuse.py --port [PORT] adc_info" equivalent in onboard code?
@johann75
Seems you are using the arduino platform and not esp-idf.
There's no point in explaining. To use these functions you need all the #includes.
Unless you have a very specific question regarding my code, you're better off asking arduino platform questions in the arduino forum. Try to make very clear what you actually want to achieve and why you were unable to so far.
Seems you are using the arduino platform and not esp-idf.
There's no point in explaining. To use these functions you need all the #includes.
Unless you have a very specific question regarding my code, you're better off asking arduino platform questions in the arduino forum. Try to make very clear what you actually want to achieve and why you were unable to so far.
Re: Get efuse vref value in code, "espefuse.py --port [PORT] adc_info" equivalent in onboard code?
@oldndumb, I am using your function. All works for me just fine. All ESP-IDF works good for me on Arduino and Platform IO.
Also wondering, why do you need to read the eFuse voltage reference and how do you use it? I have mesured the actual ESP32 internal reference voltage on a few boards and results are not matching with eFuse:
TTGO 1: eFuse: 1086. Actually mesured: 1078
TTGO 2: eFuse: 1100. Actually mesured: 1080
Using the below to route internal voltage reference to a physical GPIO and works fine on ESP-IDF and Arduino:
Also wondering, why do you need to read the eFuse voltage reference and how do you use it? I have mesured the actual ESP32 internal reference voltage on a few boards and results are not matching with eFuse:
TTGO 1: eFuse: 1086. Actually mesured: 1078
TTGO 2: eFuse: 1100. Actually mesured: 1080
Using the below to route internal voltage reference to a physical GPIO and works fine on ESP-IDF and Arduino:
Code: Select all
#include <driver/adc.h> //ADC driver or include esp_adc_cal.h Both work
void setup() {
esp_err_t status = adc_vref_to_gpio(ADC_UNIT_2, GPIO_NUM_26);
if (status == ESP_OK) {
printf("\nv_ref routed to desired GPIO\n");
} else {
printf("failed to route v_ref\n");
}
}
void loop() {
}
Re: Get efuse vref value in code, "espefuse.py --port [PORT] adc_info" equivalent in onboard code?
@johann75
What is your actual question? You're requiring me to spend time reading your long posts but, it isn't clear what you actually want. So please be more specific.
//or did you just want to share your solution to find vref? With the struct member adc_chars.vref and the calibration function that populates it. Which is simpler. That wasn't really clear.
Stand by the request for a more specific question if you've got one though. Explaining my whole 'sketch' is more work than writing it
What is your actual question? You're requiring me to spend time reading your long posts but, it isn't clear what you actually want. So please be more specific.
//or did you just want to share your solution to find vref? With the struct member adc_chars.vref and the calibration function that populates it. Which is simpler. That wasn't really clear.
Stand by the request for a more specific question if you've got one though. Explaining my whole 'sketch' is more work than writing it
Re: Get efuse vref value in code, "espefuse.py --port [PORT] adc_info" equivalent in onboard code?
@oldndumb, I was wondering, what do you need the voltage refference for and how do you calibrate ADC?
Re: Get efuse vref value in code, "espefuse.py --port [PORT] adc_info" equivalent in onboard code?
@oldndumb , I could not understand how you convert REG_GET_FIELD to human readable values. But at most, for what reason do you read eFuse and how do you use the data. Also, what is you methode to calibrate ADC?
Re: Get efuse vref value in code, "espefuse.py --port [PORT] adc_info" equivalent in onboard code?
This is done with the decode_reg_bits function.
In it you see a lot of bitwise operations.
>> means right shift, moving a binary number a number of bits to the right.
& means bitwise AND. With it you can set certain regbits to 0.
| means bitwise OR. Which lets you set certain regbits to 1.
~ means NOT. Which lets you invert a number.
The other thing to read up on to grasp the function is two's complient, which tells you how (negative) numbers are stored in memory, where you can only store 1s and 0s. And msb (most significant bit) which tells you how a number is aligned when stored in memory.
Used the vref value to check battery voltage level deviance across devices. I think the value stored in efuse should get you pretty close. Measuring might lead to improvements. But if I remember correctly the value deviates a bt depending on the boards temperature.... So hard to get an absolute value... But for my use case accuracy is not crucial anyway. Keep in mind the esp32 adc's aren't very accurate to begin with.
In it you see a lot of bitwise operations.
>> means right shift, moving a binary number a number of bits to the right.
& means bitwise AND. With it you can set certain regbits to 0.
| means bitwise OR. Which lets you set certain regbits to 1.
~ means NOT. Which lets you invert a number.
The other thing to read up on to grasp the function is two's complient, which tells you how (negative) numbers are stored in memory, where you can only store 1s and 0s. And msb (most significant bit) which tells you how a number is aligned when stored in memory.
Used the vref value to check battery voltage level deviance across devices. I think the value stored in efuse should get you pretty close. Measuring might lead to improvements. But if I remember correctly the value deviates a bt depending on the boards temperature.... So hard to get an absolute value... But for my use case accuracy is not crucial anyway. Keep in mind the esp32 adc's aren't very accurate to begin with.
Re: Get efuse vref value in code, "espefuse.py --port [PORT] adc_info" equivalent in onboard code?
@oldndumb, completely agree with you. ESP32 ADC is completely inaccurate. eFuse value is closer to actial voltage refference, but still useless. Not only eFuse, actually red Refference Voltage cannot really be used. The only more or les working ESP32 ADC calibration methode I have found so far is be the below, but I am still exploring other methodes: https://github.com/e-tinkers/esp32-adc-calibrate
But still wandering, how do you user eFuse Vref? Could you share you sketch example?
But still wandering, how do you user eFuse Vref? Could you share you sketch example?
Who is online
Users browsing this forum: iParcelBox and 87 guests