Improve CAN bus robustness: adjust NART, add transmission delays for error recovery.

This commit is contained in:
Kai Börnert
2026-05-04 17:44:54 +02:00
parent 0ed9d6bb57
commit ef0ec47d92

View File

@@ -256,12 +256,12 @@ async fn main(spawner: Spawner) {
// Improve CAN robustness for longer cables: // Improve CAN robustness for longer cables:
// 1. Enable Automatic Bus-Off Management (ABOM) // 1. Enable Automatic Bus-Off Management (ABOM)
// 2. Disable Automatic Retransmission (NART) as we send regular measurements anyway // 2. Enable Automatic Retransmission (NART) to recover from transient errors
// 3. Enable Receive FIFO Overwrite Mode (RFLM = 0, default) // 3. Enable Receive FIFO Overwrite Mode (RFLM = 0, default)
// 4. Increase Resync Jump Width (SJW) if possible by patching BTIMR // 4. Increase Resync Jump Width (SJW) if possible by patching BTIMR
hal::pac::CAN1.ctlr().modify(|w| { hal::pac::CAN1.ctlr().modify(|w| {
w.set_abom(false); w.set_abom(false);
w.set_nart(true); w.set_nart(false);
}); });
// SJW is bits 24-25 of BTIMR. HAL sets it to 0 (SJW=1). // SJW is bits 24-25 of BTIMR. HAL sets it to 0 (SJW=1).
@@ -593,11 +593,15 @@ async fn worker(
log(msg); log(msg);
let moisture = CanFrame::new(moisture_id, &(freq_hz as u32).to_be_bytes()).unwrap(); let moisture = CanFrame::new(moisture_id, &(freq_hz as u32).to_be_bytes()).unwrap();
let delay_ms = moisture_id.as_raw() as u64 % 50;
Timer::after(Duration::from_millis(delay_ms)).await;
CAN_TX_CH.send(moisture).await; CAN_TX_CH.send(moisture).await;
// Send firmware build timestamp after each measurement so the controller // Send firmware build timestamp after each measurement so the controller
// always has up-to-date build info without requiring an identify request. // always has up-to-date build info without requiring an identify request.
let firmware = CanFrame::new(firmware_build_id, &FIRMWARE_BUILD_MINUTES.to_be_bytes()).unwrap(); let firmware = CanFrame::new(firmware_build_id, &FIRMWARE_BUILD_MINUTES.to_be_bytes()).unwrap();
let delay_ms = firmware_build_id.as_raw() as u64 % 50;
Timer::after(Duration::from_millis(delay_ms)).await;
CAN_TX_CH.send(firmware).await; CAN_TX_CH.send(firmware).await;
// Wait for the other slot to measure, plus gaps to ensure no overlap // Wait for the other slot to measure, plus gaps to ensure no overlap