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?
old-commit-hash: 905f6b1b77
commatwo_master
robbederks 5 years ago committed by GitHub
parent a3568be0b0
commit 4b7588e9ab
  1. 34
      selfdrive/thermald/power_monitoring.py
  2. 2
      selfdrive/thermald/thermald.py

@ -58,11 +58,12 @@ def panda_current_to_actual_current(panda_current):
class PowerMonitoring: class PowerMonitoring:
def __init__(self): def __init__(self, is_uno):
self.last_measurement_time = None # Used for integration delta self.last_measurement_time = None # Used for integration delta
self.power_used_uWh = 0 # Integrated power usage in uWh since going into offroad self.power_used_uWh = 0 # Integrated power usage in uWh since going into offroad
self.next_pulsed_measurement_time = None self.next_pulsed_measurement_time = None
self.integration_lock = threading.Lock() self.integration_lock = threading.Lock()
self.is_uno = is_uno
# Calculation tick # Calculation tick
def calculate(self, health): def calculate(self, health):
@ -76,14 +77,17 @@ class PowerMonitoring:
# Only integrate when there is no ignition # 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, we're probably not in a car, so we don't care
if health is None or (health.health.ignitionLine or health.health.ignitionCan): if health is None or (health.health.ignitionLine or health.health.ignitionCan):
self.last_measurement_time = None with self.integration_lock:
self.power_used_uWh = 0 self.last_measurement_time = None
self.next_pulsed_measurement_time = None
self.power_used_uWh = 0
return return
# First measurement, set integration time # First measurement, set integration time
if self.last_measurement_time is None: with self.integration_lock:
self.last_measurement_time = now if self.last_measurement_time is None:
return self.last_measurement_time = now
return
# Get current power draw somehow # Get current power draw somehow
current_power = 0 current_power = 0
@ -114,6 +118,7 @@ class PowerMonitoring:
currents.append(get_battery_current()) currents.append(get_battery_current())
time.sleep(1) time.sleep(1)
current_power = ((mean(voltages) / 1000000) * (mean(currents) / 1000000)) current_power = ((mean(voltages) / 1000000) * (mean(currents) / 1000000))
self._perform_integration(now, current_power * FUDGE_FACTOR) self._perform_integration(now, current_power * FUDGE_FACTOR)
# Enable charging again # Enable charging again
@ -126,7 +131,7 @@ class PowerMonitoring:
self.next_pulsed_measurement_time = None self.next_pulsed_measurement_time = None
return 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 # 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 # 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 # We shouldn't do this very often, so make sure it has been some long-ish random time interval
@ -139,14 +144,17 @@ class PowerMonitoring:
# Do the integration # Do the integration
self._perform_integration(now, current_power) self._perform_integration(now, current_power)
except Exception: except Exception:
cloudlog.exception("Power monitoring calculation failed:") cloudlog.exception("Power monitoring calculation failed")
def _perform_integration(self, t, current_power): def _perform_integration(self, t, current_power):
self.integration_lock.acquire() with self.integration_lock:
integration_time_h = (t - self.last_measurement_time) / 3600 try:
self.power_used_uWh += (current_power * 1000000) * integration_time_h if self.last_measurement_time:
self.last_measurement_time = t integration_time_h = (t - self.last_measurement_time) / 3600
self.integration_lock.release() 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 # Get the power usage
def get_power_used(self): def get_power_used(self):

@ -187,7 +187,7 @@ def thermald_thread():
handle_fan = handle_fan_eon handle_fan = handle_fan_eon
params = Params() params = Params()
pm = PowerMonitoring() pm = PowerMonitoring(is_uno)
while 1: while 1:
health = messaging.recv_sock(health_sock, wait=True) health = messaging.recv_sock(health_sock, wait=True)

Loading…
Cancel
Save