michaelbeaumont / dht-sensor

Rust embedded-hal based driver for the DHT11/DHT22 sensor

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Working with DHT22 with a ESP32 board always returns in an TIMEOUT

yudistrange opened this issue · comments

What happened?

I am trying to get readings from a DHT22 sensor using my ESP32 dev board. The result is always a timeout.
The board and the sensor are working. I have verified that by flashing LuaRTOS and getting the sensor to respond back with the temperature / humidity readings.

I looked at the specification of the sensor and then your driver. It mostly makes sense. The timeouts are in the correct range as per the sensor specification. I also tried to implement the specification on my own, but still got the same result. I also forked your repo and increased the timeout, just to ensure that the sensor is not slow. I am also only using the --release tag for optimized binary as talked about in this issue

So I think I may be missing out on some initial setup - setting the pins to be pull-down / pull-up, some other configuration 🤷

Are you aware of any such initialization steps that must be performed for the sensor to work?
Here's my repo that's using your driver.

I also used the wowki emulator for this, just to weed out any physical issues with the device.
The project can be found here. But the result is the same, TIMEOUT

Reproducible on v0.2.1 and main branch. I use Wokwi emulator.

For anyone coming along this issue, the solution is to use the GPIO pin in open drain mode:

let mut sensor = gpio::PinDriver::input_output_od(pin).unwrap();   // instead of input_output(pin).unwrap()

Would love to hear whether that solves it for others. This may depend on exactly how the sensor is wired but I think open drain is in fact required for the DHT. It's mentioned/used in both the README and the example.

I have a similar issue on my Raspberry Pi Pico H.

I'm new to embedded and tried multiple crates which keep responding with timeouts.
Previously used dht-pio, which hasn't tested the DHT11 yet so I discovered this crate.

Didn't find the rp2040_hal crate referencing configuring pins for open drain so I guessed that pins.gpio28.into_push_pull_output() would to the trick.

My Code

#![no_std]
#![no_main]

use rp_pico as bsp;

use bsp::{entry, hal::clocks::ClockSource};
use defmt::*;
use defmt_rtt as _;
use dht_sensor::DhtReading;
use embedded_hal::digital::v2::OutputPin;
use panic_probe as _;

use bsp::hal::{clocks::init_clocks_and_plls, pac, sio::Sio, watchdog::Watchdog};

#[entry]
fn main() -> ! {
    let mut pac = pac::Peripherals::take().unwrap();
    let mut watchdog = Watchdog::new(pac.WATCHDOG);
    let clocks = init_clocks_and_plls(
        rp_pico::XOSC_CRYSTAL_FREQ,
        pac.XOSC,
        pac.CLOCKS,
        pac.PLL_SYS,
        pac.PLL_USB,
        &mut pac.RESETS,
        &mut watchdog,
    )
    .ok()
    .unwrap();

    let sio = Sio::new(pac.SIO);
    let pins = rp_pico::Pins::new(
        pac.IO_BANK0,
        pac.PADS_BANK0,
        sio.gpio_bank0,
        &mut pac.RESETS,
    );

    let core = pac::CorePeripherals::take().unwrap();
    let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.get_freq().to_Hz());

    let mut dht11_pin = pins.gpio28.into_push_pull_output();
    match dht11_pin.set_high() {
        Ok(value) => info!("Set GPIO28 HIGH: {}", value),
        Err(err) => error!("Failed to set GPIO2 HIGH: {}", err),
    };

    loop {
        info!("Reading from DHT11");
        match dht_sensor::dht11::Reading::read(&mut delay, &mut dht11_pin) {
            Ok(data) => {
                debug!(
                    "Temp info:\nHumidity: {}\nTemperature: {}",
                    data.relative_humidity, data.temperature
                );
            }
            Err(error) => {
                match error {
                    dht_sensor::DhtError::Timeout => {
                        error!("Timeout");
                    }
                    dht_sensor::DhtError::PinError(_e) => error!("DHT PinError"),
                    dht_sensor::DhtError::ChecksumMismatch => error!("DHT ChecksumMismatch"),
                }
            }
        };

        delay.delay_ms(1000);
    }
}

My sensor setup

See Pico pin layout

Data: Green cable from DHT11 left pin to Pico pin 34 (GP28)
Power: Red cable from DHT11 middle pin to Pico pin 36 (3V out)
Ground: Black cable from DHT11 right pin to Pico pin 38 (GND)

IMG_1108

@michaelbeaumont That works! Thanks for the quick response!

For reference, here is a working Wokwi project with ESP32: https://wokwi.com/projects/384087992261474305