From 9d77af462d11b5c999075ef25d8ce2996855a956 Mon Sep 17 00:00:00 2001 From: Adam Macdonald <72780006+twokilohertz@users.noreply.github.com> Date: Sat, 1 Mar 2025 01:18:16 +0000 Subject: [PATCH] Separate sensor read into a separate task --- Cargo.lock | 15 +++++++++-- Cargo.toml | 6 +++-- src/main.rs | 62 ++++++++++++++-------------------------------- src/sensor_task.rs | 53 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 47 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b82816b..bd21a4d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -800,12 +800,14 @@ name = "pico-enviro-sensor" version = "0.1.0" dependencies = [ "cortex-m-rt", - "critical-section", + "embassy-embedded-hal", "embassy-executor", "embassy-rp", + "embassy-sync", "embassy-time", "rtt-target", "scd4x", + "static_cell", ] [[package]] @@ -1038,7 +1040,7 @@ checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "scd4x" version = "0.4.0" -source = "git+https://github.com/twokilohertz/scd4x-rs.git?branch=main#b9b0cb774b78ec7317c3e66f2fae745711101abb" +source = "git+https://github.com/twokilohertz/scd4x-rs.git?branch=conversion-fixes#07730523c51d6909530c000de271832125760385" dependencies = [ "embedded-hal 1.0.0", "log", @@ -1117,6 +1119,15 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "static_cell" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89b0684884a883431282db1e4343f34afc2ff6996fe1f4a1664519b66e14c1e" +dependencies = [ + "portable-atomic", +] + [[package]] name = "string_cache" version = "0.8.8" diff --git a/Cargo.toml b/Cargo.toml index a50d8e3..a8a7ca8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,14 +22,16 @@ embassy-executor = { version = "0.7.0", features = [ "task-arena-size-65536", ] } embassy-time = "0.4.0" +embassy-sync = "0.6.2" +embassy-embedded-hal = "0.3.0" +static_cell = "2.1.0" # System cortex-m-rt = "0.7.5" -critical-section = "1.2.0" rtt-target = "0.6.1" # Peripherals -scd4x = { git = "https://github.com/twokilohertz/scd4x-rs.git", branch = "main", features = [ +scd4x = { git = "https://github.com/twokilohertz/scd4x-rs.git", branch = "conversion-fixes", features = [ "scd41", ] } diff --git a/src/main.rs b/src/main.rs index de62c12..8f2639c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,20 +1,29 @@ #![no_std] #![no_main] +mod sensor_task; + +use core::cell::RefCell; + use rtt_target::{rprintln, rtt_init_print}; use embassy_executor::Spawner; -use embassy_rp::block::ImageDef; +use embassy_rp::{block::ImageDef, i2c::Blocking, i2c::I2c, peripherals::I2C0}; +use embassy_sync::blocking_mutex::{raw::NoopRawMutex, Mutex}; +use embassy_time::Timer; +use static_cell::StaticCell; -mod sensor_task; +use sensor_task::sensor_read_task; embassy_rp::bind_interrupts!(struct Irqs { I2C0_IRQ => embassy_rp::i2c::InterruptHandler; }); +type I2c0BusType = Mutex>>; + /// Entrypoint #[embassy_executor::main] -async fn main(_spawner: Spawner) { +async fn main(spawner: Spawner) { // Initialise RTT logging rtt_init_print!(); @@ -22,52 +31,19 @@ async fn main(_spawner: Spawner) { let peripherals = embassy_rp::init(Default::default()); + // Initialise I2C0 on pins 4 & 5 for the SCD41 sensor let sda = peripherals.PIN_4; let scl = peripherals.PIN_5; - let mut i2c_config = embassy_rp::i2c::Config::default(); // TODO: Frequency is 100 MHz by default, should be 400 MHz - i2c_config.frequency = 400_000u32; + let mut i2c_config = embassy_rp::i2c::Config::default(); + i2c_config.frequency = 400_000u32; // 400 kHz let i2c_bus = embassy_rp::i2c::I2c::new_blocking(peripherals.I2C0, scl, sda, i2c_config); + static I2C0_BUS: StaticCell = StaticCell::new(); + let shared_i2c0_bus = I2C0_BUS.init(Mutex::new(RefCell::new(i2c_bus))); - embassy_time::Timer::after_millis(30).await; // SCD41 power-up delay - let mut scd41 = scd4x::Scd4x::new(i2c_bus, embassy_time::Delay); - scd41.wake_up(); - scd41.reinit().unwrap(); - - match scd41.serial_number() { - Ok(serial) => rprintln!("[SCD41] Serial number: {}", serial), - Err(error) => rprintln!( - "[SCD41] Error: did not respond to get_serial_number: {:?}", - error - ), - } - - scd41.start_periodic_measurement().unwrap(); + spawner.must_spawn(sensor_read_task(shared_i2c0_bus)); loop { - embassy_time::Timer::after_secs(5).await; - match scd41.measurement() { - Ok(data) => { - rprintln!( - "[SCD41] CO2: {} ppm, temperature: {} C, humidity: {} RH", - data.co2, - data.temperature, - data.humidity - ); - } - Err(error) => { - rprintln!( - "[SCD41] Error: failed to retrieve measurement data: {:?}", - error - ); - break; - } - } - } - - loop { - unsafe { - core::arch::asm!("wfi"); - } + Timer::after_secs(1).await; } } diff --git a/src/sensor_task.rs b/src/sensor_task.rs index e69de29..52b3cdd 100644 --- a/src/sensor_task.rs +++ b/src/sensor_task.rs @@ -0,0 +1,53 @@ +// System +use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice; +use embassy_time::Timer; +use rtt_target::rprintln; + +// Sensor +use scd4x::Scd4x; + +use crate::I2c0BusType; + +#[embassy_executor::task] +pub async fn sensor_read_task(i2c_bus: &'static I2c0BusType) { + rprintln!("Sensor read task started"); + + Timer::after_millis(30).await; // SCD41 power-up delay + let i2c_dev = I2cDevice::new(i2c_bus); + + let mut scd41 = Scd4x::new(i2c_dev, embassy_time::Delay); + scd41.wake_up(); + scd41.reinit().unwrap(); + + match scd41.serial_number() { + Ok(serial) => rprintln!("[SCD41] Serial number: {}", serial), + Err(error) => rprintln!( + "[SCD41] Error: did not respond to get_serial_number: {:?}", + error + ), + } + + scd41.start_periodic_measurement().unwrap(); + + loop { + Timer::after_secs(5).await; // start_periodic_measurement() returns new sensor data every 5 seconds + + match scd41.measurement() { + Ok(data) => { + rprintln!( + "[SCD41] CO2: {} ppm, temperature: {} C, humidity: {} RH", + data.co2, + data.temperature, + data.humidity + ); + } + Err(error) => { + rprintln!( + "[SCD41] Error: failed to retrieve measurement data: {:?}", + error + ); + break; + } + } + } +}