esp-rs / esp32-hal

A hardware abstraction layer for the esp32 written in Rust.
Apache License 2.0
192 stars 28 forks source link

Unexpected results from the ADC #65

Open lily-mara opened 2 years ago

lily-mara commented 2 years ago

I am trying to use several of the ESP crates together in a program, and I seem to be getting inconsistent results from the ADC when using this crate. I have created a minimum program to demonstrate the issue. This program reads the raw value from GPIO pin 33 and prints it to a newline on the serial interface. I wrote the same program in the Arduino IDE to validate that I do not have an issue with my hardware or circuit:

Arduino code

void setup() {
  Serial.begin(115200);
}

void loop() {
  Serial.println(analogRead(33));
  delay(200);
}

Rust code

Cargo.toml

[package]
name = "esp32-gpio"
version = "0.1.0"
edition = "2018"

[profile.release]
debug = true
opt-level = "z"

[profile.dev]
opt-level = "s"

[features]
bind = []

[dependencies]
anyhow = { version = "1", features = ["backtrace"] }
esp-idf-svc = { version = "0.20", features = ["binstart"] }
esp-idf-hal = "0.20"
esp32-hal = "0.3"
esp32 = "0.11.0"

[build-dependencies]
embuild = "0.24"
anyhow = "1"

build.rs

use std::path::PathBuf;

use embuild::{
    self, bingen,
    build::{CfgArgs, LinkArgs},
    cargo, symgen,
};

// Necessary because of this issue: https://github.com/rust-lang/cargo/issues/9641
fn main() -> anyhow::Result<()> {
    LinkArgs::output_propagated("ESP_IDF")?;

    let cfg = CfgArgs::try_from_env("ESP_IDF")?;

    if cfg.get("esp32s2").is_some() {
        let ulp_elf = PathBuf::from("ulp").join("esp32-gpio");
        symgen::run(dbg!(&ulp_elf), 0x5000_0000)?; // This is where the RTC Slow Mem is mapped within the ESP32-S2 memory space
        bingen::run(&ulp_elf)?;

        cargo::track_file(ulp_elf);
    }

    cfg.output();

    Ok(())
}

.cargo/config

[build]
target = "xtensa-esp32-espidf"

[target.xtensa-esp32-espidf]
linker = "ldproxy"

[unstable]
build-std = ["std", "panic_abort"]
build-std-features = ["panic_immediate_abort"]

[env]
ESP_IDF_SYS_GLOB_BASE = { value = ".", relative = true }

ESP_IDF_SYS_GLOB_0 = { value = "/sdkconfig.release" }
ESP_IDF_SYS_GLOB_1 = { value = "/sdkconfig.debug" }
ESP_IDF_SYS_GLOB_2 = { value = "/sdkconfig.defaults" }

src/main.rs

use std::{thread, time::Duration};

use anyhow::Result;

use esp32_hal::analog::adc::ADC;
use esp32_hal::analog::config::Adc1Config;
use esp32_hal::analog::config::Attenuation;
use esp32_hal::analog::SensExt;
use esp32_hal::gpio::GpioExt;
use esp32_hal::gpio::*;

fn main() -> Result<()> {
    // Reference to the esp_idf_svc crate to setup app_main for us
    let _ = esp_idf_svc::sysloop::EspSysLoopStack::new();

    let periphs = esp32::Peripherals::take().unwrap();
    let gpio = periphs.GPIO.split();
    let sensors = periphs.SENS.split();

    let mut pin = gpio.gpio33.into_analog();

    let mut adc1_config = Adc1Config::new();
    adc1_config.enable_pin(&pin, Attenuation::Attenuation11dB);

    let mut adc1 = ADC::adc1(sensors.adc1, adc1_config).unwrap();

    loop {
        if let Ok(r) = adc1.read(&mut pin) {
            let r: u16 = r;
            println!("{}", r);
        }

        thread::sleep(Duration::from_millis(200));
    }
}

I have my ESP32 wired up to a temperature sensor, and expect the ADC to return values around 800. Here is a plot of the values returned from the arduino code, and we can see that the values match expectations.

Screen Shot 2021-09-24 at 21 50 21

I touched the temperature sensor partway through the monitoring, causing the increase shown on the graph.

Compare this with the graph coming from the Rust code, which shows no relationship to my touching or not touching the sensor. It is even often maxing out and not moving. I'm not sure what might be going on here.

Screen Shot 2021-09-24 at 21 51 55

I'm using the latest commit (0324fc1d43294b5b0450b8a31e382e38bf3bee4b) of the esp fork of the Rust compiler and building on an aarch64-apple-darwin machine. My board is a TTGO T-Display.

MabezDev commented 2 years ago

Hi @lily-mara, sorry for the delay!

Interesting! I think you're the first person to get esp32_hal and rust-esp32-std-hello to work nicely! I don't think @schphil had such luck in #64. It's odd that there is no relation to you touching it at all, it indicates to me that perhaps esp-idf is treading on the Rust drivers feet somwhere.

When I run the adc example in this repo, I do see pin 33 reacting to my touches (I don't have a temp hooked up, but my finger will carry a small voltage), but compared to other pins like pin 25, it seems far less sensitive. Perhaps try another pin and see what results you get?

lily-mara commented 2 years ago

Oh I didn't realize that I was that much of a trailblazer 😄. Similar to schphil, I only went down this route due to missing functionality in esp-idf-hal.

I checked every GPIO pin on the board, and none of them work with this example program I provided. I checked a few with the Arduino sketch and validated that they do work, but I didn't check every pin in this way.

Perhaps the real issue here is the missing functionality in esp-idf-hal. I may have also simply not understood the docs. Should it be possible to take ADC readings with esp-idf-hal today? I wasn't able to figure this out. I don't need any other functionality from this crate, so I would have my needs met if I could use the other hal crate.