dht_sensor/
read.rs

1use embedded_hal::delay::DelayNs;
2use embedded_hal::digital::{InputPin, OutputPin};
3
4const TIMEOUT_US: u8 = 100;
5
6#[derive(Debug)]
7pub enum DhtError<E> {
8    PinError(E),
9    ChecksumMismatch,
10    Timeout,
11}
12
13impl<E> From<E> for DhtError<E> {
14    fn from(error: E) -> DhtError<E> {
15        DhtError::PinError(error)
16    }
17}
18
19fn read_bit<P: InputPin>(
20    delay: &mut impl DelayNs,
21    pin: &mut P,
22) -> Result<bool, DhtError<P::Error>> {
23    wait_until_timeout(delay, || pin.is_high())?;
24    delay.delay_us(35);
25    let high = pin.is_high()?;
26    wait_until_timeout(delay, || pin.is_low())?;
27    Ok(high)
28}
29
30fn read_byte<P: InputPin>(delay: &mut impl DelayNs, pin: &mut P) -> Result<u8, DhtError<P::Error>> {
31    let mut byte: u8 = 0;
32    for i in 0..8 {
33        let bit_mask = 1 << (7 - i);
34        if read_bit(delay, pin)? {
35            byte |= bit_mask;
36        }
37    }
38    Ok(byte)
39}
40
41pub fn read_raw<P: OutputPin + InputPin>(
42    delay: &mut impl DelayNs,
43    pin: &mut P,
44) -> Result<[u8; 4], DhtError<P::Error>> {
45    pin.set_high().ok();
46    delay.delay_us(48);
47
48    wait_until_timeout(delay, || pin.is_high())?;
49    wait_until_timeout(delay, || pin.is_low())?;
50
51    let mut data = [0; 4];
52    for b in data.iter_mut() {
53        *b = read_byte(delay, pin)?;
54    }
55    let checksum = read_byte(delay, pin)?;
56    if data.iter().fold(0u8, |sum, v| sum.wrapping_add(*v)) != checksum {
57        Err(DhtError::ChecksumMismatch)
58    } else {
59        Ok(data)
60    }
61}
62
63/// Wait until the given function returns true or the timeout is reached.
64fn wait_until_timeout<E, F>(delay: &mut impl DelayNs, mut func: F) -> Result<(), DhtError<E>>
65where
66    F: FnMut() -> Result<bool, E>,
67{
68    for _ in 0..TIMEOUT_US {
69        if func()? {
70            return Ok(());
71        }
72        delay.delay_us(1);
73    }
74    Err(DhtError::Timeout)
75}