esp-hal
esp-hal copied to clipboard
Double check results from calibrated ADC readings
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
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.
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.
| 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
| 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.
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).
Thanks everybody for the additional info. I will start digging into this next week most likely.
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.
@jessebraham did you manage to make some progress?
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.
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)
rc.1 received a fix or two that may be relevant. If you could please re-check your values with that, that would help.
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.
I can confirm that ADC readings are much better now.
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