diff --git a/Cargo.toml b/Cargo.toml index 582530e..f3d48a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dht-pio" -version = "0.2.0" +version = "0.3.0" edition = "2021" license = "MIT" diff --git a/readme.md b/readme.md index 8502ec5..870968c 100644 --- a/readme.md +++ b/readme.md @@ -28,6 +28,6 @@ For the moment, the crates have only been tested on a Raspberry Pico. - [ ] Finish Readme - [x] Add CRC read - [x] Check CRC -- [ ] DHT11 support +- [x] DHT11 support - [ ] Test DHT11 - [ ] Document code \ No newline at end of file diff --git a/readme_fr.md b/readme_fr.md index f6b4e30..020e044 100644 --- a/readme_fr.md +++ b/readme_fr.md @@ -31,6 +31,6 @@ Pour le moment le crates n'a été testé que sur un Raspberry Pico. - [ ] Finir le Readme - [x] Ajouter la lecture du CRC - [x] Vérifier le CRC -- [ ] Support du DHT11 +- [x] Support du DHT11 - [ ] Tester DHT11 - [ ] Documenter le code \ No newline at end of file diff --git a/src/dht.rs b/src/dht.rs new file mode 100644 index 0000000..120de21 --- /dev/null +++ b/src/dht.rs @@ -0,0 +1,92 @@ +use cortex_m::delay::Delay; +use pio_proc::pio_file; +use rp2040_hal::gpio::AnyPin; +use rp2040_hal::pio::{PIOExt, Running, StateMachine, StateMachineIndex, Tx}; +use rp2040_hal::pio::{Rx, UninitStateMachine}; + +use crate::DhtError; + +pub struct DhtPio { + // sm: PicoStateMachine, + sm: StateMachine<(P, STI), Running>, + rx_fifo: Rx<(P, STI)>, + tx_fifo: Tx<(P, STI)>, +} + +impl DhtPio { + pub fn new>( + mut pio: rp2040_hal::pio::PIO

, + sm: UninitStateMachine<(P, STI)>, + dht_pin: I, + ) -> Self { + let program = pio_file!("./src/dht.pio"); + + let pin = dht_pin.into(); + + let installed = pio.install(&program.program).unwrap(); + + let (int, frac) = (125, 0); + let (mut sm, rx, tx) = rp2040_hal::pio::PIOBuilder::from_program(installed) + .set_pins(pin.id().num, 1) + .clock_divisor_fixed_point(int, frac) + .push_threshold(32) + .build(sm); + sm.set_pindirs([(pin.id().num, rp2040_hal::pio::PinDir::Output)]); + + Self { + sm: sm.start(), + rx_fifo: rx, + tx_fifo: tx, + } + } + + pub fn read_data(&mut self, delay: &mut Delay) -> Result<(u32, u32), DhtError> { + let mut timeout = 2000; + let mut raw: [Option; 2] = [None; 2]; + + self.tx_fifo.write(1); + + while timeout > 0 && raw[1].is_none() { + match self.rx_fifo.read() { + Some(d) => { + if raw[0].is_none() { + raw[0] = Some(d); + } else { + raw[1] = Some(d); + } + } + None => (), + } + + delay.delay_ms(1); + timeout -= 1; + } + + if timeout <= 0 { + self.sm.restart(); + return Err(DhtError::Timeout); + } + + let data = raw[0].unwrap(); + let crc = raw[1].unwrap(); + + if Self::compute_crc(data) != crc { + return Err(DhtError::CrcMismatch( + raw[0].unwrap_or(0), + raw[1].unwrap_or(0), + )); + } + + Ok((data & 0x0000FFFF, (data & 0xFFFF0000) >> 16)) + } + + fn compute_crc(data: u32) -> u32 { + let mut crc: u32 = 0; + crc += data & 0x000000FF; + crc += (data & 0x0000FF00) >> 8; + crc += (data & 0x00FF0000) >> 16; + crc += (data & 0xFF000000) >> 24; + + crc % 256 + } +} diff --git a/src/lib.rs b/src/lib.rs index e136228..65c2ef6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,12 @@ #![no_std] use cortex_m::delay::Delay; -use pio_proc::pio_file; use rp2040_hal::gpio::AnyPin; -use rp2040_hal::pio::{PIOExt, Running, StateMachine, StateMachineIndex, Tx}; -use rp2040_hal::pio::{Rx, UninitStateMachine}; +use rp2040_hal::pio::UninitStateMachine; +use rp2040_hal::pio::{PIOExt, StateMachineIndex}; + +mod dht; +use dht::DhtPio; #[derive(Debug)] pub enum DhtError { @@ -22,94 +24,61 @@ pub struct DhtResult { pub humidity: f32, } -pub struct DhtPio { - // sm: PicoStateMachine, - sm: StateMachine<(P, STI), Running>, - rx_fifo: Rx<(P, STI)>, - tx_fifo: Tx<(P, STI)>, +pub struct Dht22 { + dht: DhtPio, } -impl DhtPio { +impl Dht22 { pub fn new>( - mut pio: rp2040_hal::pio::PIO

, + pio: rp2040_hal::pio::PIO

, sm: UninitStateMachine<(P, STI)>, dht_pin: I, ) -> Self { - let program = pio_file!("./src/dht.pio"); - - let pin = dht_pin.into(); - - let installed = pio.install(&program.program).unwrap(); - - let (int, frac) = (125, 0); - let (mut sm, rx, tx) = rp2040_hal::pio::PIOBuilder::from_program(installed) - .set_pins(pin.id().num, 1) - .clock_divisor_fixed_point(int, frac) - .push_threshold(32) - .build(sm); - sm.set_pindirs([(pin.id().num, rp2040_hal::pio::PinDir::Output)]); - Self { - sm: sm.start(), - rx_fifo: rx, - tx_fifo: tx, + dht: DhtPio::new(pio, sm, dht_pin), } } - /// Read data from the sensor. This blocking function (for maximum timeout of 2 seconds). - pub fn read_data(&mut self, delay: &mut Delay) -> Result { - let mut timeout = 2000; - let mut raw: [Option; 2] = [None; 2]; + pub fn read(&mut self, delay: &mut Delay) -> Result { + let (t, h) = self.dht.read_data(delay)?; + let mut final_t: i32 = (t & 0x7FFF) as i32; - self.tx_fifo.write(1); - - while timeout > 0 && raw[1].is_none() { - match self.rx_fifo.read() { - Some(d) => { - if raw[0].is_none() { - raw[0] = Some(d); - } else { - raw[1] = Some(d); - } - } - None => (), - } - - delay.delay_ms(1); - timeout -= 1; + if (t & 0x8000) > 0 { + final_t *= -1; } - if timeout <= 0 { - self.sm.restart(); - return Err(DhtError::Timeout); - } - - let data = raw[0].unwrap(); - let crc = raw[1].unwrap(); - - if Self::compute_crc(data) != crc { - return Err(DhtError::CrcMismatch( - raw[0].unwrap_or(0), - raw[1].unwrap_or(0), - )); - } - - let t_raw = data & 0x0000FFFF; - let h_raw = (data & 0xFFFF0000) >> 16; - Ok(DhtResult { - temperature: t_raw as f32 / 10.0, - humidity: h_raw as f32 / 10.0, + temperature: final_t as f32 / 10.0, + humidity: h as f32 / 10.0, }) } +} +pub struct Dht11 { + dht: DhtPio, +} - fn compute_crc(data: u32) -> u32 { - let mut crc: u32 = 0; - crc += data & 0x000000FF; - crc += (data & 0x0000FF00) >> 8; - crc += (data & 0x00FF0000) >> 16; - crc += (data & 0xFF000000) >> 24; +impl Dht11 { + pub fn new>( + pio: rp2040_hal::pio::PIO

, + sm: UninitStateMachine<(P, STI)>, + dht_pin: I, + ) -> Self { + Self { + dht: DhtPio::new(pio, sm, dht_pin), + } + } - crc % 256 + pub fn read(&mut self, delay: &mut Delay) -> Result { + let (t, h) = self.dht.read_data(delay)?; + let mut final_t: i32 = ((t & 0x7FFF) >> 8) as i32; + + if (t & 0x8000) > 0 { + final_t *= -1; + } + + Ok(DhtResult { + temperature: final_t as f32, + humidity: (h >> 8) as f32, + }) } }