michaelbeaumont / dht-sensor

Rust embedded-hal based driver for the DHT11/DHT22 sensor

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to convert InputOutputPin from Output<OpenDrain>

falloutkid opened this issue · comments

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.

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.

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 ()... 🤔

The second error is the biggest issue I think.

@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

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!!

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!