1use embedded_hal::{
2 delay::DelayNs,
3 digital::{InputPin, OutputPin, PinState},
4};
5
6use crate::{dht::Dht, SensorError, SensorReading};
7
8pub struct Dht22<P: InputPin + OutputPin, D: DelayNs> {
9 dht: Dht<P, D>,
10}
11
12impl<P: InputPin + OutputPin, D: DelayNs> Dht22<P, D> {
13 pub fn new(pin: P, delay: D) -> Self {
14 Self {
15 dht: Dht::new(pin, delay),
16 }
17 }
18
19 pub fn read(&mut self) -> Result<SensorReading<f32>, SensorError> {
20 let _ = self.dht.pin.set_low();
22 self.dht.delay.delay_ms(18);
23 let _ = self.dht.pin.set_high();
24
25 self.dht.delay.delay_us(48);
27
28 let _ = self.dht.wait_until_state(PinState::High);
30 let _ = self.dht.wait_until_state(PinState::Low);
31
32 let humidity_high = self.dht.read_byte()?;
34 let humidity_low = self.dht.read_byte()?;
35 let temperature_high = self.dht.read_byte()?;
36 let temperature_low = self.dht.read_byte()?;
37 let checksum = self.dht.read_byte()?;
38
39 let sum = humidity_high
41 .wrapping_add(humidity_low)
42 .wrapping_add(temperature_high)
43 .wrapping_add(temperature_low);
44 if sum != checksum {
45 return Err(SensorError::ChecksumMismatch);
46 }
47
48 let humidity_value = ((humidity_high as u16) << 8) | (humidity_low as u16);
49 let humidity_percentage = humidity_value as f32 / 10.0;
50
51 let temperature_high_clean = temperature_high & 0x7F; let temperature_value = ((temperature_high_clean as u16) << 8) | (temperature_low as u16);
53 let mut temperature_percentage = temperature_value as f32 / 10.0;
54
55 if temperature_high & 0x80 != 0 {
56 temperature_percentage = -temperature_percentage;
57 }
58
59
60 Ok(SensorReading {
61 humidity: humidity_percentage,
62 temperature: temperature_percentage,
63 })
64 }
65}