diff --git a/Cargo.lock b/Cargo.lock index 8917ced..af5bc0c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1439,6 +1439,15 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +[[package]] +name = "static_cell" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0530892bb4fa575ee0da4b86f86c667132a94b74bb72160f58ee5a4afec74c23" +dependencies = [ + "portable-atomic", +] + [[package]] name = "strsim" version = "0.11.1" @@ -1617,6 +1626,7 @@ dependencies = [ "critical-section", "embassy-executor", "embassy-net", + "embassy-sync 0.7.2", "embassy-time", "embedded-hal-bus", "esp-alloc", @@ -1628,6 +1638,7 @@ dependencies = [ "esp-rtos", "lcd-lcm1602-i2c", "scd4x", + "static_cell", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 27f488c..d889db1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,6 +57,8 @@ bosch-bme680 = "1.0.4" lcd-lcm1602-i2c = "0.3.0" embedded-hal-bus = { version = "0.3.0", features = ["alloc"] } scd4x = { version = "0.4.1", features = ["scd41"] } +embassy-sync = "0.7.2" +static_cell = "2.1.1" [profile.dev] # Rust debug is too slow. diff --git a/src/main.rs b/src/main.rs index 6cd9efc..6e589b4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,24 +10,46 @@ use core::cell::RefCell; use alloc::rc::Rc; +use alloc::string::ToString; use bosch_bme680::{Bme680, DeviceAddress}; use embassy_executor::Spawner; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::channel::{Channel, Receiver, Sender}; use embassy_time::{Delay, Duration, Timer}; use embedded_hal_bus::i2c::RcDevice; use esp_backtrace as _; +use esp_hal::Blocking; use esp_hal::clock::CpuClock; -use esp_hal::gpio::{Level, Output, OutputConfig}; use esp_hal::i2c::master::{Config as I2cConfig, I2c}; use esp_hal::timer::timg::TimerGroup; -use esp_hal::{Async, Blocking}; use scd4x::Scd4x; +use static_cell::StaticCell; extern crate alloc; +//TODO: make full async - https://github.com/embassy-rs/embassy/blob/main/examples/rp/src/bin/shared_bus.rs + // This creates a default app-descriptor required by the esp-idf bootloader. // For more information see: esp_bootloader_esp_idf::esp_app_desc!(); +#[derive(Debug)] +enum Events { + BME680 { + temp: f32, + humidity: f32, + pressure: f32, + gas_resistance: f32, + }, + SCD41 { + co2: u16, + temperature: f32, + humidity: f32, + }, +} + +static CHANNEL: StaticCell> = StaticCell::new(); + #[allow( clippy::large_stack_frames, reason = "it's not unusual to allocate larger buffers etc. in main" @@ -53,33 +75,41 @@ async fn main(spawner: Spawner) { esp_radio::wifi::new(&radio_init, peripherals.WIFI, Default::default()) .expect("Failed to initialize Wi-Fi controller"); - let pin = Output::new(peripherals.GPIO2, Level::High, OutputConfig::default()); - let i2c_v33 = I2c::new(peripherals.I2C0, I2cConfig::default()) .unwrap() .with_scl(peripherals.GPIO22) .with_sda(peripherals.GPIO21); let shared_i2c_v33 = Rc::new(RefCell::new(i2c_v33)); - spawner.spawn(flash_led(pin)).unwrap(); + let i2c_v5 = I2c::new(peripherals.I2C1, I2cConfig::default()) + .unwrap() + .with_scl(peripherals.GPIO26) + .with_sda(peripherals.GPIO25); + + let channel = CHANNEL.init(Channel::new()); + spawner - .spawn(read_bme_680(RcDevice::new(shared_i2c_v33.clone()))) + .spawn(read_bme_680( + RcDevice::new(shared_i2c_v33.clone()), + channel.sender(), + )) .unwrap(); spawner - .spawn(read_scd_41(RcDevice::new(shared_i2c_v33.clone()))) + .spawn(read_scd_41( + RcDevice::new(shared_i2c_v33.clone()), + channel.sender(), + )) + .unwrap(); + spawner + .spawn(display_data(i2c_v5, channel.receiver())) .unwrap(); } #[embassy_executor::task] -async fn flash_led(mut pin: Output<'static>) { - loop { - pin.toggle(); - Timer::after(Duration::from_secs(1)).await; - } -} - -#[embassy_executor::task] -async fn read_bme_680(i2c: RcDevice>) { +async fn read_bme_680( + i2c: RcDevice>, + sender: Sender<'static, NoopRawMutex, Events, 1>, +) { let mut sensor = Bme680::new( i2c, DeviceAddress::Primary, @@ -93,12 +123,22 @@ async fn read_bme_680(i2c: RcDevice>) { Timer::after(Duration::from_secs(5)).await; let data = sensor.measure().unwrap(); - esp_println::println!("Got data: {:?}", data); + sender + .send(Events::BME680 { + temp: data.temperature, + humidity: data.humidity, + pressure: data.pressure, + gas_resistance: data.gas_resistance.unwrap_or(0.), + }) + .await; } } #[embassy_executor::task] -async fn read_scd_41(i2c: RcDevice>) { +async fn read_scd_41( + i2c: RcDevice>, + sender: Sender<'static, NoopRawMutex, Events, 1>, +) { let mut sensor = Scd4x::new(i2c, Delay); sensor.wake_up(); sensor.stop_periodic_measurement().unwrap(); @@ -114,11 +154,65 @@ async fn read_scd_41(i2c: RcDevice>) { Timer::after(Duration::from_secs(5)).await; let data = sensor.measurement().unwrap(); - esp_println::println!( - "CO2: {}, Temperature: {} °C, Humidity: {} RH", - data.co2, - data.temperature, - data.humidity - ); + sender + .send(Events::SCD41 { + co2: data.co2, + temperature: data.temperature, + humidity: data.humidity, + }) + .await; + } +} + +#[embassy_executor::task] +async fn display_data( + mut i2c: I2c<'static, Blocking>, + receiver: Receiver<'static, NoopRawMutex, Events, 1>, +) { + let mut delay = Delay; + let mut lcd = lcd_lcm1602_i2c::sync_lcd::Lcd::new(&mut i2c, &mut delay) + .with_address(0x27) + .with_cursor_on(false) + .with_rows(2) + .init() + .unwrap(); + + struct Data { + temp: f32, + humidity: f32, + pressure: f32, + gas_resistance: f32, + co2: u16, + } + + let mut data = Data { + temp: 0.0, + humidity: 0.0, + pressure: 0.0, + gas_resistance: 0.0, + co2: 0, + }; + + loop { + match receiver.receive().await { + Events::BME680 { + temp, + humidity, + pressure, + gas_resistance, + } => { + data.temp = temp; + data.humidity = humidity; + data.pressure = pressure; + data.gas_resistance = gas_resistance; + } + Events::SCD41 { co2, .. } => { + data.co2 = co2; + } + } + + lcd.clear().unwrap(); + lcd.write_str("temp:").unwrap(); + lcd.write_str(&data.temp.to_string()).unwrap(); } }