update: refactor and enhance CAN sensor initialization, reorganize GPIO assignments, improve error detection and logging, and streamline TWAI handling
This commit is contained in:
@@ -130,15 +130,14 @@ pub struct V4<'a> {
|
||||
pump_ina: Option<
|
||||
SyncIna219<I2cDevice<'a, CriticalSectionRawMutex, I2c<'static, Blocking>>, UnCalibrated>,
|
||||
>,
|
||||
twai_peripheral: Option<esp_hal::peripherals::TWAI0<'static>>,
|
||||
twai_rx_pin: Option<esp_hal::peripherals::GPIO2<'static>>,
|
||||
twai_tx_pin: Option<esp_hal::peripherals::GPIO0<'static>>,
|
||||
can_power: Output<'static>,
|
||||
|
||||
extra1: Output<'a>,
|
||||
extra2: Output<'a>,
|
||||
can_mutex: embassy_sync::mutex::Mutex<CriticalSectionRawMutex, ()>,
|
||||
}
|
||||
|
||||
|
||||
pub(crate) async fn create_v4(
|
||||
peripherals: FreePeripherals<'static>,
|
||||
esp: Esp<'static>,
|
||||
@@ -257,35 +256,41 @@ pub(crate) async fn create_v4(
|
||||
config,
|
||||
battery_monitor,
|
||||
pump_ina,
|
||||
twai_peripheral,
|
||||
twai_rx_pin,
|
||||
twai_tx_pin,
|
||||
charger,
|
||||
extra1,
|
||||
extra2,
|
||||
can_power,
|
||||
can_mutex: embassy_sync::mutex::Mutex::new(()),
|
||||
};
|
||||
Ok(Box::new(v))
|
||||
}
|
||||
|
||||
impl<'a> V4<'a> {
|
||||
fn teardown_twai(&mut self, old: TwaiConfiguration<Blocking>) {
|
||||
drop(old);
|
||||
// Re-acquire the peripheral and pins
|
||||
let twai = unsafe { peripherals::TWAI0::steal() };
|
||||
let rx_pin = unsafe { peripherals::GPIO2::steal() };
|
||||
let tx_pin = unsafe { peripherals::GPIO0::steal() };
|
||||
fn teardown_twai(old: Twai<Async>) {
|
||||
let config = old.stop();
|
||||
drop(config);
|
||||
// Re-acquire the peripheral and pins
|
||||
let rx_pin = unsafe { peripherals::GPIO2::steal() };
|
||||
let tx_pin = unsafe { peripherals::GPIO0::steal() };
|
||||
|
||||
// Set pins to low to avoid parasitic powering
|
||||
let mut rx = Input::new(rx_pin, InputConfig::default().with_pull(Pull::None));
|
||||
let mut tx = Input::new(tx_pin, InputConfig::default().with_pull(Pull::None));
|
||||
// Set pins to low to avoid parasitic powering
|
||||
let _ = Input::new(rx_pin, InputConfig::default().with_pull(Pull::None));
|
||||
let _ = Input::new(tx_pin, InputConfig::default().with_pull(Pull::None));
|
||||
}
|
||||
|
||||
// Release the pins from Output back to raw pins and store everything
|
||||
self.twai_peripheral = Some(twai);
|
||||
self.twai_rx_pin = Some(unsafe { peripherals::GPIO2::steal() });
|
||||
self.twai_tx_pin = Some(unsafe { peripherals::GPIO0::steal() });
|
||||
self.can_power.set_low();
|
||||
}
|
||||
fn create_twai<'a>() -> Twai<'a, Async> {
|
||||
// Release the pins from Output back to raw pins and store everything
|
||||
let twai = unsafe { peripherals::TWAI0::steal() };
|
||||
let twai_rx_pin = unsafe { peripherals::GPIO2::steal() };
|
||||
let twai_tx_pin = unsafe { peripherals::GPIO0::steal() };
|
||||
|
||||
let twai_config = TwaiConfiguration::new(
|
||||
twai,
|
||||
twai_rx_pin,
|
||||
twai_tx_pin,
|
||||
TWAI_BAUDRATE,
|
||||
TwaiMode::Normal,
|
||||
);
|
||||
twai_config.into_async().start()
|
||||
}
|
||||
|
||||
#[async_trait(?Send)]
|
||||
@@ -379,14 +384,8 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
|
||||
}
|
||||
async fn measure_moisture_hz(&mut self) -> FatResult<Moistures> {
|
||||
self.can_power.set_high();
|
||||
let twai_config = TwaiConfiguration::new(
|
||||
self.twai_peripheral.take().unwrap(),
|
||||
self.twai_rx_pin.take().unwrap(),
|
||||
self.twai_tx_pin.take().unwrap(),
|
||||
TWAI_BAUDRATE,
|
||||
TwaiMode::Normal,
|
||||
);
|
||||
let mut twai = twai_config.into_async().start();
|
||||
let mut twai = create_twai();
|
||||
|
||||
|
||||
loop {
|
||||
let rec = twai.receive();
|
||||
@@ -405,11 +404,64 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
|
||||
let _ = wait_for_can_measurements(&mut twai, &mut moistures)
|
||||
.with_timeout(Duration::from_millis(2000))
|
||||
.await;
|
||||
self.teardown_twai(twai.stop().into_blocking());
|
||||
|
||||
teardown_twai(twai);
|
||||
self.can_power.set_low();
|
||||
Ok(moistures)
|
||||
}
|
||||
|
||||
async fn detect_sensors(&mut self) -> FatResult<DetectionResult> {
|
||||
self.can_power.set_high();
|
||||
let mut twai = create_twai();
|
||||
// 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 = twai
|
||||
.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 twai, &mut moistures)
|
||||
.with_timeout(Duration::from_millis(1000))
|
||||
.await;
|
||||
|
||||
|
||||
teardown_twai(twai);
|
||||
self.can_power.set_low();
|
||||
|
||||
|
||||
let result = moistures.into();
|
||||
|
||||
info!("Autodetection result: {result:?}");
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
|
||||
async fn general_fault(&mut self, enable: bool) {
|
||||
hold_disable(23);
|
||||
self.general_fault.set_level(enable.into());
|
||||
@@ -470,69 +522,9 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
|
||||
async fn get_mptt_current(&mut self) -> FatResult<Current> {
|
||||
self.charger.get_mppt_current()
|
||||
}
|
||||
|
||||
async fn detect_sensors(&mut self) -> FatResult<DetectionResult> {
|
||||
// Power on CAN transceiver and start controller
|
||||
self.can_power.set_high();
|
||||
let twai_config = TwaiConfiguration::new(
|
||||
self.twai_peripheral.take().unwrap(),
|
||||
self.twai_rx_pin.take().unwrap(),
|
||||
self.twai_tx_pin.take().unwrap(),
|
||||
TWAI_BAUDRATE,
|
||||
TwaiMode::Normal,
|
||||
);
|
||||
|
||||
|
||||
info!("convert can");
|
||||
let mut as_async = twai_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.teardown_twai(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,
|
||||
|
||||
Reference in New Issue
Block a user