diff --git a/rust/.idea/inspectionProfiles/Project_Default.xml b/rust/.idea/inspectionProfiles/Project_Default.xml
index 3fe75f2..656b6be 100644
--- a/rust/.idea/inspectionProfiles/Project_Default.xml
+++ b/rust/.idea/inspectionProfiles/Project_Default.xml
@@ -7,5 +7,6 @@
+
\ No newline at end of file
diff --git a/rust/Cargo.toml b/rust/Cargo.toml
index ae96c6a..8a67bd1 100644
--- a/rust/Cargo.toml
+++ b/rust/Cargo.toml
@@ -26,19 +26,29 @@ command = [
"partitions.csv"
]
+#this strips the bootloader, we need that tho
+#strip = true
+[profile.dev]
lto = "fat"
-strip = true
debug = false
overflow-checks = true
panic = "abort"
incremental = true
opt-level = "z"
+[profile.release]
+lto = "fat"
+#debug = false
+overflow-checks = true
+panic = "abort"
+incremental = false
+opt-level = "z"
[package.metadata.espflash]
partition_table = "partitions.csv"
+
[dependencies]
#ESP stuff
esp-bootloader-esp-idf = { version = "0.2.0", features = ["esp32c6"] }
@@ -106,7 +116,6 @@ smoltcp = { version = "0.12.0", default-features = false, features = [
] }
#static_cell = "2.1.1"
embedded-hal = "1.0.0"
-heapless = { version = "0.8", features = ["serde"] }
embedded-hal-bus = { version = "0.3.0" }
#Hardware additional driver
@@ -148,8 +157,15 @@ bincode = { version = "2.0.1", default-features = false, features = ["derive"] }
sntpc = { version = "0.6.0", default-features = false, features = ["log", "embassy-socket", "embassy-socket-ipv6"] }
option-lock = { version = "0.3.1", default-features = false }
+#stay in sync with mcutie version here!
+heapless = { version = "0.7.17", features = ["serde"] }
+mcutie = { version = "0.3.0", default-features = false }
+
+
+
[patch.crates-io]
+mcutie = { git = 'https://github.com/empirephoenix/mcutie.git' }
#bq34z100 = { path = "../../bq34z100_rust" }
[build-dependencies]
-vergen = { version = "8.2.6", features = ["build", "git", "gitcl"] }
+vergen = { version = "8.2.6", features = ["build", "git", "gitcl"] }
\ No newline at end of file
diff --git a/rust/scratch/v3_hal.rs b/rust/scratch/v3_hal.rs
deleted file mode 100644
index 1508407..0000000
--- a/rust/scratch/v3_hal.rs
+++ /dev/null
@@ -1,434 +0,0 @@
-use crate::hal::rtc::RTCModuleInteraction;
-use crate::hal::water::TankSensor;
-use crate::hal::{
- deep_sleep, BoardInteraction, FreePeripherals, Sensor, PLANT_COUNT,
-};
-use crate::log::{log, LogMessage};
-use crate::{
- config::PlantControllerConfig,
- hal::{battery::BatteryInteraction, esp::Esp},
-};
-use anyhow::{bail, Ok, Result};
-use embedded_hal::digital::OutputPin;
-use measurements::{Current, Voltage};
-use plant_ctrl2::sipo::ShiftRegister40;
-use core::result::Result::Ok as OkStd;
-use alloc::string::ToString;
-use alloc::boxed::Box;
-use esp_hall::gpio::Pull;
-
-const PUMP8_BIT: usize = 0;
-const PUMP1_BIT: usize = 1;
-const PUMP2_BIT: usize = 2;
-const PUMP3_BIT: usize = 3;
-const PUMP4_BIT: usize = 4;
-const PUMP5_BIT: usize = 5;
-const PUMP6_BIT: usize = 6;
-const PUMP7_BIT: usize = 7;
-const MS_0: usize = 8;
-const MS_4: usize = 9;
-const MS_2: usize = 10;
-const MS_3: usize = 11;
-const MS_1: usize = 13;
-const SENSOR_ON: usize = 12;
-
-const SENSOR_A_1: u8 = 7;
-const SENSOR_A_2: u8 = 6;
-const SENSOR_A_3: u8 = 5;
-const SENSOR_A_4: u8 = 4;
-const SENSOR_A_5: u8 = 3;
-const SENSOR_A_6: u8 = 2;
-const SENSOR_A_7: u8 = 1;
-const SENSOR_A_8: u8 = 0;
-
-const SENSOR_B_1: u8 = 8;
-const SENSOR_B_2: u8 = 9;
-const SENSOR_B_3: u8 = 10;
-const SENSOR_B_4: u8 = 11;
-const SENSOR_B_5: u8 = 12;
-const SENSOR_B_6: u8 = 13;
-const SENSOR_B_7: u8 = 14;
-const SENSOR_B_8: u8 = 15;
-
-const CHARGING: usize = 14;
-const AWAKE: usize = 15;
-
-const FAULT_3: usize = 16;
-const FAULT_8: usize = 17;
-const FAULT_7: usize = 18;
-const FAULT_6: usize = 19;
-const FAULT_5: usize = 20;
-const FAULT_4: usize = 21;
-const FAULT_1: usize = 22;
-const FAULT_2: usize = 23;
-
-const REPEAT_MOIST_MEASURE: usize = 1;
-
-
-pub struct V3<'a> {
- config: PlantControllerConfig,
- battery_monitor: Box,
- rtc_module: Box,
- esp: Esp<'a>,
- shift_register: ShiftRegister40<
- PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
- PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
- PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
- >,
- _shift_register_enable_invert:
- PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, esp_idf_hal::gpio::Output>,
- tank_sensor: TankSensor<'a>,
- solar_is_day: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, esp_idf_hal::gpio::Input>,
- light: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
- main_pump: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
- general_fault: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
- signal_counter: PcntDriver<'a>,
-}
-
-pub(crate) fn create_v3(
- peripherals: FreePeripherals,
- esp: Esp<'static>,
- config: PlantControllerConfig,
- battery_monitor: Box,
- rtc_module: Box,
-) -> Result + Send>> {
- log::info!("Start v3");
- let mut clock = PinDriver::input_output(peripherals.gpio15.downgrade())?;
- clock.set_pull(Pull::Floating)?;
- let mut latch = PinDriver::input_output(peripherals.gpio3.downgrade())?;
- latch.set_pull(Pull::Floating)?;
- let mut data = PinDriver::input_output(peripherals.gpio23.downgrade())?;
- data.set_pull(Pull::Floating)?;
- let shift_register = ShiftRegister40::new(clock, latch, data);
- //disable all
- for mut pin in shift_register.decompose() {
- pin.set_low()?;
- }
-
- let awake = &mut shift_register.decompose()[AWAKE];
- awake.set_high()?;
-
- let charging = &mut shift_register.decompose()[CHARGING];
- charging.set_high()?;
-
- let ms0 = &mut shift_register.decompose()[MS_0];
- ms0.set_low()?;
- let ms1 = &mut shift_register.decompose()[MS_1];
- ms1.set_low()?;
- let ms2 = &mut shift_register.decompose()[MS_2];
- ms2.set_low()?;
- let ms3 = &mut shift_register.decompose()[MS_3];
- ms3.set_low()?;
-
- let ms4 = &mut shift_register.decompose()[MS_4];
- ms4.set_high()?;
-
- let one_wire_pin = peripherals.gpio18.downgrade();
- let tank_power_pin = peripherals.gpio11.downgrade();
-
- let flow_sensor_pin = peripherals.gpio4.downgrade();
-
- let tank_sensor = TankSensor::create(
- one_wire_pin,
- peripherals.adc1,
- peripherals.gpio5,
- tank_power_pin,
- flow_sensor_pin,
- peripherals.pcnt1,
- )?;
-
- let mut signal_counter = PcntDriver::new(
- peripherals.pcnt0,
- Some(peripherals.gpio22),
- Option::::None,
- Option::::None,
- Option::::None,
- )?;
-
- signal_counter.channel_config(
- PcntChannel::Channel0,
- PinIndex::Pin0,
- PinIndex::Pin1,
- &PcntChannelConfig {
- lctrl_mode: PcntControlMode::Keep,
- hctrl_mode: PcntControlMode::Keep,
- pos_mode: PcntCountMode::Increment,
- neg_mode: PcntCountMode::Hold,
- counter_h_lim: i16::MAX,
- counter_l_lim: 0,
- },
- )?;
-
- let mut solar_is_day = PinDriver::input(peripherals.gpio7.downgrade())?;
- solar_is_day.set_pull(Pull::Floating)?;
-
- let mut light = PinDriver::input_output(peripherals.gpio10.downgrade())?;
- light.set_pull(Pull::Floating)?;
-
- let mut main_pump = PinDriver::input_output(peripherals.gpio2.downgrade())?;
- main_pump.set_pull(Pull::Floating)?;
- main_pump.set_low()?;
-
- let mut general_fault = PinDriver::input_output(peripherals.gpio6.downgrade())?;
- general_fault.set_pull(Pull::Floating)?;
- general_fault.set_low()?;
-
- let mut shift_register_enable_invert = PinDriver::output(peripherals.gpio21.downgrade())?;
-
- unsafe { gpio_hold_dis(shift_register_enable_invert.pin()) };
- shift_register_enable_invert.set_low()?;
- unsafe { gpio_hold_en(shift_register_enable_invert.pin()) };
-
- Ok(Box::new(V3 {
- config,
- battery_monitor,
- rtc_module,
- esp,
- shift_register,
- _shift_register_enable_invert: shift_register_enable_invert,
- tank_sensor,
- solar_is_day,
- light,
- main_pump,
- general_fault,
- signal_counter,
- }))
-}
-
-impl<'a> BoardInteraction<'a> for V3<'a> {
- fn get_tank_sensor(&mut self) -> Option<&mut TankSensor<'a>> {
- Some(&mut self.tank_sensor)
- }
-
- fn get_esp(&mut self) -> &mut Esp<'a> {
- &mut self.esp
- }
-
- fn get_config(&mut self) -> &PlantControllerConfig {
- &self.config
- }
-
- fn get_battery_monitor(&mut self) -> &mut Box {
- &mut self.battery_monitor
- }
-
- fn get_rtc_module(&mut self) -> &mut Box {
- &mut self.rtc_module
- }
- fn set_charge_indicator(&mut self, charging: bool) -> Result<()> {
- Ok(self.shift_register.decompose()[CHARGING].set_state(charging.into())?)
- }
-
- fn deep_sleep(&mut self, duration_in_ms: u64) -> ! {
- let _ = self.shift_register.decompose()[AWAKE].set_low();
- deep_sleep(duration_in_ms)
- }
-
- fn is_day(&self) -> bool {
- self.solar_is_day.get_level().into()
- }
-
- fn light(&mut self, enable: bool) -> Result<()> {
- unsafe { gpio_hold_dis(self.light.pin()) };
- self.light.set_state(enable.into())?;
- unsafe { gpio_hold_en(self.light.pin()) };
- Ok(())
- }
- fn pump(&mut self, plant: usize, enable: bool) -> Result<()> {
- if enable {
- self.main_pump.set_high()?;
- }
-
- let index = match plant {
- 0 => PUMP1_BIT,
- 1 => PUMP2_BIT,
- 2 => PUMP3_BIT,
- 3 => PUMP4_BIT,
- 4 => PUMP5_BIT,
- 5 => PUMP6_BIT,
- 6 => PUMP7_BIT,
- 7 => PUMP8_BIT,
- _ => bail!("Invalid pump {plant}",),
- };
- self.shift_register.decompose()[index].set_state(enable.into())?;
-
- if !enable {
- self.main_pump.set_low()?;
- }
- Ok(())
- }
-
- fn pump_current(&mut self, _plant: usize) -> Result {
- bail!("Not implemented in v3")
- }
-
- fn fault(&mut self, plant: usize, enable: bool) -> Result<()> {
- let index = match plant {
- 0 => FAULT_1,
- 1 => FAULT_2,
- 2 => FAULT_3,
- 3 => FAULT_4,
- 4 => FAULT_5,
- 5 => FAULT_6,
- 6 => FAULT_7,
- 7 => FAULT_8,
- _ => panic!("Invalid plant id {}", plant),
- };
- self.shift_register.decompose()[index].set_state(enable.into())?;
- Ok(())
- }
-
- fn measure_moisture_hz(&mut self, plant: usize, sensor: Sensor) -> Result {
- let mut results = [0_f32; REPEAT_MOIST_MEASURE];
- for repeat in 0..REPEAT_MOIST_MEASURE {
- self.signal_counter.counter_pause()?;
- self.signal_counter.counter_clear()?;
- //Disable all
- self.shift_register.decompose()[MS_4].set_high()?;
-
- let sensor_channel = match sensor {
- Sensor::A => match plant {
- 0 => SENSOR_A_1,
- 1 => SENSOR_A_2,
- 2 => SENSOR_A_3,
- 3 => SENSOR_A_4,
- 4 => SENSOR_A_5,
- 5 => SENSOR_A_6,
- 6 => SENSOR_A_7,
- 7 => SENSOR_A_8,
- _ => bail!("Invalid plant id {}", plant),
- },
- Sensor::B => match plant {
- 0 => SENSOR_B_1,
- 1 => SENSOR_B_2,
- 2 => SENSOR_B_3,
- 3 => SENSOR_B_4,
- 4 => SENSOR_B_5,
- 5 => SENSOR_B_6,
- 6 => SENSOR_B_7,
- 7 => SENSOR_B_8,
- _ => bail!("Invalid plant id {}", plant),
- },
- };
-
- let is_bit_set = |b: u8| -> bool { sensor_channel & (1 << b) != 0 };
- let pin_0 = &mut self.shift_register.decompose()[MS_0];
- let pin_1 = &mut self.shift_register.decompose()[MS_1];
- let pin_2 = &mut self.shift_register.decompose()[MS_2];
- let pin_3 = &mut self.shift_register.decompose()[MS_3];
- if is_bit_set(0) {
- pin_0.set_high()?;
- } else {
- pin_0.set_low()?;
- }
- if is_bit_set(1) {
- pin_1.set_high()?;
- } else {
- pin_1.set_low()?;
- }
- if is_bit_set(2) {
- pin_2.set_high()?;
- } else {
- pin_2.set_low()?;
- }
- if is_bit_set(3) {
- pin_3.set_high()?;
- } else {
- pin_3.set_low()?;
- }
-
- self.shift_register.decompose()[MS_4].set_low()?;
- self.shift_register.decompose()[SENSOR_ON].set_high()?;
-
- let measurement = 100; //how long to measure and then extrapolate to hz
- let factor = 1000f32 / measurement as f32; //scale raw cound by this number to get hz
-
- //give some time to stabilize
- self.esp.delay.delay_ms(10);
- self.signal_counter.counter_resume()?;
- self.esp.delay.delay_ms(measurement);
- self.signal_counter.counter_pause()?;
- self.shift_register.decompose()[MS_4].set_high()?;
- self.shift_register.decompose()[SENSOR_ON].set_low()?;
- self.esp.delay.delay_ms(10);
- let unscaled = self.signal_counter.get_counter_value()? as i32;
- let hz = unscaled as f32 * factor;
- log(
- LogMessage::RawMeasure,
- unscaled as u32,
- hz as u32,
- &plant.to_string(),
- &format!("{sensor:?}"),
- );
- 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)
- }
-
- fn general_fault(&mut self, enable: bool) {
- unsafe { gpio_hold_dis(self.general_fault.pin()) };
- self.general_fault.set_state(enable.into()).unwrap();
- unsafe { gpio_hold_en(self.general_fault.pin()) };
- }
-
- fn test(&mut self) -> Result<()> {
- self.general_fault(true);
- self.esp.delay.delay_ms(100);
- self.general_fault(false);
- self.esp.delay.delay_ms(100);
- self.light(true)?;
- self.esp.delay.delay_ms(500);
- self.light(false)?;
- self.esp.delay.delay_ms(500);
- for i in 0..PLANT_COUNT {
- self.fault(i, true)?;
- self.esp.delay.delay_ms(500);
- self.fault(i, false)?;
- self.esp.delay.delay_ms(500);
- }
- for i in 0..PLANT_COUNT {
- self.pump(i, true)?;
- self.esp.delay.delay_ms(100);
- self.pump(i, false)?;
- self.esp.delay.delay_ms(100);
- }
- for plant in 0..PLANT_COUNT {
- let a = self.measure_moisture_hz(plant, Sensor::A);
- let b = self.measure_moisture_hz(plant, Sensor::B);
- let aa = match a {
- OkStd(a) => a as u32,
- Err(_) => u32::MAX,
- };
- let bb = match b {
- OkStd(b) => b as u32,
- Err(_) => u32::MAX,
- };
- log(LogMessage::TestSensor, aa, bb, &plant.to_string(), "");
- }
- self.esp.delay.delay_ms(10);
- Ok(())
- }
-
- fn set_config(&mut self, config: PlantControllerConfig) -> Result<()> {
- self.config = config;
- self.esp.save_config(&self.config)?;
- anyhow::Ok(())
- }
-
- fn get_mptt_voltage(&mut self) -> Result {
- //assuming module to work, these are the hardware set values
- if self.is_day() {
- Ok(Voltage::from_volts(15_f64))
- } else {
- Ok(Voltage::from_volts(0_f64))
- }
- }
-
- fn get_mptt_current(&mut self) -> Result {
- bail!("Board does not have current sensor")
- }
-}
diff --git a/rust/src/fat_error.rs b/rust/src/fat_error.rs
index 5f1a5da..7512076 100644
--- a/rust/src/fat_error.rs
+++ b/rust/src/fat_error.rs
@@ -257,3 +257,9 @@ impl From>> for Fat
}
}
}
+
+impl From for FatError {
+ fn from(value: Infallible) -> Self {
+ panic!("Infallible error: {:?}", value)
+ }
+}
diff --git a/rust/src/hal/esp.rs b/rust/src/hal/esp.rs
index c3c106b..3b99fa5 100644
--- a/rust/src/hal/esp.rs
+++ b/rust/src/hal/esp.rs
@@ -28,7 +28,10 @@ use esp_bootloader_esp_idf::ota::{Ota, OtaImageState};
use esp_bootloader_esp_idf::partitions::FlashRegion;
use esp_hal::gpio::{Input, InputConfig, Pull, RtcPinWithResistors};
use esp_hal::rng::Rng;
-use esp_hal::rtc_cntl::{sleep::{TimerWakeupSource, WakeupLevel}, Rtc};
+use esp_hal::rtc_cntl::{
+ sleep::{TimerWakeupSource, WakeupLevel},
+ Rtc,
+};
use esp_hal::system::software_reset;
use esp_println::println;
use esp_storage::FlashStorage;
@@ -78,7 +81,7 @@ pub struct FileSystemSizeInfo {
pub struct MqttClient<'a> {
dummy: PhantomData<&'a ()>,
//mqtt_client: EspMqttClient<'a>,
- base_topic: heapless::String<64>,
+ base_topic: String,
}
#[derive(Copy, Clone, Default)]
@@ -86,6 +89,22 @@ struct Timestamp {
stamp: DateTime,
}
+// Minimal esp-idf equivalent for gpio_hold on esp32c6 via ROM functions
+extern "C" {
+ fn gpio_pad_hold(gpio_num: u32);
+ fn gpio_pad_unhold(gpio_num: u32);
+}
+
+#[inline(always)]
+pub fn hold_enable(gpio_num: u8) {
+ unsafe { gpio_pad_hold(gpio_num as u32) }
+}
+
+#[inline(always)]
+pub fn hold_disable(gpio_num: u8) {
+ unsafe { gpio_pad_unhold(gpio_num as u32) }
+}
+
impl NtpTimestampGenerator for Timestamp {
fn init(&mut self) {
self.stamp = DateTime::default();
@@ -495,12 +514,19 @@ impl Esp<'_> {
}
_ => {}
}
- if { let guard = TIME_ACCESS.get().await.lock().await; guard.current_time_us() } > timeout {
+ if {
+ let guard = TIME_ACCESS.get().await.lock().await;
+ guard.current_time_us()
+ } > timeout
+ {
bail!("Timeout waiting for wifi sta ready")
}
Timer::after(Duration::from_millis(500)).await;
}
- let timeout = { let guard = TIME_ACCESS.get().await.lock().await; guard.current_time_us() } + max_wait as u64 * 1000;
+ let timeout = {
+ let guard = TIME_ACCESS.get().await.lock().await;
+ guard.current_time_us()
+ } + max_wait as u64 * 1000;
loop {
let state = esp_wifi::wifi::sta_state();
match state {
@@ -509,21 +535,39 @@ impl Esp<'_> {
}
_ => {}
}
- if { let guard = TIME_ACCESS.get().await.lock().await; guard.current_time_us() } > timeout {
+ if {
+ let guard = TIME_ACCESS.get().await.lock().await;
+ guard.current_time_us()
+ } > timeout
+ {
bail!("Timeout waiting for wifi sta connected")
}
Timer::after(Duration::from_millis(500)).await;
}
- let timeout = { let guard = TIME_ACCESS.get().await.lock().await; guard.current_time_us() } + max_wait as u64 * 1000;
+ let timeout = {
+ let guard = TIME_ACCESS.get().await.lock().await;
+ guard.current_time_us()
+ } + max_wait as u64 * 1000;
while !stack.is_link_up() {
- if { let guard = TIME_ACCESS.get().await.lock().await; guard.current_time_us() } > timeout {
+ if {
+ let guard = TIME_ACCESS.get().await.lock().await;
+ guard.current_time_us()
+ } > timeout
+ {
bail!("Timeout waiting for wifi link up")
}
Timer::after(Duration::from_millis(500)).await;
}
- let timeout = { let guard = TIME_ACCESS.get().await.lock().await; guard.current_time_us() } + max_wait as u64 * 1000;
+ let timeout = {
+ let guard = TIME_ACCESS.get().await.lock().await;
+ guard.current_time_us()
+ } + max_wait as u64 * 1000;
while !stack.is_config_up() {
- if { let guard = TIME_ACCESS.get().await.lock().await; guard.current_time_us() } > timeout {
+ if {
+ let guard = TIME_ACCESS.get().await.lock().await;
+ guard.current_time_us()
+ } > timeout
+ {
bail!("Timeout waiting for wifi config up")
}
Timer::after(Duration::from_millis(100)).await
@@ -531,7 +575,11 @@ impl Esp<'_> {
Ok(stack.clone())
}
- pub fn deep_sleep(&mut self, duration_in_ms: u64, mut rtc: MutexGuard) -> ! {
+ pub fn deep_sleep(
+ &mut self,
+ duration_in_ms: u64,
+ mut rtc: MutexGuard,
+ ) -> ! {
// Configure and enter deep sleep using esp-hal. Also keep prior behavior where
// duration_in_ms == 0 triggers an immediate reset.
@@ -549,7 +597,8 @@ impl Esp<'_> {
} else {
///let timer = TimerWakeupSource::new(core::time::Duration::from_millis(duration_in_ms));
let timer = TimerWakeupSource::new(core::time::Duration::from_millis(5000));
- let mut wake_pins: [(&mut dyn RtcPinWithResistors, WakeupLevel); 1] = [(&mut self.wake_gpio1, WakeupLevel::Low)];
+ let mut wake_pins: [(&mut dyn RtcPinWithResistors, WakeupLevel); 1] =
+ [(&mut self.wake_gpio1, WakeupLevel::Low)];
let ext1 = esp_hal::rtc_cntl::sleep::Ext1WakeupSource::new(&mut wake_pins);
rtc.sleep_deep(&[&timer, &ext1]);
}
diff --git a/rust/src/hal/initial_hal.rs b/rust/src/hal/initial_hal.rs
index 6ecf8a8..6cec44b 100644
--- a/rust/src/hal/initial_hal.rs
+++ b/rust/src/hal/initial_hal.rs
@@ -1,9 +1,9 @@
use crate::alloc::boxed::Box;
+use crate::fat_error::{FatError, FatResult};
use crate::hal::esp::Esp;
use crate::hal::rtc::{BackupHeader, RTCModuleInteraction};
use crate::hal::water::TankSensor;
use crate::hal::{BoardInteraction, FreePeripherals, Sensor, TIME_ACCESS};
-use crate::fat_error::{FatError, FatResult};
use crate::{
bail,
config::PlantControllerConfig,
@@ -90,7 +90,7 @@ impl<'a> BoardInteraction<'a> for Initial<'a> {
&mut self.rtc
}
- fn set_charge_indicator(&mut self, _charging: bool) -> Result<(), FatError> {
+ async fn set_charge_indicator(&mut self, _charging: bool) -> Result<(), FatError> {
bail!("Please configure board revision")
}
diff --git a/rust/src/hal/mod.rs b/rust/src/hal/mod.rs
index 65ed891..ee11ee1 100644
--- a/rust/src/hal/mod.rs
+++ b/rust/src/hal/mod.rs
@@ -3,6 +3,7 @@ pub mod esp;
mod initial_hal;
mod little_fs2storage_adapter;
pub(crate) mod rtc;
+mod v3_hal;
mod v4_hal;
mod v4_sensor;
mod water;
@@ -79,11 +80,11 @@ use esp_hal::clock::CpuClock;
use esp_hal::gpio::{Input, InputConfig, Pull};
use measurements::{Current, Voltage};
+use crate::fat_error::{FatError, FatResult};
use crate::hal::battery::{print_battery_bq34z100, BQ34Z100G1};
use crate::hal::little_fs2storage_adapter::LittleFs2Filesystem;
use crate::hal::water::TankSensor;
use crate::log::LOG_ACCESS;
-use crate::fat_error::FatError;
use embassy_sync::mutex::Mutex;
use embassy_sync::once_lock::OnceLock;
use esp_alloc as _;
@@ -134,7 +135,7 @@ pub trait BoardInteraction<'a> {
fn get_config(&mut self) -> &PlantControllerConfig;
fn get_battery_monitor(&mut self) -> &mut Box;
fn get_rtc_module(&mut self) -> &mut Box;
- fn set_charge_indicator(&mut self, charging: bool) -> Result<(), FatError>;
+ async fn set_charge_indicator(&mut self, charging: bool) -> Result<(), FatError>;
async fn deep_sleep(&mut self, duration_in_ms: u64) -> !;
fn is_day(&self) -> bool;
@@ -230,9 +231,11 @@ impl PlantHal {
esp_alloc::heap_allocator!(#[link_section = ".dram2_uninit"] size: 64000);
let rtc: Rtc = Rtc::new(peripherals.LPWR);
- TIME_ACCESS.init(Mutex::new(rtc)).map_err(|_| FatError::String {
- error: "Init error rct".to_string(),
- })?;
+ TIME_ACCESS
+ .init(Mutex::new(rtc))
+ .map_err(|_| FatError::String {
+ error: "Init error rct".to_string(),
+ })?;
let systimer = SystemTimer::new(peripherals.SYSTIMER);
@@ -387,8 +390,8 @@ impl PlantHal {
fs,
rng,
controller: Arc::new(Mutex::new(controller)),
- interface_sta : Some(sta),
- interface_ap : Some(ap),
+ interface_sta: Some(sta),
+ interface_ap: Some(ap),
boot_button,
wake_gpio1,
mqtt_client: None,
@@ -424,7 +427,6 @@ impl PlantHal {
//TODO still required? or via button ignore? to_config_mode = true;
to_config_mode = true;
"core usb uart"
-
}
SocResetReason::CoreUsbJtag => "core usb jtag",
SocResetReason::Cpu0JtagCpu => "cpu0 jtag cpu",
@@ -539,9 +541,9 @@ impl PlantHal {
BoardVersion::INITIAL => {
initial_hal::create_initial_board(free_pins, config, esp)?
}
- // BoardVersion::V3 => {
- // v3_hal::create_v3(free_pins, esp, config, battery_interaction, rtc_module)?
- // }
+ BoardVersion::V3 => {
+ v3_hal::create_v3(free_pins, esp, config, battery_interaction, rtc_module)?
+ }
BoardVersion::V4 => {
v4_hal::create_v4(free_pins, esp, config, battery_interaction, rtc_module)
.await?
@@ -584,9 +586,9 @@ pub async fn esp_time() -> DateTime {
DateTime::from_timestamp_micros(guard.current_time_us() as i64).unwrap()
}
-pub async fn esp_set_time(time: DateTime) {
+pub async fn esp_set_time(time: DateTime) -> FatResult<()> {
{
- let mut guard = TIME_ACCESS.get().await.lock().await;
+ let guard = TIME_ACCESS.get().await.lock().await;
guard.set_current_time_us(time.timestamp_micros() as u64);
}
BOARD_ACCESS
@@ -597,5 +599,5 @@ pub async fn esp_set_time(time: DateTime) {
.board_hal
.get_rtc_module()
.set_rtc_time(&time.to_utc())
- .await;
+ .await
}
diff --git a/rust/src/hal/v3_hal.rs b/rust/src/hal/v3_hal.rs
new file mode 100644
index 0000000..7045523
--- /dev/null
+++ b/rust/src/hal/v3_hal.rs
@@ -0,0 +1,429 @@
+use crate::bail;
+use crate::fat_error::FatError;
+use crate::hal::esp::{hold_disable, hold_enable};
+use crate::hal::rtc::RTCModuleInteraction;
+use crate::hal::water::TankSensor;
+use crate::hal::{BoardInteraction, FreePeripherals, Sensor, PLANT_COUNT, TIME_ACCESS};
+use crate::log::{LogMessage, LOG_ACCESS};
+use crate::sipo::ShiftRegister40;
+use crate::{
+ config::PlantControllerConfig,
+ hal::{battery::BatteryInteraction, esp::Esp},
+};
+use alloc::boxed::Box;
+use alloc::format;
+use alloc::string::ToString;
+use async_trait::async_trait;
+use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
+use embassy_sync::blocking_mutex::CriticalSectionMutex;
+use embassy_sync::mutex::Mutex;
+use embassy_time::Timer;
+use embedded_hal::digital::OutputPin as _;
+use esp_hal::gpio::{Flex, Input, InputConfig, Level, Output, OutputConfig, Pull};
+use measurements::{Current, Voltage};
+
+const PUMP8_BIT: usize = 0;
+const PUMP1_BIT: usize = 1;
+const PUMP2_BIT: usize = 2;
+const PUMP3_BIT: usize = 3;
+const PUMP4_BIT: usize = 4;
+const PUMP5_BIT: usize = 5;
+const PUMP6_BIT: usize = 6;
+const PUMP7_BIT: usize = 7;
+const MS_0: usize = 8;
+const MS_4: usize = 9;
+const MS_2: usize = 10;
+const MS_3: usize = 11;
+const MS_1: usize = 13;
+const SENSOR_ON: usize = 12;
+
+const SENSOR_A_1: u8 = 7;
+const SENSOR_A_2: u8 = 6;
+const SENSOR_A_3: u8 = 5;
+const SENSOR_A_4: u8 = 4;
+const SENSOR_A_5: u8 = 3;
+const SENSOR_A_6: u8 = 2;
+const SENSOR_A_7: u8 = 1;
+const SENSOR_A_8: u8 = 0;
+
+const SENSOR_B_1: u8 = 8;
+const SENSOR_B_2: u8 = 9;
+const SENSOR_B_3: u8 = 10;
+const SENSOR_B_4: u8 = 11;
+const SENSOR_B_5: u8 = 12;
+const SENSOR_B_6: u8 = 13;
+const SENSOR_B_7: u8 = 14;
+const SENSOR_B_8: u8 = 15;
+
+const CHARGING: usize = 14;
+const AWAKE: usize = 15;
+
+const FAULT_3: usize = 16;
+const FAULT_8: usize = 17;
+const FAULT_7: usize = 18;
+const FAULT_6: usize = 19;
+const FAULT_5: usize = 20;
+const FAULT_4: usize = 21;
+const FAULT_1: usize = 22;
+const FAULT_2: usize = 23;
+
+const REPEAT_MOIST_MEASURE: usize = 1;
+
+pub struct V3<'a> {
+ config: PlantControllerConfig,
+ battery_monitor: Box,
+ rtc_module: Box,
+ esp: Esp<'a>,
+ shift_register:
+ Mutex, Output<'a>, Output<'a>>>,
+ _shift_register_enable_invert: Output<'a>,
+ tank_sensor: TankSensor<'a>,
+ solar_is_day: Input<'a>,
+ light: Output<'a>,
+ main_pump: Output<'a>,
+ general_fault: Output<'a>,
+}
+
+pub(crate) fn create_v3(
+ peripherals: FreePeripherals<'static>,
+ esp: Esp<'static>,
+ config: PlantControllerConfig,
+ battery_monitor: Box,
+ rtc_module: Box,
+) -> Result + Send + 'static>, FatError> {
+ log::info!("Start v3");
+ let clock = Output::new(peripherals.gpio15, Level::Low, OutputConfig::default());
+ let latch = Output::new(peripherals.gpio3, Level::Low, OutputConfig::default());
+ let data = Output::new(peripherals.gpio23, Level::Low, OutputConfig::default());
+ let shift_register = ShiftRegister40::new(clock, latch, data);
+ //disable all
+ for mut pin in shift_register.decompose() {
+ let _ = pin.set_low();
+ }
+
+ // Set always-on status bits
+ let _ = shift_register.decompose()[AWAKE].set_high();
+ let _ = shift_register.decompose()[CHARGING].set_high();
+
+ // Multiplexer defaults: ms0..ms3 low, ms4 high (disabled)
+ let _ = shift_register.decompose()[MS_0].set_low();
+ let _ = shift_register.decompose()[MS_1].set_low();
+ let _ = shift_register.decompose()[MS_2].set_low();
+ let _ = shift_register.decompose()[MS_3].set_low();
+ let _ = shift_register.decompose()[MS_4].set_high();
+
+ let one_wire_pin = Flex::new(peripherals.gpio18);
+ let tank_power_pin = Output::new(peripherals.gpio11, Level::Low, OutputConfig::default());
+
+ let flow_sensor_pin = Input::new(
+ peripherals.gpio4,
+ InputConfig::default().with_pull(Pull::Up),
+ );
+
+ let tank_sensor = TankSensor::create(
+ one_wire_pin,
+ peripherals.adc1,
+ peripherals.gpio5,
+ tank_power_pin,
+ flow_sensor_pin,
+ peripherals.pcnt1,
+ )?;
+
+ let solar_is_day = Input::new(peripherals.gpio7, InputConfig::default());
+ let light = Output::new(peripherals.gpio10, Level::Low, OutputConfig::default());
+ let mut main_pump = Output::new(peripherals.gpio2, Level::Low, OutputConfig::default());
+ main_pump.set_low();
+ let mut general_fault = Output::new(peripherals.gpio6, Level::Low, OutputConfig::default());
+ general_fault.set_low();
+
+ let mut shift_register_enable_invert =
+ Output::new(peripherals.gpio21, Level::Low, OutputConfig::default());
+ shift_register_enable_invert.set_low();
+
+ Ok(Box::new(V3 {
+ config,
+ battery_monitor,
+ rtc_module,
+ esp,
+ shift_register: Mutex::new(shift_register),
+ _shift_register_enable_invert: shift_register_enable_invert,
+ tank_sensor,
+ solar_is_day,
+ light,
+ main_pump,
+ general_fault,
+ }))
+}
+
+#[async_trait]
+impl<'a> BoardInteraction<'a> for V3<'a> {
+ fn get_tank_sensor(&mut self) -> Result<&mut TankSensor<'a>, FatError> {
+ Ok(&mut self.tank_sensor)
+ }
+
+ fn get_esp(&mut self) -> &mut Esp<'a> {
+ &mut self.esp
+ }
+
+ fn get_config(&mut self) -> &PlantControllerConfig {
+ &self.config
+ }
+
+ fn get_battery_monitor(&mut self) -> &mut Box {
+ &mut self.battery_monitor
+ }
+
+ fn get_rtc_module(&mut self) -> &mut Box {
+ &mut self.rtc_module
+ }
+ async fn set_charge_indicator(&mut self, charging: bool) -> Result<(), FatError> {
+ let shift_register = self.shift_register.lock().await;
+ if charging {
+ let _ = shift_register.decompose()[CHARGING].set_high();
+ } else {
+ let _ = shift_register.decompose()[CHARGING].set_low();
+ }
+ Ok(())
+ }
+
+ async fn deep_sleep(&mut self, duration_in_ms: u64) -> ! {
+ let _ = self.shift_register.lock().await.decompose()[AWAKE].set_low();
+ let guard = TIME_ACCESS.get().await.lock().await;
+ self.esp.deep_sleep(duration_in_ms, guard)
+ }
+
+ fn is_day(&self) -> bool {
+ self.solar_is_day.is_high()
+ }
+
+ async fn light(&mut self, enable: bool) -> Result<(), FatError> {
+ hold_disable(10);
+ if enable {
+ self.light.set_high();
+ } else {
+ self.light.set_low();
+ }
+ hold_enable(10);
+ Ok(())
+ }
+ async fn pump(&mut self, plant: usize, enable: bool) -> Result<(), FatError> {
+ if enable {
+ self.main_pump.set_high();
+ }
+
+ let index = match plant {
+ 0 => PUMP1_BIT,
+ 1 => PUMP2_BIT,
+ 2 => PUMP3_BIT,
+ 3 => PUMP4_BIT,
+ 4 => PUMP5_BIT,
+ 5 => PUMP6_BIT,
+ 6 => PUMP7_BIT,
+ 7 => PUMP8_BIT,
+ _ => bail!("Invalid pump {plant}"),
+ };
+ let shift_register = self.shift_register.lock().await;
+ if enable {
+ let _ = shift_register.decompose()[index].set_high();
+ } else {
+ let _ = shift_register.decompose()[index].set_low();
+ }
+
+ if !enable {
+ self.main_pump.set_low();
+ }
+ Ok(())
+ }
+
+ async fn pump_current(&mut self, _plant: usize) -> Result {
+ bail!("Not implemented in v3")
+ }
+
+ async fn fault(&mut self, plant: usize, enable: bool) -> Result<(), FatError> {
+ let index = match plant {
+ 0 => FAULT_1,
+ 1 => FAULT_2,
+ 2 => FAULT_3,
+ 3 => FAULT_4,
+ 4 => FAULT_5,
+ 5 => FAULT_6,
+ 6 => FAULT_7,
+ 7 => FAULT_8,
+ _ => panic!("Invalid plant id {}", plant),
+ };
+ let shift_register = self.shift_register.lock().await;
+ if enable {
+ let _ = shift_register.decompose()[index].set_high();
+ } else {
+ let _ = shift_register.decompose()[index].set_low();
+ }
+ Ok(())
+ }
+
+ async fn measure_moisture_hz(&mut self, plant: usize, sensor: Sensor) -> Result {
+ let mut results = [0_f32; REPEAT_MOIST_MEASURE];
+ for repeat in 0..REPEAT_MOIST_MEASURE {
+ //self.signal_counter.counter_pause()?;
+ //self.signal_counter.counter_clear()?;
+ //Disable all
+ {
+ let mut shift_register = self.shift_register.lock().await;
+ shift_register.decompose()[MS_4].set_high()?;
+ }
+
+ let sensor_channel = match sensor {
+ Sensor::A => match plant {
+ 0 => SENSOR_A_1,
+ 1 => SENSOR_A_2,
+ 2 => SENSOR_A_3,
+ 3 => SENSOR_A_4,
+ 4 => SENSOR_A_5,
+ 5 => SENSOR_A_6,
+ 6 => SENSOR_A_7,
+ 7 => SENSOR_A_8,
+ _ => bail!("Invalid plant id {}", plant),
+ },
+ Sensor::B => match plant {
+ 0 => SENSOR_B_1,
+ 1 => SENSOR_B_2,
+ 2 => SENSOR_B_3,
+ 3 => SENSOR_B_4,
+ 4 => SENSOR_B_5,
+ 5 => SENSOR_B_6,
+ 6 => SENSOR_B_7,
+ 7 => SENSOR_B_8,
+ _ => bail!("Invalid plant id {}", plant),
+ },
+ };
+
+ let is_bit_set = |b: u8| -> bool { sensor_channel & (1 << b) != 0 };
+ {
+ let mut shift_register = self.shift_register.lock().await;
+ let pin_0 = &mut shift_register.decompose()[MS_0];
+ let pin_1 = &mut shift_register.decompose()[MS_1];
+ let pin_2 = &mut shift_register.decompose()[MS_2];
+ let pin_3 = &mut shift_register.decompose()[MS_3];
+ if is_bit_set(0) {
+ pin_0.set_high()?;
+ } else {
+ pin_0.set_low()?;
+ }
+ if is_bit_set(1) {
+ pin_1.set_high()?;
+ } else {
+ pin_1.set_low()?;
+ }
+ if is_bit_set(2) {
+ pin_2.set_high()?;
+ } else {
+ pin_2.set_low()?;
+ }
+ if is_bit_set(3) {
+ pin_3.set_high()?;
+ } else {
+ pin_3.set_low()?;
+ }
+
+ shift_register.decompose()[MS_4].set_low()?;
+ shift_register.decompose()[SENSOR_ON].set_high()?;
+ }
+ let measurement = 100; //how long to measure and then extrapolate to hz
+ let factor = 1000f32 / measurement as f32; //scale raw cound by this number to get hz
+
+ //give some time to stabilize
+ Timer::after_millis(10).await;
+ //self.signal_counter.counter_resume()?;
+ Timer::after_millis(measurement).await;
+ //self.signal_counter.counter_pause()?;
+ {
+ let mut shift_register = self.shift_register.lock().await;
+ shift_register.decompose()[MS_4].set_high()?;
+ shift_register.decompose()[SENSOR_ON].set_low()?;
+ }
+ Timer::after_millis(10).await;
+ let unscaled = 1337; //self.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 general_fault(&mut self, enable: bool) {
+ hold_disable(6);
+ if enable {
+ self.general_fault.set_high();
+ } else {
+ self.general_fault.set_low();
+ }
+ hold_enable(6);
+ }
+
+ async fn test(&mut self) -> Result<(), FatError> {
+ self.general_fault(true).await;
+ Timer::after_millis(100).await;
+ self.general_fault(false).await;
+ Timer::after_millis(100).await;
+ self.light(true).await?;
+ Timer::after_millis(500).await;
+
+ self.light(false).await?;
+ Timer::after_millis(500).await;
+ for i in 0..PLANT_COUNT {
+ self.fault(i, true).await?;
+ Timer::after_millis(500).await;
+ self.fault(i, false).await?;
+ Timer::after_millis(500).await;
+ }
+ for i in 0..PLANT_COUNT {
+ self.pump(i, true).await?;
+ Timer::after_millis(100).await;
+ self.pump(i, false).await?;
+ Timer::after_millis(100).await;
+ }
+ for plant in 0..PLANT_COUNT {
+ let a = self.measure_moisture_hz(plant, Sensor::A).await;
+ let b = self.measure_moisture_hz(plant, Sensor::B).await;
+ let aa = match a {
+ Ok(a) => a as u32,
+ Err(_) => u32::MAX,
+ };
+ let bb = match b {
+ Ok(b) => b as u32,
+ Err(_) => u32::MAX,
+ };
+ LOG_ACCESS
+ .lock()
+ .await
+ .log(LogMessage::TestSensor, aa, bb, &plant.to_string(), "")
+ .await;
+ }
+ Timer::after_millis(10).await;
+ Ok(())
+ }
+
+ fn set_config(&mut self, config: PlantControllerConfig) {
+ self.config = config;
+ }
+
+ async fn get_mptt_voltage(&mut self) -> Result {
+ bail!("Not implemented in v3")
+ }
+ async fn get_mptt_current(&mut self) -> Result {
+ bail!("Not implemented in v3")
+ }
+}
diff --git a/rust/src/hal/v4_hal.rs b/rust/src/hal/v4_hal.rs
index 005da27..02533d9 100644
--- a/rust/src/hal/v4_hal.rs
+++ b/rust/src/hal/v4_hal.rs
@@ -1,6 +1,6 @@
use crate::config::PlantControllerConfig;
use crate::hal::battery::BatteryInteraction;
-use crate::hal::esp::Esp;
+use crate::hal::esp::{hold_disable, hold_enable, Esp};
use crate::hal::rtc::RTCModuleInteraction;
use crate::hal::water::TankSensor;
use crate::hal::{BoardInteraction, FreePeripherals, Sensor, I2C_DRIVER, PLANT_COUNT, TIME_ACCESS};
@@ -14,8 +14,9 @@ use esp_hal::analog::adc::{Adc, AdcConfig, Attenuation};
use esp_hal::{twai, Blocking};
//use embedded_hal_bus::i2c::MutexDevice;
use crate::bail;
-use crate::hal::v4_sensor::{SensorImpl, SensorInteraction};
use crate::fat_error::{FatError, FatResult};
+use crate::hal::v4_sensor::{SensorImpl, SensorInteraction};
+use crate::log::{LogMessage, LOG_ACCESS};
use esp_hal::gpio::{Flex, Input, InputConfig, Level, Output, OutputConfig, Pull};
use esp_hal::i2c::master::I2c;
use esp_hal::pcnt::Pcnt;
@@ -28,23 +29,6 @@ use ina219::SyncIna219;
use measurements::Resistance;
use measurements::{Current, Voltage};
use pca9535::{GPIOBank, Pca9535Immediate, StandardExpanderInterface};
-use crate::log::{LogMessage, LOG_ACCESS};
-
-// Minimal esp-idf equivalent for gpio_hold on esp32c6 via ROM functions
-extern "C" {
- fn gpio_pad_hold(gpio_num: u32);
- fn gpio_pad_unhold(gpio_num: u32);
-}
-
-#[inline(always)]
-fn hold_enable(gpio_num: u8) {
- unsafe { gpio_pad_hold(gpio_num as u32) }
-}
-
-#[inline(always)]
-fn hold_disable(gpio_num: u8) {
- unsafe { gpio_pad_unhold(gpio_num as u32) }
-}
const MPPT_CURRENT_SHUNT_OHMS: f64 = 0.05_f64;
const TWAI_BAUDRATE: twai::BaudRate = twai::BaudRate::B125K;
@@ -356,7 +340,7 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
&mut self.rtc_module
}
- fn set_charge_indicator(&mut self, charging: bool) -> Result<(), FatError> {
+ async fn set_charge_indicator(&mut self, charging: bool) -> Result<(), FatError> {
self.charger.set_charge_indicator(charging)
}
@@ -435,11 +419,11 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
}
async fn test(&mut self) -> Result<(), FatError> {
- self.general_fault(true).await;
+ self.general_fault(true).await;
Timer::after_millis(100).await;
- self.general_fault(false).await;
+ self.general_fault(false).await;
Timer::after_millis(500).await;
- self.light(true).await?;
+ self.light(true).await?;
Timer::after_millis(500).await;
self.light(false).await?;
Timer::after_millis(500).await;
@@ -449,25 +433,29 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
self.fault(i, false).await?;
Timer::after_millis(500).await;
}
- for i in 0..PLANT_COUNT {
- self.pump(i, true).await?;
- Timer::after_millis(100).await;
- self.pump(i, false).await?;
- Timer::after_millis(100).await;
- }
- for plant in 0..PLANT_COUNT {
- let a = self.measure_moisture_hz(plant, Sensor::A).await;
- let b = self.measure_moisture_hz(plant, Sensor::B).await;
- let aa = match a {
- Ok(a) => a as u32,
- Err(_) => u32::MAX,
- };
- let bb = match b {
- Ok(b) => b as u32,
- Err(_) => u32::MAX,
- };
- LOG_ACCESS.lock().await.log(LogMessage::TestSensor, aa, bb, &plant.to_string(), "").await;
- }
+ for i in 0..PLANT_COUNT {
+ self.pump(i, true).await?;
+ Timer::after_millis(100).await;
+ self.pump(i, false).await?;
+ Timer::after_millis(100).await;
+ }
+ for plant in 0..PLANT_COUNT {
+ let a = self.measure_moisture_hz(plant, Sensor::A).await;
+ let b = self.measure_moisture_hz(plant, Sensor::B).await;
+ let aa = match a {
+ Ok(a) => a as u32,
+ Err(_) => u32::MAX,
+ };
+ let bb = match b {
+ Ok(b) => b as u32,
+ Err(_) => u32::MAX,
+ };
+ LOG_ACCESS
+ .lock()
+ .await
+ .log(LogMessage::TestSensor, aa, bb, &plant.to_string(), "")
+ .await;
+ }
Timer::after_millis(10).await;
Ok(())
}
diff --git a/rust/src/main.rs b/rust/src/main.rs
index 4c1cc4c..f0492d6 100644
--- a/rust/src/main.rs
+++ b/rust/src/main.rs
@@ -44,7 +44,6 @@ use log::LogMessage;
use option_lock::OptionLock;
use plant_state::PlantState;
use serde::{Deserialize, Serialize};
-use smoltcp::socket::udp::PacketMetadata;
#[no_mangle]
extern "C" fn custom_halt() -> ! {
@@ -248,7 +247,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
try_connect_wifi_sntp_mqtt(&mut board, &mut stack).await
} else {
info!("No wifi configured");
- //the current sensors require this amount to stabilize, in case of wifi this is already handles for sure;
+ //the current sensors require this amount to stabilize, in case of wifi this is already handled due to connect timings;
Timer::after_millis(100).await;
NetworkMode::OFFLINE
};
@@ -411,7 +410,6 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
PlantState::read_hardware_state(7, &mut board).await,
];
-
//publish_plant_states(&timezone_time.clone(), &plantstate).await;
// let pump_required = plantstate
@@ -500,7 +498,6 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
.await
.unwrap_or(BatteryState::Unknown);
-
info!("Battery state is {:?}", battery_state);
let mut light_state = LightState {
enabled: board.board_hal.get_config().night_lamp.enabled,
diff --git a/rust/src/sipo.rs b/rust/src/sipo.rs
index 7784b5b..f051ee2 100644
--- a/rust/src/sipo.rs
+++ b/rust/src/sipo.rs
@@ -7,7 +7,7 @@ use core::mem::{self, MaybeUninit};
use core::result::{Result, Result::Ok};
use embedded_hal::digital::OutputPin;
-trait ShiftRegisterInternal {
+trait ShiftRegisterInternal: Send {
fn update(&self, index: usize, command: bool) -> Result<(), ()>;
}
@@ -47,9 +47,9 @@ macro_rules! ShiftRegisterBuilder {
/// Serial-in parallel-out shift register
pub struct $name
where
- Pin1: OutputPin,
- Pin2: OutputPin,
- Pin3: OutputPin,
+ Pin1: OutputPin + Send,
+ Pin2: OutputPin + Send,
+ Pin3: OutputPin + Send,
{
clock: RefCell,
latch: RefCell,
@@ -59,9 +59,9 @@ macro_rules! ShiftRegisterBuilder {
impl ShiftRegisterInternal for $name
where
- Pin1: OutputPin,
- Pin2: OutputPin,
- Pin3: OutputPin,
+ Pin1: OutputPin + Send,
+ Pin2: OutputPin + Send,
+ Pin3: OutputPin + Send,
{
/// Sets the value of the shift register output at `index` to value `command`
fn update(&self, index: usize, command: bool) -> Result<(), ()> {
@@ -86,9 +86,9 @@ macro_rules! ShiftRegisterBuilder {
impl $name
where
- Pin1: OutputPin,
- Pin2: OutputPin,
- Pin3: OutputPin,
+ Pin1: OutputPin + Send,
+ Pin2: OutputPin + Send,
+ Pin3: OutputPin + Send,
{
/// Creates a new SIPO shift register from clock, latch, and data output pins
pub fn new(clock: Pin1, latch: Pin2, data: Pin3) -> Self {
diff --git a/rust/src/webserver/mod.rs b/rust/src/webserver/mod.rs
index a7cf81c..0baa0de 100644
--- a/rust/src/webserver/mod.rs
+++ b/rust/src/webserver/mod.rs
@@ -1,11 +1,11 @@
//offer ota and config mode
use crate::config::PlantControllerConfig;
+use crate::fat_error::{FatError, FatResult};
use crate::hal::rtc::X25;
use crate::hal::{esp_set_time, esp_time};
use crate::log::LOG_ACCESS;
use crate::tank::determine_tank_state;
-use crate::fat_error::{FatError, FatResult};
use crate::{bail, do_secure_pump, get_version, log::LogMessage, BOARD_ACCESS};
use alloc::borrow::ToOwned;
use alloc::format;
@@ -13,12 +13,12 @@ use alloc::string::{String, ToString};
use alloc::sync::Arc;
use alloc::vec::Vec;
use chrono::DateTime;
+use chrono_tz::Tz;
use core::fmt::{Debug, Display};
use core::net::{IpAddr, Ipv4Addr, SocketAddr};
use core::result::Result::Ok;
use core::str::{from_utf8, FromStr};
use core::sync::atomic::{AtomicBool, Ordering};
-use chrono_tz::Tz;
use edge_http::io::server::{Connection, Handler, Server};
use edge_http::Method;
use edge_nal::TcpBind;
@@ -409,7 +409,7 @@ impl Handler for HttpHandler {
async fn get_timezones(
request: &mut Connection<'_, T, N>,
-) -> FatResult