Skip to content

Commit 2606b9d

Browse files
committed
update dependencies and refactor DHT11 sensor for async support
1 parent bf0812f commit 2606b9d

File tree

5 files changed

+46
-48
lines changed

5 files changed

+46
-48
lines changed

.github/workflows/rust_ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
default: true
3535
buildtargets: esp32
3636
ldproxy: false
37-
version: "1.84.0"
37+
version: "1.85.0"
3838
- name: Enable caching
3939
uses: Swatinem/rust-cache@v2
4040
- name: Run build

Cargo.lock

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+6-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ esp-backtrace = { version = "0.15.0", features = [
1010
"panic-handler",
1111
"defmt",
1212
] }
13-
esp-hal = { version = "1.0.0-beta.0", features = ["esp32s3", "defmt", "unstable"] }
13+
esp-hal = { version = "1.0.0-beta.0", features = [
14+
"esp32s3",
15+
"defmt",
16+
"unstable",
17+
] }
1418
esp-alloc = { version = "0.7.0" }
1519
embassy-net = { version = "0.6.0", features = [
1620
"tcp",
@@ -43,6 +47,7 @@ rust-mqtt = { version = "0.3.0", default-features = false, features = [
4347
embedded-text = "0.7.2"
4448
embedded-graphics = { version = "0.8.1", features = ["defmt"] }
4549
embedded-hal = { version = "1.0.0", features = ["defmt-03"] }
50+
embedded-hal-async = { version = "1.0.0", features = ["defmt-03"] }
4651
serde = { version = "1.0.215", default-features = false, features = ["derive"] }
4752
serde_json = { version = "1.0.133", default-features = false, features = [
4853
"alloc",

src/dht11.rs

+34-39
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use embedded_hal::{
2-
delay::DelayNs,
3-
digital::{InputPin, OutputPin},
4-
};
1+
use embassy_time::{with_timeout, Duration, Instant};
2+
use embedded_hal::digital::{InputPin, OutputPin};
3+
use embedded_hal_async::delay::DelayNs;
4+
use embedded_hal_async::digital::Wait;
55

66
/// How long to wait for a pulse on the data line (in microseconds).
7-
const TIMEOUT_US: u16 = 1_000;
7+
const TIMEOUT_US: u64 = 1_000;
88

99
/// Error type for this crate.
1010
#[derive(Debug)]
@@ -39,7 +39,7 @@ pub struct Measurement {
3939

4040
impl<GPIO, D, E> Dht11<GPIO, D>
4141
where
42-
GPIO: InputPin<Error = E> + OutputPin<Error = E>,
42+
GPIO: InputPin<Error = E> + OutputPin<Error = E> + Wait,
4343
D: DelayNs,
4444
{
4545
/// Creates a new DHT11 device connected to the specified pin.
@@ -48,22 +48,22 @@ where
4848
}
4949

5050
/// Performs a reading of the sensor.
51-
pub fn read(&mut self) -> Result<Measurement, Error<E>> {
51+
pub async fn read(&mut self) -> Result<Measurement, Error<E>> {
5252
let mut data = [0u8; 5];
5353

5454
// Perform initial handshake
55-
self.perform_handshake()?;
55+
self.perform_handshake().await?;
5656

5757
// Read bits
5858
for i in 0..40 {
5959
data[i / 8] <<= 1;
60-
if self.read_bit()? {
60+
if self.read_bit().await? {
6161
data[i / 8] |= 1;
6262
}
6363
}
6464

6565
// Finally wait for line to go idle again.
66-
self.wait_for_pulse(true)?;
66+
self.wait_for_pulse(true).await?;
6767

6868
// Check CRC
6969
let crc = data[0]
@@ -80,55 +80,50 @@ where
8080
})
8181
}
8282

83-
fn perform_handshake(&mut self) -> Result<(), Error<E>> {
83+
async fn perform_handshake(&mut self) -> Result<(), Error<E>> {
8484
// Set pin as floating to let pull-up raise the line and start the reading process.
8585
self.gpio.set_high().map_err(Error::Gpio)?;
86-
self.delay.delay_ms(1);
86+
self.delay.delay_ms(1).await;
8787

8888
// Pull line low for at least 18ms to send a start command.
8989
self.gpio.set_low().map_err(Error::Gpio)?;
90-
self.delay.delay_ms(20);
90+
self.delay.delay_ms(20).await;
9191

9292
// Restore floating
9393
self.gpio.set_high().map_err(Error::Gpio)?;
94-
self.delay.delay_us(40);
94+
self.delay.delay_us(40).await;
9595

9696
// As a response, the device pulls the line low for 80us and then high for 80us.
97-
self.read_bit()?;
97+
self.read_bit().await?;
9898

9999
Ok(())
100100
}
101101

102-
fn read_bit(&mut self) -> Result<bool, Error<E>> {
103-
let low = self.wait_for_pulse(true)?;
104-
let high = self.wait_for_pulse(false)?;
102+
async fn read_bit(&mut self) -> Result<bool, Error<E>> {
103+
let low = self.wait_for_pulse(true).await?;
104+
let high = self.wait_for_pulse(false).await?;
105105
Ok(high > low)
106106
}
107107

108-
fn wait_for_pulse(&mut self, level: bool) -> Result<u32, Error<E>> {
109-
let mut count = 0;
108+
async fn wait_for_pulse(&mut self, level: bool) -> Result<u64, Error<E>> {
109+
let timeout_duration = Duration::from_micros(TIMEOUT_US);
110+
let start = Instant::now();
110111

111-
while self.gpio.is_high().map_err(Error::Gpio)? != level {
112-
count += 1;
113-
if count > TIMEOUT_US {
114-
return Err(Error::Timeout);
112+
let wait_future = async {
113+
if level {
114+
self.gpio.wait_for_rising_edge().await.map_err(Error::Gpio)
115+
} else {
116+
self.gpio.wait_for_falling_edge().await.map_err(Error::Gpio)
115117
}
116-
self.delay.delay_us(1);
117-
}
118+
};
118119

119-
Ok(u32::from(count))
120-
}
121-
}
120+
// Wait for the pulse with timeout.
121+
with_timeout(timeout_duration, wait_future)
122+
.await
123+
.map_err(|_| Error::Timeout)??;
124+
let elapsed = Instant::now() - start;
122125

123-
impl<GPIO, D, E> Drop for Dht11<GPIO, D>
124-
where
125-
GPIO: InputPin<Error = E> + OutputPin<Error = E>,
126-
D: DelayNs,
127-
{
128-
fn drop(&mut self) {
129-
// Set pin high (floating with pull-up) as safe state
130-
// Ignore errors during drop
131-
let _ = self.gpio.set_high();
132-
self.delay.delay_us(40);
126+
// Using microseconds for finer measurement.
127+
Ok(elapsed.as_micros())
133128
}
134129
}

src/sensors_task.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
use alloc::vec;
22
use defmt::{error, info, warn};
33
use embassy_sync::{blocking_mutex::raw::NoopRawMutex, channel::Sender};
4-
use embassy_time::{Duration, Timer};
4+
use embassy_time::{Delay, Duration, Timer};
55
use esp_hal::{
66
analog::adc::{
77
Adc, AdcCalCurve, AdcCalLine, AdcCalScheme, AdcChannel, AdcConfig, AdcPin, Attenuation,
88
RegisterAccess,
99
},
10-
delay::Delay,
1110
gpio::{DriveMode, GpioPin, Input, InputConfig, Level, Output, OutputConfig, Pull},
1211
peripherals::{ADC1, ADC2},
1312
Blocking,
@@ -42,9 +41,6 @@ pub async fn sensor_task(
4241
mut p: SensorPeripherals,
4342
) {
4443
info!("Create");
45-
46-
let delay = Delay::new();
47-
4844
let mut adc2_config = AdcConfig::new();
4945
let mut moisture_pin = adc2_config
5046
.enable_pin_with_cal::<_, AdcCalCurve<ADC2>>(p.moisture_analog_pin, Attenuation::_11dB);
@@ -95,11 +91,11 @@ pub async fn sensor_task(
9591
.into_flex();
9692
dht11_pin.enable_input(true);
9793

98-
let mut dht11_sensor = Dht11::new(dht11_pin, delay);
94+
let mut dht11_sensor = Dht11::new(dht11_pin, Delay);
9995

10096
// DHT11 needs a longer initial delay
10197
Timer::after(Duration::from_millis(DHT11_WARMUP_DELAY_MILLISECONDS)).await;
102-
if let Ok(result) = dht11_sensor.read() {
98+
if let Ok(result) = dht11_sensor.read().await {
10399
air_temperature_samples.push(result.temperature);
104100
air_humidity_samples.push(result.humidity);
105101
}

0 commit comments

Comments
 (0)