remove HAL implementation files for v3 and v4, and the build script
This commit is contained in:
@@ -1,32 +1,33 @@
|
||||
use crate::bail;
|
||||
use crate::config::PlantControllerConfig;
|
||||
use crate::fat_error::{FatError, FatResult};
|
||||
use crate::fat_error::{ContextExt, FatError, FatResult};
|
||||
use crate::hal::battery::BatteryInteraction;
|
||||
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,
|
||||
BoardInteraction, DetectionResult, FreePeripherals, Moistures, Sensor, I2C_DRIVER, PLANT_COUNT,
|
||||
TIME_ACCESS,
|
||||
};
|
||||
use crate::log::{LogMessage, LOG_ACCESS};
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::ToString;
|
||||
use async_trait::async_trait;
|
||||
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::Timer;
|
||||
use embassy_time::{Duration, Timer, WithTimeout};
|
||||
use embedded_can::{Frame, Id};
|
||||
use esp_hal::gpio::{Flex, Input, InputConfig, Level, Output, OutputConfig, Pull};
|
||||
use esp_hal::i2c::master::I2c;
|
||||
use esp_hal::pcnt::channel::CtrlMode::Keep;
|
||||
use esp_hal::pcnt::channel::EdgeMode::{Hold, Increment};
|
||||
use esp_hal::twai::TwaiMode;
|
||||
use esp_hal::{twai, Blocking};
|
||||
use esp_hal::twai::{EspTwaiError, EspTwaiFrame, StandardId, Twai, TwaiConfiguration, TwaiMode};
|
||||
use esp_hal::{twai, Async, Blocking};
|
||||
use ina219::address::{Address, Pin};
|
||||
use ina219::calibration::UnCalibrated;
|
||||
use ina219::configuration::{Configuration, OperatingMode, Resolution};
|
||||
use ina219::SyncIna219;
|
||||
use log::{error, info, warn};
|
||||
use measurements::Resistance;
|
||||
use measurements::{Current, Voltage};
|
||||
use pca9535::{GPIOBank, Pca9535Immediate, StandardExpanderInterface};
|
||||
@@ -88,7 +89,7 @@ impl Charger<'_> {
|
||||
operating_mode: OperatingMode::PowerDown,
|
||||
})
|
||||
.map_err(|e| {
|
||||
log::info!(
|
||||
info!(
|
||||
"Error setting ina mppt configuration during deep sleep preparation{e:?}"
|
||||
);
|
||||
});
|
||||
@@ -127,7 +128,8 @@ pub struct V4<'a> {
|
||||
pump_ina: Option<
|
||||
SyncIna219<I2cDevice<'a, CriticalSectionRawMutex, I2c<'static, Blocking>>, UnCalibrated>,
|
||||
>,
|
||||
sensor: SensorImpl,
|
||||
twai_config: Option<TwaiConfiguration<'static, Blocking>>,
|
||||
can_power: Output<'static>,
|
||||
extra1: Output<'a>,
|
||||
extra2: Output<'a>,
|
||||
}
|
||||
@@ -139,7 +141,7 @@ pub(crate) async fn create_v4(
|
||||
battery_monitor: Box<dyn BatteryInteraction + Send>,
|
||||
rtc_module: Box<dyn RTCModuleInteraction + Send>,
|
||||
) -> Result<Box<dyn BoardInteraction<'static> + Send + 'static>, FatError> {
|
||||
log::info!("Start v4");
|
||||
info!("Start v4");
|
||||
let mut awake = Output::new(peripherals.gpio21, Level::High, OutputConfig::default());
|
||||
awake.set_high();
|
||||
|
||||
@@ -165,53 +167,14 @@ pub(crate) async fn create_v4(
|
||||
peripherals.pcnt1,
|
||||
)?;
|
||||
|
||||
let sensor_expander_device = I2cDevice::new(I2C_DRIVER.get().await);
|
||||
let mut sensor_expander = Pca9535Immediate::new(sensor_expander_device, 34);
|
||||
let sensor = match sensor_expander.pin_into_output(GPIOBank::Bank0, 0) {
|
||||
Ok(_) => {
|
||||
log::info!("SensorExpander answered");
|
||||
|
||||
let signal_counter = peripherals.pcnt0;
|
||||
|
||||
signal_counter.set_high_limit(Some(i16::MAX))?;
|
||||
|
||||
let ch0 = &signal_counter.channel0;
|
||||
let edge_pin = Input::new(peripherals.gpio22, InputConfig::default());
|
||||
ch0.set_edge_signal(edge_pin.peripheral_input());
|
||||
ch0.set_input_mode(Hold, Increment);
|
||||
ch0.set_ctrl_mode(Keep, Keep);
|
||||
signal_counter.listen();
|
||||
|
||||
for pin in 0..8 {
|
||||
let _ = sensor_expander.pin_into_output(GPIOBank::Bank0, pin);
|
||||
let _ = sensor_expander.pin_into_output(GPIOBank::Bank1, pin);
|
||||
let _ = sensor_expander.pin_set_low(GPIOBank::Bank0, pin);
|
||||
let _ = sensor_expander.pin_set_low(GPIOBank::Bank1, pin);
|
||||
}
|
||||
|
||||
SensorImpl::PulseCounter {
|
||||
signal_counter,
|
||||
sensor_expander,
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
log::info!("Can bus mode ");
|
||||
let twai_config = Some(twai::TwaiConfiguration::new(
|
||||
peripherals.twai,
|
||||
peripherals.gpio2,
|
||||
peripherals.gpio0,
|
||||
TWAI_BAUDRATE,
|
||||
TwaiMode::Normal,
|
||||
));
|
||||
let can_power = Output::new(peripherals.gpio22, Level::Low, OutputConfig::default());
|
||||
|
||||
//can bus version
|
||||
SensorImpl::CanBus {
|
||||
twai_config,
|
||||
can_power,
|
||||
}
|
||||
}
|
||||
};
|
||||
let twai_config = Some(TwaiConfiguration::new(
|
||||
peripherals.twai,
|
||||
peripherals.gpio2,
|
||||
peripherals.gpio0,
|
||||
TWAI_BAUDRATE,
|
||||
TwaiMode::Normal,
|
||||
));
|
||||
let can_power = Output::new(peripherals.gpio22, Level::Low, OutputConfig::default());
|
||||
|
||||
let solar_is_day = Input::new(peripherals.gpio7, InputConfig::default());
|
||||
let light = Output::new(peripherals.gpio10, Level::Low, Default::default());
|
||||
@@ -241,7 +204,7 @@ pub(crate) async fn create_v4(
|
||||
Some(ina)
|
||||
}
|
||||
Err(err) => {
|
||||
log::info!("Error creating mppt ina: {err:?}");
|
||||
info!("Error creating mppt ina: {err:?}");
|
||||
None
|
||||
}
|
||||
};
|
||||
@@ -250,7 +213,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:?}");
|
||||
info!("Error creating pump ina: {err:?}");
|
||||
None
|
||||
}
|
||||
};
|
||||
@@ -262,7 +225,7 @@ pub(crate) async fn create_v4(
|
||||
bus_voltage_range: Default::default(),
|
||||
shunt_voltage_range: Default::default(),
|
||||
bus_resolution: Default::default(),
|
||||
shunt_resolution: ina219::configuration::Resolution::Avg128,
|
||||
shunt_resolution: Resolution::Avg128,
|
||||
operating_mode: Default::default(),
|
||||
})?;
|
||||
|
||||
@@ -275,6 +238,7 @@ pub(crate) async fn create_v4(
|
||||
None => Charger::ErrorInit {},
|
||||
};
|
||||
|
||||
info!("Assembling final v4 board interaction object");
|
||||
let v = V4 {
|
||||
rtc_module,
|
||||
esp,
|
||||
@@ -286,10 +250,11 @@ pub(crate) async fn create_v4(
|
||||
config,
|
||||
battery_monitor,
|
||||
pump_ina,
|
||||
twai_config,
|
||||
charger,
|
||||
extra1,
|
||||
extra2,
|
||||
sensor,
|
||||
can_power,
|
||||
};
|
||||
Ok(Box::new(v))
|
||||
}
|
||||
@@ -383,9 +348,35 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
async fn measure_moisture_hz(&mut self) -> FatResult<Moistures> {
|
||||
self.can_power.set_high();
|
||||
let config = self.twai_config.take().expect("twai config not set");
|
||||
let mut twai = config.into_async().start();
|
||||
|
||||
async fn measure_moisture_hz(&mut self) -> Result<Moistures, FatError> {
|
||||
self.sensor.measure_moisture_hz().await
|
||||
loop {
|
||||
let rec = twai.receive();
|
||||
match rec {
|
||||
Ok(_) => {}
|
||||
Err(err) => {
|
||||
info!("Error receiving CAN message: {err:?}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer::after_millis(10).await;
|
||||
|
||||
let mut moistures = Moistures::default();
|
||||
let _ = wait_for_can_measurements(&mut twai, &mut moistures)
|
||||
.with_timeout(Duration::from_millis(2000))
|
||||
.await;
|
||||
|
||||
self.can_power.set_low();
|
||||
|
||||
let config = twai.stop().into_blocking();
|
||||
self.twai_config.replace(config);
|
||||
|
||||
Ok(moistures)
|
||||
}
|
||||
|
||||
async fn general_fault(&mut self, enable: bool) {
|
||||
@@ -450,6 +441,123 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
|
||||
}
|
||||
|
||||
async fn detect_sensors(&mut self) -> FatResult<DetectionResult> {
|
||||
self.sensor.autodetect().await
|
||||
// Power on CAN transceiver and start controller
|
||||
self.can_power.set_high();
|
||||
let config = self.twai_config.take().expect("twai config not set");
|
||||
info!("convert can");
|
||||
let mut as_async = config.into_async().start();
|
||||
// Give CAN some time to stabilize
|
||||
Timer::after_millis(10).await;
|
||||
|
||||
info!("Sending info messages now");
|
||||
// Send a few test messages per potential sensor node
|
||||
for plant in 0..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 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)
|
||||
.with_timeout(Duration::from_millis(1000))
|
||||
.await;
|
||||
match resu {
|
||||
Ok(_) => {
|
||||
info!("Sent test message to plant {plant} sensor {sensor:?}");
|
||||
}
|
||||
Err(err) => {
|
||||
info!(
|
||||
"Error sending test message to plant {plant} sensor {sensor:?}: {err:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
info!("Error building CAN frame");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut moistures = Moistures::default();
|
||||
let _ = wait_for_can_measurements(&mut as_async, &mut moistures)
|
||||
.with_timeout(Duration::from_millis(1000))
|
||||
.await;
|
||||
|
||||
let config = as_async.stop().into_blocking();
|
||||
self.can_power.set_low();
|
||||
self.twai_config.replace(config);
|
||||
|
||||
let result = moistures.into();
|
||||
|
||||
info!("Autodetection result: {result:?}");
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
async fn wait_for_can_measurements(
|
||||
as_async: &mut Twai<'_, Async>,
|
||||
moistures: &mut Moistures,
|
||||
) -> FatResult<()> {
|
||||
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;
|
||||
let data = can_frame.data();
|
||||
if data.len() == 2 {
|
||||
let frequency = u16::from_be_bytes([data[0], data[1]]);
|
||||
match sensor {
|
||||
SensorSlot::A => {
|
||||
moistures.sensor_a_hz[plant] = frequency as f32;
|
||||
}
|
||||
SensorSlot::B => {
|
||||
moistures.sensor_b_hz[plant] = frequency as f32;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Id::Extended(ext) => {
|
||||
warn!("Received extended ID: {ext:?}");
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
match err {
|
||||
EspTwaiError::BusOff => {
|
||||
bail!("Bus offline")
|
||||
}
|
||||
EspTwaiError::NonCompliantDlc(_) => {}
|
||||
EspTwaiError::EmbeddedHAL(_) => {}
|
||||
}
|
||||
error!("Error receiving CAN message: {err:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Moistures> for DetectionResult {
|
||||
fn from(value: Moistures) -> Self {
|
||||
let mut result = DetectionResult::default();
|
||||
for (plant, sensor) in value.sensor_a_hz.iter().enumerate() {
|
||||
result.plant[plant].sensor_a = *sensor > 1.0_f32;
|
||||
}
|
||||
for (plant, sensor) in value.sensor_b_hz.iter().enumerate() {
|
||||
result.plant[plant].sensor_b = *sensor > 1.0_f32;
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user