esp-hal icon indicating copy to clipboard operation
esp-hal copied to clipboard

Double check results from calibrated ADC readings

Open bjoernQ opened this issue 1 year ago • 7 comments
trafficstars

At least on C6 we see suspicious results.

e.g. for AdcCalCurve

PIN2 ADC reading = 7734 mV
PIN2 ADC reading = 6681 mV
PIN2 ADC reading = 6832 mV
PIN2 ADC reading = 6992 mV

for AdcCalLine

PIN2 ADC reading = 7985 mV
PIN2 ADC reading = 7343 mV
PIN2 ADC reading = 7506 mV
PIN2 ADC reading = 7007 mV
PIN2 ADC reading = 7017 mV
PIN2 ADC reading = 7506 mV

AdcCalBasic

PIN2 ADC reading = 8223 mV
PIN2 ADC reading = 7218 mV
PIN2 ADC reading = 7385 mV
PIN2 ADC reading = 7553 mV
PIN2 ADC reading = 7207 mV
PIN2 ADC reading = 7385 mV

bjoernQ avatar Feb 26 '24 15:02 bjoernQ

Not sure what's going on here, but based on my testing C6 worked without issue. I did see incorrect readings for the C3 and S3, however.

Possibly due to different chip revisions or something? Not sure, needs further investigating. I did double-check the curve coefficients at the very least and they seem to be more or less correct.

jessebraham avatar Mar 26 '24 15:03 jessebraham

I've just done a quick round of testing on all devkits I have available to me. I've included the revisions as reported by espflash board-info as this may make a difference. Values listed in each column are when connected to the GND and 3V3 pins respectively, and are printed by the adc_cal and adc examples.

Anyway, results are all over the place, so we need to spend some time fixing all this for sure.

Chip None (GND/3V3) Basic (GND/3V3) Line (GND/3V3) Curve (GND/3V3)
ESP32 (v3.0) 4095/4095
ESP32-C2 (v1.0) 2138/4095 0/3450 0/3343
ESP32-C3 (v0.3) 1690/4095 7/4095 5/2960 6/2860
ESP32-C6 (v0.0) 2160/4081 1/3393 0/3262 0/3250
ESP32-H2 (v0.0) 2160/4081
ESP32-S2 (v0.0) 8192/3470
ESP32-S3 (v0.1) 1960/4095 0/4096 0/3456 0/64562

I know it's a bit of a pain, but if 1 or 2 other people would be able to do this same test that would be helpful. More data won't hurt here.

jessebraham avatar Jun 10 '24 16:06 jessebraham

Chip None (GND/3V3) Basic (GND/3V3) Line (GND/3V3) Curve (GND/3V3)
ESP32 (v1.0) 0/4095
ESP32-C2 (v2.0) 2155/4095 0/3460 0/3308
ESP32-C3 (v0.3) 1674/4095 10/4095 10/2885 13/2796
ESP32-C6 (v0.0) 2145/4081 1/3377 5/35367❓ 0/34789 ❓
ESP32-H2 (v0.1) 2144/4081
ESP32-S2 (v0.0) 2825/8191
ESP32-S3 (v0.1) 1971/4095 0/4095 0/3540 0/3159

  • ESP32: the example should use GPIO32 but I only get readings when using GPIO33

bjoernQ avatar Jun 11 '24 08:06 bjoernQ

Chip None (GND/3V3) Basic (GND/3V3) Line (GND/3V3) Curve (GND/3V3)
ESP32 (v3.0) 3830/4095
ESP32-C2 (v2.0) 2180/4095 1/3431 1/3374
ESP32-C3 (v0.3) 1693/4095 3/4095 3/2949 3/2852
ESP32-C6 (v0.0) 2160/4081 0/3313 0/3295 0/3283
ESP32-H2 (v0.2) 2160/4081
ESP32-S2 (v0.0) 2821/8191

I don't have S3 right now.

JurajSadel avatar Jun 11 '24 08:06 JurajSadel

My results with adc_cal example from esp-hal (d2a9389):

Board Chip None Basic Line Curve
ESP32-C3-DevKitC-02 "1.1" ESP32-C3 (v0.4) 1680..1689 / 4095 0 / 4095 0..1 / 3014 1..2 / 2906
ESP32-C3-DevKit-RUST-1 "1.2a 04/2022" ESP32-C3 (v0.4) 1680..1690 / 4095 0..18 / 4095 5..17 / 3040 6..14 / 2927
ESP32-C6-DevKitM-1 "1.0" ESP32-C6 (v0.0) 2176..2177 / 4081 0..1 / 3281..3297 0..1 / 3304..3321 0..1 / 3292..3309

Values "gnd / 3v3" like from the other people. I don't know what to make of this. Hope it helps.

The quoted strings are what's seen on the underside of the dev board PCB. DevKitC was controlled by uart, others by JTAG (don't think that matters).

lure23 avatar Jun 12 '24 14:06 lure23

Thanks everybody for the additional info. I will start digging into this next week most likely.

jessebraham avatar Jun 12 '24 15:06 jessebraham

I did some more detailled measurements with my ESP32-S3-DevKitC-1. I connected a pot to GPIO3 and set some inbetween voltages. As you can see, all calibrated results below 0.3V are near 0, so there's a large gap, while the raw values are still changing. Above 3.0V, the curve calibration is completely broken.

Voltage None Basic Line Curve
0.0 1973 0 0 0
0.1 2095 0 0 0
0.2 2233 0 0 0
0.3 2348 93 83 83
0.4 2473 222 188 195
0.5 2582 331 275 285
0.6 2711 463 385 393
0.7 2857 614 512 518
0.8 2957 717 585 597
0.9 3079 829 689 694
1.0 3207 955 805 794
1.5 3870 1628 1349 1323
2.0 4095 2180 1830 1785
2.5 4095 2967 2465 2404
3.0 4095 3800 3172 64400
3.2 4095 4071 3395 65534

After doing these measurements, I did a quick check against the C example from the IDF and it shows that calibrated results start at about 25mV of input voltage. They are not very accurate, but they are not zeroed.

sourcebox avatar Jun 24 '24 09:06 sourcebox

@jessebraham did you manage to make some progress?

dimpolo avatar Jan 16 '25 17:01 dimpolo

Apologies for the lack of updates. We had decided that ADC was not a priority, and as such I spent my time elsewhere, so have not really made any progress on this front.

However, recently I discovered that the eFuse field definitions we parsed to generate each device's efuse module contain a number of errors, and have done a fair bit of work in espflash correcting this. This week I will port these changes over to esp-hal, and hopefully this will improve calibration given that we are reading certain values from eFuse fields where, in the HAL's current state, are probably incorrect.

I will post any updates here once I have completed this work. No guarantees it will resolve the issues, but I'm hoping it does.

jessebraham avatar Apr 22 '25 08:04 jessebraham

Maybe related: I find that readings become a lot better when first flashing ESP-IDF (the original C framework), which initializes the adc, and then overwrite with esp-hal firmware. This persists across reboots, but not after leaving it unpowered for some time.

All pins show 4095 when pulled up, but when pulled to GND I get wild results:

pin just esp-hal after one run esp-idf, then running esp-hal
GPIO2 (ADC1) 1980 0
GPIO16 (ADC2) 615 825

This is on ESP32S3 running 1.0.0-rc.0. Simple read_oneshot (haven't gotten into calibration yet)

mikabytes avatar Oct 15 '25 16:10 mikabytes

rc.1 received a fix or two that may be relevant. If you could please re-check your values with that, that would help.

bugadani avatar Oct 15 '25 16:10 bugadani

Tried again with rc.1 but it didn't show significant changes for me. However, switching from cfg.enable_pin to cfg.enable_pin_with_cal::<_, AdcCalLine<_>> was significant. Pins now show 0 when pulled to GND. So maybe what I was seeing was just some calibration done by IDF that was lingering around somehow. I'm sort of new to ESP programming so it's probably my mistake.

mikabytes avatar Oct 16 '25 11:10 mikabytes

I can confirm that ADC readings are much better now.

sourcebox avatar Oct 18 '25 12:10 sourcebox

I did some experiments (on the ESP32S3) to see what the state of the efuse situation is:

using espflash v4.2.0:

ADC1_INIT_CODE_ATTEN0: 121
ADC1_INIT_CODE_ATTEN1: 6
ADC1_INIT_CODE_ATTEN2: 24
ADC1_INIT_CODE_ATTEN3: 34
ADC1_CAL_VOL_ATTEN0: 93
ADC1_CAL_VOL_ATTEN1: 95
ADC1_CAL_VOL_ATTEN2: 86
ADC1_CAL_VOL_ATTEN3: 97
Ignore this one, I forgot to also use this change https://github.com/esp-rs/espflash/pull/961

~using espflash v4.2.0 with the change in https://github.com/esp-rs/espflash/pull/964/:~

ADC1_INIT_CODE_ATTEN0: 38
ADC1_INIT_CODE_ATTEN1: 6
ADC1_INIT_CODE_ATTEN2: 56
ADC1_INIT_CODE_ATTEN3: 41
ADC1_CAL_VOL_ATTEN0: 95
ADC1_CAL_VOL_ATTEN1: 86
ADC1_CAL_VOL_ATTEN2: 97
ADC1_CAL_VOL_ATTEN3: 126

using esp-hal v1.0.0:

ADC1_INIT_CODE_ATTEN0: 121
ADC1_INIT_CODE_ATTEN1: 38
ADC1_INIT_CODE_ATTEN2: 24
ADC1_INIT_CODE_ATTEN3: 34
ADC1_CAL_VOL_ATTEN0: 93
ADC1_CAL_VOL_ATTEN1: 95
ADC1_CAL_VOL_ATTEN2: 86
ADC1_CAL_VOL_ATTEN3: 97

So three different results 🫤

Testing code:

esp-flash
use espflash::connection::{Connection, ResetAfterOperation, ResetBeforeOperation};
use espflash::target::Chip;
use serialport::{FlowControl, SerialPortType};

fn main() {
    let chip = Chip::Esp32s3;

    let (port, usb_info) = serialport::available_ports()
        .unwrap()
        .into_iter()
        .filter_map(|info| match info.port_type {
            SerialPortType::UsbPort(usb_info) => {
                if usb_info.vid == 0x303a && usb_info.pid == 0x1001 {
                    let port = serialport::new(info.port_name, 115_200)
                        .flow_control(FlowControl::None)
                        .open_native()
                        .unwrap();

                    Some((port, usb_info))
                } else {
                    None
                }
            }
            _ => None,
        })
        .next()
        .unwrap();

    let mut connection = Connection::new(
        port,
        usb_info,
        ResetAfterOperation::HardReset,
        ResetBeforeOperation::DefaultReset,
        115_200,
    );
    connection.begin().unwrap();
    
    use espflash::target::efuse::esp32s3::*;
    for (field, name) in [
        (ADC1_INIT_CODE_ATTEN0, "ADC1_INIT_CODE_ATTEN0"),
        (ADC1_INIT_CODE_ATTEN1, "ADC1_INIT_CODE_ATTEN1"),
        (ADC1_INIT_CODE_ATTEN2, "ADC1_INIT_CODE_ATTEN2"),
        (ADC1_INIT_CODE_ATTEN3, "ADC1_INIT_CODE_ATTEN3"),
        (ADC1_CAL_VOL_ATTEN0, "ADC1_CAL_VOL_ATTEN0"),
        (ADC1_CAL_VOL_ATTEN1, "ADC1_CAL_VOL_ATTEN1"),
        (ADC1_CAL_VOL_ATTEN2, "ADC1_CAL_VOL_ATTEN2"),
        (ADC1_CAL_VOL_ATTEN3, "ADC1_CAL_VOL_ATTEN3"),
    ] {
        let value = chip.read_efuse(&mut connection, field).unwrap();
        println!("{}: {}", name, value);
    }
}
esp-hal
fn test(){
    use esp_hal::efuse::*;
    for (field, name) in [
        (ADC1_INIT_CODE_ATTEN0, "ADC1_INIT_CODE_ATTEN0"),
        (ADC1_INIT_CODE_ATTEN1, "ADC1_INIT_CODE_ATTEN1"),
        (ADC1_INIT_CODE_ATTEN2, "ADC1_INIT_CODE_ATTEN2"),
        (ADC1_INIT_CODE_ATTEN3, "ADC1_INIT_CODE_ATTEN3"),
        (ADC1_CAL_VOL_ATTEN0, "ADC1_CAL_VOL_ATTEN0"),
        (ADC1_CAL_VOL_ATTEN1, "ADC1_CAL_VOL_ATTEN1"),
        (ADC1_CAL_VOL_ATTEN2, "ADC1_CAL_VOL_ATTEN2"),
        (ADC1_CAL_VOL_ATTEN3, "ADC1_CAL_VOL_ATTEN3"),
    ] {
        let value: u16 = Efuse::read_field_le(field);
        println!("{}: {}", name, value);
    }
}

Edit:

using esptool:

> espefuse --port COM7 adc-info 
espefuse v5.1.0
Connecting...
Detecting chip type... ESP32-S3

=== Run "adc-info" command ===

Block version: 103
Temperature Sensor Calibration = -8.3C
ADC OCode        =  84
ADC1:
INIT_CODE_ATTEN0 =  484
INIT_CODE_ATTEN1 =  -24
INIT_CODE_ATTEN2 =  96
INIT_CODE_ATTEN3 =  -8
CAL_VOL_ATTEN0   =  372
CAL_VOL_ATTEN1   =  380
CAL_VOL_ATTEN2   =  344
CAL_VOL_ATTEN3   =  388

Edit 2

Ok, so the issue is on the espflash side, see https://github.com/esp-rs/espflash/issues/960

Now I'm just curios about the difference between the esp-hal and esptool

dimpolo avatar Nov 13 '25 10:11 dimpolo