VersBinarii / bme280-rs

A platform agnostic Rust driver for the Bosch BM[PE]-280
Other
59 stars 72 forks source link

Consumes the delay provider #10

Closed nebelgrau77 closed 2 years ago

nebelgrau77 commented 4 years ago

The driver works great, but consumes the delay provider, making it unavailable for the rest of the code. Of course the delay is necessary for soft_reset and measure functions, but I was wondering whether it could be done differently. Possible ideas (which may or may not work):

I don't know enough Rust to try and tackle it myself yet, but maybe one of these could be tried?

dtantsur commented 3 years ago

I agree, this feature makes the driver practically unusable on embedded where Delay cannot be cloned.

fishrockz commented 3 years ago

I am looking to write a version that will allow this to work by borrowing but as a first pass i have implemented a very simple release() function here https://github.com/fishrockz/bme280-rs/tree/willsalmon/release

Release is not ideal but it lets you do things like

    loop {
        delay(clocks.sysclk().0 / 100);
        // The Aidafruit boards have address 0x77 without closing the jumper on the back, the BME280 lib connects to 0x77 with `new_secondary`, use
        // `new_primary` for 0x76 if you close teh jumper/solder bridge.
        {
            let mut bme280 = BME280::new(spi, cs_bme, delay_ob).unwrap();
            bme280
                .init()
                .map_err(|error| {
                    hprintln!("Could not initialize bme280, Error: {:?}", error).unwrap();
                    panic!();
                })
                .unwrap();
            match bme280.measure() {
                Ok(measurements) => {
                    hprintln!("Relative Humidity = {}%", measurements.humidity).unwrap();
                    hprintln!("Temperature = {} deg C", measurements.temperature).unwrap();
                    hprintln!("Pressure = {} pascals", measurements.pressure).unwrap();
                    write!(&mut arr_message, "The presure is {}", measurements.pressure)
                        .expect("Can't write");
                }
                Err(error) => {
                    hprintln!("Could not read bme280 due to error: {:?}", error).unwrap();
                }
            }
            for (i, c) in arr_message.chars().enumerate() {
                buffer[i] = c as u8;
            }

            hprintln!("buffer {:?}?", buffer).unwrap();

            (spi, cs_bme, delay_ob) = bme280.release();
        }
        {
            //lora.set_mode(sx127x_lora::RadioMode::Tx).unwrap();
            let mut lora = sx127x_lora::LoRa::new(spi, cs_lora, reset, 434, delay_ob).unwrap();
            lora.set_tx_power(17, 1).unwrap(); //Using PA_BOOST. See your board for correct pin.

            let transmit = lora.transmit_payload(buffer, arr_message.len());
            match transmit {
                Ok(()) => hprintln!("Sent packet").unwrap(),
                Err(e) => hprintln!("Error {:?}", e).unwrap(),
            };
            delay(clocks.sysclk().0 * 5);
            (spi, cs_lora, reset, delay_ob) = lora.release();
        }
    }

Which is no good if you need to quickly swap back and forth but dose let you swap back and for slowly.

I have not created a PR yet as I am working on top of https://github.com/uber-foo/bme280-rs/pull/6 which is approved but not merged.

keestux commented 2 years ago

Notice that VersBinarii has a solution.

nebelgrau77 commented 2 years ago

Notice that VersBinarii has a solution.

I'm missing something: what is the solution? Looks to me like it has the same problem, consuming the delay. Which unfortunately is a problem of some other sensors, too, those that require a specific amount of time between one thing and another. Ideally there is a bit you can keep reading, but if the datasheet says "wait 30 ms", the delay seems to be the (only?) option.

keestux commented 2 years ago

Let me first say that I'm just a Rust beginner. As far as I know VersBinarii's version does not consume the delay. That's the whole point. It takes mutable reference (or whatever that's called in Rust).

    /// Initializes the BME280
    pub fn init<D>(&mut self, delay: &mut D) -> Result<(), Error<E>>
    where
        D: DelayMs<u8>,
    {...}

The constructor doesn't even see the delay. With VersBinarii's version I was able to build my little nRF example, reading sensor data in a loop with a 1s delay.


    let mut delay = Delay::new(cp.SYST);

    // initialize the BME280 using the primary I2C address 0x76
    let mut bme280 = BME280::new_secondary(i2c);

    let _ = bme280.init(&mut delay).unwrap();

    loop {
        delay.delay_ms(1000u16);
        let measurements = bme280.measure(&mut delay).unwrap();
        rprintln!("Relative Humidity = {:.2}%", measurements.humidity);
        rprintln!("Temperature = {:.1} °C", measurements.temperature);
        rprintln!("Pressure = {:.2} hPa", measurements.pressure / 100f32);
    }
nebelgrau77 commented 2 years ago

Let me first say that I'm just a Rust beginner. As far as I know VersBinarii's version does not consume the delay. That's the whole point. It takes mutable reference (or whatever that's called in Rust).

Gotcha! Yes, I didn't notice that it was only borrowing the delay (yep, it is called a mutable reference). Thanks!!!