Refactor for Support DHT11
This commit is contained in:
parent
568f843bc9
commit
5672fe8b5f
5 changed files with 138 additions and 77 deletions
|
@ -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"
|
||||||
|
|
|
@ -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
|
|
@ -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
92
src/dht.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
117
src/lib.rs
117
src/lib.rs
|
@ -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,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue