Skip to content

Difference between Arduino ADC read and esp-idf-hal read #550

@BoguesUser

Description

@BoguesUser

Bug description

The oneshot api is providing different values than I am expecting to see from an ADC read.
Adc.read() appears to apply an incorrect calibration value driving the output to be much lower than expected. The Raw values seem to agree however.

To Reproduce

I have pin 7 hooked up to a voltage divider providing about 0.876v

use esp_idf_hal::{adc::{attenuation, oneshot::{config::{AdcChannelConfig, Calibration, Resolution}, 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: Resolution::Resolution12Bit,
        calibration: Calibration::None
    };

    let mut tank_channel_driver = AdcChannelDriver::new(tank_driver, peripherals.pins.gpio7, &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!("Value is {}, Raw is {}", 3.3*(value as f32/4095.0), 3.3*(raw_value as f32/4095.0));
    }
    // Actual voltage 7.332v
    // Actual V_Div 0.8076v
    // Arduino val: Calibrated 0.79v, Raw 0.7374v
    // Actual output (Curve); Value is 0.63663006 Raw is 0.7373626
    // Actual output (None); Value is 0.5544322 Raw is 0.7373626
}

Here is my Arduino code for comparison

// Select the GPIO pin we are reading
const int adcPin = 7;

void setup() {
  // Start the serial connection
  Serial.begin(115200);
  delay(1000);
  Serial.println("Hello");

  // Set up the basics of my ADC. 12 bit resolution, ~(0v - 3.3v Range)
  analogReadResolution(12);
  analogSetAttenuation(ADC_11db);

}

void loop() {

  Serial.println(analogRead(adcPin));

  // Wait 100 milliseconds
  delay(100);
}

Expected behavior

I'd expect read() to read the same values from both the arduino code and the esp-idf-hal. The calibration seems to be pretty far off though and I'm not sure why.

// Actual V_Div 0.8076v
// Arduino val: Calibrated 0.79v, Raw 0.7374v
// Actual output (Curve); Value is 0.63663006 Raw is 0.7373626
// Actual output (None); Value is 0.5544322 Raw is 0.7373626

Environment

  • Crate (esp-idf-hal) version: 0.45.2
  • Crate (esp-idf-svc) version: 0.51.0
  • Crate (esp-idf-sys) version: 0.36.1
  • ESP-IDF branch or tag: 5.3.4
  • Target device (MCU): esp32s3
  • OS: Arch Linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions