DEV Community

Cover image for Embedded Rust on the ESP32 : Sensor Integration : DHT22 (Temperature and Humidity Sensor)
Vaishnav-sabari-girish
Vaishnav-sabari-girish

Posted on

Embedded Rust on the ESP32 : Sensor Integration : DHT22 (Temperature and Humidity Sensor)

In my previous blog, we interfaced a button.

We shall now get started with interfacing a few sensors. This blog will walk you through interfacing the DHT22 temperature and Humidity Sensor.

Getting Started

Let us create our new project

esp-generate --chip=esp32 dht22_sensor
Enter fullscreen mode Exit fullscreen mode

Open src/bin/main.rs and type the below code

#![no_std]
#![no_main]
#![deny(
    clippy::mem_forget,
    reason = "mem::forget is generally not safe to do with esp_hal types, especially those \
    holding buffers for the duration of a data transfer."
)]

use esp_backtrace as _;
use esp_hal::{
    clock::CpuClock,
    delay::Delay,
    gpio::{DriveMode, Output, OutputConfig, Pull},
    main, 
};
use esp_println::println;
use embedded_dht_rs::dht22;
esp_bootloader_esp_idf::esp_app_desc!();

#[main]
fn main() -> ! {
    let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
    let peripherals = esp_hal::init(config);

    let od_config = OutputConfig::default()
        .with_drive_mode(DriveMode::OpenDrain)
        .with_pull(Pull::None);

    let od_for_dht22 = Output::new(
            peripherals.GPIO4, esp_hal::gpio::Level::High, od_config
        )
        .into_flex();

    od_for_dht22.peripheral_input();


    let delay = Delay::new();

    let mut dht22 = dht22::Dht22::new(od_for_dht22, delay);

    loop {
        delay.delay_millis(2000);

        println!("");

        match dht22.read() {
            Ok(sensor_reading) => println!(
                "DHT22 Sensor - Temperature: {} C , Humidity: {} %",
                sensor_reading.temperature,
                sensor_reading.humidity
            ),
            Err(error) => println!("An error occurred while trying to read the sensor"),
        }

        println!("_____________________________________________________");
    }
}
Enter fullscreen mode Exit fullscreen mode

Output GIF

Output GIF

Into the code : Line-by-line explanation

#![no_std]
Enter fullscreen mode Exit fullscreen mode
  • Disables the Rust standard library for embedded programming.
#![no_main]
Enter fullscreen mode Exit fullscreen mode
  • Replaces the default main entry point with a custom embedded one.
#![deny(
    clippy::mem_forget,
    reason = "mem::forget is generally not safe to do with esp_hal types, especially those \
    holding buffers for the duration of a data transfer."
)]
Enter fullscreen mode Exit fullscreen mode
  • Prevents the use of mem::forget as it can cause unsafe behavior in this context.
use esp_backtrace as _;
Enter fullscreen mode Exit fullscreen mode
  • Enables backtrace support on panic (if supported by target). as _ suppresses warnings.
use esp_hal::{
    clock::CpuClock,
    delay::Delay,
    gpio::{DriveMode, Output, OutputConfig, Pull},
    main,
};
Enter fullscreen mode Exit fullscreen mode
  • Imports required ESP HAL modules:
    • Clock configuration
    • Delay handling
    • GPIO configuration (including open-drain and pull options)
    • main macro
use esp_println::println;
Enter fullscreen mode Exit fullscreen mode
  • Enables UART-based printing to a terminal.
use embedded_dht_rs::dht22;
Enter fullscreen mode Exit fullscreen mode
  • Imports DHT22 support from the embedded_dht_rs crate.
esp_bootloader_esp_idf::esp_app_desc!();
Enter fullscreen mode Exit fullscreen mode
  • Embeds metadata about the application (like name, version).
#[main]
fn main() -> ! {
Enter fullscreen mode Exit fullscreen mode
  • Entry point of the embedded program that never returns (-> !).
    let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
Enter fullscreen mode Exit fullscreen mode
  • Configures system with maximum CPU clock speed.
    let peripherals = esp_hal::init(config);
Enter fullscreen mode Exit fullscreen mode
  • Initializes the HAL and returns access to hardware peripherals.
    let od_config = OutputConfig::default()
        .with_drive_mode(DriveMode::OpenDrain)
        .with_pull(Pull::None);
Enter fullscreen mode Exit fullscreen mode
  • Sets up GPIO pin as Open-Drain with no internal pull-up/down. This is essential for DHT22 communication.
    let od_for_dht22 = Output::new(
            peripherals.GPIO4, esp_hal::gpio::Level::High, od_config
        )
        .into_flex();
Enter fullscreen mode Exit fullscreen mode
  • Initializes GPIO4 with the config above and converts it to a flexible IO pin (Flex), which allows bidirectional control.
    od_for_dht22.peripheral_input();
Enter fullscreen mode Exit fullscreen mode
  • Enables input mode for this flexible pin — DHT22 is bidirectional, so the pin needs to receive data too.
    let delay = Delay::new();
Enter fullscreen mode Exit fullscreen mode
  • Creates a delay instance for timing control.
    let mut dht22 = dht22::Dht22::new(od_for_dht22, delay);
Enter fullscreen mode Exit fullscreen mode
  • Initializes the DHT22 driver with the GPIO and delay.
    loop {
Enter fullscreen mode Exit fullscreen mode
  • Begins infinite polling loop.
        delay.delay_millis(2000);
Enter fullscreen mode Exit fullscreen mode
  • Waits 2 seconds between each sensor read (recommended minimum delay for DHT22).
        println!("");
Enter fullscreen mode Exit fullscreen mode
  • Prints a blank line for readability.
        match dht22.read() {
Enter fullscreen mode Exit fullscreen mode
  • Tries to read temperature and humidity from the sensor.
            Ok(sensor_reading) => println!(
                "DHT22 Sensor - Temperature: {} C , Humidity: {} %",
                sensor_reading.temperature,
                sensor_reading.humidity
            ),
Enter fullscreen mode Exit fullscreen mode
  • If read is successful, prints temperature and humidity.
            Err(error) => println!("An error occurred while trying to read the sensor"),
Enter fullscreen mode Exit fullscreen mode
  • If read fails, prints a basic error message (you can expand this with {:?} for debugging).
        println!("_____________________________________________________");
Enter fullscreen mode Exit fullscreen mode
  • Prints a separator line to visually break up readings.
    }
}
Enter fullscreen mode Exit fullscreen mode
  • Closes loop and function.

Summary:

This ESP32 firmware reads data from a DHT22 sensor connected to GPIO4 and prints temperature and humidity to the serial console every 2 seconds. It uses open-drain GPIO configuration and the embedded_dht_rs crate for protocol handling.

Thank You

Important Links

  1. Getting Started Blog
  2. Interfacing a Button Blog
  3. GitHub Repository

Top comments (0)