From cc6358d983479e918d8deac95554c39ed5866e1a Mon Sep 17 00:00:00 2001 From: robbederks Date: Mon, 23 Mar 2020 18:02:53 -0700 Subject: [PATCH] Power monitoring fix (#1269) * Release lock after exceptions * No pulsed measurement on uno * Fix last_measurement_time=None while integrating when going offroad * Also clear next pulsed measurement time * Move around locks * Locks are good now? --- selfdrive/thermald/power_monitoring.py | 34 ++++++++++++++++---------- selfdrive/thermald/thermald.py | 2 +- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/selfdrive/thermald/power_monitoring.py b/selfdrive/thermald/power_monitoring.py index e03ef69855d705..376ec0704d1123 100644 --- a/selfdrive/thermald/power_monitoring.py +++ b/selfdrive/thermald/power_monitoring.py @@ -58,11 +58,12 @@ def panda_current_to_actual_current(panda_current): class PowerMonitoring: - def __init__(self): + def __init__(self, is_uno): self.last_measurement_time = None # Used for integration delta self.power_used_uWh = 0 # Integrated power usage in uWh since going into offroad self.next_pulsed_measurement_time = None self.integration_lock = threading.Lock() + self.is_uno = is_uno # Calculation tick def calculate(self, health): @@ -76,14 +77,17 @@ def calculate(self, health): # Only integrate when there is no ignition # If health is None, we're probably not in a car, so we don't care if health is None or (health.health.ignitionLine or health.health.ignitionCan): - self.last_measurement_time = None - self.power_used_uWh = 0 + with self.integration_lock: + self.last_measurement_time = None + self.next_pulsed_measurement_time = None + self.power_used_uWh = 0 return # First measurement, set integration time - if self.last_measurement_time is None: - self.last_measurement_time = now - return + with self.integration_lock: + if self.last_measurement_time is None: + self.last_measurement_time = now + return # Get current power draw somehow current_power = 0 @@ -114,6 +118,7 @@ def perform_pulse_measurement(now): currents.append(get_battery_current()) time.sleep(1) current_power = ((mean(voltages) / 1000000) * (mean(currents) / 1000000)) + self._perform_integration(now, current_power * FUDGE_FACTOR) # Enable charging again @@ -126,7 +131,7 @@ def perform_pulse_measurement(now): self.next_pulsed_measurement_time = None return - elif self.next_pulsed_measurement_time is None: + elif self.next_pulsed_measurement_time is None and not self.is_uno: # On a charging EON with black panda, or drawing more than 400mA out of a white/grey one # Only way to get the power draw is to turn off charging for a few sec and check what the discharging rate is # We shouldn't do this very often, so make sure it has been some long-ish random time interval @@ -139,14 +144,17 @@ def perform_pulse_measurement(now): # Do the integration self._perform_integration(now, current_power) except Exception: - cloudlog.exception("Power monitoring calculation failed:") + cloudlog.exception("Power monitoring calculation failed") def _perform_integration(self, t, current_power): - self.integration_lock.acquire() - integration_time_h = (t - self.last_measurement_time) / 3600 - self.power_used_uWh += (current_power * 1000000) * integration_time_h - self.last_measurement_time = t - self.integration_lock.release() + with self.integration_lock: + try: + if self.last_measurement_time: + integration_time_h = (t - self.last_measurement_time) / 3600 + self.power_used_uWh += (current_power * 1000000) * integration_time_h + self.last_measurement_time = t + except Exception: + cloudlog.exception("Integration failed") # Get the power usage def get_power_used(self): diff --git a/selfdrive/thermald/thermald.py b/selfdrive/thermald/thermald.py index 8870ffcc0965b5..f273a40b78bdc1 100755 --- a/selfdrive/thermald/thermald.py +++ b/selfdrive/thermald/thermald.py @@ -187,7 +187,7 @@ def thermald_thread(): handle_fan = handle_fan_eon params = Params() - pm = PowerMonitoring() + pm = PowerMonitoring(is_uno) while 1: health = messaging.recv_sock(health_sock, wait=True)