diff --git a/openemc-firmware/src/bq25713.rs b/openemc-firmware/src/bq25713.rs index 965d5ce..c55a8cc 100644 --- a/openemc-firmware/src/bq25713.rs +++ b/openemc-firmware/src/bq25713.rs @@ -186,23 +186,30 @@ pub struct Battery { } impl Battery { - /// Whether the battery status changed significantly. - pub fn changed_significantly(&self, other: &Battery) -> bool { - const DIFF: u32 = 75; - + fn changed_significantly_with_diff(&self, other: &Battery, diff: u32) -> bool { self.present != other.present - || self.voltage_mv.unwrap_or(u32::MAX).abs_diff(other.voltage_mv.unwrap_or(u32::MAX)) >= DIFF - || self.current_ma.unwrap_or(i32::MAX).abs_diff(other.current_ma.unwrap_or(i32::MAX)) >= DIFF + || self.voltage_mv.unwrap_or(u32::MAX).abs_diff(other.voltage_mv.unwrap_or(u32::MAX)) >= diff + || self.current_ma.unwrap_or(i32::MAX).abs_diff(other.current_ma.unwrap_or(i32::MAX)) >= diff || self.system_voltage_mv.unwrap_or(u32::MAX).abs_diff(other.system_voltage_mv.unwrap_or(u32::MAX)) - >= DIFF + >= diff || self.input_voltage_mv.unwrap_or(u32::MAX).abs_diff(other.input_voltage_mv.unwrap_or(u32::MAX)) - >= DIFF + >= diff || self.input_current_ma.unwrap_or(u32::MAX).abs_diff(other.input_current_ma.unwrap_or(u32::MAX)) - >= DIFF + >= diff || self.max_voltage_mv != other.max_voltage_mv || self.max_charge_current_ma != other.max_charge_current_ma || self.charging != other.charging } + + /// Whether the battery status changed significantly. + pub fn changed_significantly(&self, other: &Battery) -> bool { + self.changed_significantly_with_diff(other, 75) + } + + /// Whether the battery status changed significantly for logging. + pub fn changed_significantly_for_logging(&self, other: &Battery) -> bool { + self.changed_significantly_with_diff(other, 250) + } } /// Battery charging status. diff --git a/openemc-firmware/src/main.rs b/openemc-firmware/src/main.rs index 9e92643..e2db65c 100644 --- a/openemc-firmware/src/main.rs +++ b/openemc-firmware/src/main.rs @@ -613,6 +613,9 @@ mod app { } blink_charging!(board, delay, watchman, 10); + // Log battery status. + defmt::unwrap!(battery_status_report::spawn_after(1u64.secs())); + // Power on board. watchman.force_pet(); defmt::info!("board power on in mode {:?}", board.power_mode()); @@ -1059,7 +1062,7 @@ mod app { _ => true, }; if changed { - defmt::info!("Battery report: {:?}", &report); + defmt::debug!("Battery report: {:?}", &report); *battery = report; irq.pend_soft(IrqState::SUPPLY | IrqState::BATTERY); } @@ -1070,6 +1073,33 @@ mod app { defmt::unwrap!(bq25713_periodic::spawn_after(1u64.secs())); } + /// Logs the battery status. + #[task(shared = [battery], local = [last: Option = None, last_log: Option = None])] + fn battery_status_report(mut cx: battery_status_report::Context) { + const REPORT_PERIOD: Duration = Duration::minutes(10); + + cx.shared.battery.lock(|battery| { + let changed = match (&battery, &cx.local.last) { + (Some(battery), Some(last)) => battery.changed_significantly_for_logging(last), + (None, None) => false, + _ => true, + }; + + let last_log = cx.local.last_log.get_or_insert_with(monotonics::now); + let since_last_log = monotonics::now() - *last_log; + + if changed || since_last_log >= REPORT_PERIOD { + if let Some(battery) = &battery { + defmt::info!("Battery status: {:?}", battery); + *last_log = monotonics::now(); + } + *cx.local.last = battery.clone(); + } + }); + + defmt::unwrap!(battery_status_report::spawn_after(10u64.secs())); + } + /// Performs power off when battery has reached lower voltage limit. #[task( shared = [board, undervoltage_power_off],