chore: 📎 + fmt
This commit is contained in:
@@ -105,7 +105,7 @@ impl BatteryInteraction for BQ34Z100G1 {
|
||||
.state_of_charge()
|
||||
.map(|v| v as f32)
|
||||
.map_err(|e| FatError::String {
|
||||
error: alloc::format!("{:?}", e),
|
||||
error: alloc::format!("{e:?}"),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ impl BatteryInteraction for BQ34Z100G1 {
|
||||
self.battery_driver
|
||||
.remaining_capacity()
|
||||
.map_err(|e| FatError::String {
|
||||
error: alloc::format!("{:?}", e),
|
||||
error: alloc::format!("{e:?}"),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ impl BatteryInteraction for BQ34Z100G1 {
|
||||
self.battery_driver
|
||||
.full_charge_capacity()
|
||||
.map_err(|e| FatError::String {
|
||||
error: alloc::format!("{:?}", e),
|
||||
error: alloc::format!("{e:?}"),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -129,13 +129,13 @@ impl BatteryInteraction for BQ34Z100G1 {
|
||||
self.battery_driver
|
||||
.design_capacity()
|
||||
.map_err(|e| FatError::String {
|
||||
error: alloc::format!("{:?}", e),
|
||||
error: alloc::format!("{e:?}"),
|
||||
})
|
||||
}
|
||||
|
||||
async fn voltage_milli_volt(&mut self) -> FatResult<u16> {
|
||||
self.battery_driver.voltage().map_err(|e| FatError::String {
|
||||
error: alloc::format!("{:?}", e),
|
||||
error: alloc::format!("{e:?}"),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ impl BatteryInteraction for BQ34Z100G1 {
|
||||
self.battery_driver
|
||||
.average_current()
|
||||
.map_err(|e| FatError::String {
|
||||
error: alloc::format!("{:?}", e),
|
||||
error: alloc::format!("{e:?}"),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ impl BatteryInteraction for BQ34Z100G1 {
|
||||
self.battery_driver
|
||||
.cycle_count()
|
||||
.map_err(|e| FatError::String {
|
||||
error: alloc::format!("{:?}", e),
|
||||
error: alloc::format!("{e:?}"),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ impl BatteryInteraction for BQ34Z100G1 {
|
||||
self.battery_driver
|
||||
.state_of_health()
|
||||
.map_err(|e| FatError::String {
|
||||
error: alloc::format!("{:?}", e),
|
||||
error: alloc::format!("{e:?}"),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ impl BatteryInteraction for BQ34Z100G1 {
|
||||
self.battery_driver
|
||||
.temperature()
|
||||
.map_err(|e| FatError::String {
|
||||
error: alloc::format!("{:?}", e),
|
||||
error: alloc::format!("{e:?}"),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -190,16 +190,16 @@ pub fn print_battery_bq34z100(
|
||||
) -> FatResult<()> {
|
||||
log::info!("Try communicating with battery");
|
||||
let fwversion = battery_driver.fw_version().unwrap_or_else(|e| {
|
||||
log::info!("Firmware {:?}", e);
|
||||
log::info!("Firmware {e:?}");
|
||||
0
|
||||
});
|
||||
log::info!("fw version is {}", fwversion);
|
||||
log::info!("fw version is {fwversion}");
|
||||
|
||||
let design_capacity = battery_driver.design_capacity().unwrap_or_else(|e| {
|
||||
log::info!("Design capacity {:?}", e);
|
||||
log::info!("Design capacity {e:?}");
|
||||
0
|
||||
});
|
||||
log::info!("Design Capacity {}", design_capacity);
|
||||
log::info!("Design Capacity {design_capacity}");
|
||||
if design_capacity == 1000 {
|
||||
log::info!("Still stock configuring battery, readouts are likely to be wrong!");
|
||||
}
|
||||
@@ -219,39 +219,39 @@ pub fn print_battery_bq34z100(
|
||||
cf: false,
|
||||
ocv_taken: false,
|
||||
});
|
||||
log::info!("Flags {:?}", flags);
|
||||
log::info!("Flags {flags:?}");
|
||||
|
||||
let chem_id = battery_driver.chem_id().unwrap_or_else(|e| {
|
||||
log::info!("Chemid {:?}", e);
|
||||
log::info!("Chemid {e:?}");
|
||||
0
|
||||
});
|
||||
|
||||
let bat_temp = battery_driver.internal_temperature().unwrap_or_else(|e| {
|
||||
log::info!("Bat Temp {:?}", e);
|
||||
log::info!("Bat Temp {e:?}");
|
||||
0
|
||||
});
|
||||
let temp_c = Temperature::from_kelvin(bat_temp as f64 / 10_f64).as_celsius();
|
||||
let voltage = battery_driver.voltage().unwrap_or_else(|e| {
|
||||
log::info!("Bat volt {:?}", e);
|
||||
log::info!("Bat volt {e:?}");
|
||||
0
|
||||
});
|
||||
let current = battery_driver.current().unwrap_or_else(|e| {
|
||||
log::info!("Bat current {:?}", e);
|
||||
log::info!("Bat current {e:?}");
|
||||
0
|
||||
});
|
||||
let state = battery_driver.state_of_charge().unwrap_or_else(|e| {
|
||||
log::info!("Bat Soc {:?}", e);
|
||||
log::info!("Bat Soc {e:?}");
|
||||
0
|
||||
});
|
||||
let charge_voltage = battery_driver.charge_voltage().unwrap_or_else(|e| {
|
||||
log::info!("Bat Charge Volt {:?}", e);
|
||||
log::info!("Bat Charge Volt {e:?}");
|
||||
0
|
||||
});
|
||||
let charge_current = battery_driver.charge_current().unwrap_or_else(|e| {
|
||||
log::info!("Bat Charge Current {:?}", e);
|
||||
log::info!("Bat Charge Current {e:?}");
|
||||
0
|
||||
});
|
||||
log::info!("ChemId: {} Current voltage {} and current {} with charge {}% and temp {} CVolt: {} CCur {}", chem_id, voltage, current, state, temp_c, charge_voltage, charge_current);
|
||||
log::info!("ChemId: {chem_id} Current voltage {voltage} and current {current} with charge {state}% and temp {temp_c} CVolt: {charge_voltage} CCur {charge_current}");
|
||||
let _ = battery_driver.unsealed();
|
||||
let _ = battery_driver.it_enable();
|
||||
Ok(())
|
||||
|
||||
@@ -155,7 +155,7 @@ impl Esp<'_> {
|
||||
pub(crate) async fn delete_file(&self, filename: String) -> FatResult<()> {
|
||||
let file = PathBuf::try_from(filename.as_str())?;
|
||||
let access = self.fs.lock().await;
|
||||
access.remove(&*file)?;
|
||||
access.remove(&file)?;
|
||||
Ok(())
|
||||
}
|
||||
pub(crate) async fn write_file(
|
||||
@@ -168,7 +168,7 @@ impl Esp<'_> {
|
||||
let access = self.fs.lock().await;
|
||||
access.open_file_with_options_and_then(
|
||||
|options| options.read(true).write(true).create(true),
|
||||
&*file,
|
||||
&file,
|
||||
|file| {
|
||||
file.seek(SeekFrom::Start(offset))?;
|
||||
file.write(buf)?;
|
||||
@@ -181,7 +181,7 @@ impl Esp<'_> {
|
||||
pub async fn get_size(&mut self, filename: String) -> FatResult<usize> {
|
||||
let file = PathBuf::try_from(filename.as_str())?;
|
||||
let access = self.fs.lock().await;
|
||||
let data = access.metadata(&*file)?;
|
||||
let data = access.metadata(&file)?;
|
||||
Ok(data.len())
|
||||
}
|
||||
pub(crate) async fn get_file(
|
||||
@@ -198,7 +198,7 @@ impl Esp<'_> {
|
||||
let offset = chunk * buf.len() as u32;
|
||||
access.open_file_with_options_and_then(
|
||||
|options| options.read(true),
|
||||
&*file,
|
||||
&file,
|
||||
|file| {
|
||||
let length = file.len()? as u32;
|
||||
if length == 0 {
|
||||
@@ -226,7 +226,7 @@ impl Esp<'_> {
|
||||
self.ota_target.write(offset, buf)?;
|
||||
self.ota_target.read(offset, read_back)?;
|
||||
if buf != read_back {
|
||||
info!("Expected {:?} but got {:?}", buf, read_back);
|
||||
info!("Expected {buf:?} but got {read_back:?}");
|
||||
bail!(
|
||||
"Flash error, read back does not match write buffer at offset {:x}",
|
||||
offset
|
||||
@@ -238,10 +238,7 @@ impl Esp<'_> {
|
||||
pub(crate) async fn finalize_ota(&mut self) -> Result<(), FatError> {
|
||||
let current = self.ota.current_slot()?;
|
||||
if self.ota.current_ota_state()? != OtaImageState::Valid {
|
||||
info!(
|
||||
"Validating current slot {:?} as it was able to ota",
|
||||
current
|
||||
);
|
||||
info!("Validating current slot {current:?} as it was able to ota");
|
||||
self.ota.set_current_ota_state(Valid)?;
|
||||
}
|
||||
|
||||
@@ -250,7 +247,7 @@ impl Esp<'_> {
|
||||
self.ota.set_current_ota_state(OtaImageState::New)?;
|
||||
info!("switched state for new partition");
|
||||
let state_new = self.ota.current_ota_state()?;
|
||||
info!("state on new partition now {:?}", state_new);
|
||||
info!("state on new partition now {state_new:?}");
|
||||
//determine nextslot crc
|
||||
|
||||
self.set_restart_to_conf(true);
|
||||
@@ -290,7 +287,7 @@ impl Esp<'_> {
|
||||
if ntp_addrs.is_empty() {
|
||||
bail!("Failed to resolve DNS");
|
||||
}
|
||||
info!("NTP server: {:?}", ntp_addrs);
|
||||
info!("NTP server: {ntp_addrs:?}");
|
||||
|
||||
let mut counter = 0;
|
||||
loop {
|
||||
@@ -302,12 +299,12 @@ impl Esp<'_> {
|
||||
match timeout {
|
||||
Ok(result) => {
|
||||
let time = result?;
|
||||
info!("Time: {:?}", time);
|
||||
info!("Time: {time:?}");
|
||||
return DateTime::from_timestamp(time.seconds as i64, 0)
|
||||
.context("Could not convert Sntp result");
|
||||
}
|
||||
Err(err) => {
|
||||
warn!("sntp timeout, retry: {:?}", err);
|
||||
warn!("sntp timeout, retry: {err:?}");
|
||||
counter += 1;
|
||||
if counter > 10 {
|
||||
bail!("Failed to get time from NTP server");
|
||||
@@ -426,7 +423,7 @@ impl Esp<'_> {
|
||||
println!("start net task");
|
||||
spawner.spawn(net_task(runner)).ok();
|
||||
println!("run dhcp");
|
||||
spawner.spawn(run_dhcp(stack.clone(), gw_ip_addr_str)).ok();
|
||||
spawner.spawn(run_dhcp(*stack, gw_ip_addr_str)).ok();
|
||||
|
||||
loop {
|
||||
if stack.is_link_up() {
|
||||
@@ -442,7 +439,7 @@ impl Esp<'_> {
|
||||
.config_v4()
|
||||
.inspect(|c| println!("ipv4 config: {c:?}"));
|
||||
|
||||
Ok(stack.clone())
|
||||
Ok(*stack)
|
||||
}
|
||||
|
||||
pub(crate) async fn wifi(
|
||||
@@ -505,12 +502,9 @@ impl Esp<'_> {
|
||||
} + max_wait as u64 * 1000;
|
||||
loop {
|
||||
let state = esp_wifi::wifi::sta_state();
|
||||
match state {
|
||||
WifiState::StaStarted => {
|
||||
self.controller.lock().await.connect()?;
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
if state == WifiState::StaStarted {
|
||||
self.controller.lock().await.connect()?;
|
||||
break;
|
||||
}
|
||||
if {
|
||||
let guard = TIME_ACCESS.get().await.lock().await;
|
||||
@@ -527,11 +521,8 @@ impl Esp<'_> {
|
||||
} + max_wait as u64 * 1000;
|
||||
loop {
|
||||
let state = esp_wifi::wifi::sta_state();
|
||||
match state {
|
||||
WifiState::StaConnected => {
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
if state == WifiState::StaConnected {
|
||||
break;
|
||||
}
|
||||
if {
|
||||
let guard = TIME_ACCESS.get().await.lock().await;
|
||||
@@ -572,7 +563,7 @@ impl Esp<'_> {
|
||||
}
|
||||
|
||||
info!("Connected WIFI, dhcp: {:?}", stack.config_v4());
|
||||
Ok(stack.clone())
|
||||
Ok(*stack)
|
||||
}
|
||||
|
||||
pub fn deep_sleep(
|
||||
@@ -611,12 +602,12 @@ impl Esp<'_> {
|
||||
}
|
||||
let data = self.fs.lock().await.read::<4096>(&cfg)?;
|
||||
let config: PlantControllerConfig = serde_json::from_slice(&data)?;
|
||||
return Ok(config);
|
||||
Ok(config)
|
||||
}
|
||||
pub(crate) async fn save_config(&mut self, config: Vec<u8>) -> FatResult<()> {
|
||||
let filesystem = self.fs.lock().await;
|
||||
let cfg = PathBuf::try_from(CONFIG_FILE)?;
|
||||
filesystem.write(&cfg, &*config)?;
|
||||
filesystem.write(&cfg, &config)?;
|
||||
Ok(())
|
||||
}
|
||||
pub(crate) async fn list_files(&self) -> FatResult<FileList> {
|
||||
@@ -690,19 +681,15 @@ impl Esp<'_> {
|
||||
"",
|
||||
)
|
||||
.await;
|
||||
for i in 0..PLANT_COUNT {
|
||||
log::info!(
|
||||
"LAST_WATERING_TIMESTAMP[{}] = UTC {}",
|
||||
i,
|
||||
LAST_WATERING_TIMESTAMP[i]
|
||||
);
|
||||
// is executed before main, no other code will alter these values during printing
|
||||
#[allow(static_mut_refs)]
|
||||
for (i, time) in LAST_WATERING_TIMESTAMP.iter().enumerate() {
|
||||
log::info!("LAST_WATERING_TIMESTAMP[{i}] = UTC {time}");
|
||||
}
|
||||
for i in 0..PLANT_COUNT {
|
||||
log::info!(
|
||||
"CONSECUTIVE_WATERING_PLANT[{}] = {}",
|
||||
i,
|
||||
CONSECUTIVE_WATERING_PLANT[i]
|
||||
);
|
||||
// is executed before main, no other code will alter these values during printing
|
||||
#[allow(static_mut_refs)]
|
||||
for (i, item) in CONSECUTIVE_WATERING_PLANT.iter().enumerate() {
|
||||
log::info!("CONSECUTIVE_WATERING_PLANT[{i}] = {item}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -734,9 +721,9 @@ impl Esp<'_> {
|
||||
bail!("Mqtt url was empty")
|
||||
}
|
||||
|
||||
let last_will_topic = format!("{}/state", base_topic);
|
||||
let round_trip_topic = format!("{}/internal/roundtrip", base_topic);
|
||||
let stay_alive_topic = format!("{}/stay_alive", base_topic);
|
||||
let last_will_topic = format!("{base_topic}/state");
|
||||
let round_trip_topic = format!("{base_topic}/internal/roundtrip");
|
||||
let stay_alive_topic = format!("{base_topic}/stay_alive");
|
||||
|
||||
let mut builder: McutieBuilder<'_, String, PublishDisplay<String, &str>, 0> =
|
||||
McutieBuilder::new(stack, "plant ctrl", mqtt_url);
|
||||
@@ -879,8 +866,7 @@ impl Esp<'_> {
|
||||
Ok(()) => {}
|
||||
Err(err) => {
|
||||
info!(
|
||||
"Error during mqtt send on topic {} with message {:#?} error is {:?}",
|
||||
subtopic, message, err
|
||||
"Error during mqtt send on topic {subtopic} with message {message:#?} error is {err:?}"
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -932,7 +918,7 @@ async fn mqtt_incoming_task(
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(LogMessage::UnknownTopic, 0, 0, "", &*topic)
|
||||
.log(LogMessage::UnknownTopic, 0, 0, "", &topic)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +121,6 @@ impl<'a> BoardInteraction<'a> for Initial<'a> {
|
||||
bail!("Please configure board revision")
|
||||
}
|
||||
|
||||
|
||||
async fn general_fault(&mut self, enable: bool) {
|
||||
self.general_fault.set_level(enable.into());
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ impl lfs2Storage for LittleFs2Filesystem {
|
||||
fn read(&mut self, off: usize, buf: &mut [u8]) -> lfs2Result<usize> {
|
||||
let read_size: usize = Self::READ_SIZE;
|
||||
if off % read_size != 0 {
|
||||
error!("Littlefs2Filesystem read error: offset not aligned to read size offset: {} read_size: {}", off, read_size);
|
||||
error!("Littlefs2Filesystem read error: offset not aligned to read size offset: {off} read_size: {read_size}");
|
||||
return Err(lfs2Error::IO);
|
||||
}
|
||||
if buf.len() % read_size != 0 {
|
||||
@@ -34,7 +34,7 @@ impl lfs2Storage for LittleFs2Filesystem {
|
||||
match self.storage.read(off as u32, buf) {
|
||||
Ok(..) => Ok(buf.len()),
|
||||
Err(err) => {
|
||||
error!("Littlefs2Filesystem read error: {:?}", err);
|
||||
error!("Littlefs2Filesystem read error: {err:?}");
|
||||
Err(lfs2Error::IO)
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ impl lfs2Storage for LittleFs2Filesystem {
|
||||
fn write(&mut self, off: usize, data: &[u8]) -> lfs2Result<usize> {
|
||||
let write_size: usize = Self::WRITE_SIZE;
|
||||
if off % write_size != 0 {
|
||||
error!("Littlefs2Filesystem write error: offset not aligned to write size offset: {} write_size: {}", off, write_size);
|
||||
error!("Littlefs2Filesystem write error: offset not aligned to write size offset: {off} write_size: {write_size}");
|
||||
return Err(lfs2Error::IO);
|
||||
}
|
||||
if data.len() % write_size != 0 {
|
||||
@@ -53,7 +53,7 @@ impl lfs2Storage for LittleFs2Filesystem {
|
||||
match self.storage.write(off as u32, data) {
|
||||
Ok(..) => Ok(data.len()),
|
||||
Err(err) => {
|
||||
error!("Littlefs2Filesystem write error: {:?}", err);
|
||||
error!("Littlefs2Filesystem write error: {err:?}");
|
||||
Err(lfs2Error::IO)
|
||||
}
|
||||
}
|
||||
@@ -62,25 +62,25 @@ impl lfs2Storage for LittleFs2Filesystem {
|
||||
fn erase(&mut self, off: usize, len: usize) -> lfs2Result<usize> {
|
||||
let block_size: usize = Self::BLOCK_SIZE;
|
||||
if off % block_size != 0 {
|
||||
error!("Littlefs2Filesystem erase error: offset not aligned to block size offset: {} block_size: {}", off, block_size);
|
||||
error!("Littlefs2Filesystem erase error: offset not aligned to block size offset: {off} block_size: {block_size}");
|
||||
return lfs2Result::Err(lfs2Error::IO);
|
||||
}
|
||||
if len % block_size != 0 {
|
||||
error!("Littlefs2Filesystem erase error: length not aligned to block size length: {} block_size: {}", len, block_size);
|
||||
error!("Littlefs2Filesystem erase error: length not aligned to block size length: {len} block_size: {block_size}");
|
||||
return lfs2Result::Err(lfs2Error::IO);
|
||||
}
|
||||
|
||||
match check_erase(self.storage, off as u32, (off+len) as u32) {
|
||||
match check_erase(self.storage, off as u32, (off + len) as u32) {
|
||||
Ok(_) => {}
|
||||
Err(err) => {
|
||||
error!("Littlefs2Filesystem check erase error: {:?}", err);
|
||||
error!("Littlefs2Filesystem check erase error: {err:?}");
|
||||
return lfs2Result::Err(lfs2Error::IO);
|
||||
}
|
||||
}
|
||||
match self.storage.erase(off as u32, (off + len) as u32) {
|
||||
Ok(..) => lfs2Result::Ok(len),
|
||||
Err(err) => {
|
||||
error!("Littlefs2Filesystem erase error: {:?}", err);
|
||||
error!("Littlefs2Filesystem erase error: {err:?}");
|
||||
lfs2Result::Err(lfs2Error::IO)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,9 +58,9 @@ use alloc::sync::Arc;
|
||||
use async_trait::async_trait;
|
||||
use bincode::{Decode, Encode};
|
||||
use bq34z100::Bq34z100g1Driver;
|
||||
use canapi::SensorSlot;
|
||||
use chrono::{DateTime, FixedOffset, Utc};
|
||||
use core::cell::RefCell;
|
||||
use canapi::SensorSlot;
|
||||
use ds323x::ic::DS3231;
|
||||
use ds323x::interface::I2cInterface;
|
||||
use ds323x::{DateTimeAccess, Ds323x};
|
||||
@@ -108,7 +108,6 @@ use log::{error, info, warn};
|
||||
use portable_atomic::AtomicBool;
|
||||
use serde::Serialize;
|
||||
|
||||
|
||||
pub static TIME_ACCESS: OnceLock<Mutex<CriticalSectionRawMutex, Rtc>> = OnceLock::new();
|
||||
|
||||
//Only support for 8 right now!
|
||||
@@ -127,9 +126,9 @@ pub enum Sensor {
|
||||
B,
|
||||
}
|
||||
|
||||
impl Into<SensorSlot> for Sensor {
|
||||
fn into(self) -> SensorSlot {
|
||||
match self {
|
||||
impl From<Sensor> for SensorSlot {
|
||||
fn from(val: Sensor) -> Self {
|
||||
match val {
|
||||
Sensor::A => SensorSlot::A,
|
||||
Sensor::B => SensorSlot::B,
|
||||
}
|
||||
@@ -138,6 +137,7 @@ impl Into<SensorSlot> for Sensor {
|
||||
|
||||
pub struct PlantHal {}
|
||||
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
pub struct HAL<'a> {
|
||||
pub board_hal: Box<dyn BoardInteraction<'a> + Send>,
|
||||
}
|
||||
@@ -177,17 +177,17 @@ pub trait BoardInteraction<'a> {
|
||||
let current = counter % PLANT_COUNT as u32;
|
||||
for led in 0..PLANT_COUNT {
|
||||
if let Err(err) = self.fault(led, current == led as u32).await {
|
||||
warn!("Fault on plant {}: {:?}", led, err);
|
||||
warn!("Fault on plant {led}: {err:?}");
|
||||
}
|
||||
}
|
||||
let even = counter % 2 == 0;
|
||||
let _ = self.general_fault(even.into()).await;
|
||||
let _ = self.general_fault(even).await;
|
||||
}
|
||||
|
||||
async fn clear_progress(&mut self) {
|
||||
for led in 0..PLANT_COUNT {
|
||||
if let Err(err) = self.fault(led, false).await {
|
||||
warn!("Fault on plant {}: {:?}", led, err);
|
||||
warn!("Fault on plant {led}: {err:?}");
|
||||
}
|
||||
}
|
||||
let _ = self.general_fault(false).await;
|
||||
@@ -272,11 +272,11 @@ impl PlantHal {
|
||||
let timg0 = TimerGroup::new(peripherals.TIMG0);
|
||||
let esp_wifi_ctrl = &*mk_static!(
|
||||
EspWifiController<'static>,
|
||||
init(timg0.timer0, rng.clone()).expect("Could not init wifi controller")
|
||||
init(timg0.timer0, rng).expect("Could not init wifi controller")
|
||||
);
|
||||
|
||||
let (controller, interfaces) =
|
||||
esp_wifi::wifi::new(&esp_wifi_ctrl, peripherals.WIFI).expect("Could not init wifi");
|
||||
esp_wifi::wifi::new(esp_wifi_ctrl, peripherals.WIFI).expect("Could not init wifi");
|
||||
|
||||
use esp_hal::timer::systimer::SystemTimer;
|
||||
esp_hal_embassy::init(systimer.alarm0);
|
||||
@@ -351,9 +351,9 @@ impl PlantHal {
|
||||
let running = get_current_slot_and_fix_ota_data(&mut ota, state_0, state_1)?;
|
||||
let target = running.next();
|
||||
|
||||
info!("Currently running OTA slot: {:?}", running);
|
||||
info!("Slot0 state: {:?}", state_0);
|
||||
info!("Slot1 state: {:?}", state_1);
|
||||
info!("Currently running OTA slot: {running:?}");
|
||||
info!("Slot0 state: {state_0:?}");
|
||||
info!("Slot1 state: {state_1:?}");
|
||||
|
||||
//obtain current_state and next_state here!
|
||||
let ota_target = match target {
|
||||
@@ -401,11 +401,12 @@ impl PlantHal {
|
||||
log::info!("Littlefs2 filesystem is formatted");
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Littlefs2 filesystem could not be formatted: {:?}", err);
|
||||
error!("Littlefs2 filesystem could not be formatted: {err:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::arc_with_non_send_sync)]
|
||||
let fs = Arc::new(Mutex::new(
|
||||
lfs2Filesystem::mount(alloc, lfs2filesystem).expect("Could not mount lfs2 filesystem"),
|
||||
));
|
||||
@@ -498,8 +499,8 @@ impl PlantHal {
|
||||
I2C_DRIVER.init(i2c_bus).expect("Could not init i2c driver");
|
||||
|
||||
let i2c_bus = I2C_DRIVER.get().await;
|
||||
let rtc_device = I2cDevice::new(&i2c_bus);
|
||||
let eeprom_device = I2cDevice::new(&i2c_bus);
|
||||
let rtc_device = I2cDevice::new(i2c_bus);
|
||||
let eeprom_device = I2cDevice::new(i2c_bus);
|
||||
|
||||
let mut rtc: Ds323x<
|
||||
I2cInterface<I2cDevice<CriticalSectionRawMutex, I2c<Blocking>>>,
|
||||
@@ -511,10 +512,10 @@ impl PlantHal {
|
||||
let rtc_time = rtc.datetime();
|
||||
match rtc_time {
|
||||
Ok(tt) => {
|
||||
log::info!("Rtc Module reports time at UTC {}", tt);
|
||||
log::info!("Rtc Module reports time at UTC {tt}");
|
||||
}
|
||||
Err(err) => {
|
||||
log::info!("Rtc Module could not be read {:?}", err);
|
||||
log::info!("Rtc Module could not be read {err:?}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -566,7 +567,7 @@ impl PlantHal {
|
||||
};
|
||||
|
||||
let board_hal: Box<dyn BoardInteraction + Send> = match config.hardware.board {
|
||||
BoardVersion::INITIAL => {
|
||||
BoardVersion::Initial => {
|
||||
initial_hal::create_initial_board(free_pins, config, esp)?
|
||||
}
|
||||
BoardVersion::V3 => {
|
||||
@@ -620,8 +621,8 @@ fn ota_state(slot: ota_slot, ota_data: &mut FlashRegion<FlashStorage>) -> OtaIma
|
||||
let _ = ota_data.read(0x1000, &mut slot_buf);
|
||||
}
|
||||
let raw_state = u32::from_le_bytes(slot_buf[24..28].try_into().unwrap_or([0xff; 4]));
|
||||
let state0 = OtaImageState::try_from(raw_state).unwrap_or(OtaImageState::Undefined);
|
||||
state0
|
||||
|
||||
OtaImageState::try_from(raw_state).unwrap_or(OtaImageState::Undefined)
|
||||
}
|
||||
|
||||
fn get_current_slot_and_fix_ota_data(
|
||||
@@ -666,10 +667,7 @@ fn get_current_slot_and_fix_ota_data(
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
info!(
|
||||
"Current slot has state {:?} other state has {:?} swapping",
|
||||
state, other
|
||||
);
|
||||
info!("Current slot has state {state:?} other state has {other:?} swapping");
|
||||
ota.set_current_slot(current.next())?;
|
||||
//we actually booted other slot, than partition table assumes
|
||||
return Ok(ota.current_slot()?);
|
||||
@@ -699,17 +697,17 @@ pub async fn esp_set_time(time: DateTime<FixedOffset>) -> FatResult<()> {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize)]
|
||||
pub struct Moistures{
|
||||
pub struct Moistures {
|
||||
pub sensor_a_hz: [f32; PLANT_COUNT],
|
||||
pub sensor_b_hz: [f32; PLANT_COUNT],
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize)]
|
||||
pub struct DetectionResult {
|
||||
plant: [DetectionSensorResult; crate::hal::PLANT_COUNT]
|
||||
plant: [DetectionSensorResult; crate::hal::PLANT_COUNT],
|
||||
}
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize)]
|
||||
pub struct DetectionSensorResult{
|
||||
pub struct DetectionSensorResult {
|
||||
sensor_a: bool,
|
||||
sensor_b: bool,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::hal::Box;
|
||||
use crate::fat_error::FatResult;
|
||||
use crate::hal::Box;
|
||||
use async_trait::async_trait;
|
||||
use bincode::config::Configuration;
|
||||
use bincode::{config, Decode, Encode};
|
||||
@@ -65,7 +65,7 @@ impl RTCModuleInteraction for DS3231Module {
|
||||
let (header, len): (BackupHeader, usize) =
|
||||
bincode::decode_from_slice(&header_page_buffer[..], CONFIG)?;
|
||||
|
||||
log::info!("Raw header is {:?} with size {}", header_page_buffer, len);
|
||||
log::info!("Raw header is {header_page_buffer:?} with size {len}");
|
||||
Ok(header)
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ impl RTCModuleInteraction for DS3231Module {
|
||||
async fn backup_config(&mut self, offset: usize, bytes: &[u8]) -> FatResult<()> {
|
||||
//skip header and write after
|
||||
self.storage
|
||||
.write((BACKUP_HEADER_MAX_SIZE + offset) as u32, &bytes)?;
|
||||
.write((BACKUP_HEADER_MAX_SIZE + offset) as u32, bytes)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -113,11 +113,7 @@ impl RTCModuleInteraction for DS3231Module {
|
||||
};
|
||||
let config = config::standard();
|
||||
let encoded = bincode::encode_into_slice(&header, &mut header_page_buffer, config)?;
|
||||
log::info!(
|
||||
"Raw header is {:?} with size {}",
|
||||
header_page_buffer,
|
||||
encoded
|
||||
);
|
||||
log::info!("Raw header is {header_page_buffer:?} with size {encoded}");
|
||||
self.storage.write(0, &header_page_buffer)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -171,10 +171,13 @@ pub(crate) fn create_v3(
|
||||
}
|
||||
|
||||
impl V3<'_> {
|
||||
|
||||
async fn inner_measure_moisture_hz(&mut self, plant: usize, sensor: Sensor) -> Result<f32, FatError> {
|
||||
async fn inner_measure_moisture_hz(
|
||||
&mut self,
|
||||
plant: usize,
|
||||
sensor: Sensor,
|
||||
) -> Result<f32, FatError> {
|
||||
let mut results = [0_f32; REPEAT_MOIST_MEASURE];
|
||||
for repeat in 0..REPEAT_MOIST_MEASURE {
|
||||
for sample in results.iter_mut() {
|
||||
self.signal_counter.pause();
|
||||
self.signal_counter.clear();
|
||||
//Disable all
|
||||
@@ -266,7 +269,7 @@ impl V3<'_> {
|
||||
&format!("{sensor:?}"),
|
||||
)
|
||||
.await;
|
||||
results[repeat] = hz;
|
||||
*sample = hz;
|
||||
}
|
||||
results.sort_by(|a, b| a.partial_cmp(b).unwrap()); // floats don't seem to implement total_ord
|
||||
|
||||
@@ -386,12 +389,18 @@ impl<'a> BoardInteraction<'a> for V3<'a> {
|
||||
for plant in 0..PLANT_COUNT {
|
||||
let a = self.inner_measure_moisture_hz(plant, Sensor::A).await;
|
||||
let b = self.inner_measure_moisture_hz(plant, Sensor::B).await;
|
||||
let aa = a.unwrap_or_else(|_| u32::MAX as f32);
|
||||
let bb = b.unwrap_or_else(|_| u32::MAX as f32);
|
||||
let aa = a.unwrap_or(u32::MAX as f32);
|
||||
let bb = b.unwrap_or(u32::MAX as f32);
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(LogMessage::TestSensor, aa as u32, bb as u32, &plant.to_string(), "")
|
||||
.log(
|
||||
LogMessage::TestSensor,
|
||||
aa as u32,
|
||||
bb as u32,
|
||||
&plant.to_string(),
|
||||
"",
|
||||
)
|
||||
.await;
|
||||
result.sensor_a_hz[plant] = aa;
|
||||
result.sensor_b_hz[plant] = bb;
|
||||
@@ -399,7 +408,6 @@ impl<'a> BoardInteraction<'a> for V3<'a> {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
|
||||
async fn general_fault(&mut self, enable: bool) {
|
||||
hold_disable(6);
|
||||
if enable {
|
||||
|
||||
@@ -6,7 +6,10 @@ use crate::hal::esp::{hold_disable, hold_enable, Esp};
|
||||
use crate::hal::rtc::RTCModuleInteraction;
|
||||
use crate::hal::v4_sensor::{SensorImpl, SensorInteraction};
|
||||
use crate::hal::water::TankSensor;
|
||||
use crate::hal::{BoardInteraction, DetectionResult, FreePeripherals, Moistures, I2C_DRIVER, PLANT_COUNT, TIME_ACCESS};
|
||||
use crate::hal::{
|
||||
BoardInteraction, DetectionResult, FreePeripherals, Moistures, I2C_DRIVER, PLANT_COUNT,
|
||||
TIME_ACCESS,
|
||||
};
|
||||
use crate::log::{LogMessage, LOG_ACCESS};
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::ToString;
|
||||
@@ -74,35 +77,29 @@ impl<'a> Charger<'a> {
|
||||
|
||||
impl Charger<'_> {
|
||||
pub(crate) fn power_save(&mut self) {
|
||||
match self {
|
||||
Charger::SolarMpptV1 { mppt_ina, .. } => {
|
||||
let _ = mppt_ina
|
||||
.set_configuration(Configuration {
|
||||
reset: Default::default(),
|
||||
bus_voltage_range: Default::default(),
|
||||
shunt_voltage_range: Default::default(),
|
||||
bus_resolution: Default::default(),
|
||||
shunt_resolution: Default::default(),
|
||||
operating_mode: OperatingMode::PowerDown,
|
||||
})
|
||||
.map_err(|e| {
|
||||
log::info!(
|
||||
"Error setting ina mppt configuration during deep sleep preparation{:?}",
|
||||
e
|
||||
);
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
if let Charger::SolarMpptV1 { mppt_ina, .. } = self {
|
||||
let _ = mppt_ina
|
||||
.set_configuration(Configuration {
|
||||
reset: Default::default(),
|
||||
bus_voltage_range: Default::default(),
|
||||
shunt_voltage_range: Default::default(),
|
||||
bus_resolution: Default::default(),
|
||||
shunt_resolution: Default::default(),
|
||||
operating_mode: OperatingMode::PowerDown,
|
||||
})
|
||||
.map_err(|e| {
|
||||
log::info!(
|
||||
"Error setting ina mppt configuration during deep sleep preparation{e:?}"
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
fn set_charge_indicator(&mut self, charging: bool) -> FatResult<()> {
|
||||
match self {
|
||||
Self::SolarMpptV1 {
|
||||
charge_indicator, ..
|
||||
} => {
|
||||
charge_indicator.set_level(charging.into());
|
||||
}
|
||||
_ => {}
|
||||
if let Self::SolarMpptV1 {
|
||||
charge_indicator, ..
|
||||
} = self
|
||||
{
|
||||
charge_indicator.set_level(charging.into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -244,7 +241,7 @@ pub(crate) async fn create_v4(
|
||||
Some(ina)
|
||||
}
|
||||
Err(err) => {
|
||||
log::info!("Error creating mppt ina: {:?}", err);
|
||||
log::info!("Error creating mppt ina: {err:?}");
|
||||
None
|
||||
}
|
||||
};
|
||||
@@ -253,7 +250,7 @@ pub(crate) async fn create_v4(
|
||||
let pump_ina = match SyncIna219::new(pump_current_dev, Address::from_pins(Pin::Gnd, Pin::Sda)) {
|
||||
Ok(ina) => Some(ina),
|
||||
Err(err) => {
|
||||
log::info!("Error creating pump ina: {:?}", err);
|
||||
log::info!("Error creating pump ina: {err:?}");
|
||||
None
|
||||
}
|
||||
};
|
||||
@@ -362,7 +359,7 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
|
||||
let v = pump_ina
|
||||
.shunt_voltage()
|
||||
.map_err(|e| FatError::String {
|
||||
error: alloc::format!("{:?}", e),
|
||||
error: alloc::format!("{e:?}"),
|
||||
})
|
||||
.map(|v| {
|
||||
let shunt_voltage =
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use canapi::id::{classify, plant_id, MessageKind, IDENTIFY_CMD_OFFSET};
|
||||
use crate::bail;
|
||||
use crate::fat_error::{ContextExt, FatError, FatResult};
|
||||
use canapi::{SensorSlot};
|
||||
use crate::hal::{DetectionResult, Moistures, Sensor};
|
||||
use crate::hal::Box;
|
||||
use crate::hal::{DetectionResult, Moistures, Sensor};
|
||||
use crate::log::{LogMessage, LOG_ACCESS};
|
||||
use alloc::format;
|
||||
use alloc::string::ToString;
|
||||
use async_trait::async_trait;
|
||||
use bincode::config;
|
||||
use canapi::id::{classify, plant_id, MessageKind, IDENTIFY_CMD_OFFSET};
|
||||
use canapi::SensorSlot;
|
||||
use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
|
||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||
use embassy_time::{Duration, Instant, Timer, WithTimeout};
|
||||
@@ -23,8 +23,6 @@ use pca9535::{GPIOBank, Pca9535Immediate, StandardExpanderInterface};
|
||||
|
||||
const REPEAT_MOIST_MEASURE: usize = 10;
|
||||
|
||||
|
||||
|
||||
#[async_trait(?Send)]
|
||||
pub trait SensorInteraction {
|
||||
async fn measure_moisture_hz(&mut self) -> FatResult<Moistures>;
|
||||
@@ -59,11 +57,25 @@ impl SensorInteraction for SensorImpl {
|
||||
..
|
||||
} => {
|
||||
let mut result = Moistures::default();
|
||||
for plant in 0..crate::hal::PLANT_COUNT{
|
||||
result.sensor_a_hz[plant] = Self::inner_pulse(plant, Sensor::A, signal_counter, sensor_expander).await?;
|
||||
info!("Sensor {} {:?}: {}", plant, Sensor::A, result.sensor_a_hz[plant]);
|
||||
result.sensor_b_hz[plant] = Self::inner_pulse(plant, Sensor::B, signal_counter, sensor_expander).await?;
|
||||
info!("Sensor {} {:?}: {}", plant, Sensor::B, result.sensor_b_hz[plant]);
|
||||
for plant in 0..crate::hal::PLANT_COUNT {
|
||||
result.sensor_a_hz[plant] =
|
||||
Self::inner_pulse(plant, Sensor::A, signal_counter, sensor_expander)
|
||||
.await?;
|
||||
info!(
|
||||
"Sensor {} {:?}: {}",
|
||||
plant,
|
||||
Sensor::A,
|
||||
result.sensor_a_hz[plant]
|
||||
);
|
||||
result.sensor_b_hz[plant] =
|
||||
Self::inner_pulse(plant, Sensor::B, signal_counter, sensor_expander)
|
||||
.await?;
|
||||
info!(
|
||||
"Sensor {} {:?}: {}",
|
||||
plant,
|
||||
Sensor::B,
|
||||
result.sensor_b_hz[plant]
|
||||
);
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
@@ -81,7 +93,7 @@ impl SensorInteraction for SensorImpl {
|
||||
match rec {
|
||||
Ok(_) => {}
|
||||
Err(err) => {
|
||||
info!("Error receiving CAN message: {:?}", err);
|
||||
info!("Error receiving CAN message: {err:?}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -102,8 +114,6 @@ impl SensorInteraction for SensorImpl {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl SensorImpl {
|
||||
pub async fn autodetect(&mut self) -> FatResult<DetectionResult> {
|
||||
match self {
|
||||
@@ -124,164 +134,176 @@ impl SensorImpl {
|
||||
// Send a few test messages per potential sensor node
|
||||
for plant in 0..crate::hal::PLANT_COUNT {
|
||||
for sensor in [Sensor::A, Sensor::B] {
|
||||
let target = StandardId::new(plant_id(IDENTIFY_CMD_OFFSET, sensor.into(), plant as u16)).context(">> Could not create address for sensor! (plant: {}) <<")?;
|
||||
let target = StandardId::new(plant_id(
|
||||
IDENTIFY_CMD_OFFSET,
|
||||
sensor.into(),
|
||||
plant as u16,
|
||||
))
|
||||
.context(">> Could not create address for sensor! (plant: {}) <<")?;
|
||||
let can_buffer = [0_u8; 0];
|
||||
if let Some(frame) = EspTwaiFrame::new(target, &can_buffer) {
|
||||
// Try a few times; we intentionally ignore rx here and rely on stub logic
|
||||
let resu = as_async.transmit_async(&frame).await;
|
||||
match resu {
|
||||
Ok(_) => {
|
||||
info!(
|
||||
"Sent test message to plant {} sensor {:?}",
|
||||
plant, sensor
|
||||
);
|
||||
info!("Sent test message to plant {plant} sensor {sensor:?}");
|
||||
}
|
||||
Err(err) => {
|
||||
info!("Error sending test message to plant {} sensor {:?}: {:?}", plant, sensor, err);
|
||||
info!(
|
||||
"Error sending test message to plant {plant} sensor {sensor:?}: {err:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
info!("Error building CAN frame");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
let mut result = DetectionResult::default();
|
||||
// Wait for messages to arrive
|
||||
let _ = Self::wait_for_can_measurements(&mut as_async, &mut result).with_timeout(Duration::from_millis(5000)).await;
|
||||
let _ = Self::wait_for_can_measurements(&mut as_async, &mut result)
|
||||
.with_timeout(Duration::from_millis(5000))
|
||||
.await;
|
||||
|
||||
let config = as_async.stop().into_blocking();
|
||||
can_power.set_low();
|
||||
twai_config.replace(config);
|
||||
|
||||
info!("Autodetection result: {:?}", result);
|
||||
info!("Autodetection result: {result:?}");
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn wait_for_can_measurements(as_async: &mut Twai<'_, Async>, result: &mut DetectionResult) {
|
||||
async fn wait_for_can_measurements(
|
||||
as_async: &mut Twai<'_, Async>,
|
||||
result: &mut DetectionResult,
|
||||
) {
|
||||
loop {
|
||||
match as_async.receive_async().await {
|
||||
Ok(can_frame) => {
|
||||
match can_frame.id() {
|
||||
Id::Standard(id) => {
|
||||
info!("Received CAN message: {:?}", id);
|
||||
let rawid = id.as_raw();
|
||||
match classify(rawid) {
|
||||
None => {}
|
||||
Some(msg) => {
|
||||
info!("received message of kind {:?} (plant: {}, sensor: {:?})", msg.0, msg.1, msg.2);
|
||||
if msg.0 == MessageKind::MoistureData {
|
||||
let plant = msg.1 as usize;
|
||||
let sensor = msg.2;
|
||||
match sensor {
|
||||
SensorSlot::A => {
|
||||
result.plant[plant].sensor_a = true;
|
||||
}
|
||||
SensorSlot::B => {
|
||||
result.plant[plant].sensor_b = true;
|
||||
}
|
||||
Ok(can_frame) => match can_frame.id() {
|
||||
Id::Standard(id) => {
|
||||
info!("Received CAN message: {id:?}");
|
||||
let rawid = id.as_raw();
|
||||
match classify(rawid) {
|
||||
None => {}
|
||||
Some(msg) => {
|
||||
info!(
|
||||
"received message of kind {:?} (plant: {}, sensor: {:?})",
|
||||
msg.0, msg.1, msg.2
|
||||
);
|
||||
if msg.0 == MessageKind::MoistureData {
|
||||
let plant = msg.1 as usize;
|
||||
let sensor = msg.2;
|
||||
match sensor {
|
||||
SensorSlot::A => {
|
||||
result.plant[plant].sensor_a = true;
|
||||
}
|
||||
SensorSlot::B => {
|
||||
result.plant[plant].sensor_b = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Id::Extended(ext) => {
|
||||
warn!("Received extended ID: {:?}", ext);
|
||||
}
|
||||
}
|
||||
}
|
||||
Id::Extended(ext) => {
|
||||
warn!("Received extended ID: {ext:?}");
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
error!("Error receiving CAN message: {:?}", err);
|
||||
error!("Error receiving CAN message: {err:?}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn inner_pulse(plant: usize, sensor: Sensor, signal_counter: &mut Unit<'_, 0>, sensor_expander: &mut Pca9535Immediate<I2cDevice<'static, CriticalSectionRawMutex, I2c<'static, Blocking>>>) -> FatResult<f32> {
|
||||
pub async fn inner_pulse(
|
||||
plant: usize,
|
||||
sensor: Sensor,
|
||||
signal_counter: &mut Unit<'_, 0>,
|
||||
sensor_expander: &mut Pca9535Immediate<
|
||||
I2cDevice<'static, CriticalSectionRawMutex, I2c<'static, Blocking>>,
|
||||
>,
|
||||
) -> FatResult<f32> {
|
||||
let mut results = [0_f32; REPEAT_MOIST_MEASURE];
|
||||
for sample in results.iter_mut() {
|
||||
signal_counter.pause();
|
||||
signal_counter.clear();
|
||||
|
||||
let mut results = [0_f32; REPEAT_MOIST_MEASURE];
|
||||
for repeat in 0..REPEAT_MOIST_MEASURE {
|
||||
signal_counter.pause();
|
||||
signal_counter.clear();
|
||||
//Disable all
|
||||
sensor_expander.pin_set_high(GPIOBank::Bank0, MS4)?;
|
||||
|
||||
//Disable all
|
||||
sensor_expander.pin_set_high(GPIOBank::Bank0, MS4)?;
|
||||
let sensor_channel = match sensor {
|
||||
Sensor::A => plant as u32,
|
||||
Sensor::B => (15 - plant) as u32,
|
||||
};
|
||||
|
||||
let sensor_channel = match sensor {
|
||||
Sensor::A => plant as u32,
|
||||
Sensor::B => (15 - plant) as u32,
|
||||
};
|
||||
let is_bit_set = |b: u8| -> bool { sensor_channel & (1 << b) != 0 };
|
||||
if is_bit_set(0) {
|
||||
sensor_expander.pin_set_high(GPIOBank::Bank0, MS0)?;
|
||||
} else {
|
||||
sensor_expander.pin_set_low(GPIOBank::Bank0, MS0)?;
|
||||
}
|
||||
if is_bit_set(1) {
|
||||
sensor_expander.pin_set_high(GPIOBank::Bank0, MS1)?;
|
||||
} else {
|
||||
sensor_expander.pin_set_low(GPIOBank::Bank0, MS1)?;
|
||||
}
|
||||
if is_bit_set(2) {
|
||||
sensor_expander.pin_set_high(GPIOBank::Bank0, MS2)?;
|
||||
} else {
|
||||
sensor_expander.pin_set_low(GPIOBank::Bank0, MS2)?;
|
||||
}
|
||||
if is_bit_set(3) {
|
||||
sensor_expander.pin_set_high(GPIOBank::Bank0, MS3)?;
|
||||
} else {
|
||||
sensor_expander.pin_set_low(GPIOBank::Bank0, MS3)?;
|
||||
}
|
||||
|
||||
let is_bit_set = |b: u8| -> bool { sensor_channel & (1 << b) != 0 };
|
||||
if is_bit_set(0) {
|
||||
sensor_expander.pin_set_high(GPIOBank::Bank0, MS0)?;
|
||||
} else {
|
||||
sensor_expander.pin_set_low(GPIOBank::Bank0, MS0)?;
|
||||
}
|
||||
if is_bit_set(1) {
|
||||
sensor_expander.pin_set_high(GPIOBank::Bank0, MS1)?;
|
||||
} else {
|
||||
sensor_expander.pin_set_low(GPIOBank::Bank0, MS1)?;
|
||||
}
|
||||
if is_bit_set(2) {
|
||||
sensor_expander.pin_set_high(GPIOBank::Bank0, MS2)?;
|
||||
} else {
|
||||
sensor_expander.pin_set_low(GPIOBank::Bank0, MS2)?;
|
||||
}
|
||||
if is_bit_set(3) {
|
||||
sensor_expander.pin_set_high(GPIOBank::Bank0, MS3)?;
|
||||
} else {
|
||||
sensor_expander.pin_set_low(GPIOBank::Bank0, MS3)?;
|
||||
sensor_expander.pin_set_low(GPIOBank::Bank0, MS4)?;
|
||||
sensor_expander.pin_set_high(GPIOBank::Bank0, SENSOR_ON)?;
|
||||
|
||||
let measurement = 100; // TODO what is this scaling factor? what is its purpose?
|
||||
let factor = 1000f32 / measurement as f32;
|
||||
|
||||
//give some time to stabilize
|
||||
Timer::after_millis(10).await;
|
||||
signal_counter.resume();
|
||||
Timer::after_millis(measurement).await;
|
||||
signal_counter.pause();
|
||||
sensor_expander.pin_set_high(GPIOBank::Bank0, MS4)?;
|
||||
sensor_expander.pin_set_low(GPIOBank::Bank0, SENSOR_ON)?;
|
||||
sensor_expander.pin_set_low(GPIOBank::Bank0, MS0)?;
|
||||
sensor_expander.pin_set_low(GPIOBank::Bank0, MS1)?;
|
||||
sensor_expander.pin_set_low(GPIOBank::Bank0, MS2)?;
|
||||
sensor_expander.pin_set_low(GPIOBank::Bank0, MS3)?;
|
||||
Timer::after_millis(10).await;
|
||||
let unscaled = 1337; //signal_counter.get_counter_value()? as i32;
|
||||
let hz = unscaled as f32 * factor;
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(
|
||||
LogMessage::RawMeasure,
|
||||
unscaled as u32,
|
||||
hz as u32,
|
||||
&plant.to_string(),
|
||||
&format!("{sensor:?}"),
|
||||
)
|
||||
.await;
|
||||
*sample = hz;
|
||||
}
|
||||
results.sort_by(|a, b| a.partial_cmp(b).unwrap()); // floats don't seem to implement total_ord
|
||||
|
||||
let mid = results.len() / 2;
|
||||
let median = results[mid];
|
||||
Ok(median)
|
||||
}
|
||||
|
||||
sensor_expander.pin_set_low(GPIOBank::Bank0, MS4)?;
|
||||
sensor_expander.pin_set_high(GPIOBank::Bank0, SENSOR_ON)?;
|
||||
|
||||
let measurement = 100; // TODO what is this scaling factor? what is its purpose?
|
||||
let factor = 1000f32 / measurement as f32;
|
||||
|
||||
//give some time to stabilize
|
||||
Timer::after_millis(10).await;
|
||||
signal_counter.resume();
|
||||
Timer::after_millis(measurement).await;
|
||||
signal_counter.pause();
|
||||
sensor_expander.pin_set_high(GPIOBank::Bank0, MS4)?;
|
||||
sensor_expander.pin_set_low(GPIOBank::Bank0, SENSOR_ON)?;
|
||||
sensor_expander.pin_set_low(GPIOBank::Bank0, MS0)?;
|
||||
sensor_expander.pin_set_low(GPIOBank::Bank0, MS1)?;
|
||||
sensor_expander.pin_set_low(GPIOBank::Bank0, MS2)?;
|
||||
sensor_expander.pin_set_low(GPIOBank::Bank0, MS3)?;
|
||||
Timer::after_millis(10).await;
|
||||
let unscaled = 1337; //signal_counter.get_counter_value()? as i32;
|
||||
let hz = unscaled as f32 * factor;
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(
|
||||
LogMessage::RawMeasure,
|
||||
unscaled as u32,
|
||||
hz as u32,
|
||||
&plant.to_string(),
|
||||
&format!("{sensor:?}"),
|
||||
)
|
||||
.await;
|
||||
results[repeat] = hz;
|
||||
}
|
||||
results.sort_by(|a, b| a.partial_cmp(b).unwrap()); // floats don't seem to implement total_ord
|
||||
|
||||
let mid = results.len() / 2;
|
||||
let median = results[mid];
|
||||
Ok(median)
|
||||
}
|
||||
|
||||
async fn inner_can(
|
||||
twai: &mut Twai<'static, Blocking>,
|
||||
) -> FatResult<Moistures> {
|
||||
[0_u8; 8];
|
||||
async fn inner_can(twai: &mut Twai<'static, Blocking>) -> FatResult<Moistures> {
|
||||
config::standard();
|
||||
|
||||
let timeout = Instant::now()
|
||||
@@ -291,7 +313,7 @@ impl SensorImpl {
|
||||
let answer = twai.receive();
|
||||
match answer {
|
||||
Ok(answer) => {
|
||||
info!("Received CAN message: {:?}", answer);
|
||||
info!("Received CAN message: {answer:?}");
|
||||
}
|
||||
Err(error) => match error {
|
||||
nb::Error::Other(error) => {
|
||||
|
||||
@@ -137,11 +137,11 @@ impl<'a> TankSensor<'a> {
|
||||
Timer::after_millis(100).await;
|
||||
|
||||
let mut store = [0_u16; TANK_MULTI_SAMPLE];
|
||||
for multisample in 0..TANK_MULTI_SAMPLE {
|
||||
for sample in store.iter_mut() {
|
||||
let value = self.tank_channel.read_oneshot(&mut self.tank_pin);
|
||||
//force yield
|
||||
Timer::after_millis(10).await;
|
||||
store[multisample] = value.unwrap();
|
||||
*sample = value.unwrap();
|
||||
}
|
||||
self.tank_power.set_low();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user