ADC Direct register programming...

FX2032
Posts: 4
Joined: Sun Nov 17, 2024 8:57 pm

ADC Direct register programming...

Postby FX2032 » Wed Nov 20, 2024 7:20 pm

I am trying to better understand the basics of the ESP32-S3 registers.
I wish to run a simple test ADC conversion on GPIO pin 2. But am unable to get the ADC running.
I can use the APIs:

adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(ADC1_CHANNEL_1,ADC_ATTEN_DB_0);
val = adc1_get_raw(ADC1_CHANNEL_1);


Which works OK (I seem unable to actually trace what registers adc1_get_raw(ADC1_CHANNEL_1) actually manipulates.)

My own code is:
SET_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_PWM0_CLK_EN );

SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD2_REG, RTC_IO_TOUCH_PAD2_MUX_SEL); // Contrary to table 6-5 Analog Select should =1;
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD2_REG, RTC_IO_TOUCH_PAD2_RDE | RTC_IO_TOUCH_PAD2_RUE | RTC_IO_TOUCH_PAD2_FUN_IE);

WRITE_PERI_REG(SENS_SAR_ATTEN1_REG,0xFFFFFFF3);
SET_PERI_REG_MASK(SENS_SAR_PERI_CLK_GATE_CONF_REG, SENS_IOMUX_CLK_EN | SENS_SARADC_CLK_EN);
WRITE_PERI_REG(SENS_SAR_READER1_CTRL_REG, SENS_SAR1_INT_EN | 1 << SENS_SAR1_CLK_DIV_S);

WRITE_PERI_REG(SENS_SAR_MEAS1_CTRL2_REG, SENS_SAR1_EN_PAD_FORCE | 0b10<<SENS_SAR1_EN_PAD_S | SENS_MEAS1_START_FORCE);

SET_PERI_REG_MASK(SENS_SAR_MEAS1_CTRL2_REG, SENS_MEAS1_START_SAR);

while (!(READ_PERI_REG(SENS_SAR_MEAS1_CTRL2_REG) & SENS_MEAS2_DONE_SAR)) {

}
val =READ_PERI_REG(SENS_SAR_MEAS1_CTRL2_REG);

The code runs but strangely give ADC values that are much too high. (Checked with a controlled test voltage <1V)
I have compared all the registers I can think of, and they are all the same, although I am mystified why the "analog function =1" is not used. I have also double checked the attenuation registers. So what am I missing?!

I would also like to understand what the Calibration API actually does.. like where and what are the calibration settings that are programmed into the ESP32 memory.

FX2032
Posts: 4
Joined: Sun Nov 17, 2024 8:57 pm

Re: ADC Direct register programming...

Postby FX2032 » Thu Nov 21, 2024 11:30 pm

So with some help from ChatGpt and much MUCH.. digging and reverse engineering of the header files, what seems to happen is when you use some of the ADC APIs, the code actually pulls out a table of "Attenuation values" from the EFuses on the ESP32, at boot up.

When you then call the API to do an ADC readout, it copies the used values via the internal I2C into some part of the ADC, which then uses them to fiddle the values returned by the register calls!

This is not a simple case of calibration though as even with no set pin attenuation level, and voltages well below the reference voltage of the device, the "virgin" raw registry data has a very non linear response to input voltage and will actually give a full scale reading at less than half the reference voltage.

My great frustration with all this however is that none of this is mentioned in the Technical Reference Manual. Most embedded ADC peripherals have some non-linearity and offset, and calibration values are only really needed to obtain better accuracy. In this case however, you can't use the thing without AND there seems to be no information mentioning any of this! It begs the question why go to the bother of listing the various registers at all?!

Who is online

Users browsing this forum: No registered users and 178 guests