feat: implement interleaved sensor measurement timing with slot-based coordination to prevent overlap
This commit is contained in:
@@ -289,6 +289,7 @@ async fn main(spawner: Spawner) {
|
||||
standard_moisture_id,
|
||||
standard_identify_id,
|
||||
standard_firmware_build_id,
|
||||
slot,
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
@@ -369,7 +370,7 @@ async fn can_task(
|
||||
warn: &'static mut Output<'static>,
|
||||
identify_id: StandardId,
|
||||
moisture_id: StandardId,
|
||||
firmware_build_id: StandardId,
|
||||
_firmware_build_id: StandardId,
|
||||
) {
|
||||
// Non-blocking beacon blink timing.
|
||||
// We keep this inside the CAN task so it can't stall other tasks (like `worker`) with `await`s.
|
||||
@@ -469,6 +470,7 @@ async fn worker(
|
||||
moisture_id: StandardId,
|
||||
identify_id: StandardId,
|
||||
firmware_build_id: StandardId,
|
||||
slot: SensorSlot,
|
||||
) {
|
||||
// 555 emulation state: Q initially Low
|
||||
let mut q_high = false;
|
||||
@@ -478,6 +480,33 @@ async fn worker(
|
||||
const AVG_WINDOWS: u32 = 4;
|
||||
const YIELD_EVERY: u32 = 64;
|
||||
let probe_duration = Duration::from_millis(100);
|
||||
let measurement_time = probe_duration.as_millis() * AVG_WINDOWS as u64; // 400ms
|
||||
let interleaving_gap = Duration::from_millis(50);
|
||||
|
||||
// Interleaving timing to ensure A and B never overlap:
|
||||
// - Sensor A: measures for 400ms
|
||||
// - Gap: 50ms
|
||||
// - Sensor B: measures for 400ms
|
||||
// - Gap: 50ms
|
||||
// Total cycle: 900ms, so each sensor measures every 900ms (~1.1 measurements/second)
|
||||
//
|
||||
// Timeline:
|
||||
// 0-400ms: A measures, B idle
|
||||
// 400-450ms: both idle (gap)
|
||||
// 450-850ms: B measures, A idle
|
||||
// 850-900ms: both idle (gap)
|
||||
// Then repeat from 0ms
|
||||
|
||||
// Initial offset: B waits for A's measurement time + one gap
|
||||
match slot {
|
||||
SensorSlot::A => {
|
||||
// A sensors start measuring immediately
|
||||
}
|
||||
SensorSlot::B => {
|
||||
// B sensors wait for A to finish measuring + gap
|
||||
Timer::after(Duration::from_millis(measurement_time + interleaving_gap.as_millis())).await;
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
let mut total_pulses: u32 = 0;
|
||||
@@ -555,6 +584,12 @@ async fn worker(
|
||||
if let Some(build_frame) = CanFrame::new(firmware_build_id, &FIRMWARE_BUILD_MINUTES.to_be_bytes()) {
|
||||
CAN_TX_CH.send(build_frame).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
|
||||
// After B finishes measuring: wait 50ms (gap) + 400ms (A measures) + 50ms (gap) = 500ms
|
||||
// This ensures the full 900ms cycle is maintained and A/B never overlap
|
||||
Timer::after(Duration::from_millis(interleaving_gap.as_millis() + measurement_time + interleaving_gap.as_millis())).await;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user