plorefice / dht11-rs

Platform-agnostic Rust driver for the DHT11 temperature and humidity sensor
Apache License 2.0
15 stars 7 forks source link

Not working with stm32f3xx-hal #1

Closed leon-jakob-schneider closed 4 years ago

leon-jakob-schneider commented 4 years ago

Example:

#![no_std]
#![no_main]

extern crate panic_halt;

use cortex_m_rt::entry;
// use stm32f4xx_hal::{stm32, gpio::GpioExt, rcc::RccExt};
use stm32f3xx_hal::{stm32, gpio::GpioExt, rcc::RccExt};

#[entry]
fn main() -> ! {
    let dp = stm32::Peripherals::take().unwrap();
    let mut rcc = dp.RCC.constrain();

    // let mut gpiob = dp.GPIOB.split();
    let mut gpiob = dp.GPIOB.split(&mut rcc.ahb);
    // let pin = gpiob.pb9.into_open_drain_output();
    let pin = gpiob.pb9.into_open_drain_output(&mut gpiob.moder, &mut gpiob.otyper);
    let mut dht11 = dht11::Dht11::new(pin);

    loop {}
}

Error message:

19 |     let mut dht11 = dht11::Dht11::new(pin);
   |                                       ^^^ the trait embedded_hal::digital::v1::InputPin is not implemented for stm32f3xx_hal::gpio::gpiob::PB9<stm32f3xx_hal::gpio::Output<stm32f3xx_hal::gpio::OpenDrain>>
   |
plorefice commented 4 years ago

I think the issue here is that the stm32f3xx-hal crate only implements version 1 of the embedded_hal::digital traits, while this crate has been developed with version 2 in mind.

I will look into the possibility of supporting both versions and I'll get back to you.

plorefice commented 4 years ago

Actually, scratch that. The problem is with the HAL implementation of F3 pins, that unfortunately does not implement the InputPin trait for pins in Output<OpenDrain> mode, unlike the F4 crate which does.

You can wrap the pin into a newtype and implement InputPin + OutputPin yourself, like this:

use stm32f3xx_hal::{
    gpio::{gpiob::PB9, GpioExt, OpenDrain, Output},
    hal::digital::v2::{InputPin, OutputPin},
    rcc::RccExt,
    stm32,
};

struct OpenDrainOutput(PB9<Output<OpenDrain>>);

impl InputPin for OpenDrainOutput {
    type Error = ();

    fn is_high(&self) -> Result<bool, Self::Error> {
        self.is_low().map(|v| !v)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        Ok(unsafe { (*stm32::GPIOB::ptr()).idr.read().bits() & (1 << 9) == 0 })
    }
}

impl OutputPin for OpenDrainOutput {
    type Error = ();

    fn set_low(&mut self) -> Result<(), Self::Error> {
        self.0.set_low()
    }

    fn set_high(&mut self) -> Result<(), Self::Error> {
        self.0.set_high()
    }
}

You can then wrap the pin returned by .into_open_drain_output() in this newtype and it should work:

let mut dht11 = dht11::Dht11::new(OpenDrainOutput(pin));

The above example builds just fine, but I don't have an STM32F3 on my hands to test it. If the peripheral is the same as for the F4 family, this code should work. Give it a try and let me know, I could also include this example for future reference.

leon-jakob-schneider commented 4 years ago

Sadly this did not work out of the box. But after some more debugging I found out that my dht11 may be the problem. I will have to order another one and try again. Apart from that, I can confirm that with your workaround my code compiles for the stm32f3xx-hal. Thanks for your work btw.

plorefice commented 4 years ago

No problem, let me know if you need anything else. I'll close the issue for the time being, feel free to open a new one if the problem is still there with the new sensor.