Don't crash on every error
This commit is contained in:
parent
4aa87dedc9
commit
a6927ac39e
6
Cargo.lock
generated
6
Cargo.lock
generated
|
@ -742,13 +742,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "embedded-sdmmc"
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da528dbf3f1c1f0b321552bc334d04799bb17c1936de55bccfb643a4f39300d8"
|
||||
checksum = "150f320125310e179b9e73b081173b349e63c5c7d4ca44db4e5b9121b10387ec"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"embedded-hal 1.0.0",
|
||||
"heapless 0.7.17",
|
||||
"heapless 0.8.0",
|
||||
"log",
|
||||
]
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ log = "0.4"
|
|||
pio-proc = "0.2"
|
||||
pio = "0.2.1"
|
||||
rand = { version = "0.8.5", default-features = false }
|
||||
embedded-sdmmc = "0.7.0"
|
||||
embedded-sdmmc = "0.8.0"
|
||||
|
||||
# Dependencies of embedded-sdmmc that I need to use directly
|
||||
byteorder = {version = "1", default-features = false}
|
||||
|
|
130
src/main.rs
130
src/main.rs
|
@ -8,6 +8,8 @@
|
|||
|
||||
mod co2;
|
||||
|
||||
use core::fmt::Debug;
|
||||
|
||||
use byteorder::ByteOrder;
|
||||
use core2::io::{Cursor, Write};
|
||||
use defmt::*;
|
||||
|
@ -20,8 +22,8 @@ use embassy_rp::{gpio, spi};
|
|||
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
|
||||
use embassy_sync::channel::Channel;
|
||||
use embedded_hal_bus::spi::ExclusiveDevice;
|
||||
use embedded_sdmmc::sdcard::{DummyCsPin, SdCard};
|
||||
use embedded_sdmmc::{Block, BlockDevice, BlockIdx, VolumeIdx};
|
||||
use embedded_sdmmc::sdcard::SdCard;
|
||||
use embedded_sdmmc::{Block, BlockDevice, BlockIdx, File, VolumeIdx};
|
||||
use gpio::{Level, Output};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
|
@ -70,43 +72,77 @@ async fn main(spawner: Spawner) {
|
|||
// Wait for sensor to boot
|
||||
Timer::after(Duration::from_secs(1)).await;
|
||||
|
||||
let status = co2::get_status(&mut i2c).await.unwrap();
|
||||
loop {
|
||||
let init_sensor = async {
|
||||
let status = co2::get_status(&mut i2c).await?;
|
||||
|
||||
info!("CO2 sesor reported status on boot: {}", status);
|
||||
info!("CO2 sesor reported status on boot: {}", status);
|
||||
// Byte 7 is FW_MODE which indicates if the app is already running.
|
||||
if status & 128u8 == 0 {
|
||||
info!("App is not running yet. Booting sensor...");
|
||||
// App is not running
|
||||
co2::start_app(&mut i2c).await.unwrap();
|
||||
// After APP_START, we have to wait at least 1 ms (according to datasheet)
|
||||
Timer::after(Duration::from_millis(2)).await;
|
||||
|
||||
// Byte 7 is FW_MODE which indicates if the app is already running.
|
||||
if status & 128u8 == 0 {
|
||||
info!("App is not running yet. Booting sensor...");
|
||||
// App is not running
|
||||
co2::start_app(&mut i2c).await.unwrap();
|
||||
// After APP_START, we have to wait at least 1 ms (according to datasheet)
|
||||
Timer::after(Duration::from_millis(2)).await;
|
||||
if co2::get_status(&mut i2c).await.unwrap() & 128u8 == 0 {
|
||||
error!("App still not running after boot! Aborting initialization...");
|
||||
// FIXME: Can't be bothered to come up with a different error type
|
||||
return Err(embassy_rp::i2c::Error::Abort(i2c::AbortReason::Other(1337)));
|
||||
}
|
||||
} else {
|
||||
info!("App is already running. Skipping boot...");
|
||||
}
|
||||
// 16 is measurement mode 1 => do 1 measurement per second
|
||||
co2::set_measurement_mode(&mut i2c, 16).await?;
|
||||
co2::set_environment_values(&mut i2c, 25000, 660).await
|
||||
};
|
||||
|
||||
if co2::get_status(&mut i2c).await.unwrap() & 128u8 == 0 {
|
||||
error!("App still not running after boot! Terminating...");
|
||||
return;
|
||||
if let Err(e) = init_sensor.await {
|
||||
error!(
|
||||
"Failed to init CO2 sensor: {:?}. Retrying...",
|
||||
defmt::Debug2Format(&e)
|
||||
);
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
info!("App is already running. Skipping boot...");
|
||||
}
|
||||
|
||||
// 16 is measurement mode 1 => 1 measurement per second
|
||||
co2::set_measurement_mode(&mut i2c, 16).await.unwrap();
|
||||
co2::set_environment_values(&mut i2c, 25000, 660)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
loop {
|
||||
let status = co2::get_status(&mut i2c).await.unwrap();
|
||||
let measured_value = co2::get_measurement(&mut i2c).await.unwrap();
|
||||
info!(
|
||||
"Reported status: {}\tMeasured value: {}",
|
||||
status, measured_value
|
||||
);
|
||||
let read_value_if_available = async {
|
||||
let status = co2::get_status(&mut i2c).await?;
|
||||
// Bit 3 is `DATA_READY`
|
||||
if status & 0b00001000u8 != 0 {
|
||||
let measured_value = co2::get_measurement(&mut i2c).await?;
|
||||
return Ok::<Option<(u8, u16)>, embassy_rp::i2c::Error>(Some((
|
||||
status,
|
||||
measured_value,
|
||||
)));
|
||||
}
|
||||
Ok(None)
|
||||
};
|
||||
|
||||
MEASUREMENT_VALUES.send(measured_value).await;
|
||||
|
||||
Timer::after(Duration::from_secs(2)).await;
|
||||
match read_value_if_available.await {
|
||||
Ok(Some((status, measured_value))) => {
|
||||
info!(
|
||||
"Reported status: {}\tMeasured value: {}",
|
||||
status, measured_value
|
||||
);
|
||||
MEASUREMENT_VALUES.send(measured_value).await;
|
||||
}
|
||||
Ok(None) => {
|
||||
info!("No value available. Waiting for new value...")
|
||||
}
|
||||
Err(e) => {
|
||||
error!(
|
||||
"Failed to read value from CO2 sensor: {:?}. Retrying...",
|
||||
defmt::Debug2Format(&e)
|
||||
);
|
||||
}
|
||||
}
|
||||
// Wait a little shorter than the measurement interval to catch all values
|
||||
Timer::after(Duration::from_millis(900)).await;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,12 +152,10 @@ async fn write_to_sd(spi1: SPI1, pin10: PIN_10, pin11: PIN_11, pin12: PIN_12, pi
|
|||
let mut config = spi::Config::default();
|
||||
config.frequency = 400_000;
|
||||
let spi = Spi::new_blocking(spi1, pin10, pin11, pin12, config);
|
||||
// Use a dummy cs pin here, for embedded-hal SpiDevice compatibility reasons
|
||||
let spi_dev = ExclusiveDevice::new_no_delay(spi, DummyCsPin);
|
||||
// Real cs pin
|
||||
let cs = Output::new(pin16, Level::High);
|
||||
let spi_dev = ExclusiveDevice::new_no_delay(spi, cs);
|
||||
|
||||
let sdcard = SdCard::new(spi_dev, cs, embassy_time::Delay);
|
||||
let sdcard = SdCard::new(spi_dev, embassy_time::Delay);
|
||||
|
||||
info!("Card size is {} bytes", sdcard.num_bytes().unwrap());
|
||||
|
||||
|
@ -171,14 +205,17 @@ async fn write_to_sd(spi1: SPI1, pin10: PIN_10, pin11: PIN_11, pin12: PIN_12, pi
|
|||
|
||||
info!("Creating new text file: {}", file_name);
|
||||
|
||||
let mut file = root_dir
|
||||
.open_file_in_dir(file_name, embedded_sdmmc::Mode::ReadWriteCreateOrAppend)
|
||||
.unwrap();
|
||||
loop {
|
||||
let new_value = MEASUREMENT_VALUES.receive().await;
|
||||
|
||||
let mut file = root_dir
|
||||
.open_file_in_dir(file_name, embedded_sdmmc::Mode::ReadWriteCreateOrAppend)
|
||||
.unwrap();
|
||||
|
||||
info!("Writing measurement value {} to file", new_value);
|
||||
info!(
|
||||
"Writing measurement value {} to file {}.TXT",
|
||||
new_value,
|
||||
file_count + 1
|
||||
);
|
||||
|
||||
// Space for five characters to fit numbers up to 65535 + '\n'
|
||||
let mut to_write = [b' '; 6];
|
||||
|
@ -186,8 +223,17 @@ async fn write_to_sd(spi1: SPI1, pin10: PIN_10, pin11: PIN_11, pin12: PIN_12, pi
|
|||
core::write!(&mut cursor, "{}", new_value)
|
||||
.expect("We have more than enough bytes to fit an u16");
|
||||
to_write[5] = b'\n';
|
||||
file.write(&to_write).unwrap();
|
||||
drop(file);
|
||||
|
||||
let mut write_flush = || {
|
||||
file.write(&to_write)?;
|
||||
file.flush()
|
||||
};
|
||||
if let Err(e) = write_flush() {
|
||||
error!(
|
||||
"Failed to write measuement: {:?}.\nIgnoring missing value...",
|
||||
defmt::Debug2Format(&e)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue