Improve line graph drawing function & begin input handling

This commit is contained in:
Adam 2025-06-08 01:16:38 +01:00
parent 219e43fee8
commit 3255976961
8 changed files with 224 additions and 171 deletions

View File

@ -1,11 +1,3 @@
[alias]
build-arm = "build --target=thumbv8m.main-none-eabihf"
build-riscv = "build --target=riscv32imac-unknown-none-elf"
run-arm = "run --target=thumbv8m.main-none-eabihf"
run-riscv = "run --target=riscv32imac-unknown-none-elf"
[build] [build]
target = "thumbv8m.main-none-eabihf" target = "thumbv8m.main-none-eabihf"
@ -18,10 +10,8 @@ rustflags = [
"-C", "-C",
"target-cpu=cortex-m33", "target-cpu=cortex-m33",
] ]
runner = "probe-rs run --chip RP235x"
runner = "picotool load -u -v -x -t elf"
[target.riscv32imac-unknown-none-elf] [target.riscv32imac-unknown-none-elf]
rustflags = ["-C", "link-arg=--nmagic", "-C", "link-arg=-Trp235x_riscv.x"] rustflags = ["-C", "link-arg=--nmagic", "-C", "link-arg=-Trp235x_riscv.x"]
runner = "probe-rs run --chip RP235x"
runner = "picotool load -u -v -x -t elf"

20
Cargo.lock generated
View File

@ -703,15 +703,6 @@ dependencies = [
"either", "either",
] ]
[[package]]
name = "itertools"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
dependencies = [
"either",
]
[[package]] [[package]]
name = "lalrpop" name = "lalrpop"
version = "0.19.12" version = "0.19.12"
@ -723,7 +714,7 @@ dependencies = [
"diff", "diff",
"ena", "ena",
"is-terminal", "is-terminal",
"itertools 0.10.5", "itertools",
"lalrpop-util", "lalrpop-util",
"petgraph", "petgraph",
"regex", "regex",
@ -896,18 +887,20 @@ name = "pico-enviro-sensor"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"circular-buffer", "circular-buffer",
"cortex-m",
"cortex-m-rt", "cortex-m-rt",
"critical-section",
"display-interface-spi", "display-interface-spi",
"embassy-embedded-hal", "embassy-embedded-hal",
"embassy-executor", "embassy-executor",
"embassy-futures",
"embassy-rp", "embassy-rp",
"embassy-sync", "embassy-sync",
"embassy-time", "embassy-time",
"embedded-graphics", "embedded-graphics",
"embedded-graphics-framebuf", "embedded-graphics-framebuf",
"fixed",
"heapless", "heapless",
"itertools 0.14.0",
"num-traits",
"rtt-target", "rtt-target",
"scd4x", "scd4x",
"ssd1351", "ssd1351",
@ -1144,7 +1137,8 @@ checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
[[package]] [[package]]
name = "scd4x" name = "scd4x"
version = "0.4.0" version = "0.4.0"
source = "git+https://github.com/twokilohertz/scd4x-rs.git?branch=conversion-fixes#07730523c51d6909530c000de271832125760385" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "550fedc97e7880654aa7dc840f5eb3b2201a01aae566c4584a3601bb0086cd4c"
dependencies = [ dependencies = [
"embedded-hal 1.0.0", "embedded-hal 1.0.0",
"log", "log",

View File

@ -22,12 +22,14 @@ embassy-executor = { version = "0.7.0", features = [
"task-arena-size-65536", "task-arena-size-65536",
] } ] }
embassy-time = "0.4.0" embassy-time = "0.4.0"
embassy-sync = "0.6.2"
embassy-embedded-hal = "0.3.0" embassy-embedded-hal = "0.3.0"
static_cell = "2.1.0" embassy-futures = "0.1.1"
embassy-sync = "0.6.2"
# System # System
cortex-m-rt = "0.7.5" cortex-m-rt = "0.7.5"
cortex-m = "0.7.7"
critical-section = "1.2.0"
rtt-target = "0.6.1" rtt-target = "0.6.1"
# embedded-graphics # embedded-graphics
@ -40,10 +42,10 @@ ssd1351 = "0.5.0"
display-interface-spi = "0.5.0" display-interface-spi = "0.5.0"
# Extra # Extra
static_cell = "2.1.0"
heapless = "0.8.0" heapless = "0.8.0"
circular-buffer = { version = "1.0.0", default-features = false } circular-buffer = { version = "1.0.0", default-features = false }
itertools = { version = "0.14.0", default-features = false } fixed = "1.29.0"
num-traits = { version = "0.2.19", default-features = false }
[profile.dev] [profile.dev]
opt-level = "s" opt-level = "s"

View File

@ -1,3 +1,3 @@
export PICO_BOARD=pico2_w export PICO_BOARD=pico2_w
export PICO_PLATFORM=rp2350-arm-s export PICO_PLATFORM=rp2350-arm-s
export PICO_SDK_PATH=~/devel/clones/pico-sdk/ export PICO_SDK_PATH=~/devel/clones/pico-sdk

View File

@ -1,8 +1,11 @@
use core::fmt::Write;
// System // System
use embassy_embedded_hal::shared_bus::blocking::spi::SpiDeviceWithConfig; use embassy_embedded_hal::shared_bus::blocking::spi::SpiDeviceWithConfig;
use embassy_rp::{gpio::Output, spi::Config}; use embassy_rp::{gpio::Output, spi::Config};
use embedded_graphics_framebuf::FrameBuf; use embedded_graphics_framebuf::FrameBuf;
use rtt_target::rprintln; use fixed::types::U16F16;
use rtt_target::debug_rprintln;
// Display // Display
use display_interface_spi::SPIInterface; use display_interface_spi::SPIInterface;
@ -16,9 +19,9 @@ use ssd1351::{
use embedded_graphics::{ use embedded_graphics::{
draw_target::DrawTarget, draw_target::DrawTarget,
mono_font::{ascii::FONT_6X10, MonoTextStyle}, mono_font::{ascii::FONT_6X10, MonoTextStyle},
pixelcolor::Rgb565, pixelcolor::{Rgb565, Rgb888},
prelude::{Point, Primitive, RgbColor, Size, WebColors}, prelude::{Point, Primitive, RgbColor, Size, WebColors},
primitives::{Line, PrimitiveStyle, PrimitiveStyleBuilder, Rectangle}, primitives::{Line, PrimitiveStyle, Rectangle, StyledDrawable},
text::{Alignment, Text, TextStyleBuilder}, text::{Alignment, Text, TextStyleBuilder},
Drawable, Drawable,
}; };
@ -26,15 +29,13 @@ use embedded_graphics::{
// Containers // Containers
use circular_buffer::CircularBuffer; use circular_buffer::CircularBuffer;
use heapless::String; use heapless::String;
use itertools::Itertools;
use core::fmt::Write;
use num_traits::{Num, NumCast};
use crate::{Spi0BusMutex, SENSOR_DATA_SIGNAL}; use crate::{Spi0BusMutex, SENSOR_DATA_SIGNAL};
const DISPLAY_WIDTH: usize = 128; const DISPLAY_WIDTH: usize = 128;
const DISPLAY_HEIGHT: usize = 128; const DISPLAY_HEIGHT: usize = 128;
const DISPLAY_PADDING: usize = 5;
type SensorDataBuffer = CircularBuffer<60, U16F16>;
/// Output to the SSD1351 display /// Output to the SSD1351 display
#[embassy_executor::task] #[embassy_executor::task]
@ -45,7 +46,7 @@ pub async fn display_output_task(
rst: &'static mut Output<'static>, rst: &'static mut Output<'static>,
spi_config: Config, spi_config: Config,
) { ) {
rprintln!("Display output task started"); debug_rprintln!("Display output task started");
let spi_dev = SpiDeviceWithConfig::new(spi_bus, cs, spi_config); let spi_dev = SpiDeviceWithConfig::new(spi_bus, cs, spi_config);
let interface = SPIInterface::new(spi_dev, dc); let interface = SPIInterface::new(spi_dev, dc);
@ -73,14 +74,14 @@ pub async fn display_output_task(
let humidity_text_style = MonoTextStyle::new(&FONT_6X10, Rgb565::CSS_AQUAMARINE); let humidity_text_style = MonoTextStyle::new(&FONT_6X10, Rgb565::CSS_AQUAMARINE);
// Format string buffers // Format string buffers
let mut co2_text_buf = String::<16>::new(); let mut co2_text_buf = String::<20>::new();
let mut temp_text_buf = String::<16>::new(); let mut temp_text_buf = String::<20>::new();
let mut humidity_text_buf = String::<16>::new(); let mut humidity_text_buf = String::<20>::new();
// Ring buffer for storing past measurement data // Ring buffer for storing past measurement data
let mut co2_samples = CircularBuffer::<60, u16>::new(); let mut co2_samples = SensorDataBuffer::new();
let mut temp_samples = CircularBuffer::<60, f32>::new(); let mut temp_samples = SensorDataBuffer::new();
let mut humidity_samples = CircularBuffer::<60, f32>::new(); let mut humidity_samples = SensorDataBuffer::new();
loop { loop {
// Clear the framebuffer // Clear the framebuffer
@ -98,28 +99,19 @@ pub async fn display_output_task(
write!(&mut humidity_text_buf, "RH: {:.1} %", sensor_data.humidity).unwrap(); write!(&mut humidity_text_buf, "RH: {:.1} %", sensor_data.humidity).unwrap();
// Record samples // Record samples
co2_samples.push_back(sensor_data.co2); co2_samples.push_back(U16F16::from_num(sensor_data.co2));
temp_samples.push_back(sensor_data.temperature); temp_samples.push_back(U16F16::from_num(sensor_data.temperature));
humidity_samples.push_back(sensor_data.humidity); humidity_samples.push_back(U16F16::from_num(sensor_data.humidity));
co2_samples.make_contiguous();
temp_samples.make_contiguous();
humidity_samples.make_contiguous();
let co2_min = *co2_samples.iter().min().unwrap(); let co2_min = *co2_samples.iter().min().unwrap();
let co2_max = *co2_samples.iter().max().unwrap(); let co2_max = *co2_samples.iter().max().unwrap();
let temp_min = *temp_samples let temp_min = *temp_samples.iter().min().unwrap();
.iter() let temp_max = *temp_samples.iter().max().unwrap();
.reduce(|a: &f32, b: &f32| if a.le(b) { a } else { b }) let humid_min = *humidity_samples.iter().min().unwrap();
.unwrap(); let humid_max = *humidity_samples.iter().max().unwrap();
let temp_max = *temp_samples
.iter()
.reduce(|a: &f32, b: &f32| if a.ge(b) { a } else { b })
.unwrap();
let humid_min = *humidity_samples
.iter()
.reduce(|a: &f32, b: &f32| if a.le(b) { a } else { b })
.unwrap();
let humid_max = *humidity_samples
.iter()
.reduce(|a: &f32, b: &f32| if a.ge(b) { a } else { b })
.unwrap();
/* /*
Note about drawing positions: Note about drawing positions:
@ -130,44 +122,53 @@ pub async fn display_output_task(
// Draw line graphs // Draw line graphs
if co2_samples.len() >= 2 { const LINE_GRAPH_WIDTH: u32 = (DISPLAY_WIDTH - (DISPLAY_PADDING * 2)) as u32;
draw_line_graph( const LINE_GRAPH_HEIGHT: u32 = 36;
&co2_samples,
co2_max.into(),
co2_min.into(),
4,
Rgb565::CSS_DARK_GREEN,
Some(Rgb565::new(3, 5, 3)),
&mut framebuf,
)
.unwrap();
}
if temp_samples.len() >= 2 { draw_line_graph(
draw_line_graph( Rectangle::new(
&temp_samples, Point::new(DISPLAY_PADDING as i32, DISPLAY_PADDING as i32),
temp_max as i32, Size::new(LINE_GRAPH_WIDTH, LINE_GRAPH_HEIGHT),
temp_min as i32, ),
38, co2_min,
Rgb565::CSS_ORANGE, co2_max,
Some(Rgb565::new(3, 5, 3)), co2_samples.as_slices().0,
&mut framebuf, Rgb565::CSS_DARK_GREEN,
) Some(Rgb888::new(24, 24, 24).into()),
.unwrap(); &mut framebuf,
} );
if humidity_samples.len() >= 2 { draw_line_graph(
draw_line_graph( Rectangle::new(
&humidity_samples, Point::new(
humid_max as i32, DISPLAY_PADDING as i32,
humid_min as i32, (LINE_GRAPH_HEIGHT + (DISPLAY_PADDING as u32 * 2)) as i32,
72, ),
Rgb565::CSS_AQUA, Size::new(LINE_GRAPH_WIDTH, LINE_GRAPH_HEIGHT),
Some(Rgb565::new(3, 5, 3)), ),
&mut framebuf, temp_min,
) temp_max,
.unwrap(); temp_samples.as_slices().0,
} Rgb565::CSS_ORANGE,
Some(Rgb888::new(24, 24, 24).into()),
&mut framebuf,
);
draw_line_graph(
Rectangle::new(
Point::new(
DISPLAY_PADDING as i32,
((LINE_GRAPH_HEIGHT * 2) + (DISPLAY_PADDING as u32 * 3)) as i32,
),
Size::new(LINE_GRAPH_WIDTH, LINE_GRAPH_HEIGHT),
),
humid_min,
humid_max,
humidity_samples.as_slices().0,
Rgb565::CSS_AQUA,
Some(Rgb888::new(24, 24, 24).into()),
&mut framebuf,
);
// Draw the text to the screen // Draw the text to the screen
@ -206,62 +207,61 @@ pub async fn display_output_task(
); );
display.fill_contiguous(&area, framebuf.data).unwrap(); display.fill_contiguous(&area, framebuf.data).unwrap();
} }
}
fn draw_line_graph<'a, I, V, D, C>(
collection: I, fn draw_line_graph<C, D>(
graph_max: i32, bounds: Rectangle,
graph_min: i32, y_min: U16F16,
y_start: i32, y_max: U16F16,
line_colour: C, samples: &[U16F16],
back_colour: Option<C>, fg_colour: C,
target: &mut D, bg_colour: Option<C>,
) -> Result<(), D::Error> target: &mut D,
where ) where
I: IntoIterator<Item = &'a V>, C: RgbColor,
I::IntoIter: DoubleEndedIterator, D: DrawTarget<Color = C>,
V: ?Sized + 'a + Num + NumCast + Clone, {
C: RgbColor, // Draw background colour first, if supplied
D: DrawTarget<Color = C>,
{ if let Some(bg_col) = bg_colour {
let mut x_pos: i32 = (DISPLAY_WIDTH - 5) as i32; let _ = bounds.draw_styled(&PrimitiveStyle::with_fill(bg_col), target);
}
match back_colour {
Some(c) => { // Draw the data points
let style = PrimitiveStyleBuilder::new().fill_color(c).build();
if samples.len() < 2 {
Rectangle::new(Point::new(4, y_start), Size::new(120, 30)) // Drawing a line requires a minimum of two points
.into_styled(style) return;
.draw(target)?; }
}
None => {} let graph_width = U16F16::from_num(bounds.size.width);
} let graph_height = U16F16::from_num(bounds.size.height);
let y_range = y_max - y_min;
for (a, b) in collection.into_iter().rev().tuple_windows::<(_, _)>() { let mut x_offset: i32 = bounds.top_left.x;
let range: i32 = if (graph_max - graph_min) == 0 { let n_samples: U16F16 = U16F16::from_num(samples.len());
1_i32 let mut n_samples_seen: U16F16 = U16F16::from_num(1);
} else {
graph_max - graph_min for sample in samples.windows(2) {
}; let x_pos_start: i32 = x_offset;
let y_pos_start: i32 = bounds.top_left.y
let a_i32: i32 = match NumCast::from(a.clone()) { + (graph_height - (((sample[0] - y_min) / y_range) * graph_height)).to_num::<i32>();
Some(v) => v, let x_pos_end: i32 = bounds.top_left.x
None => 0, + (((n_samples_seen + U16F16::from_num(1)) / n_samples)
}; * (graph_width - U16F16::from_num(1)))
let b_i32: i32 = match NumCast::from(b.clone()) { .to_num::<i32>();
Some(v) => v, let y_pos_end: i32 = bounds.top_left.y
None => 0, + (graph_height - (((sample[1] - y_min) / y_range) * graph_height)).to_num::<i32>();
};
let _ = Line::new(
let a_y_pos: i32 = y_start + (((graph_max - a_i32) * 30) / range); Point::new(x_pos_start, y_pos_start),
let b_y_pos: i32 = y_start + (((graph_max - b_i32) * 30) / range); Point::new(x_pos_end, y_pos_end),
)
Line::new(Point::new(x_pos, a_y_pos), Point::new(x_pos - 2, b_y_pos)) .into_styled(PrimitiveStyle::with_stroke(fg_colour, 1))
.into_styled(PrimitiveStyle::with_stroke(line_colour, 1)) .draw(target);
.draw(target)?;
x_offset = x_pos_end;
x_pos -= 2; n_samples_seen += U16F16::from_num(1);
} }
return Ok(()); return;
}
} }

60
src/input_task.rs Normal file
View File

@ -0,0 +1,60 @@
use embassy_futures::select::{select3, Either3};
use embassy_rp::gpio::Input;
use embassy_time::{with_timeout, Duration, Instant};
use rtt_target::debug_rprintln;
const DEBOUNCE_TIME_MILLIS: u64 = 20;
#[embassy_executor::task]
pub async fn input_handling_task(
mut button_enter: Input<'static>,
mut button_left: Input<'static>,
mut button_right: Input<'static>,
) {
debug_rprintln!("Input handling task started");
loop {
let enter_pressed = button_enter.wait_for_falling_edge();
let left_pressed = button_left.wait_for_falling_edge();
let right_pressed = button_right.wait_for_falling_edge();
match select3(enter_pressed, left_pressed, right_pressed).await {
Either3::First(_) => {
let pressed_at = Instant::now();
if with_timeout(Duration::from_secs(2), button_enter.wait_for_rising_edge())
.await
.is_ok()
{
if pressed_at.elapsed().as_millis() < DEBOUNCE_TIME_MILLIS {
continue;
}
debug_rprintln!("Enter button pressed!");
}
}
Either3::Second(_) => {
let pressed_at = Instant::now();
if with_timeout(Duration::from_secs(2), button_left.wait_for_rising_edge())
.await
.is_ok()
{
if pressed_at.elapsed().as_millis() < DEBOUNCE_TIME_MILLIS {
continue;
}
debug_rprintln!("Left button pressed!");
}
}
Either3::Third(_) => {
let pressed_at = Instant::now();
if with_timeout(Duration::from_secs(2), button_right.wait_for_rising_edge())
.await
.is_ok()
{
if pressed_at.elapsed().as_millis() < DEBOUNCE_TIME_MILLIS {
continue;
}
debug_rprintln!("Right button pressed!");
}
}
};
}
}

View File

@ -2,16 +2,17 @@
#![no_main] #![no_main]
mod display_task; mod display_task;
mod input_task;
mod sensor_task; mod sensor_task;
use core::cell::RefCell; use core::cell::RefCell;
use rtt_target::{rprintln, rtt_init_print}; use rtt_target::{debug_rprintln, debug_rtt_init_print};
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_rp::{ use embassy_rp::{
block::ImageDef, block::ImageDef,
gpio::{Level, Output}, gpio::{Input, Level, Output, Pull},
i2c, i2c,
peripherals::{I2C0, SPI0}, peripherals::{I2C0, SPI0},
spi, spi,
@ -27,6 +28,7 @@ use embassy_time::Timer;
use static_cell::StaticCell; use static_cell::StaticCell;
use display_task::display_output_task; use display_task::display_output_task;
use input_task::input_handling_task;
use sensor_task::sensor_read_task; use sensor_task::sensor_read_task;
type I2c0BusMutex = Mutex<NoopRawMutex, RefCell<i2c::I2c<'static, I2C0, i2c::Blocking>>>; type I2c0BusMutex = Mutex<NoopRawMutex, RefCell<i2c::I2c<'static, I2C0, i2c::Blocking>>>;
@ -41,11 +43,11 @@ static SENSOR_DATA_SIGNAL: Signal<CriticalSectionRawMutex, scd4x::types::SensorD
/// Entrypoint /// Entrypoint
#[embassy_executor::main] #[embassy_executor::main]
async fn main(spawner: Spawner) { async fn main(spawner: Spawner) -> ! {
// Initialise RTT logging // Initialise RTT logging
rtt_init_print!(); debug_rtt_init_print!();
rprintln!("RTT logging initialised"); debug_rprintln!("RTT logging initialised");
let peripherals = embassy_rp::init(Default::default()); let peripherals = embassy_rp::init(Default::default());
@ -70,7 +72,7 @@ async fn main(spawner: Spawner) {
let rst = SPI0_RST_PIN.init(Output::new(peripherals.PIN_15, Level::Low)); let rst = SPI0_RST_PIN.init(Output::new(peripherals.PIN_15, Level::Low));
let mut spi_config = spi::Config::default(); let mut spi_config = spi::Config::default();
spi_config.frequency = 4_000_000u32; // 4 MHz spi_config.frequency = 20_000_000u32; // 20 MHz
let spi_bus = spi::Spi::new_blocking_txonly(peripherals.SPI0, sclk, mosi, spi_config.clone()); let spi_bus = spi::Spi::new_blocking_txonly(peripherals.SPI0, sclk, mosi, spi_config.clone());
static SPI0_BUS: StaticCell<Spi0BusMutex> = StaticCell::new(); static SPI0_BUS: StaticCell<Spi0BusMutex> = StaticCell::new();
let shared_spi0_bus = SPI0_BUS.init(Mutex::new(RefCell::new(spi_bus))); let shared_spi0_bus = SPI0_BUS.init(Mutex::new(RefCell::new(spi_bus)));
@ -84,6 +86,11 @@ async fn main(spawner: Spawner) {
spi_config.clone(), spi_config.clone(),
)); ));
let enter_button = Input::new(peripherals.PIN_8, Pull::Up);
let left_button = Input::new(peripherals.PIN_6, Pull::Up);
let right_button = Input::new(peripherals.PIN_7, Pull::Up);
spawner.must_spawn(input_handling_task(enter_button, left_button, right_button));
loop { loop {
Timer::after_secs(1).await; Timer::after_secs(1).await;
} }
@ -92,7 +99,7 @@ async fn main(spawner: Spawner) {
/// Panic handler /// Panic handler
#[panic_handler] #[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! { fn panic(info: &core::panic::PanicInfo) -> ! {
rprintln!("Panicked! {}", info); debug_rprintln!("Panicked! {}", info);
loop { loop {
unsafe { unsafe {

View File

@ -1,7 +1,7 @@
// System // System
use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice; use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
use embassy_time::Timer; use embassy_time::Timer;
use rtt_target::rprintln; use rtt_target::debug_rprintln;
// Sensor // Sensor
use scd4x::Scd4x; use scd4x::Scd4x;
@ -11,7 +11,7 @@ use crate::{I2c0BusMutex, SENSOR_DATA_SIGNAL};
/// Read CO2/temp./humidity data from the sensor /// Read CO2/temp./humidity data from the sensor
#[embassy_executor::task] #[embassy_executor::task]
pub async fn sensor_read_task(i2c_bus: &'static I2c0BusMutex) { pub async fn sensor_read_task(i2c_bus: &'static I2c0BusMutex) {
rprintln!("Sensor read task started"); debug_rprintln!("Sensor read task started");
Timer::after_millis(30).await; // SCD41 power-up delay Timer::after_millis(30).await; // SCD41 power-up delay
let i2c_dev = I2cDevice::new(i2c_bus); let i2c_dev = I2cDevice::new(i2c_bus);
@ -21,8 +21,8 @@ pub async fn sensor_read_task(i2c_bus: &'static I2c0BusMutex) {
scd41.reinit().unwrap(); scd41.reinit().unwrap();
match scd41.serial_number() { match scd41.serial_number() {
Ok(serial) => rprintln!("[SCD41] Serial number: {}", serial), Ok(serial) => debug_rprintln!("[SCD41] Serial number: {}", serial),
Err(error) => rprintln!( Err(error) => debug_rprintln!(
"[SCD41] Error: did not respond to get_serial_number: {:?}", "[SCD41] Error: did not respond to get_serial_number: {:?}",
error error
), ),
@ -35,8 +35,8 @@ pub async fn sensor_read_task(i2c_bus: &'static I2c0BusMutex) {
match scd41.measurement() { match scd41.measurement() {
Ok(data) => { Ok(data) => {
rprintln!( debug_rprintln!(
"[SCD41] CO2: {} ppm, temperature: {} C, humidity: {} RH", "[SCD41] CO2: {} ppm, temperature: {} C, humidity: {} % RH",
data.co2, data.co2,
data.temperature, data.temperature,
data.humidity data.humidity
@ -45,7 +45,7 @@ pub async fn sensor_read_task(i2c_bus: &'static I2c0BusMutex) {
SENSOR_DATA_SIGNAL.signal(data); SENSOR_DATA_SIGNAL.signal(data);
} }
Err(error) => { Err(error) => {
rprintln!( debug_rprintln!(
"[SCD41] Error: failed to retrieve measurement data: {:?}", "[SCD41] Error: failed to retrieve measurement data: {:?}",
error error
); );