2 Commits

Author SHA1 Message Date
1ace878488 Refactor extra1 to fertilizer_pump in HAL and main logic
- Renamed `extra1` method and related calls to `fertilizer_pump` for clarity and better domain alignment.
- Updated HAL implementation to control `extra2` GPIO for fertilizer pump operations.
- Added build script trigger to refresh `VERGEN_BUILD_TIMESTAMP` on each build.
2026-05-01 13:11:47 +02:00
a30d59605d Improve CAN bus error handling and logging
- Enhanced error detection with detailed status logging for bus-off, error warning, and passive errors.
- Added line breaks to CAN and RX error logs for better readability.
- Refined CAN transmission logic and error feedback, including buffer overflow handling.
- Simplified firmware timestamp frame creation and ensured successful sending.
2026-05-01 13:11:37 +02:00
6 changed files with 33 additions and 20 deletions

View File

@@ -415,7 +415,7 @@ async fn can_task(
Timer::after_millis(100).await;
}
let mut msg: heapless::String<128> = heapless::String::new();
let _ = write!(&mut msg, "rx err {:?}", err);
let _ = write!(&mut msg, "rx err {:?} \r\n", err);
log(msg);
}
}
@@ -429,14 +429,25 @@ async fn can_task(
}
}
// Check CAN error status register for bus-off condition
if hal::pac::CAN1.errsr().read().boff() {
blink_error_loop(info, warn, 3, 3).await; // Bus-off error
}
while let Ok(mut frame) = CAN_TX_CH.try_receive() {
match can.transmit(&mut frame) {
Ok(..) => {
Ok(_ok) => {
let status = hal::pac::CAN1.errsr().read();
// Check CAN error status register for bus-off condition
if status.boff() || status.ewgf() || status.epvf() {
let mut msg: heapless::String<128> = heapless::String::new();
let _ = write!(&mut msg, "canbus status {} {} {} \r\n", status.boff(), status.ewgf(), status.epvf());
log(msg);
for _ in 0..2 {
warn.set_high();
Timer::after_millis(100).await;
warn.set_low();
Timer::after_millis(100).await;
}
}
}
Err(nb::Error::WouldBlock) => {
for _ in 0..2 {
@@ -446,7 +457,7 @@ async fn can_task(
Timer::after_millis(100).await;
}
let mut msg: heapless::String<128> = heapless::String::new();
let _ = write!(&mut msg, "canbus out buffer full");
let _ = write!(&mut msg, "canbus out buffer full \r\n");
log(msg);
}
Err(nb::Error::Other(err)) => {
@@ -457,7 +468,7 @@ async fn can_task(
Timer::after_millis(100).await;
}
let mut msg: heapless::String<128> = heapless::String::new();
let _ = write!(&mut msg, "tx err {:?}", err);
let _ = write!(&mut msg, "tx err {:?} \r\n", err);
log(msg);
}
}
@@ -516,7 +527,7 @@ async fn worker(
loop {
let mut total_pulses: u32 = 0;
for _ in 0..AVG_WINDOWS {
for _window in 0..AVG_WINDOWS {
// Count rising edges of Q in a 100 ms window
let start = Instant::now();
let mut pulses: u32 = 0;
@@ -586,9 +597,8 @@ async fn worker(
// Send firmware build timestamp after each measurement so the controller
// always has up-to-date build info without requiring an identify request.
if let Some(build_frame) = CanFrame::new(firmware_build_id, &FIRMWARE_BUILD_MINUTES.to_be_bytes()) {
CAN_TX_CH.send(build_frame).await;
}
let firmware = CanFrame::new(firmware_build_id, &FIRMWARE_BUILD_MINUTES.to_be_bytes()).unwrap();
CAN_TX_CH.send(firmware).await;
// Wait for the other slot to measure, plus gaps to ensure no overlap
// After A finishes measuring: wait 50ms (gap) + 400ms (B measures) + 50ms (gap) = 500ms

View File

@@ -49,5 +49,8 @@ fn linker_be_nice() {
fn main() {
linker_be_nice();
// Non-existent path causes Cargo to always re-run this script,
// keeping VERGEN_BUILD_TIMESTAMP fresh on every build.
println!("cargo:rerun-if-changed=ALWAYS_REBUILD_SENTINEL");
let _ = EmitBuilder::builder().all_git().all_build().emit();
}

View File

@@ -164,7 +164,7 @@ pub trait BoardInteraction<'a> {
async fn get_mptt_voltage(&mut self) -> FatResult<Voltage>;
async fn get_mptt_current(&mut self) -> FatResult<Current>;
async fn can_power(&mut self, state: bool) -> FatResult<()>;
async fn extra1(&mut self, enable: bool) -> FatResult<()>;
async fn fertilizer_pump(&mut self, enable: bool) -> FatResult<()>;
async fn backup_config(&mut self, config: &PlantControllerConfig) -> FatResult<()>;
async fn read_backup(&mut self) -> FatResult<PlantControllerConfig>;

View File

@@ -484,11 +484,11 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
Ok(())
}
async fn extra1(&mut self, enable: bool) -> FatResult<()> {
async fn fertilizer_pump(&mut self, enable: bool) -> FatResult<()> {
if enable {
self.extra1.set_high();
self.extra2.set_high();
} else {
self.extra1.set_low();
self.extra2.set_low();
}
Ok(())
}

View File

@@ -733,9 +733,9 @@ pub async fn do_secure_pump(
&elapsed_minutes.to_string(),
"",
);
board.board_hal.extra1(true).await?;
board.board_hal.fertilizer_pump(true).await?;
Timer::after_millis(plant_config.fertilizer_s as u64 * 1000).await;
board.board_hal.extra1(false).await?;
board.board_hal.fertilizer_pump(false).await?;
info!("Fertilizer pump stopped");
// Store the current time as last fertilizer time

View File

@@ -109,9 +109,9 @@ where
T: Read + Write,
{
let mut board = BOARD_ACCESS.get().await.lock().await;
board.board_hal.extra1(true).await?;
board.board_hal.fertilizer_pump(true).await?;
embassy_time::Timer::after_millis(1000).await;
board.board_hal.extra1(false).await?;
board.board_hal.fertilizer_pump(false).await?;
Ok(None)
}