From 647182759a72b7eaa26efcb28cfe631964cf9a2c Mon Sep 17 00:00:00 2001 From: Jonathan BAUDIN Date: Fri, 8 Sep 2023 23:09:15 +0200 Subject: [PATCH] First commit --- .cargo/config.toml | 14 ++++++++ .gitignore | 2 ++ Cargo.toml | 16 +++++++++ src/dht.pio | 29 ++++++++++++++++ src/lib.rs | 87 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 148 insertions(+) create mode 100644 .cargo/config.toml create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 src/dht.pio create mode 100644 src/lib.rs diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..283569a --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,14 @@ +[build] +# Set the default target to match the Cortex-M0+ in the RP2040 +target = "thumbv6m-none-eabi" + +[target.thumbv6m-none-eabi] +rustflags = [ + "-C", "link-arg=--nmagic", + "-C", "link-arg=-Tlink.x", + "-C", "inline-threshold=5", + "-C", "no-vectorize-loops", +] + +runner = "elf2uf2-rs -d" + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4fffb2f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..6902bbd --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "rp-dht" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +embedded-hal = { version = "0.2.5" } +cortex-m = { version = "0.7.6"} +cortex-m-rt = "0.7.3" +rp2040-boot2 = "0.2.1" +rp2040-hal = { version = "0.9.0", features = ["rp2040-e5"] } +pio-proc = "0.2.2" +pio = "0.2.1" +# embedded-alloc = "0.5.0" diff --git a/src/dht.pio b/src/dht.pio new file mode 100644 index 0000000..98824f8 --- /dev/null +++ b/src/dht.pio @@ -0,0 +1,29 @@ +.program dht + ; Clock must be set for 1µs per instruction + + pull block ; Wait for start + + set x, 31 ; set x register with 31 (for 31 * 32 µS) + set pindirs, 1 ; set pin as output + set pins, 0 ; set pin to low + loop_init_low: ; wait 992 ms + jmp x-- loop_init_low [31] + + set pins, 1 ; set pin to high + set pindirs, 0 ; set pin as input + + wait 0 pin 0 ; Wait for low + wait 1 pin 0 ; wait for high + + set x, 31 ; Set number bit to received (ignore CRC :( sorry ) + loop_data: + wait 0 pin 0 ; Wait for low + wait 1 pin 0 ; wait for high + + nop [29] ; wait for ~ 30 µS + + in pins, 1 ; read the pin state and store bit value + + jmp x--, loop_data ; Run until read all bits + + push ; send result diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..0e32250 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,87 @@ +#![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}; + +#[derive(Debug)] +pub enum DhtError { + /// DHT never aswer to start signal + StartTimout, + /// Timeout during communication. + Timeout, + /// CRC mismatch. + CrcMismatch, + /// Failed to get pin state (low or high) + ReadPinError, + /// Internal state error + InternatError, +} + +#[derive(Debug)] +pub struct DhtResult { + pub temperature: f32, + pub humidity: f32, +} + +pub struct PicoDht { + // sm: PicoStateMachine, + sm: StateMachine<(P, STI), Running>, + rx_fifo: Rx<(P, STI)>, + tx_fifo: Tx<(P, STI)>, +} + +impl PicoDht { + 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) + .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 { + let mut timeout = 2000; + + self.tx_fifo.write(1); + + while timeout > 0 && self.rx_fifo.is_empty() { + delay.delay_ms(1); + timeout -= 1; + } + + if timeout <= 0 { + self.sm.restart(); + return Err(DhtError::Timeout); + } + + let raw = self.rx_fifo.read().unwrap_or_default(); + + let t_raw = raw & 0x0000FFFF; + let h_raw = (raw & 0xFFFF0000) >> 16; + + Ok(DhtResult { + temperature: t_raw as f32 / 10.0, + humidity: h_raw as f32 / 10.0, + }) + } +}