From fbde5c13ac1ca83d55a7f4834f2f6f7592f8f1ef Mon Sep 17 00:00:00 2001 From: Stephen D <webmaster@scd31.com> Date: Sun, 24 Nov 2024 11:49:54 -0400 Subject: [PATCH] add bme280 support --- Cargo.lock | 10 ++++++++++ Cargo.toml | 1 + src/main.rs | 47 ++++++++++++++++++++++++++++++++++++++++++----- src/shell.rs | 21 ++++++++++++++++++++- 4 files changed, 73 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b6d03ce..bcfdfd5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -65,6 +65,15 @@ dependencies = [ "wyz", ] +[[package]] +name = "bme280" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32c139eaf2284d0c91a25f61d84dd326444cace86cb0371f45d71d2d055ba432" +dependencies = [ + "embedded-hal 0.2.7", +] + [[package]] name = "byteorder" version = "1.5.0" @@ -76,6 +85,7 @@ name = "cats-mobile-transceiver-mainboard" version = "0.2.1" dependencies = [ "arrayvec", + "bme280", "cortex-m", "cortex-m-rt", "cortex-m-rtic", diff --git a/Cargo.toml b/Cargo.toml index 6412f1d..1891060 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,3 +36,4 @@ num-traits = { version = "0.2.17", default-features = false, features = ["libm"] rand = { version = "0.8", default-features = false, features = ["small_rng"] } postcard = "1.0.8" serde = { version = "1.0.196", default-features = false, features = ["derive"] } +bme280 = { version = "0.3", default-features = false } diff --git a/src/main.rs b/src/main.rs index 1037e27..1a68693 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,6 +24,7 @@ mod app { use core::fmt::Write; use arrayvec::ArrayString; + use bme280::i2c::BME280; use cortex_m::singleton; use hal::{ adc::{config::AdcConfig, Adc}, @@ -42,7 +43,12 @@ mod app { packet::Packet, whisker::{Gps, NodeInfoBuilder, Route}, }; - use stm32f4xx_hal as hal; + use stm32f4xx_hal::{ + self as hal, + i2c::I2c, + pac::{I2C1, TIM11}, + timer::Delay, + }; use systick_monotonic::{fugit::Instant, ExtU64, Systick}; use usb_device::prelude::*; @@ -73,6 +79,8 @@ mod app { #[monotonic(binds = SysTick, default = true)] type MyMono = Systick<{ SYS_TICK_FREQ }>; + pub type MyBme280 = BME280<I2c<I2C1>, Delay<TIM11, 1000>>; + #[local] struct Local { green: gpio::Pin<'B', 15, gpio::Output>, @@ -91,6 +99,7 @@ mod app { radio: Option<RadioManager<'static>>, gps: GpsModule, volt_meter: VoltMeter, + bme280: MyBme280, usb_dev: UsbDevice<'static, UsbBusType>, shell: Shell, @@ -191,6 +200,19 @@ mod app { .with_u8_data(); gps_serial.listen(serial::Event::Rxne); + // Set up BME280 + let scl = gpiob.pb8; + let sda = gpiob.pb9; + let i2c = I2c::new( + dp.I2C1, + (scl, sda), + hal::i2c::Mode::standard(100.kHz()), + &clocks, + ); + + let mut bme280 = BME280::new_primary(i2c, dp.TIM11.delay_ms(&clocks)); + let _ = bme280.init(); + // Setup USB static mut EP_MEMORY: [u32; 1024] = [0; 1024]; static mut USB_BUS: Option<usb_device::bus::UsbBusAllocator<UsbBusType>> = None; @@ -258,6 +280,7 @@ mod app { radio, gps: GpsModule::new(), volt_meter, + bme280, usb_dev, shell, @@ -292,7 +315,7 @@ mod app { } } - #[task(priority = 2, local = [buf, bootup_time], shared = [red, radio, gps, config, status, volt_meter])] + #[task(priority = 2, local = [buf, bootup_time], shared = [red, radio, gps, config, status, volt_meter, bme280])] fn transmit_position(mut ctx: transmit_position::Context) { let mut config = ctx.shared.config; let (black_hole, transmit_period_seconds) = @@ -331,6 +354,14 @@ mod app { .to_secs() .try_into() .unwrap_or(0); + let (temperature, pressure, humidity) = ctx.shared.bme280.lock(|b| match b.measure() { + Ok(o) => (o.temperature, o.pressure, o.humidity), + Err(_) => { + let _ = b.init(); // hail mary attempt + + (0.0, 0.0, 0.0) + } + }); let mut info_builder = NodeInfoBuilder::default() .hardware_id(HARDWARE_ID) @@ -348,7 +379,12 @@ mod app { .unwrap(); let mut buf: ArrayString<64> = ArrayString::new(); - write!(&mut buf, "{} {} {}", sensors[0], sensors[1], sensors[2]).unwrap(); + write!( + &mut buf, + "{} {} {} {} {} {}", + sensors[0], sensors[1], sensors[2], temperature, pressure, humidity + ) + .unwrap(); cats.add_comment(&buf).unwrap(); cats.add_route(Route::new(config.max_hops)).unwrap(); @@ -467,17 +503,18 @@ mod app { } } - #[task(binds=OTG_FS, priority = 2, local=[flash], shared=[usb_dev, shell, volt_meter])] + #[task(binds=OTG_FS, priority = 2, local=[flash], shared=[usb_dev, shell, volt_meter,bme280])] fn usb_fs(cx: usb_fs::Context) { let usb_fs::SharedResources { mut usb_dev, mut shell, mut volt_meter, + mut bme280, } = cx.shared; (&mut usb_dev, &mut shell).lock(|usb_dev, shell| { while usb_dev.poll(&mut [shell.ushell.get_serial_mut()]) { - shell.poll(cx.local.flash, &mut volt_meter); + shell.poll(cx.local.flash, &mut volt_meter, &mut bme280); } }); } diff --git a/src/shell.rs b/src/shell.rs index dc9fab4..1a9c596 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -10,6 +10,7 @@ use usbd_serial::SerialPort; use ushell::{autocomplete::StaticAutocomplete, history::LRUHistory, Input, ShellError, UShell}; use crate::{ + app::MyBme280, config::{BlackHoleSetting, Config, Frequency, GpsSetting, Maybe, MaybeBlackHole}, voltage::VoltMeter, }; @@ -54,7 +55,12 @@ impl Shell { Self { ushell, config } } - pub fn poll<V: Mutex<T = VoltMeter>>(&mut self, flash: &mut LockedFlash, volt_meter: &mut V) { + pub fn poll<V: Mutex<T = VoltMeter>, B: Mutex<T = MyBme280>>( + &mut self, + flash: &mut LockedFlash, + volt_meter: &mut V, + bme280: &mut B, + ) { loop { let ushell = &mut self.ushell; match ushell.poll() { @@ -266,6 +272,19 @@ impl Shell { ) .ok(); } + "bme280" => match bme280.lock(|b| b.measure()) { + Ok(m) => { + write!( + ushell, + "\r\nTemperature: {} deg C\r\nPressure: {} pascals\r\nHumidity: {}%\r\n", + m.temperature, m.pressure, m.humidity + ).ok(); + } + Err(e) => { + write!(ushell, "Could not communicate with the bme280: {:?}", e) + .ok(); + } + }, "help" => { write!(ushell, "{}", HELP_TEXT).ok(); } -- GitLab