michaelbeaumont / dht-sensor

Rust embedded-hal based driver for the DHT11/DHT22 sensor
MIT License
26 stars 16 forks source link

How to convert InputOutputPin from Output<OpenDrain> #15

Closed falloutkid closed 1 year ago

falloutkid commented 3 years ago

I implement following code with reference to the sample code for STM32L 476RG.

#![no_main]
#![no_std]

use panic_halt as _;

use cortex_m_rt::entry;
use stm32l4xx_hal::delay::Delay;
use stm32l4xx_hal::prelude::*;
use cortex_m_semihosting::{debug, hprintln};

use dht_sensor::*;

#[entry]
fn main() -> ! {
    // Peripheral access
    let cp = cortex_m::Peripherals::take().unwrap();
    let dp = stm32l4xx_hal::stm32::Peripherals::take().unwrap();
    let mut flash = dp.FLASH.constrain();
    let mut rcc = dp.RCC.constrain();
    let mut pwr = dp.PWR.constrain(&mut rcc.apb1r1);

    let clocks = rcc.cfgr.freeze(&mut flash.acr, &mut pwr);
    let mut timer = Delay::new(cp.SYST, clocks);

    let mut gpioa = dp.GPIOA.split(&mut rcc.ahb2);
    let temp_pin = gpioa.pa1.into_open_drain_output(&mut gpioa.moder, &mut gpioa.otyper);

    temp_pin.set_high().ok();

    hprintln!("Waiting on the sensor...").unwrap();
    timer.delay_ms(1000_u16);

    loop {
        match dht11::Reading::read(&mut timer, &mut temp_pin) {
            Ok(dht11::Reading {
                temperature,
                relative_humidity,
            }) => hprintln!("{}°, {}% RH", temperature, relative_humidity).unwrap(),
            Err(e) => hprintln!("Error {:?}", e).unwrap(),
        }

        // Delay of at least 500ms before polling the sensor again, 1 second or more advised
        timer.delay_ms(500_u16); 
    }
}

But there are some error.

error[E0271]: type mismatch resolving `<PA1<Output<OpenDrain>> as stm32l4xx_hal::prelude::OutputPin>::Error == ()`
  --> examples/temparature.rs:50:15
   |
50 |         match dht11::Reading::read(&mut timer, &mut temp_pin) {
   |               ^^^^^^^^^^^^^^^^^^^^ expected enum `Infallible`, found `()`
   |
   = note: required because of the requirements on the impl of `InputOutputPin<()>` for `PA1<Output<OpenDrain>>`
   = note: required by `dht_sensor::DhtReading::read`

error[E0277]: the trait bound `PA1<Output<OpenDrain>>: _embedded_hal_digital_InputPin` is not satisfied
  --> examples/temparature.rs:50:48
   |
50 |         match dht11::Reading::read(&mut timer, &mut temp_pin) {
   |                                                ^^^^^^^^^^^^^ the trait `_embedded_hal_digital_InputPin` is not implemented for `PA1<Output<OpenDrain>>`
   |
   = note: required because of the requirements on the impl of `stm32l4xx_hal::prelude::InputPin` for `PA1<Output<OpenDrain>>`
   = note: required because of the requirements on the impl of `InputOutputPin<()>` for `PA1<Output<OpenDrain>>`
   = note: required by `dht_sensor::DhtReading::read`

I think it could not convert to InputOutputPin from Output. Could you give some advice.

michaelbeaumont commented 3 years ago

Sure, for the second issue, the pin you pass must implement both InputPin and OutputPin from embedded-hal (i.e. you don't need to convert anything, InputOutputPin is automatically implemented given the first two impls).

For example with stm32l0xx-hal, PA1<Output<_>> implements OutputPin but also InputPin, same with stm32-l4xx-hal. Unfortunately, for stm32l4xx-hal this is missing. It's almost certainly possible with l4xx chips because you can read the state of the pin just like with the other chips, but should be added upstream. Of course, until then you could manually create such a wrapper type.

Here's the PR that added support to stm32f4xx-hal, for example.

michaelbeaumont commented 3 years ago

I'm not sure where the first error is coming from, can you post your Cargo.toml? The only other requirement is that the associated Error type for InputPin and OutputPin is the same, but that seems to be the case for stm32l4xx-hal anyway. Nothing in dht-sensor constrains the error type to be ()... :thinking:

The second error is the biggest issue I think.

falloutkid commented 3 years ago

@michaelbeaumont Thank you for quick reply!

for stm32l4xx-hal this is missing.

Oh... I'll try a wrapper type. When I check this advice, I'll report.

can you post your Cargo.toml?

My Cargo.toml is here

[dependencies]
cortex-m = "0.6.0"
cortex-m-rt = "0.6.10"
cortex-m-semihosting = "0.3.3"
panic-halt = "0.2.0"
nb = "1.0.0"
heapless = "0.6.1"
dht-sensor = "0.2.1"

# Uncomment for the panic example.
# panic-itm = "0.4.1"

# Uncomment for the allocator example.
# alloc-cortex-m = "0.4.0"

# Uncomment for the device example.
# Update `memory.x`, set target to `thumbv7em-none-eabihf` in `.cargo/config`,
# and then use `cargo build --examples device` to build it.
[dependencies.stm32l4]
version = "0.13.0"
features = ["stm32l4x6", "rt"]

[dependencies.stm32l4xx-hal]
version = "0.6.0"
features = ["stm32l4x6", "rt"]

[[bin]]
name = "nucleo_l476rg_sample"
test = false
bench = false

[profile.release]
codegen-units = 1 # better optimizations
debug = true # symbols are nice and they don't increase the size on Flash
lto = true # better optimizations
falloutkid commented 3 years ago

I could build this code and check behavior. But I could not get a value. It happened Error Timeout I'll change data pin.

Thanks!!

michaelbeaumont commented 1 year ago

Closing this since the correct traits have been available in stm32-l4xx-hal since v0.7.0. Definitely open an issue if you want to look at the Timeout error further!