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

ESP32C6 analog read working wonky

Open empirephoenix opened this issue 3 months ago • 1 comments

The analog abstraction does not seem to work correctly. When using Any other Attenuation than 0db, the reported mv values are way off. (This seem to be both the case with calibration=true or not). read_raw might be correct. Additionally the 11db attenuation does not exist for the c6 but it uses a 12db attenuation instead.

The issue sounds similar to this one. https://www.esp32.com/viewtopic.php?t=33015.

empirephoenix avatar May 10 '24 22:05 empirephoenix

Your information are a little sparse. We have wrappers for the legacy adc api and the oneshort / continouse measurement api? I assume you only used the legacy api? What esp-idf version where you using? How did your test-code look like?

Vollbrecht avatar May 11 '24 08:05 Vollbrecht

Ok finally got time to go further here: Basically it is just a devboard, with a adjustable power supply connected with GND and GPIO5.

Useing the legacy api I guess (see code at end):

ESP32C6 Power supply at 0V: All Attunations: Valie is 0 raw is 0

ESP32C6 Power supply at 1.0V (switching calibration to true did not seem to do a difference here):

  • NONE: Valie is 685 raw is 3808
  • attenuation::DB_2_5: Valie is 726 raw is 2833
  • attenuation::DB_6: Valie is 609 raw is 1905
  • attenuation::DB_11: Valie is 615 raw is 1008 Note: if i half the voltage the raw value roughly halfes as well, so it is actually measuring something, but it is strangly offsetted.

ESP32C3 Power supply at 1.0V (needed to switch to adc2 for this one):

  • NONE: Valie is 750 raw is 4095
  • attenuation::DB_2_5: Valie is 904 raw is 3519
  • attenuation::DB_6: Valie is 807 raw is 2603
  • attenuation::DB_11: Valie is 815 raw is 1307

ESP32 (M5 Echo) Power supply at 1.0V (needed to switch gpio to 21):

  • NONE: Valie is 950 raw is 4095
  • attenuation::DB_2_5: Valie is 952 raw is 3099
  • attenuation::DB_6:Valie is 957 raw is 2117
  • attenuation::DB_11: Valie is 700 raw is 1168 (using calibration=true improved to Valie is 1024 raw is 1115)

code for the c6 is this:


use esp_idf_hal::{adc::{attenuation, AdcChannelDriver, AdcDriver}, delay::Delay, gpio::{ADCPin, Gpio5}, peripherals::Peripherals};


fn main() {
    esp_idf_svc::sys::link_patches();

    // Bind the log crate to the ESP Logging facilities
    esp_idf_svc::log::EspLogger::initialize_default();

    let peripherals = Peripherals::take().unwrap();
    let adc_config = esp_idf_hal::adc::config::Config {
        resolution: esp_idf_hal::adc::config::Resolution::Resolution12Bit,
        calibration: false,
    };
    let mut tank_driver = AdcDriver::new(peripherals.adc1, &adc_config).unwrap();
    let mut tank_channel: AdcChannelDriver<'_, { attenuation::DB_2_5 }, Gpio5> =
        AdcChannelDriver::new(peripherals.pins.gpio5).unwrap();

    let delay = Delay::new(1);
    loop {
        delay.delay_ms(500);
        let value = tank_driver.read(&mut tank_channel).unwrap();
        let raw_value = tank_driver.read_raw(&mut tank_channel).unwrap();
        println!("Valie is {} raw is {}",  value, raw_value);
    }
}

After this I tested with the oneshot:

ESP32C6 Power supply at 1.0V:

  • NONE: Valie is 1005 raw is 3744
  • attenuation::DB_2_5: Valie is 989 raw is 2833
  • attenuation::DB_6: Valie is 995 raw is 1921
  • attenuation::DB_11: Valie is 1031 raw is 993

I guess it is pretty safe to say, that the legacy api does not seem to work for the ESP32C6 (and C3). The raw values seem to be similar but the calculated voltage is way off, while it does seem to be ok with oneshot. Is this a bug or a issue with the legacy api?

oneshot code here:


use esp_idf_hal::{adc::{attenuation, oneshot::{config::AdcChannelConfig, AdcChannelDriver, AdcDriver}}, delay::Delay, peripherals::Peripherals};


fn main() {
    // It is necessary to call this function once. Otherwise some patches to the runtime
    // implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
    esp_idf_svc::sys::link_patches();

    // Bind the log crate to the ESP Logging facilities
    esp_idf_svc::log::EspLogger::initialize_default();

    log::info!("Hello, world!");


    let peripherals = Peripherals::take().unwrap();
    let tank_driver = AdcDriver::new(peripherals.adc1).unwrap();
    let config = AdcChannelConfig {
        attenuation:attenuation::DB_11,
        resolution : esp_idf_hal::adc::config::Resolution::Resolution12Bit,
        calibration: false
    };
        

    let mut tank_channel_driver = AdcChannelDriver::new(tank_driver, peripherals.pins.gpio5, &config).unwrap();

    let delay = Delay::new(1);
    loop {
        delay.delay_ms(500);
        let value = tank_channel_driver.read().unwrap();
        let raw_value = tank_channel_driver.read_raw().unwrap();
        println!("Valie is {} raw is {}",  value, raw_value);
    }
}

empirephoenix avatar May 14 '24 19:05 empirephoenix

if you have a look at the official supported version schema for esp-idf and the mcu's you see that since the c6 is a fairly new esp and its only supported since 5.1. And since they deprecated the old api with v5 they did not put any development into it for there newer chip. So they only work on a best effort way. So for newer esp's i would try to only use the oneshot/continuous adc api.

Vollbrecht avatar May 14 '24 19:05 Vollbrecht

I see, a bit disappointing that they care so little but at least not a bug then. I added a comment for others in the first post, so others that end up here see it.

empirephoenix avatar May 14 '24 20:05 empirephoenix