Compare commits
3 Commits
e0b8acd55c
...
542ff578bc
| Author | SHA1 | Date | |
|---|---|---|---|
| 542ff578bc | |||
| 2e16163b0e | |||
| 9280bbb244 |
@@ -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.
|
||||
@@ -428,6 +429,11 @@ 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(..) => {
|
||||
@@ -469,6 +475,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 +485,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 +589,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ pub trait BoardInteraction<'a> {
|
||||
async fn get_time(&mut self) -> DateTime<Utc>;
|
||||
async fn set_time(&mut self, time: &DateTime<FixedOffset>) -> FatResult<()>;
|
||||
async fn set_charge_indicator(&mut self, charging: bool) -> Result<(), FatError>;
|
||||
async fn deep_sleep(&mut self, duration_in_ms: u64) -> !;
|
||||
async fn deep_sleep_ms(&mut self, duration_in_ms: u64) -> !;
|
||||
|
||||
fn is_day(&self) -> bool;
|
||||
//should be multsampled
|
||||
|
||||
@@ -320,7 +320,7 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
|
||||
self.charger.set_charge_indicator(charging)
|
||||
}
|
||||
|
||||
async fn deep_sleep(&mut self, duration_in_ms: u64) -> ! {
|
||||
async fn deep_sleep_ms(&mut self, duration_in_ms: u64) -> ! {
|
||||
self.awake.set_low();
|
||||
self.charger.power_save();
|
||||
self.esp.deep_sleep(duration_in_ms);
|
||||
|
||||
@@ -692,7 +692,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
||||
board.board_hal.get_esp().set_restart_to_conf(false);
|
||||
board
|
||||
.board_hal
|
||||
.deep_sleep(1000 * 1000 * 60 * deep_sleep_duration_minutes as u64)
|
||||
.deep_sleep_ms(1000 * 60 * deep_sleep_duration_minutes as u64)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
@@ -1122,7 +1122,7 @@ async fn wait_infinity(
|
||||
board.board_hal.get_esp().set_restart_to_conf(false);
|
||||
// ensure clean http answer / visible confirmation
|
||||
Timer::after_millis(500).await;
|
||||
board.board_hal.deep_sleep(0).await;
|
||||
board.board_hal.deep_sleep_ms(0).await;
|
||||
}
|
||||
|
||||
// Short tick while holding so the pattern updates smoothly.
|
||||
@@ -1231,7 +1231,7 @@ async fn wait_infinity(
|
||||
.lock()
|
||||
.await
|
||||
.board_hal
|
||||
.deep_sleep(0)
|
||||
.deep_sleep_ms(0)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user