From 16c40a5f7ce554f663eb90b0e81bb0a3eb2e696e Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Thu, 21 Apr 2022 23:13:20 -0700 Subject: [PATCH] CI: power draw test (#24292) * CI: power draw test * initialize hardware * try this * fix that * happy linter * actually happy Co-authored-by: Comma Device old-commit-hash: 37dbc7be0c70adff2f002c1c77c277f7addddd81 --- Jenkinsfile | 1 + selfdrive/hardware/tici/power_monitor.py | 21 +++++++ .../hardware/tici/precise_power_measure.py | 14 +---- selfdrive/hardware/tici/test_power_draw.py | 61 +++++++++++++++++++ 4 files changed, 86 insertions(+), 11 deletions(-) create mode 100755 selfdrive/hardware/tici/test_power_draw.py diff --git a/Jenkinsfile b/Jenkinsfile index b188539b14..aa73ccfc49 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -120,6 +120,7 @@ pipeline { steps { phone_steps("tici2", [ ["build", "cd selfdrive/manager && ./build.py"], + ["test power draw", "python selfdrive/hardware/tici/test_power_draw.py"], ["test boardd loopback", "python selfdrive/boardd/tests/test_boardd_loopback.py"], ["test loggerd", "python selfdrive/loggerd/tests/test_loggerd.py"], ["test encoder", "LD_LIBRARY_PATH=/usr/local/lib python selfdrive/loggerd/tests/test_encoder.py"], diff --git a/selfdrive/hardware/tici/power_monitor.py b/selfdrive/hardware/tici/power_monitor.py index d7f113cf2c..033266f465 100755 --- a/selfdrive/hardware/tici/power_monitor.py +++ b/selfdrive/hardware/tici/power_monitor.py @@ -1,11 +1,32 @@ #!/usr/bin/env python3 import sys import time +import numpy as np +from typing import List + +from common.realtime import Ratekeeper def average(avg, sample): # Weighted avg between existing value and new sample return ((avg[0] * avg[1] + sample) / (avg[1] + 1), avg[1] + 1) + +def sample_power(seconds=5) -> List[float]: + rate = 123 + rk = Ratekeeper(rate, print_delay_threshold=None) + + pwrs = [] + for _ in range(rate*seconds): + with open("/sys/bus/i2c/devices/0-0040/hwmon/hwmon1/power1_input") as f: + pwrs.append(int(f.read()) / 1e6) + rk.keep_time() + return pwrs + +def get_power(seconds=5): + pwrs = sample_power(seconds) + return np.mean(pwrs) + + if __name__ == '__main__': sample_time = None diff --git a/selfdrive/hardware/tici/precise_power_measure.py b/selfdrive/hardware/tici/precise_power_measure.py index f1fb254b26..c66936aef8 100755 --- a/selfdrive/hardware/tici/precise_power_measure.py +++ b/selfdrive/hardware/tici/precise_power_measure.py @@ -1,17 +1,9 @@ #!/usr/bin/env python3 import numpy as np -from common.realtime import Ratekeeper +from selfdrive.hardware.tici.power_monitor import sample_power if __name__ == '__main__': - RATE = 123 - print("measuring for 5 seconds at %dhz 3 times" % RATE) - rk = Ratekeeper(RATE, print_delay_threshold=None) - + print("measuring for 5 seconds") for _ in range(3): - pwrs = [] - for _ in range(RATE*5): - with open("/sys/bus/i2c/devices/0-0040/hwmon/hwmon1/power1_input") as f: - pwrs.append(int(f.read()) / 1000.) - rk.keep_time() + pwrs = sample_power() print("mean %.2f std %.2f" % (np.mean(pwrs), np.std(pwrs))) - diff --git a/selfdrive/hardware/tici/test_power_draw.py b/selfdrive/hardware/tici/test_power_draw.py new file mode 100755 index 0000000000..3e8323452e --- /dev/null +++ b/selfdrive/hardware/tici/test_power_draw.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +import unittest +import time +import math +from collections import OrderedDict + +from selfdrive.hardware import HARDWARE, TICI +from selfdrive.hardware.tici.power_monitor import get_power +from selfdrive.manager.process_config import managed_processes +from selfdrive.manager.manager import manager_cleanup + +POWER = OrderedDict( + camerad=2.65, + modeld=1.15, + dmonitoringmodeld=0.25, + loggerd=0.45, +) + + +class TestPowerDraw(unittest.TestCase): + + @classmethod + def setUpClass(cls): + if not TICI: + raise unittest.SkipTest + + def setUp(self): + HARDWARE.initialize_hardware() + HARDWARE.set_power_save(False) + + def tearDown(self): + manager_cleanup() + + def test_camera_procs(self): + baseline = get_power() + + prev = baseline + used = {} + for proc in POWER.keys(): + managed_processes[proc].start() + time.sleep(6) + + now = get_power(8) + used[proc] = now - prev + prev = now + + manager_cleanup() + + print("-"*35) + print(f"Baseline {baseline:.2f}W\n") + for proc in POWER.keys(): + cur = used[proc] + expected = POWER[proc] + print(f"{proc.ljust(20)} {expected:.2f}W {cur:.2f}W") + with self.subTest(proc=proc): + self.assertTrue(math.isclose(cur, expected, rel_tol=0.10, abs_tol=0.1)) + print("-"*35) + + +if __name__ == "__main__": + unittest.main()