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?
robbederks 2020-03-23 18:02:53 -07:00 committed by Willem Melching
parent a5c3340c8d
commit cc6358d983
2 changed files with 22 additions and 14 deletions

View File

@ -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 @@ class PowerMonitoring:
# 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 @@ class PowerMonitoring:
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 @@ class PowerMonitoring:
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 @@ class PowerMonitoring:
# 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):

View File

@ -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)