Refactor for Support DHT11

This commit is contained in:
Jonathan BAUDIN 2023-09-09 22:22:30 +02:00
parent 568f843bc9
commit 5672fe8b5f
5 changed files with 138 additions and 77 deletions

View file

@ -1,6 +1,6 @@
[package] [package]
name = "dht-pio" name = "dht-pio"
version = "0.2.0" version = "0.3.0"
edition = "2021" edition = "2021"
license = "MIT" license = "MIT"

View file

@ -28,6 +28,6 @@ For the moment, the crates have only been tested on a Raspberry Pico.
- [ ] Finish Readme - [ ] Finish Readme
- [x] Add CRC read - [x] Add CRC read
- [x] Check CRC - [x] Check CRC
- [ ] DHT11 support - [x] DHT11 support
- [ ] Test DHT11 - [ ] Test DHT11
- [ ] Document code - [ ] Document code

View file

@ -31,6 +31,6 @@ Pour le moment le crates n'a été testé que sur un Raspberry Pico.
- [ ] Finir le Readme - [ ] Finir le Readme
- [x] Ajouter la lecture du CRC - [x] Ajouter la lecture du CRC
- [x] Vérifier le CRC - [x] Vérifier le CRC
- [ ] Support du DHT11 - [x] Support du DHT11
- [ ] Tester DHT11 - [ ] Tester DHT11
- [ ] Documenter le code - [ ] Documenter le code

92
src/dht.rs Normal file
View file

@ -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<P: PIOExt, STI: StateMachineIndex> {
// sm: PicoStateMachine<P, STI>,
sm: StateMachine<(P, STI), Running>,
rx_fifo: Rx<(P, STI)>,
tx_fifo: Tx<(P, STI)>,
}
impl<P: PIOExt, STI: StateMachineIndex> DhtPio<P, STI> {
pub fn new<I: AnyPin<Function = P::PinFunction>>(
mut pio: rp2040_hal::pio::PIO<P>,
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<u32>; 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
}
}

View file

@ -1,10 +1,12 @@
#![no_std] #![no_std]
use cortex_m::delay::Delay; use cortex_m::delay::Delay;
use pio_proc::pio_file;
use rp2040_hal::gpio::AnyPin; use rp2040_hal::gpio::AnyPin;
use rp2040_hal::pio::{PIOExt, Running, StateMachine, StateMachineIndex, Tx}; use rp2040_hal::pio::UninitStateMachine;
use rp2040_hal::pio::{Rx, UninitStateMachine}; use rp2040_hal::pio::{PIOExt, StateMachineIndex};
mod dht;
use dht::DhtPio;
#[derive(Debug)] #[derive(Debug)]
pub enum DhtError { pub enum DhtError {
@ -22,94 +24,61 @@ pub struct DhtResult {
pub humidity: f32, pub humidity: f32,
} }
pub struct DhtPio<P: PIOExt, STI: StateMachineIndex> { pub struct Dht22<P: PIOExt, STI: StateMachineIndex> {
// sm: PicoStateMachine<P, STI>, dht: DhtPio<P, STI>,
sm: StateMachine<(P, STI), Running>,
rx_fifo: Rx<(P, STI)>,
tx_fifo: Tx<(P, STI)>,
} }
impl<P: PIOExt, STI: StateMachineIndex> DhtPio<P, STI> { impl<P: PIOExt, STI: StateMachineIndex> Dht22<P, STI> {
pub fn new<I: AnyPin<Function = P::PinFunction>>( pub fn new<I: AnyPin<Function = P::PinFunction>>(
mut pio: rp2040_hal::pio::PIO<P>, pio: rp2040_hal::pio::PIO<P>,
sm: UninitStateMachine<(P, STI)>, sm: UninitStateMachine<(P, STI)>,
dht_pin: I, dht_pin: I,
) -> Self { ) -> 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 { Self {
sm: sm.start(), dht: DhtPio::new(pio, sm, dht_pin),
rx_fifo: rx,
tx_fifo: tx,
} }
} }
/// Read data from the sensor. This blocking function (for maximum timeout of 2 seconds). pub fn read(&mut self, delay: &mut Delay) -> Result<DhtResult, DhtError> {
pub fn read_data(&mut self, delay: &mut Delay) -> Result<DhtResult, DhtError> { let (t, h) = self.dht.read_data(delay)?;
let mut timeout = 2000; let mut final_t: i32 = (t & 0x7FFF) as i32;
let mut raw: [Option<u32>; 2] = [None; 2];
self.tx_fifo.write(1); if (t & 0x8000) > 0 {
final_t *= -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),
));
}
let t_raw = data & 0x0000FFFF;
let h_raw = (data & 0xFFFF0000) >> 16;
Ok(DhtResult { Ok(DhtResult {
temperature: t_raw as f32 / 10.0, temperature: final_t as f32 / 10.0,
humidity: h_raw as f32 / 10.0, humidity: h as f32 / 10.0,
}) })
} }
}
pub struct Dht11<P: PIOExt, STI: StateMachineIndex> {
dht: DhtPio<P, STI>,
}
fn compute_crc(data: u32) -> u32 { impl<P: PIOExt, STI: StateMachineIndex> Dht11<P, STI> {
let mut crc: u32 = 0; pub fn new<I: AnyPin<Function = P::PinFunction>>(
crc += data & 0x000000FF; pio: rp2040_hal::pio::PIO<P>,
crc += (data & 0x0000FF00) >> 8; sm: UninitStateMachine<(P, STI)>,
crc += (data & 0x00FF0000) >> 16; dht_pin: I,
crc += (data & 0xFF000000) >> 24; ) -> Self {
Self {
dht: DhtPio::new(pio, sm, dht_pin),
}
}
crc % 256 pub fn read(&mut self, delay: &mut Delay) -> Result<DhtResult, DhtError> {
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,
})
} }
} }