From aeef5fdeebd9f098f2da8854588bfb99a2bdd18d Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 21 Sep 2024 10:32:52 -0400 Subject: [PATCH 001/181] Fixing things being double tabbed --- hil/components/component.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hil/components/component.py b/hil/components/component.py index cfa632a..b690171 100644 --- a/hil/components/component.py +++ b/hil/components/component.py @@ -62,12 +62,12 @@ def __init__(self, name, hil_con, mode, hil): if (hil_port_num >= 0): print(f"Creating new component '{self.name}' of type {mode} on {hil_con}") if (mode == "DI"): - if self.inv_meas: - self.read_func = lambda : not dev.read_gpio(hil_port_num) - else: - self.read_func = lambda : dev.read_gpio(hil_port_num) + if self.inv_meas: + self.read_func = lambda : not dev.read_gpio(hil_port_num) + else: + self.read_func = lambda : dev.read_gpio(hil_port_num) elif (mode == "AI"): - self.read_func = lambda : dev.read_analog(hil_port_num) + self.read_func = lambda : dev.read_analog(hil_port_num) elif (mode == "DO"): if self.inv_emul: self.write_func = lambda s: dev.write_gpio(hil_port_num, not s) From c17d12362a06224b94ebba83c0b4f35428409bab Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 21 Sep 2024 10:33:13 -0400 Subject: [PATCH 002/181] Fixing string formatting to avoid invalid escape characters --- hil/hil.py | 2 +- hil/hil_devices/hil_device.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hil/hil.py b/hil/hil.py index 3d9a0c3..2b0fc83 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -20,7 +20,7 @@ NET_MAP_PATH = "..\\net_maps" PIN_MAP_PATH = "..\\pin_maps" -PARAMS_PATH = "..\hil_params.json" +PARAMS_PATH = "..\\hil_params.json" class HIL(): diff --git a/hil/hil_devices/hil_device.py b/hil/hil_devices/hil_device.py index 92e7645..52c91b2 100644 --- a/hil/hil_devices/hil_device.py +++ b/hil/hil_devices/hil_device.py @@ -14,7 +14,7 @@ HIL_ID_MASK = 0xFF -HIL_DEVICES_PATH = "..\hil\hil_devices" +HIL_DEVICES_PATH = "../hil/hil_devices" class HilDevice(): From 3725109a74405e4c91f90cf462b628fe96f4c472 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 21 Sep 2024 10:33:22 -0400 Subject: [PATCH 003/181] Fixing import error --- scripts/test_charger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test_charger.py b/scripts/test_charger.py index 61ea023..87a6fa4 100644 --- a/scripts/test_charger.py +++ b/scripts/test_charger.py @@ -1,7 +1,7 @@ from os import sys, path sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) from hil import HIL -import utils +import hil.utils as utils import time from rules_constants import * from vehicle_constants import * From ae8ac966985f8f470dcf66ac40f5890eb6357efb Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sun, 22 Sep 2024 20:06:03 -0400 Subject: [PATCH 004/181] unix file slash directions --- hil/hil.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hil/hil.py b/hil/hil.py index 2b0fc83..99bb05c 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -15,12 +15,12 @@ """ HIL TESTER """ JSON_CONFIG_SCHEMA_PATH = "" -CONFIG_PATH = "..\\configurations" +CONFIG_PATH = "../configurations" -NET_MAP_PATH = "..\\net_maps" -PIN_MAP_PATH = "..\\pin_maps" +NET_MAP_PATH = "../net_maps" +PIN_MAP_PATH = "../pin_maps" -PARAMS_PATH = "..\\hil_params.json" +PARAMS_PATH = "../hil_params.json" class HIL(): From c29603e1eddbc04ae28ab7164fe7ec6d1755504e Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sun, 22 Sep 2024 20:07:07 -0400 Subject: [PATCH 005/181] Creating a super simple pytest example --- millan-pytest/fake_test.py | 57 ++++++++++++++++++++++++++++++++++++++ scripts/test.sh | 9 ++++++ 2 files changed, 66 insertions(+) create mode 100644 millan-pytest/fake_test.py create mode 100755 scripts/test.sh diff --git a/millan-pytest/fake_test.py b/millan-pytest/fake_test.py new file mode 100644 index 0000000..c0dfca8 --- /dev/null +++ b/millan-pytest/fake_test.py @@ -0,0 +1,57 @@ +# import pytest + +# @pytest.mark.section("FAKE 1") +# def test_fake(): +# assert 1 == 1, "Power" +# assert 2 == 3, "Fire" +# assert 3 == 3, "Cooling" +# assert 4 == 5, "Brakes" +# assert 5 == 5, "Steering" +# assert 6 == 6, "Suspension" + +# @pytest.mark.section("FAKE 2") +# def test_fake2(): +# assert False +# assert True +# assert False +# assert True + +# @pytest.mark.section("FAKE 3") +# def test_fake3(): +# assert True +# assert True +# assert True +# assert True + + +import pytest +import pytest_check as check + +@pytest.fixture(scope="session") +def param(): + param_instance = None + yield param_instance + + +def test_fake(param): + check.equal(1, 1, "Power") + check.equal(2, 3, "Fire") + check.equal(3, 3, "Cooling") + check.equal(4, 5, "Brakes") + check.equal(5, 5, "Steering") + check.equal(6, 6, "Suspension") + check.between_equal(5, 1, 10, "Speed") + check.between_equal(11, 1, 10, "Speed 2") + +def test_fake2(param): + check.is_true(False, "A") + check.is_true(True, "B") + check.is_true(False, "C") + check.is_true(True, "D") + +def test_fake3(param): + check.is_true(True, "True 1") + check.is_true(True, "True 2") + check.is_true(True, "True 3") + check.is_true(True, "True 4") + diff --git a/scripts/test.sh b/scripts/test.sh new file mode 100755 index 0000000..7750468 --- /dev/null +++ b/scripts/test.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Check if a Python file was passed as an argument +if [ "$#" -ne 1 ]; then + echo "Usage: ./test " + exit 1 +fi + +pytest --cache-clear --no-header -v "$1" \ No newline at end of file From f7f6f3e9571c622188e43303b4a3a41c85d8aaff Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sun, 22 Sep 2024 20:08:19 -0400 Subject: [PATCH 006/181] Trying to convert to pytest Not sure if it is working because I don't understand how to actually test the code without all the boards --- millan-pytest/fake_test.py | 3 - millan-pytest/test.sh | 9 ++ scripts/pytest_charger.py | 185 +++++++++++++++++++++++++++++++++++++ 3 files changed, 194 insertions(+), 3 deletions(-) create mode 100755 millan-pytest/test.sh create mode 100644 scripts/pytest_charger.py diff --git a/millan-pytest/fake_test.py b/millan-pytest/fake_test.py index c0dfca8..35d834a 100644 --- a/millan-pytest/fake_test.py +++ b/millan-pytest/fake_test.py @@ -1,6 +1,5 @@ # import pytest -# @pytest.mark.section("FAKE 1") # def test_fake(): # assert 1 == 1, "Power" # assert 2 == 3, "Fire" @@ -9,14 +8,12 @@ # assert 5 == 5, "Steering" # assert 6 == 6, "Suspension" -# @pytest.mark.section("FAKE 2") # def test_fake2(): # assert False # assert True # assert False # assert True -# @pytest.mark.section("FAKE 3") # def test_fake3(): # assert True # assert True diff --git a/millan-pytest/test.sh b/millan-pytest/test.sh new file mode 100755 index 0000000..7750468 --- /dev/null +++ b/millan-pytest/test.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Check if a Python file was passed as an argument +if [ "$#" -ne 1 ]; then + echo "Usage: ./test " + exit 1 +fi + +pytest --cache-clear --no-header -v "$1" \ No newline at end of file diff --git a/scripts/pytest_charger.py b/scripts/pytest_charger.py new file mode 100644 index 0000000..c116f23 --- /dev/null +++ b/scripts/pytest_charger.py @@ -0,0 +1,185 @@ +from os import sys, path +sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) + +from hil import HIL +# import hil.utils as utils +import utils +import time +from rules_constants import * +from vehicle_constants import * + +import pytest_check as check +import pytest + + +AMS_STAT_OKAY = 1 +AMS_STAT_TRIP = 0 +AMS_CTRL_OKAY = 1 +AMS_CTRL_TRIP = 0 + +def reset_ams(ams_stat): + ams_stat.state = AMS_STAT_OKAY + +IMD_STAT_OKAY = 1 +IMD_STAT_TRIP = 0 +def reset_imd(imd_stat): + imd_stat.state = IMD_STAT_OKAY + +power = None + +CYCLE_POWER_OFF_DELAY = 2.0 +CYCLE_POWER_ON_DELAY = 3.0 + +def cycle_power(): + power.state = 1 + time.sleep(CYCLE_POWER_OFF_DELAY) + power.state = 0 + time.sleep(CYCLE_POWER_ON_DELAY) + + +IMD_RC_MIN_TRIP_TIME_S = IMD_STARTUP_TIME_S +IMD_RC_MAX_TRIP_TIME_S = R_IMD_MAX_TRIP_TIME_S - IMD_MEASURE_TIME_S +IMD_CTRL_OKAY = 1 +IMD_CTRL_TRIP = 0 + + +@pytest.fixture(scope="session") +def hil(): + hil_instance = HIL() + hil_instance.load_config("config_charger.json") + hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + yield hil_instance + hil_instance.shutdown() + + +def test_imd(hil): + # Begin the test + # hil.start_test(test_imd.__name__) + + # Outputs + imd_stat = hil.dout("Charger", "IMD_STATUS") + + # Outputs to set SDC status to okay + ams_stat = hil.dout("Charger", "BMS_STATUS") + + # Inputs + imd_ctrl = hil.din("Main_Module", "SDC_FINAL") # assuming AMS closed + + # Set other SDC nodes to okay + reset_ams(ams_stat) + + # IMD Fault + reset_imd(imd_stat) + cycle_power() + # hil.check(imd_ctrl.state == IMD_CTRL_OKAY, "Power On") + check.equal(imd_ctrl.state, IMD_CTRL_OKAY, "Power On") + + time.sleep(1) + imd_stat.state = IMD_STAT_TRIP + t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) + print(f"Target trip time: [{IMD_RC_MIN_TRIP_TIME_S}, {IMD_RC_MAX_TRIP_TIME_S}]") + # hil.check(IMD_RC_MIN_TRIP_TIME_S < t < IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Trip") + check.between(t, IMD_RC_MIN_TRIP_TIME_S, IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Trip") + + imd_stat.state = IMD_STAT_OKAY + time.sleep(IMD_RC_MAX_TRIP_TIME_S * 1.1) + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Stays Latched") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Stays Latched") + + + # IMD Fault on Power On + reset_imd(imd_stat) + imd_stat.state = IMD_STAT_TRIP + cycle_power() + time.sleep(IMD_RC_MAX_TRIP_TIME_S) + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Power On") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Power On") + + + # IMD Floating + reset_imd(imd_stat) + imd_stat.hiZ() + cycle_power() + t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) + # hil.check(t < R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Floating Trip") + check.less(t, R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Floating Trip") + + # hil.end_test() + +def test_ams(hil): + # Begin the test + hil.start_test(test_ams.__name__) + + # Outputs + ams_stat = hil.dout("Charger", "BMS_STATUS") + + + # Outputs to set SDC status to okay + imd_stat = hil.dout("Charger", "IMD_STATUS") + + # Inputs + ams_ctrl = hil.din("Main_Module", "SDC_FINAL") # assuming AMS closed + + # Set other SDC nodes to okay + reset_imd(imd_stat) + + # AMS Fault + reset_ams(ams_stat) + cycle_power() + # hil.check(ams_ctrl.state == AMS_CTRL_OKAY, "Power On") + check.equal(ams_ctrl.state, AMS_CTRL_OKAY, "Power On") + + time.sleep(1) + ams_stat.state = AMS_STAT_TRIP + t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) + # hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Trip") + check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Trip") + + ams_stat.state = AMS_STAT_OKAY + time.sleep(AMS_MAX_TRIP_DELAY_S * 1.1) + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Stays Latched") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Stays Latched") + + + # AMS Fault on Power On + reset_ams(ams_stat) + ams_stat.state = AMS_STAT_TRIP + cycle_power() + time.sleep(AMS_MAX_TRIP_DELAY_S) + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Power On") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Power On") + + + # AMS Floating + reset_ams(ams_stat) + ams_stat.hiZ() + cycle_power() + t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) + # hil.check(0 <= t < AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Floating Trip") + check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Floating Trip") + + # hil.end_test() + + +if __name__ == "__main__": + hil = HIL() + + hil.load_config("config_charger.json") + hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + #hil.init_can() + + power = hil.dout("RearTester", "RLY1") + + test_imd() + test_ams() + + hil.shutdown() From db43eabd86357412a47404867fa1e408f64ce814 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sun, 22 Sep 2024 21:51:38 -0400 Subject: [PATCH 007/181] Testing check.almost_equal() --- millan-pytest/fake_test.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/millan-pytest/fake_test.py b/millan-pytest/fake_test.py index 35d834a..42748b1 100644 --- a/millan-pytest/fake_test.py +++ b/millan-pytest/fake_test.py @@ -52,3 +52,6 @@ def test_fake3(param): check.is_true(True, "True 3") check.is_true(True, "True 4") +def test_fake4(param): + check.almost_equal(0.2, 0.23, abs=0.1, rel=0.0, msg="Almost 1") + From 8944f406e77559ebd7dc277c7523b76a6be9018e Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sun, 22 Sep 2024 21:52:26 -0400 Subject: [PATCH 008/181] Bugfix: setting up all of hil in the pytest fixture --- scripts/pytest_charger.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/scripts/pytest_charger.py b/scripts/pytest_charger.py index c116f23..a4e153d 100644 --- a/scripts/pytest_charger.py +++ b/scripts/pytest_charger.py @@ -45,10 +45,19 @@ def cycle_power(): @pytest.fixture(scope="session") def hil(): + global power + hil_instance = HIL() + hil_instance.load_config("config_charger.json") hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + # hil_instance.init_can() + + power = hil_instance.dout("RearTester", "RLY1") + yield hil_instance + hil_instance.shutdown() @@ -170,16 +179,16 @@ def test_ams(hil): if __name__ == "__main__": - hil = HIL() + # hil = HIL() - hil.load_config("config_charger.json") - hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + # hil.load_config("config_charger.json") + # hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") #hil.init_can() - power = hil.dout("RearTester", "RLY1") + # power = hil.dout("RearTester", "RLY1") test_imd() test_ams() - hil.shutdown() + # hil.shutdown() From 6dc84e303ea1e271e65316aef83980db7fadceb1 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sun, 22 Sep 2024 21:52:47 -0400 Subject: [PATCH 009/181] Section dividers --- scripts/pytest_charger.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/scripts/pytest_charger.py b/scripts/pytest_charger.py index a4e153d..1af07f1 100644 --- a/scripts/pytest_charger.py +++ b/scripts/pytest_charger.py @@ -12,6 +12,7 @@ import pytest +# ---------------------------------------------------------------------------- # AMS_STAT_OKAY = 1 AMS_STAT_TRIP = 0 AMS_CTRL_OKAY = 1 @@ -41,8 +42,10 @@ def cycle_power(): IMD_RC_MAX_TRIP_TIME_S = R_IMD_MAX_TRIP_TIME_S - IMD_MEASURE_TIME_S IMD_CTRL_OKAY = 1 IMD_CTRL_TRIP = 0 +# ---------------------------------------------------------------------------- # +# ---------------------------------------------------------------------------- # @pytest.fixture(scope="session") def hil(): global power @@ -59,8 +62,10 @@ def hil(): yield hil_instance hil_instance.shutdown() +# ---------------------------------------------------------------------------- # +# ---------------------------------------------------------------------------- # def test_imd(hil): # Begin the test # hil.start_test(test_imd.__name__) @@ -118,7 +123,9 @@ def test_imd(hil): check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Floating Trip") # hil.end_test() +# ---------------------------------------------------------------------------- # +# ---------------------------------------------------------------------------- # def test_ams(hil): # Begin the test hil.start_test(test_ams.__name__) @@ -176,8 +183,10 @@ def test_ams(hil): check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Floating Trip") # hil.end_test() +# ---------------------------------------------------------------------------- # +# ---------------------------------------------------------------------------- # if __name__ == "__main__": # hil = HIL() @@ -192,3 +201,4 @@ def test_ams(hil): test_ams() # hil.shutdown() +# ---------------------------------------------------------------------------- # \ No newline at end of file From 8e47132071c2b578f7d2a2911034fc4227b0df44 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sun, 22 Sep 2024 21:54:40 -0400 Subject: [PATCH 010/181] Trying abox pytest --- scripts/pytest_abox.py | 338 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 338 insertions(+) create mode 100644 scripts/pytest_abox.py diff --git a/scripts/pytest_abox.py b/scripts/pytest_abox.py new file mode 100644 index 0000000..2283f42 --- /dev/null +++ b/scripts/pytest_abox.py @@ -0,0 +1,338 @@ +from os import sys, path +sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) +from hil import HIL +import utils +import time +from rules_constants import * +from vehicle_constants import * + + +import pytest_check as check +import pytest + + + +# ---------------------------------------------------------------------------- # +@pytest.fixture(scope="session") +def hil(): + hil_instance = HIL() + + hil_instance.load_config("config_charger.json") + hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + hil_instance.init_can() + + yield hil_instance + + hil_instance.shutdown() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +def test_abox_ams(hil): + # Begin the test + # hil.start_test(test_abox_ams.__name__) + + # Outputs + den = hil.dout("a_box", "Discharge Enable") + csafe = hil.dout("a_box", "Charger Safety") + bms_override = hil.daq_var("a_box", "bms_daq_override") + bms_stat = hil.daq_var("a_box", "bms_daq_stat") + + # Inputs + chrg_stat = hil.din("a_box", "BMS Status Charger") + main_stat = hil.din("a_box", "BMS Status PDU") + + bms_override.state = 1 + + for i in range(0, 8): + dchg_set = bool(i & 0x1) + chg_set = bool(i & 0x2) + bms_set = bool(i & 0x4) + exp_chrg = not (chg_set or bms_set) + exp_dchg = not (dchg_set or bms_set) + + den.state = dchg_set + csafe.state = chg_set + bms_stat.state = bms_set + print(f"Combo {i}") + time.sleep(0.1) + # hil.check(chrg_stat.state == exp_chrg, f"Chrg stat {exp_chrg}") + # hil.check(main_stat.state == exp_dchg, f"Main stat {exp_dchg}") + check.equal(chrg_stat.state, exp_chrg, f"Chrg stat {exp_chrg}") + check.equal(main_stat.state, exp_dchg, f"Main stat {exp_dchg}") + + bms_override.state = 0 + + # hil.end_test() +# ---------------------------------------------------------------------------- # + +# ---------------------------------------------------------------------------- # +def test_isense(hil): + # Begin the test + # hil.start_test(test_isense.__name__) + + # Outputs + ch1_raw = hil.aout("a_box", "Isense_Ch1_raw") + + # Inputs + ch1_filt = hil.ain("a_box", "ISense Ch1") + + # Need to test voltage divider transfer function correct + for v in [0.0, DHAB_S124_MIN_OUT_V, DHAB_S124_OFFSET_V, 3.2, DHAB_S124_MAX_OUT_V, 5.0]: + ch1_raw.state = v + time.sleep(1) + exp_out = ABOX_DHAB_CH1_DIV.div(v) + input(f"enter to meas, set to {v}, expected {exp_out}") + meas = ch1_filt.state + print(f"isense expected: {exp_out}V, measured: {meas}V") + # hil.check_within(meas, exp_out, 0.05, f"Isense v={v:.3}") + check.almost_equal(meas, exp_out, abs=0.05, rel=0.0, msg=f"Isense v={v:.3}") + + ch1_raw.hiZ() + time.sleep(0.01) + # hil.check_within(ch1_filt.state, 0.0, 0.05, f"Isense float pulled down") + check.almost_equal(ch1_filt.state, 0.0, abs=0.05, rel=0.0, msg="Isense float pulled down") + + # hil.end_test() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +RLY_ON = 0 +RLY_OFF = 1 +RLY_DLY = 0.01 # Mechanicl relay takes time to transition + +def test_precharge(hil): + # Begin the test + # hil.start_test(test_precharge.__name__) + + # Outputs + n_pchg_cmplt = hil.dout("a_box", "NotPrechargeComplete") + sdc = hil.dout("a_box", "SDC") + bat_p = hil.dout("a_box", "Batt+") + + # Inputs + resistor = hil.din("a_box", "NetK1_4") # To precharge resistor + + bat_p.state = RLY_ON + + print("Combo 1") + n_pchg_cmplt.state = 0 + sdc.state = RLY_OFF + time.sleep(RLY_DLY) + # hil.check(resistor.state == 0, "Resistor disconnected") + check.equal(resistor.state, 0, "Combo 1, resistor disconnected") + + print("Combo 2") + n_pchg_cmplt.state = 1 + sdc.state = RLY_OFF + time.sleep(RLY_DLY) + # hil.check(resistor.state == 0, "Resistor disconnected") + check.equal(resistor.state, 0, "Combo 2, resistor disconnected") + + print("Combo 3") + n_pchg_cmplt.state = 1 + sdc.state = RLY_ON + time.sleep(RLY_DLY) + # hil.check(resistor.state == 1, "Resistor connected") + check.equal(resistor.state, 1, "Combo 3, resistor connected") + + print("Combo 4") + n_pchg_cmplt.state = 0 + sdc.state = RLY_ON + time.sleep(RLY_DLY) + # hil.check(resistor.state == 0, "Resistor disconnected") + check.equal(resistor.state, 0, "Combo 4, resistor disconnected") + + # Duration test + time.sleep(1) + n_pchg_cmplt.state = 1 + sdc.state = RLY_ON + time.sleep(RLY_DLY) + # hil.check(resistor.state == 1, "Duration init") + check.equal(resistor.state, 1, "Duration init") + + time.sleep(9) + # hil.check(resistor.state == 1, "Duration mid") + check.equal(resistor.state, 1, "Duration mid") + + n_pchg_cmplt.state = 0 + time.sleep(RLY_DLY) + # hil.check(resistor.state == 0, "Duration end") + check.equal(resistor.state, 0, "Duration end") + + # hil.end_test() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +SUPPLY_VOLTAGE = 24.0 +TIFF_DLY = 0.3 + +def test_tiffomy(hil): + # Begin the test + # hil.start_test(test_tiffomy.__name__) + + # Outputs + bat_p = hil.dout("a_box", "Batt+") + + # Inputs + vbat = hil.ain("a_box", "VBatt") + imd_hv = hil.din("a_box", "Batt+_Fused") + + # NOTE: the IMD test confirms that the relay closed + # This is a bit redundant of the tiffomy voltage measurement + + utils.log_warning(f"Assuming supply = {SUPPLY_VOLTAGE} V") + utils.log_warning(f"Do not reverse polarity Vbat, it will kill Arduino ADC") + input("Click enter to acknowledge or ctrl+c to cancel") + + bat_p.state = RLY_OFF + time.sleep(TIFF_DLY) + # hil.check_within(vbat.state, 0.0, 0.1, "TIff off") + # hil.check(imd_hv.state == 0, "IMD HV off") + check.almost_equal(vbat.state, 0.0, abs=0.1, rel=0.0, msg="TIff off") + check.equal(imd_hv.state, 0, "IMD HV off") + + bat_p.state = RLY_ON + time.sleep(TIFF_DLY) + exp = SUPPLY_VOLTAGE + #input("press enter, tiff should be getting volts") + meas = tiff_lv_to_hv(vbat.state) + print(f"Tiff HV reading: {meas} V, expect: {SUPPLY_VOLTAGE} V") + # hil.check_within(meas, exp, 2.5, "Tiff on") + # hil.check(imd_hv.state == 1, "IMD HV on") + check.almost_equal(meas, exp, abs=2.5, rel=0.0, msg="Tiff on") + check.equal(imd_hv.state, 1, "IMD HV on") + + # hil.end_test() +# ---------------------------------------------------------------------------- # + +# ---------------------------------------------------------------------------- # +def test_tmu(hil): + # Begin the test + # hil.start_test(test_tmu.__name__) + + # Outputs + tmu_a_do = hil.dout("a_box", "TMU_1") + tmu_b_do = hil.dout("a_box", "TMU_2") + tmu_c_do = hil.dout("a_box", "TMU_3") + tmu_d_do = hil.dout("a_box", "TMU_4") + + daq_override = hil.daq_var("a_box", "tmu_daq_override") + daq_therm = hil.daq_var("a_box", "tmu_daq_therm") + + # Inputs + mux_a = hil.din("a_box", "MUX_A_NON_ISO") + mux_b = hil.din("a_box", "MUX_B_NON_ISO") + mux_c = hil.din("a_box", "MUX_C_NON_ISO") + mux_d = hil.din("a_box", "MUX_D_NON_ISO") + + tmu_a_ai = hil.daq_var("a_box", "tmu_1") + tmu_b_ai = hil.daq_var("a_box", "tmu_2") + tmu_c_ai = hil.daq_var("a_box", "tmu_3") + tmu_d_ai = hil.daq_var("a_box", "tmu_4") + + daq_therm.state = 0 + daq_override.state = 1 + + # mux line test + for i in range(0,16): + daq_therm.state = i + time.sleep(0.05) + # hil.check(mux_a.state == bool(i & 0x1), f"Mux A test {i}") + # hil.check(mux_b.state == bool(i & 0x2), f"Mux B test {i}") + # hil.check(mux_c.state == bool(i & 0x4), f"Mux C test {i}") + # hil.check(mux_d.state == bool(i & 0x8), f"Mux D test {i}") + check.equal(mux_a.state, bool(i & 0x1), f"Mux A test {i}") + check.equal(mux_b.state, bool(i & 0x2), f"Mux B test {i}") + check.equal(mux_c.state, bool(i & 0x4), f"Mux C test {i}") + check.equal(mux_d.state, bool(i & 0x8), f"Mux D test {i}") + + daq_override.state = 0 + + TMU_TOLERANCE = 100 + TMU_HIGH_VALUE = 1970 #2148 + + # thermistors + for i in range(0,16): + tmu_a_do.state = bool(i & 0x1) + tmu_b_do.state = bool(i & 0x2) + tmu_c_do.state = bool(i & 0x4) + tmu_d_do.state = bool(i & 0x8) + time.sleep(1.0) + a = int(tmu_a_ai.state) + b = int(tmu_b_ai.state) + c = int(tmu_c_ai.state) + d = int(tmu_d_ai.state) + print(f"Readings at therm={i}: {a}, {b}, {c}, {d}") + # hil.check_within(a, TMU_HIGH_VALUE if (i & 0x1) else 0, TMU_TOLERANCE, f"TMU 1 test {i}") + # hil.check_within(b, TMU_HIGH_VALUE if (i & 0x2) else 0, TMU_TOLERANCE, f"TMU 2 test {i}") + # hil.check_within(c, TMU_HIGH_VALUE if (i & 0x4) else 0, TMU_TOLERANCE, f"TMU 3 test {i}") + # hil.check_within(d, TMU_HIGH_VALUE if (i & 0x8) else 0, TMU_TOLERANCE, f"TMU 4 test {i}") + check.almost_equal(a, TMU_HIGH_VALUE if (i & 0x1) else 0, abs=TMU_TOLERANCE, rel=0.0, msg=f"TMU 1 test {i}") + check.almost_equal(b, TMU_HIGH_VALUE if (i & 0x2) else 0, abs=TMU_TOLERANCE, rel=0.0, msg=f"TMU 2 test {i}") + check.almost_equal(c, TMU_HIGH_VALUE if (i & 0x4) else 0, abs=TMU_TOLERANCE, rel=0.0, msg=f"TMU 3 test {i}") + check.almost_equal(d, TMU_HIGH_VALUE if (i & 0x8) else 0, abs=TMU_TOLERANCE, rel=0.0, msg=f"TMU 4 test {i}") + + # hil.end_test() +# ---------------------------------------------------------------------------- # + +# ---------------------------------------------------------------------------- # +def test_imd(hil): + # hil.start_test(test_imd.__name__) + + # Outputs + imd_out = hil.dout('a_box', 'IMD_Status') + + # Inputs + imd_in = hil.din('a_box', 'IMD_STATUS_LV_COMP') + imd_mcu = hil.mcu_pin('a_box', 'IMD_STATUS_LV_COMP') + + + imd_out.state = RLY_OFF + time.sleep(RLY_DLY) + + # hil.check(imd_in.state == 0, 'IMD LV OFF') + # hil.check(imd_mcu.state == 0, 'IMD MCU OFF') + check.equal(imd_in.state, 0, 'IMD LV OFF') + check.equal(imd_mcu.state, 0, 'IMD MCU OFF') + + imd_out.state = RLY_ON + time.sleep(RLY_DLY) + + # hil.check(imd_in.state == 1, 'IMD LV ON') + # hil.check(imd_mcu.state == 1, 'IMD MCU ON') + check.equal(imd_in.state, 1, 'IMD LV ON') + check.equal(imd_mcu.state, 1, 'IMD MCU ON') + + imd_out.state = RLY_OFF + time.sleep(RLY_DLY) + + # hil.check(imd_in.state == 0, 'IMD LV BACK OFF') + # hil.check(imd_mcu.state == 0, 'IMD MCU BACK OFF') + check.equal(imd_in.state, 0, 'IMD LV BACK OFF') + check.equal(imd_mcu.state, 0, 'IMD MCU BACK OFF') + + # hil.end_test() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +if __name__ == "__main__": + # hil = HIL() + # hil.load_config("config_abox_bench.json") + # hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + # hil.init_can() + + test_abox_ams() + test_isense() + test_precharge() + test_tiffomy() + test_tmu() + test_imd() + + # hil.shutdown() +# ---------------------------------------------------------------------------- # From a1293549f3d8b03440718dc2aa6b9e4fff81375a Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sun, 22 Sep 2024 21:55:32 -0400 Subject: [PATCH 011/181] Don't need to call the functions when using pytest --- scripts/pytest_abox.py | 21 +-------------------- scripts/pytest_charger.py | 18 ------------------ 2 files changed, 1 insertion(+), 38 deletions(-) diff --git a/scripts/pytest_abox.py b/scripts/pytest_abox.py index 2283f42..0172d62 100644 --- a/scripts/pytest_abox.py +++ b/scripts/pytest_abox.py @@ -316,23 +316,4 @@ def test_imd(hil): check.equal(imd_mcu.state, 0, 'IMD MCU BACK OFF') # hil.end_test() -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # -if __name__ == "__main__": - # hil = HIL() - # hil.load_config("config_abox_bench.json") - # hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") - - # hil.init_can() - - test_abox_ams() - test_isense() - test_precharge() - test_tiffomy() - test_tmu() - test_imd() - - # hil.shutdown() -# ---------------------------------------------------------------------------- # +# ---------------------------------------------------------------------------- # \ No newline at end of file diff --git a/scripts/pytest_charger.py b/scripts/pytest_charger.py index 1af07f1..8044f4b 100644 --- a/scripts/pytest_charger.py +++ b/scripts/pytest_charger.py @@ -183,22 +183,4 @@ def test_ams(hil): check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Floating Trip") # hil.end_test() -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # -if __name__ == "__main__": - # hil = HIL() - - # hil.load_config("config_charger.json") - # hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") - - #hil.init_can() - - # power = hil.dout("RearTester", "RLY1") - - test_imd() - test_ams() - - # hil.shutdown() # ---------------------------------------------------------------------------- # \ No newline at end of file From 89cf479bdbb997ec186b230cdf1bf2a670a35d40 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 24 Sep 2024 20:01:20 -0400 Subject: [PATCH 012/181] Can pass no arguments to run on all files --- millan-pytest/test.sh | 13 +++++++------ scripts/test.sh | 13 +++++++------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/millan-pytest/test.sh b/millan-pytest/test.sh index 7750468..9a919dd 100755 --- a/millan-pytest/test.sh +++ b/millan-pytest/test.sh @@ -1,9 +1,10 @@ #!/bin/bash -# Check if a Python file was passed as an argument +# If no file passed, run on all files if [ "$#" -ne 1 ]; then - echo "Usage: ./test " - exit 1 -fi - -pytest --cache-clear --no-header -v "$1" \ No newline at end of file + echo "Running tests on all files..." + pytest --cache-clear --no-header -v +else + echo "Running tests on $1..." + pytest --cache-clear --no-header -v "$1" +fi \ No newline at end of file diff --git a/scripts/test.sh b/scripts/test.sh index 7750468..9a919dd 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -1,9 +1,10 @@ #!/bin/bash -# Check if a Python file was passed as an argument +# If no file passed, run on all files if [ "$#" -ne 1 ]; then - echo "Usage: ./test " - exit 1 -fi - -pytest --cache-clear --no-header -v "$1" \ No newline at end of file + echo "Running tests on all files..." + pytest --cache-clear --no-header -v +else + echo "Running tests on $1..." + pytest --cache-clear --no-header -v "$1" +fi \ No newline at end of file From a85b82ff1dff9fe9780fb111241eb0eb1976f851 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Thu, 3 Oct 2024 20:01:11 -0400 Subject: [PATCH 013/181] Readability/format changes --- hil/utils.py | 45 +++++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/hil/utils.py b/hil/utils.py index be46c8f..2cbd388 100644 --- a/hil/utils.py +++ b/hil/utils.py @@ -8,32 +8,48 @@ def initGlobals(): global signals signals = {} + global plot_x_range_sec plot_x_range_sec = 10 + global events events = [] + global b_str b_str = "Main" + global data_types data_types = { - 'uint8_t':np.dtype(' Date: Thu, 10 Oct 2024 20:23:52 -0400 Subject: [PATCH 014/181] Python decorator for logging HIL status --- hil/hil.py | 83 +++++++++++++++++++------------------- hil/utils.py | 9 +++++ millan-pytest/fake_test.py | 14 +++++++ 3 files changed, 64 insertions(+), 42 deletions(-) diff --git a/hil/hil.py b/hil/hil.py index 99bb05c..3d33cf5 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -25,6 +25,7 @@ class HIL(): + @utils.log_function_start_end def __init__(self): utils.initGlobals() self.components = {} @@ -40,6 +41,7 @@ def __init__(self): self.global_check_count = 0 # multiple checks within a test self.global_test_count = 0 + @utils.log_function_start_end def init_can(self): config = self.hil_params self.daq_config = utils.load_json_config(os.path.join(config['firmware_path'], config['daq_config_path']), os.path.join(config['firmware_path'], config['daq_schema_path'])) @@ -51,6 +53,7 @@ def init_can(self): self.can_bus.connect() self.can_bus.start() + @utils.log_function_start_end def load_pin_map(self, net_map, pin_map): net_map_f = os.path.join(NET_MAP_PATH, net_map) pin_map_f = os.path.join(PIN_MAP_PATH, pin_map) @@ -58,40 +61,29 @@ def load_pin_map(self, net_map, pin_map): self.pin_map = PinMapper(net_map_f) self.pin_map.load_mcu_pin_map(pin_map_f) + @utils.log_function_start_end def clear_components(self): """ Reset HIL""" for c in self.components.values(): c.shutdown() self.components = {} + @utils.log_function_start_end def clear_hil_devices(self): self.hil_devices = {} self.serial_manager.close_devices() + @utils.log_function_start_end def shutdown(self): + print(f"{utils.bcolors.OKCYAN}HIL shutdown START{utils.bcolors.ENDC}") self.clear_components() self.clear_hil_devices() self.stop_can() + print(f"{utils.bcolors.OKGREEN}HIL shutdown START{utils.bcolors.OKGREEN}") - print(f"{utils.bcolors.OKCYAN}{utils.bcolors.UNDERLINE}") - utils.log("TEST SUMMARY") - print(f"{utils.bcolors.ENDC}") - utils.log(f"{self.global_test_count} tests with {self.global_check_count} checks performed:") - utils.log(', '.join(self.global_test_names)) - num_fail = len(self.global_failed_checks) - num_pass = self.global_check_count - num_fail - if (self.global_check_count == 0): - return - utils.log(f"{num_pass}/{self.global_check_count} ({num_pass/self.global_check_count*100:.5}%) of checks passing") - if (num_fail > 0): - utils.log(f"{utils.bcolors.FAIL}{utils.bcolors.BOLD}Failing {num_fail} checks:{utils.bcolors.ENDC}") - for c in self.global_failed_checks: - utils.log(f"{c[0]} - {c[1]}") - else: - utils.log(f"{utils.bcolors.OKGREEN}{utils.bcolors.BOLD}ALL CHECKS PASSING{utils.bcolors.ENDC}") - - + @utils.log_function_start_end def stop_can(self): + print(f"{utils.bcolors.OKCYAN}HIL stop_can START{utils.bcolors.ENDC}") if not self.can_bus: return if self.can_bus.connected: self.can_bus.connected = False @@ -100,7 +92,9 @@ def stop_can(self): # # wait for bus receive to finish # pass self.can_bus.disconnect_bus() + print(f"{utils.bcolors.OKGREEN}HIL stop_can END{utils.bcolors.ENDC}") + @utils.log_function_start_end def load_config(self, config_name): config = utils.load_json_config(os.path.join(CONFIG_PATH, config_name), None) # TODO: validate w/ schema @@ -112,6 +106,7 @@ def load_config(self, config_name): # Setup corresponding components self.load_connections(config['dut_connections']) + @utils.log_function_start_end def load_connections(self, dut_connections): self.dut_connections = {} # Dictionary format: @@ -128,6 +123,7 @@ def load_connections(self, dut_connections): self.dut_connections[board_name][connector] = {} self.dut_connections[board_name][connector][pin] = hil_port + @utils.log_function_start_end def add_component(self, board, net, mode): # If board is a HIL device, net is expected to be port name # If board is a DUT device, net is expected to be a net name from the board @@ -143,6 +139,7 @@ def add_component(self, board, net, mode): utils.log_warning(f"Component {comp_name} already exists") return self.components[comp_name] + @utils.log_function_start_end def load_hil_devices(self, hil_devices): self.clear_hil_devices() self.serial_manager.discover_devices() @@ -152,12 +149,14 @@ def load_hil_devices(self, hil_devices): else: self.handle_error(f"Failed to discover HIL device {hil_device['name']} with id {hil_device['id']}") + @utils.log_function_start_end def get_hil_device(self, name): if name in self.hil_devices: return self.hil_devices[name] else: self.handle_error(f"HIL device {name} not recognized") + @utils.log_function_start_end def get_hil_device_connection(self, board, net): """ Converts dut net to hil port name """ if not board in self.dut_connections: @@ -209,30 +208,30 @@ def mcu_pin(self, board, net): self.handle_error(f"Failed to get mcu pin for {board} net {net}") return DAQPin(net, board, bank, pin) - def start_test(self, name): - print(f"{utils.bcolors.OKCYAN}Starting {name}{utils.bcolors.ENDC}") - self.curr_test = name - self.curr_test_fail_count = 0 - self.curr_test_count = 0 - self.global_test_count = self.global_test_count + 1 - self.global_test_names.append(name) - - def check(self, stat, check_name): - stat_str = "PASS" if stat else "FAIL" - stat_clr = utils.bcolors.OKGREEN if stat else utils.bcolors.FAIL - print(f"{self.curr_test + ' - ' + check_name:<50}: {stat_clr+'['+stat_str+']'+utils.bcolors.ENDC:>10}") - if (not stat): - self.curr_test_fail_count = self.curr_test_fail_count + 1 - self.global_failed_checks.append((self.curr_test,check_name)) - self.curr_test_count = self.curr_test_count + 1 - self.global_check_count = self.global_check_count + 1 - return stat - - def check_within(self, val1, val2, thresh, check_name): - self.check(abs(val1 - val2) <= thresh, check_name) - - def end_test(self): - print(f"{utils.bcolors.OKCYAN}{self.curr_test} failed {self.curr_test_fail_count} out of {self.curr_test_count} checks{utils.bcolors.ENDC}") + # def start_test(self, name): + # print(f"{utils.bcolors.OKCYAN}Starting {name}{utils.bcolors.ENDC}") + # self.curr_test = name + # self.curr_test_fail_count = 0 + # self.curr_test_count = 0 + # self.global_test_count = self.global_test_count + 1 + # self.global_test_names.append(name) + + # def check(self, stat, check_name): + # stat_str = "PASS" if stat else "FAIL" + # stat_clr = utils.bcolors.OKGREEN if stat else utils.bcolors.FAIL + # print(f"{self.curr_test + ' - ' + check_name:<50}: {stat_clr+'['+stat_str+']'+utils.bcolors.ENDC:>10}") + # if (not stat): + # self.curr_test_fail_count = self.curr_test_fail_count + 1 + # self.global_failed_checks.append((self.curr_test,check_name)) + # self.curr_test_count = self.curr_test_count + 1 + # self.global_check_count = self.global_check_count + 1 + # return stat + + # def check_within(self, val1, val2, thresh, check_name): + # self.check(abs(val1 - val2) <= thresh, check_name) + + # def end_test(self): + # print(f"{utils.bcolors.OKCYAN}{self.curr_test} failed {self.curr_test_fail_count} out of {self.curr_test_count} checks{utils.bcolors.ENDC}") def handle_error(self, msg): utils.log_error(msg) diff --git a/hil/utils.py b/hil/utils.py index 2cbd388..feaa0ec 100644 --- a/hil/utils.py +++ b/hil/utils.py @@ -53,6 +53,15 @@ def initGlobals(): global hilProt hilProt = None +# display current function start/end +def log_function_start_end(func): + def wrapper_function(*args, **kwargs): + global debug_mode + if debug_mode: print(f"{bcolors.OKCYAN}START: {func.__name__}{bcolors.ENDC}") + func(*args, **kwargs) + if debug_mode: print(f"{bcolors.OKCYAN}END: {func.__name__}{bcolors.ENDC}") + return wrapper_function + # Logging helper functions class bcolors: HEADER = '\033[95m' diff --git a/millan-pytest/fake_test.py b/millan-pytest/fake_test.py index 42748b1..0646f98 100644 --- a/millan-pytest/fake_test.py +++ b/millan-pytest/fake_test.py @@ -30,11 +30,25 @@ def param(): yield param_instance +def log_function_start_end(func): + def wrapper_function(*args, **kwargs): + print(f"START: {func.__name__}") + func(*args, **kwargs) + print(f"END: {func.__name__}") + return wrapper_function + + +@log_function_start_end +def do_something(): + pass + def test_fake(param): check.equal(1, 1, "Power") + do_something() check.equal(2, 3, "Fire") check.equal(3, 3, "Cooling") check.equal(4, 5, "Brakes") + do_something() check.equal(5, 5, "Steering") check.equal(6, 6, "Suspension") check.between_equal(5, 1, 10, "Speed") From 109132b3b1347bd51efe0e3596bb1dd15bc85c52 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Thu, 10 Oct 2024 20:29:35 -0400 Subject: [PATCH 015/181] Typo in abox text config load Copied the charger template, forgot to switch it out --- scripts/pytest_abox.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/pytest_abox.py b/scripts/pytest_abox.py index 0172d62..18d5fe9 100644 --- a/scripts/pytest_abox.py +++ b/scripts/pytest_abox.py @@ -17,7 +17,7 @@ def hil(): hil_instance = HIL() - hil_instance.load_config("config_charger.json") + hil_instance.load_config("config_abox_bench.json") hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") hil_instance.init_can() From 4724f5d6f8d1ea26024db5826fc0c3147f5e36e0 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Thu, 10 Oct 2024 20:30:06 -0400 Subject: [PATCH 016/181] Trying Pytest collector --- scripts/pytest_collector.py | 87 +++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 scripts/pytest_collector.py diff --git a/scripts/pytest_collector.py b/scripts/pytest_collector.py new file mode 100644 index 0000000..30cdd2f --- /dev/null +++ b/scripts/pytest_collector.py @@ -0,0 +1,87 @@ +from os import sys, path +sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) +from hil import HIL +import utils +import time + +import pytest_check as check +import pytest + + +# ---------------------------------------------------------------------------- # +@pytest.fixture(scope="session") +def hil(): + global power + + hil_instance = HIL() + + hil_instance.load_config("config_collector_bench.json") + hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + # hil_instance.init_can() + + power = hil_instance.dout("RearTester", "RLY1") + + yield hil_instance + + hil_instance.shutdown() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +def test_collector(hil): + # Begin the test + # hil.start_test(test_collector.__name__) + + # Outputs + m1 = hil.dout("Collector", "MUX_A") + m2 = hil.dout("Collector", "MUX_B") + m3 = hil.dout("Collector", "MUX_C") + m4 = hil.dout("Collector", "MUX_D") + + # Inputs + to = hil.ain("Collector", "TEMP_OUT") + + tolerance_v = 0.1 # volts + current_res = 9100.0 # ohms + pullup_res = 4700.0 # ohms + test_voltage = 3.3 # volts + pullup_voltage = 5 # volts + num_therm = 10 + + test_voltage = (pullup_voltage / (current_res + pullup_res)) * current_res + + utils.log_warning(test_voltage) + + for thermistor in range(num_therm): + print(f"Place test input on thermistor {thermistor}. Press Enter when ready") + input("") + + for i in range(num_therm): + m1.state = i & 0x1 + m2.state = i & 0x2 + m3.state = i & 0x4 + m4.state = i & 0x8 + time.sleep(0.01) + + if (i == thermistor): + # hil.check_within(to.state, test_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") + check.almost_equal(to.state, test_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") + else: + # hil.check_within(to.state, pullup_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") + check.almost_equal(to.state, pullup_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") + print(to.state) + + # End the test + # hil.end_test() +# ---------------------------------------------------------------------------- # + +# ---------------------------------------------------------------------------- # +# if __name__ == "__main__": + hil = HIL() + hil.load_config("config_collector_bench.json") + hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + test_collector(hil) + + hil.shutdown() From 8471391059de6a0fe2a51cebc3c55db9305f151d Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Thu, 10 Oct 2024 20:31:40 -0400 Subject: [PATCH 017/181] Folder rename --- {millan-pytest => pytest-example}/fake_test.py | 0 {millan-pytest => pytest-example}/test.sh | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {millan-pytest => pytest-example}/fake_test.py (100%) rename {millan-pytest => pytest-example}/test.sh (100%) diff --git a/millan-pytest/fake_test.py b/pytest-example/fake_test.py similarity index 100% rename from millan-pytest/fake_test.py rename to pytest-example/fake_test.py diff --git a/millan-pytest/test.sh b/pytest-example/test.sh similarity index 100% rename from millan-pytest/test.sh rename to pytest-example/test.sh From 15ffd0ceed26610360ba0c1371f6249eea5b69f6 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Thu, 10 Oct 2024 20:54:24 -0400 Subject: [PATCH 018/181] < now correctly <= for the left bound --- scripts/pytest_charger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/pytest_charger.py b/scripts/pytest_charger.py index 8044f4b..8dea486 100644 --- a/scripts/pytest_charger.py +++ b/scripts/pytest_charger.py @@ -179,7 +179,7 @@ def test_ams(hil): t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) # hil.check(0 <= t < AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Floating Trip") - check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") + check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time", ge=True) check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Floating Trip") # hil.end_test() From 35f2c4f74967fe7e76776e5e0acf107751035bf4 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Thu, 10 Oct 2024 20:54:36 -0400 Subject: [PATCH 019/181] Trying Pytest main base --- scripts/pytest_main_base.py | 552 ++++++++++++++++++++++++++++++++++++ 1 file changed, 552 insertions(+) create mode 100644 scripts/pytest_main_base.py diff --git a/scripts/pytest_main_base.py b/scripts/pytest_main_base.py new file mode 100644 index 0000000..c553f4a --- /dev/null +++ b/scripts/pytest_main_base.py @@ -0,0 +1,552 @@ +from os import sys, path +sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) +from hil import HIL +import utils +import time +from rules_constants import * +from vehicle_constants import * + +import pytest_check as check +import pytest + + +# ---------------------------------------------------------------------------- # +AMS_STAT_OKAY = 1 +AMS_STAT_TRIP = 0 +AMS_CTRL_OKAY = 1 +AMS_CTRL_TRIP = 0 + +def reset_ams(ams_stat): + ams_stat.state = AMS_STAT_OKAY + +def set_bspd_current(ch1, current): + ch1.state = ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(current)) + +def reset_bspd(fail, stat, ch1): + fail.state = 0 + stat.state = 0 + set_bspd_current(ch1, 0.0) + +IMD_STAT_OKAY = 1 +IMD_STAT_TRIP = 0 +def reset_imd(imd_stat): + imd_stat.state = IMD_STAT_OKAY + +def reset_pchg(v_bat, v_mc): + print(f"Setting v_bat to {tiff_hv_to_lv(ACCUM_NOM_V)}") + v_bat.state = tiff_hv_to_lv(ACCUM_NOM_V) + print(f"Setting v_mc to {tiff_hv_to_lv(0.0)}") + v_mc.state = tiff_hv_to_lv(0.0) + +def reset_tsal(v_mc): + v_mc.state = tiff_hv_to_lv(0.0) + +power = None + +CYCLE_POWER_ON_DELAY = 0.1 + +def cycle_power(): + power.state = 1 + time.sleep(0.75) + power.state = 0 + time.sleep(CYCLE_POWER_ON_DELAY) +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +@pytest.fixture(scope="session") +def hil(): + global power + + hil_instance = HIL() + + hil_instance.load_config("config_main_base_bench.json") + hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + hil_instance.init_can() + + power = hil_instance.dout("Arduino2", "RLY1") + + yield hil_instance + + hil_instance.shutdown() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +def test_precharge(hil): + # Begin the test + # hil.start_test(test_precharge.__name__) + + # Outputs + v_bat = hil.aout("Main_Module", "VBatt") + v_mc = hil.aout("Main_Module", "Voltage MC Transducer") + + # Inputs + pchg_cmplt = hil.mcu_pin("Main_Module", "PrechargeComplete_Prot") + not_pchg_cmplt_delayed = hil.din("Main_Module", "NotPrechargeCompleteSchmitt") + # v_bat_mcu = hil.daq_var("Main_Module", "Varname") # TODO + # v_mc_mcu = hil.daq_var("Main_Module", "Varname") # TODO + # pchg_mux = hil.daq_var("Main_Module", "Varname") # TODO + + # Initial State + reset_pchg(v_bat, v_mc) + time.sleep(2.5) + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on startup") + # hil.check(not_pchg_cmplt_delayed.state == 1, "Not precharge complete delayed high on startup") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on startup") + check.equal(not_pchg_cmplt_delayed.state, 1, "Not precharge complete delayed high on startup") + + # Check delay + v_mc.state = tiff_hv_to_lv(ACCUM_NOM_V) + t = utils.measure_trip_time(not_pchg_cmplt_delayed, PCHG_COMPLETE_DELAY_S*3, is_falling=True) + # hil.check(not_pchg_cmplt_delayed.state == 0, "Precharge complete delayed") + # hil.check_within(t, PCHG_COMPLETE_DELAY_S, 0.25, f"Precharge complete delay of {t:.3}s close to expected {PCHG_COMPLETE_DELAY_S}s") + check.equal(not_pchg_cmplt_delayed.state, 0, "Precharge complete delayed") + check.almost_equal(t, PCHG_COMPLETE_DELAY_S, abs=0.25, rel=0.0, msg=f"Precharge complete delay of {t:.3}s close to expected {PCHG_COMPLETE_DELAY_S}s") + + + # Find threshold at nominal pack voltage + for v in [ACCUM_MIN_V, ACCUM_NOM_V, ACCUM_MAX_V]: + reset_pchg(v_bat, v_mc) + print(f"Testing precharge threshold at V_bat = {v}") + v_bat.state = tiff_hv_to_lv(v) + v_mc.state = tiff_hv_to_lv(v*0.8) + time.sleep(0.01) + # hil.check(pchg_cmplt.state == 0, "Precharge Complete Low at Initial State") + check.equal(pchg_cmplt.state, 0, "Precharge Complete Low at Initial State") + + start = tiff_hv_to_lv(v*0.8) + stop = tiff_hv_to_lv(v) + step = tiff_hv_to_lv(1) + thresh = utils.measure_trip_thresh(v_mc, start, stop, step, 0.01, + pchg_cmplt, is_falling=0) + thresh_hv = tiff_lv_to_hv(thresh) + print(f"Precharge triggered at {thresh_hv / v * 100:.4}% ({thresh_hv:.5}V) of vbat={v}.") + # hil.check_within(thresh_hv / v, R_PCHG_V_BAT_THRESH, 0.03, f"Precharge threshold of {R_PCHG_V_BAT_THRESH*100}% at vbat = {v}V") + check.almost_equal(thresh_hv / v, R_PCHG_V_BAT_THRESH, abs=0.03, rel=0.0, msg=f"Precharge threshold of {R_PCHG_V_BAT_THRESH*100}% at vbat = {v}V") + + v_mc.state = tiff_hv_to_lv(v) + time.sleep(0.25) + # hil.check(pchg_cmplt.state == 1, f"Precharge completed at vbat = {v}V") + check.equal(pchg_cmplt.state, 1, f"Precharge completed at vbat = {v}V") + + + # Floating conditions (check never precharge complete) + reset_pchg(v_bat, v_mc) + v_bat.hiZ() + v_mc.state = tiff_hv_to_lv(0) + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc 0V") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat float, v_mc 0V") + + v_mc.state = tiff_hv_to_lv(ACCUM_MAX_V) + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc max V") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat float, v_mc max V") + + reset_pchg(v_bat, v_mc) + v_mc.hiZ() + v_bat.state = tiff_hv_to_lv(ACCUM_MIN_V) + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat min, v_mc float") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat min, v_mc float") + v_bat.state = tiff_hv_to_lv(ACCUM_MAX_V) + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat max, v_mc float") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat max, v_mc float") + + reset_pchg(v_bat, v_mc) + v_bat.hiZ() + v_mc.hiZ() + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc float") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat float, v_mc float") + + # TODO: software precharge validity checks (make precharge take forever) + # hil.end_test() +# ---------------------------------------------------------------------------- # + +# ---------------------------------------------------------------------------- # +def test_bspd(hil): + # Begin the test + # hil.start_test(test_bspd.__name__) + + # Outputs + brk_fail = hil.dout("Main_Module", "Brake Fail") + brk_stat = hil.dout("Main_Module", "Brake Status") + c_sense = hil.aout("Main_Module", "Current Sense C1") + + # Outputs to set SDC status to okay + ams_stat = hil.dout("Main_Module", "BMS-Status-Main") + imd_stat = hil.dout("Main_Module", "IMD_Status") + + # Inputs + bspd_ctrl = hil.din("Main_Module", "SDC3") # Assuming IMD and AMS closed + + # Set other SDC nodes to okay + reset_ams(ams_stat) + reset_imd(imd_stat) + + # Brake Fail + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power() + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + brk_fail.state = 1 + t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") + check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") + brk_fail.state = 0 + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 0, "Brake Fail Stays Latched") + check.equal(bspd_ctrl.state, 0, "Brake Fail Stays Latched") + + # Brake Fail on Power On + reset_bspd(brk_fail, brk_stat, c_sense) + # Manual power cycle, setting brk_fail on before + # Will cause power to feed back into system + power.state = 1 + time.sleep(2) + brk_fail.state = 1 + power.state = 0 + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 0, "Power On Brake Fail") + check.equal(bspd_ctrl.state, 0, "Power On Brake Fail") + + # Current no brake + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power() + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + time.sleep(2) # TODO: I am not sure why this fails, but oh well + set_bspd_current(c_sense, 75) + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # time.sleep(100) + + # hil.check(bspd_ctrl.state == 1, "Current no brake") + check.equal(bspd_ctrl.state, 1, "Current no brake") + + # Current Sense Short to Ground + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power() + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + c_sense.state = 0.0 + t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") + check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") + set_bspd_current(c_sense, 0.0) + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 0, "Current short to ground stays latched") + check.equal(bspd_ctrl.state, 0, "Current short to ground stays latched") + + # Current Sense Short to 5V + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power() + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + c_sense.state = ABOX_DHAB_CH1_DIV.div(5.0) + t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") + check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") + set_bspd_current(c_sense, 0.0) + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 0, "Current short to 5V stays latched") + check.equal(bspd_ctrl.state, 0, "Current short to 5V stays latched") + + # Braking + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power() + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + brk_stat.state = 1 + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 1, "Brake no current") + check.equal(bspd_ctrl.state, 1, "Brake no current") + + # Lowest current required to trip at + min_trip_current = R_BSPD_POWER_THRESH_W / ACCUM_MAX_V + set_bspd_current(c_sense, min_trip_current) + t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Braking with current") + check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Braking with current") + + # Measure braking with current threshold + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power() + brk_stat.state = 1 + + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + start = ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(0.0)) + stop = ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(DHAB_S124_CH1_MAX_A)) + step = 0.1 + thresh = utils.measure_trip_thresh(c_sense, start, stop, step, + R_BSPD_MAX_TRIP_TIME_S, + bspd_ctrl, is_falling=True) + thresh_amps = dhab_ch1_v_to_a(ABOX_DHAB_CH1_DIV.reverse(thresh)) + print(f"Current while braking threshold: {thresh}V = {thresh_amps}A") + # hil.check_within(thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), 0.1, "Current while braking threshold") + check.almost_equal( + thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), + abs=0.1, rel=0.0, + msg="Current while braking threshold" + ) + + # Determine the current sense short to gnd threshold + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power() + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + set_bspd_current(c_sense, DHAB_S124_CH1_MIN_A) + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 1, "Min output current okay") + check.equal(bspd_ctrl.state, 1, "Min output current okay") + start = ABOX_DHAB_CH1_DIV.div(DHAB_S124_MIN_OUT_V) + stop = 0.0 + step = -0.1 + thresh = utils.measure_trip_thresh(c_sense, start, stop, step, + R_BSPD_MAX_TRIP_TIME_S, + bspd_ctrl, is_falling=True) + print(f"Short to ground threshold: {thresh}V") + # hil.check(stop < (thresh) < start, "Current short to ground threshold") + check.between(thresh, stop, start, "Current short to ground threshold") + + # Determine the current sense short to 5V threshold + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power() + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + time.sleep(2) + + set_bspd_current(c_sense, DHAB_S124_CH1_MAX_A) + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 1, "Max output current okay") + check.equal(bspd_ctrl.state, 1, "Max output current okay") + start = ABOX_DHAB_CH1_DIV.div(DHAB_S124_MAX_OUT_V) + stop = ABOX_DHAB_CH1_DIV.div(5.0) + step = 0.01 + + thresh = utils.measure_trip_thresh(c_sense, start, stop, step, + R_BSPD_MAX_TRIP_TIME_S, + bspd_ctrl, is_falling=True) + print(f"Short to 5V threshold: {thresh}V") + # hil.check(bspd_ctrl.state == 0, "Short to 5V trips") + check.equal(bspd_ctrl.state, 0, "Short to 5V trips") + print(stop) + print(start) + # hil.check(start < (thresh) <= stop, "Current short to 5V threshold") + check.between(thresh, stop, start, "Current short to 5V threshold", le=True) + + # Floating current + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power() + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + c_sense.hiZ() + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 0, "Floating current") + check.equal(bspd_ctrl.state, 0, "Floating current") + + # Floating brake_fail + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power() + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + brk_fail.hiZ() + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 0, "Floating brake fail") + check.equal(bspd_ctrl.state, 0, "Floating brake fail") + + # Floating brake_stat + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power() + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + brk_stat.hiZ() + set_bspd_current(c_sense, min_trip_current) + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 0, "Floating brake status") + check.equal(bspd_ctrl.state, 0, "Floating brake status") + + # End the test + # hil.end_test() +# ---------------------------------------------------------------------------- # + +# ---------------------------------------------------------------------------- # +IMD_RC_MIN_TRIP_TIME_S = IMD_STARTUP_TIME_S +IMD_RC_MAX_TRIP_TIME_S = R_IMD_MAX_TRIP_TIME_S - IMD_MEASURE_TIME_S +IMD_CTRL_OKAY = 1 +IMD_CTRL_TRIP = 0 + +def test_imd(hil): + # Begin the test + # hil.start_test(test_imd.__name__) + + # Outputs + imd_stat = hil.dout("Main_Module", "IMD_Status") + + # Outputs to set SDC status to okay + ams_stat = hil.dout("Main_Module", "BMS-Status-Main") + brk_fail = hil.dout("Main_Module", "Brake Fail") + brk_stat = hil.dout("Main_Module", "Brake Status") + c_sense = hil.aout("Main_Module", "Current Sense C1") + + # Inputs + imd_ctrl = hil.din("Main_Module", "SDC3") # assuming AMS and BSPD closed + + # Set other SDC nodes to okay + reset_ams(ams_stat) + reset_bspd(brk_fail, brk_stat, c_sense) + + # IMD Fault + reset_imd(imd_stat) + cycle_power() + # hil.check(imd_ctrl.state == IMD_CTRL_OKAY, "Power On") + check.equal(imd_ctrl.state, IMD_CTRL_OKAY, "Power On") + time.sleep(1) + imd_stat.state = IMD_STAT_TRIP + t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) + print(f"Target trip time: [{IMD_RC_MIN_TRIP_TIME_S}, {IMD_RC_MAX_TRIP_TIME_S}]") + # hil.check(IMD_RC_MIN_TRIP_TIME_S < t < IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Trip") + check.between(t, IMD_RC_MIN_TRIP_TIME_S, IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Trip") + imd_stat.state = IMD_STAT_OKAY + time.sleep(IMD_RC_MAX_TRIP_TIME_S * 1.1) + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Stays Latched") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Stays Latched") + + # IMD Fault on Power On + reset_imd(imd_stat) + imd_stat.state = IMD_STAT_TRIP + cycle_power() + time.sleep(IMD_RC_MAX_TRIP_TIME_S) + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Power On") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Power On") + + # IMD Floating + reset_imd(imd_stat) + imd_stat.hiZ() + cycle_power() + t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) + # hil.check(t < R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Floating Trip") + check.between(t, 0, R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Floating Trip") + + # hil.end_test() +# ---------------------------------------------------------------------------- # + +# ---------------------------------------------------------------------------- # +def test_ams(hil): + # Begin the test + # hil.start_test(test_ams.__name__) + + # Outputs + ams_stat = hil.dout("Main_Module", "BMS-Status-Main") + + # Outputs to set SDC status to okay + imd_stat = hil.dout("Main_Module", "IMD_Status") + brk_fail = hil.dout("Main_Module", "Brake Fail") + brk_stat = hil.dout("Main_Module", "Brake Status") + c_sense = hil.aout("Main_Module", "Current Sense C1") + + # Inputs + ams_ctrl = hil.din("Main_Module", "SDC3") # assumes IMD and BSPD closed + + # Set other SDC nodes to okay + reset_imd(imd_stat) + reset_bspd(brk_fail, brk_stat, c_sense) + + # AMS Fault + reset_ams(ams_stat) + cycle_power() + # hil.check(ams_ctrl.state == AMS_CTRL_OKAY, "Power On") + check.equal(ams_ctrl.state, AMS_CTRL_OKAY, "Power On") + time.sleep(1) + ams_stat.state = AMS_STAT_TRIP + t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) + # hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Trip") + check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Trip") + ams_stat.state = AMS_STAT_OKAY + time.sleep(AMS_MAX_TRIP_DELAY_S * 1.1) + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Stays Latched") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Stays Latched") + + # AMS Fault on Power On + reset_ams(ams_stat) + ams_stat.state = AMS_STAT_TRIP + cycle_power() + time.sleep(AMS_MAX_TRIP_DELAY_S) + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Power On") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Power On") + + # AMS Floating + reset_ams(ams_stat) + ams_stat.hiZ() + cycle_power() + t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) + # hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Floating Trip") + check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Floating Trip") + + # hil.end_test() +# ---------------------------------------------------------------------------- # + +# ---------------------------------------------------------------------------- # +def test_tsal(hil): + + # Begin the test + # hil.start_test(test_tsal.__name__) + + # Outputs + v_mc = hil.aout("Main_Module", "Voltage MC Transducer") + + # Inputs + tsal = hil.din("Main_Module", "TSAL+") + lval = hil.din("Main_Module", "LVAL+") + + # Initial State + reset_tsal(v_mc) + time.sleep(0.2) + # No need to power cycle + + # hil.check(lval.state == 1, "LVAL on at v_mc = 0") + # hil.check(tsal.state == 0, "TSAL off at v_mc = 0") + check.equal(lval.state, 1, "LVAL on at v_mc = 0") + check.equal(tsal.state, 0, "TSAL off at v_mc = 0") + + time.sleep(5) + # hil.check(lval.state == 1, "LVAL stays on") + check.equal(lval.state, 1, "LVAL stays on") + + v_mc.state = tiff_hv_to_lv(ACCUM_MIN_V) + time.sleep(0.1) + + # hil.check(lval.state == 0, f"LVAL off at {ACCUM_MIN_V:.4} V") + # hil.check(tsal.state == 1, f"TSAL on at {ACCUM_MIN_V:.4} V") + check.equal(lval.state, 0, f"LVAL off at {ACCUM_MIN_V:.4} V") + check.equal(tsal.state, 1, f"TSAL on at {ACCUM_MIN_V:.4} V") + + reset_tsal(v_mc) + time.sleep(0.2) + # hil.check(lval.state == 1, f"LVAL turns back on") + check.equal(lval.state, 1, f"LVAL turns back on") + + start = tiff_hv_to_lv(0.0) + stop = tiff_hv_to_lv(R_TSAL_HV_V * 1.5) + step = tiff_hv_to_lv(1) + thresh = utils.measure_trip_thresh(v_mc, start, stop, step, + 0.01, + tsal, is_falling=False) + thresh = tiff_lv_to_hv(thresh) + print(f"TSAL on at {thresh:.4} V") + # hil.check_within(thresh, R_TSAL_HV_V, 4, f"TSAL trips at {R_TSAL_HV_V:.4} +-4") + # hil.check(lval.state == 0, f"LVAL off V") + # hil.check(tsal.state == 1, f"TSAL on V") + check.almost_equal(thresh, R_TSAL_HV_V, abs=4, rel=0.0, msg=f"TSAL trips at {R_TSAL_HV_V:.4} +-4") + check.equal(lval.state, 0, f"LVAL off V") + check.equal(tsal.state, 1, f"TSAL on V") + + # hil.end_test() +# ---------------------------------------------------------------------------- # \ No newline at end of file From b7351e2840ed7fd25c202e8708a0dfd5c9396fd5 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 12 Oct 2024 14:43:42 -0400 Subject: [PATCH 020/181] Confirming that non "hil" params are not effected --- pytest-example/fake_test.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pytest-example/fake_test.py b/pytest-example/fake_test.py index 0646f98..a85317e 100644 --- a/pytest-example/fake_test.py +++ b/pytest-example/fake_test.py @@ -40,17 +40,23 @@ def wrapper_function(*args, **kwargs): @log_function_start_end def do_something(): - pass + print("Doing something") + +@log_function_start_end +def do_something_with_args(arg1, arg2): + print(f"Arg1: {arg1}, Arg2: {arg2}") def test_fake(param): check.equal(1, 1, "Power") do_something() check.equal(2, 3, "Fire") check.equal(3, 3, "Cooling") + do_something_with_args(1, 2) check.equal(4, 5, "Brakes") do_something() check.equal(5, 5, "Steering") check.equal(6, 6, "Suspension") + do_something_with_args(3, 4) check.between_equal(5, 1, 10, "Speed") check.between_equal(11, 1, 10, "Speed 2") @@ -58,12 +64,14 @@ def test_fake2(param): check.is_true(False, "A") check.is_true(True, "B") check.is_true(False, "C") + do_something_with_args(5, 6) check.is_true(True, "D") def test_fake3(param): check.is_true(True, "True 1") check.is_true(True, "True 2") check.is_true(True, "True 3") + do_something_with_args(7, 8) check.is_true(True, "True 4") def test_fake4(param): From e52a1668ce86c637fcffc6cee3a4d74e1f081f10 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 12 Oct 2024 14:44:04 -0400 Subject: [PATCH 021/181] Trying Pyest for main sdc --- scripts/pytest_main_sdc.py | 369 +++++++++++++++++++++++++++++++++++++ 1 file changed, 369 insertions(+) create mode 100644 scripts/pytest_main_sdc.py diff --git a/scripts/pytest_main_sdc.py b/scripts/pytest_main_sdc.py new file mode 100644 index 0000000..040b90a --- /dev/null +++ b/scripts/pytest_main_sdc.py @@ -0,0 +1,369 @@ +from os import sys, path +sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) +from hil import HIL +import utils +import time +from rules_constants import * +from vehicle_constants import * + +import pytest_check as check +import pytest + + +# ---------------------------------------------------------------------------- # +@pytest.fixture(scope="session") +def hil(): + global power + + hil_instance = HIL() + + hil_instance.load_config("config_main_sdc_bench.json") + hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + # hil_instance.init_can() + + power = hil_instance.dout("RearTester", "RLY1") + + yield hil_instance + + hil_instance.shutdown() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +# SETUP for CSENSE +# Current Sensor (DHAB) -> ABOX V Divider -> MAIN_SDC + +DAC_GAIN = 1 + 4.7 / 4.7 - 0.05 + +def cycle_power(pow): + pow.state = 0 + time.sleep(0.75) + pow.state = 1 + +def set_bspd_current(ch1, current): + v = ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(current)) + ch1.state = v / DAC_GAIN + +def reset_bspd(fail, stat, ch1): + fail.state = 0 + stat.state = 0 + set_bspd_current(ch1, 0.0) + + +# ---------------------------------------------------------------------------- # +def test_bspd(hil): + # Begin the test + # hil.start_test(test_bspd.__name__) + + # Outputs + brk_fail = hil.dout("MainSDC", "Brake Fail") + brk_stat = hil.dout("MainSDC", "Brake Status") + c_sense = hil.aout("MainSDC", "Current Sense C1") + pow = hil.dout("MainSDC", "5V_Crit") + + # Inputs + bspd_ctrl = hil.din("MainSDC", "BSPD_Control") + + # Brake Fail + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power(pow) + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + brk_fail.state = 1 + t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") + check.below(t, R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") + brk_fail.state = 0 + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 0, "Brake Fail Stays Latched") + check.equal(bspd_ctrl.state, 0, "Brake Fail Stays Latched") + + # Brake Fail on Power On + reset_bspd(brk_fail, brk_stat, c_sense) + brk_fail.state = 1 + cycle_power(pow) + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 0, "Power On Brake Fail") + check.equal(bspd_ctrl.state, 0, "Power On Brake Fail") + + # Current no brake + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power(pow) + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + time.sleep(2) # TODO: I am not sure why this fails, but oh well + set_bspd_current(c_sense, 75) + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # time.sleep(100) + + # hil.check(bspd_ctrl.state == 1, "Current no brake") + check.equal(bspd_ctrl.state, 1, "Current no brake") + + # Current Sense Short to Ground + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power(pow) + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + c_sense.state = 0.0 + t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") + check.below(t, R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") + set_bspd_current(c_sense, 0.0) + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 0, "Current short to ground stays latched") + check.equal(bspd_ctrl.state, 0, "Current short to ground stays latched") + + # Current Sense Short to 5V + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power(pow) + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + c_sense.state = ABOX_DHAB_CH1_DIV.div(5.0) / DAC_GAIN + t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") + check.below(t, R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") + set_bspd_current(c_sense, 0.0) + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 0, "Current short to 5V stays latched") + check.equal(bspd_ctrl.state, 0, "Current short to 5V stays latched") + + # Braking + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power(pow) + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + brk_stat.state = 1 + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 1, "Brake no current") + check.equal(bspd_ctrl.state, 1, "Brake no current") + + # Lowest current required to trip at + min_trip_current = R_BSPD_POWER_THRESH_W / ACCUM_MAX_V + set_bspd_current(c_sense, min_trip_current) + t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Braking with current") + check.below(t, R_BSPD_MAX_TRIP_TIME_S, "Braking with current") + + # Measure braking with current threshold + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power(pow) + brk_stat.state = 1 + + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + start = ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(0.0)) / DAC_GAIN + stop = ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(DHAB_S124_CH1_MAX_A)) / DAC_GAIN + step = 0.1 / DAC_GAIN + thresh = utils.measure_trip_thresh(c_sense, start, stop, step, + R_BSPD_MAX_TRIP_TIME_S, + bspd_ctrl, is_falling=True) + thresh *= DAC_GAIN + thresh_amps = dhab_ch1_v_to_a(ABOX_DHAB_CH1_DIV.reverse(thresh)) + print(f"Current while braking threshold: {thresh}V = {thresh_amps}A") + # hil.check_within(thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), 0.1, "Current while braking threshold") + check.within(thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), 0.1, "Current while braking threshold") + + # Determine the current sense short to gnd threshold + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power(pow) + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + set_bspd_current(c_sense, DHAB_S124_CH1_MIN_A) + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 1, "Min output current okay") + check.equal(bspd_ctrl.state, 1, "Min output current okay") + start = ABOX_DHAB_CH1_DIV.div(DHAB_S124_MIN_OUT_V) / DAC_GAIN + stop = 0.0 + step = -0.1 / DAC_GAIN + thresh = utils.measure_trip_thresh(c_sense, start, stop, step, + R_BSPD_MAX_TRIP_TIME_S, + bspd_ctrl, is_falling=True) + thresh *= DAC_GAIN + print(f"Short to ground threshold: {thresh}V") + # hil.check(stop < (thresh / DAC_GAIN) < start, "Current short to ground threshold") + check.between(thresh / DAC_GAIN, stop, start, "Current short to ground threshold") + + # Determine the current sense short to 5V threshold + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power(pow) + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + time.sleep(2) + + set_bspd_current(c_sense, DHAB_S124_CH1_MAX_A) + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 1, "Max output current okay") + check.equal(bspd_ctrl.state, 1, "Max output current okay") + start = ABOX_DHAB_CH1_DIV.div(DHAB_S124_MAX_OUT_V) / DAC_GAIN + stop = ABOX_DHAB_CH1_DIV.div(5.0) / DAC_GAIN + step = 0.01 / DAC_GAIN + + thresh = utils.measure_trip_thresh(c_sense, start, stop, step, + R_BSPD_MAX_TRIP_TIME_S, + bspd_ctrl, is_falling=True) + thresh *= DAC_GAIN + print(f"Short to 5V threshold: {thresh}V") + # hil.check(bspd_ctrl.state == 0, "Short to 5V trips") + check.equal(bspd_ctrl.state, 0, "Short to 5V trips") + print(stop * DAC_GAIN) + print(start * DAC_GAIN) + # hil.check(start < (thresh / DAC_GAIN) <= stop, "Current short to 5V threshold") + check.between(thresh / DAC_GAIN, stop, start, "Current short to 5V threshold") + + # Floating current + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power(pow) + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + c_sense.hiZ() + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 0, "Floating current") + check.equal(bspd_ctrl.state, 0, "Floating current") + + # Floating brake_fail + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power(pow) + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + brk_fail.hiZ() + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 0, "Floating brake fail") + check.equal(bspd_ctrl.state, 0, "Floating brake fail") + + # Floating brake_stat + reset_bspd(brk_fail, brk_stat, c_sense) + cycle_power(pow) + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + brk_stat.hiZ() + set_bspd_current(c_sense, min_trip_current) + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 0, "Floating brake status") + check.equal(bspd_ctrl.state, 0, "Floating brake status") + + # End the test + # hil.end_test() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +IMD_RC_MIN_TRIP_TIME_S = IMD_STARTUP_TIME_S +IMD_RC_MAX_TRIP_TIME_S = R_IMD_MAX_TRIP_TIME_S - IMD_MEASURE_TIME_S +IMD_STAT_OKAY = 1 +IMD_STAT_TRIP = 0 +IMD_CTRL_OKAY = 1 +IMD_CTRL_TRIP = 0 + +def reset_imd(imd_stat): + imd_stat.state = IMD_STAT_OKAY + + +def test_imd(hil): + # Begin the test + # hil.start_test(test_imd.__name__) + + # Outputs + imd_stat = hil.dout("MainSDC", "IMD_Status") + pow = hil.dout("MainSDC", "5V_Crit") + + # Inputs + imd_ctrl = hil.din("MainSDC", "IMD_Control") + + # IMD Fault + reset_imd(imd_stat) + cycle_power(pow) + # hil.check(imd_ctrl.state == IMD_CTRL_OKAY, "Power On") + check.equal(imd_ctrl.state, IMD_CTRL_OKAY, "Power On") + time.sleep(1) + imd_stat.state = IMD_STAT_TRIP + t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) + # hil.check(IMD_RC_MIN_TRIP_TIME_S < t < IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Trip") + check.between(t, IMD_RC_MIN_TRIP_TIME_S, IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Trip") + imd_stat.state = IMD_STAT_OKAY + time.sleep(IMD_RC_MAX_TRIP_TIME_S * 1.1) + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Stays Latched") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Stays Latched") + + # IMD Fault on Power On + reset_imd(imd_stat) + imd_stat.state = IMD_STAT_TRIP + cycle_power(pow) + time.sleep(IMD_RC_MAX_TRIP_TIME_S) + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Power On") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Power On") + + # IMD Floating + reset_imd(imd_stat) + imd_stat.hiZ() + cycle_power(pow) + t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) + # hil.check(t < R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Floating Trip") + check.below(t, R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Floating Trip") + + # hil.end_test() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +AMS_STAT_OKAY = 1 +AMS_STAT_TRIP = 0 +AMS_CTRL_OKAY = 1 +AMS_CTRL_TRIP = 0 + +def reset_ams(ams_stat): + ams_stat.state = AMS_STAT_OKAY + + +def test_ams(hil): + # Begin the test + # hil.start_test(test_ams.__name__) + + # Outputs + ams_stat = hil.dout("MainSDC", "BMS-Status-Main") + pow = hil.dout("MainSDC", "5V_Crit") + + # Inputs + ams_ctrl = hil.din("MainSDC", "BMS_Control") + + # AMS Fault + reset_ams(ams_stat) + cycle_power(pow) + # hil.check(ams_ctrl.state == AMS_CTRL_OKAY, "Power On") + check.equal(ams_ctrl.state, AMS_CTRL_OKAY, "Power On") + time.sleep(1) + ams_stat.state = AMS_STAT_TRIP + t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) + # hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Trip") + check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Trip") + ams_stat.state = AMS_STAT_OKAY + time.sleep(AMS_MAX_TRIP_DELAY_S * 1.1) + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Stays Latched") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Stays Latched") + + # AMS Fault on Power On + reset_ams(ams_stat) + ams_stat.state = AMS_STAT_TRIP + cycle_power(pow) + time.sleep(AMS_MAX_TRIP_DELAY_S) + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Power On") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Power On") + + # AMS Floating + reset_ams(ams_stat) + ams_stat.hiZ() + cycle_power(pow) + t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) + # hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Floating Trip") + check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time", ge=True) + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Floating Trip") + + # hil.end_test() +# ---------------------------------------------------------------------------- # \ No newline at end of file From e91075ba41847adecd44588c12c32460c549450f Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 12 Oct 2024 15:08:57 -0400 Subject: [PATCH 022/181] Typo: these tests don't read power Result of copying and pasting without looking :shrug: --- scripts/pytest_collector.py | 4 ---- scripts/pytest_main_sdc.py | 4 ---- 2 files changed, 8 deletions(-) diff --git a/scripts/pytest_collector.py b/scripts/pytest_collector.py index 30cdd2f..382f977 100644 --- a/scripts/pytest_collector.py +++ b/scripts/pytest_collector.py @@ -11,8 +11,6 @@ # ---------------------------------------------------------------------------- # @pytest.fixture(scope="session") def hil(): - global power - hil_instance = HIL() hil_instance.load_config("config_collector_bench.json") @@ -20,8 +18,6 @@ def hil(): # hil_instance.init_can() - power = hil_instance.dout("RearTester", "RLY1") - yield hil_instance hil_instance.shutdown() diff --git a/scripts/pytest_main_sdc.py b/scripts/pytest_main_sdc.py index 040b90a..119d7a1 100644 --- a/scripts/pytest_main_sdc.py +++ b/scripts/pytest_main_sdc.py @@ -13,8 +13,6 @@ # ---------------------------------------------------------------------------- # @pytest.fixture(scope="session") def hil(): - global power - hil_instance = HIL() hil_instance.load_config("config_main_sdc_bench.json") @@ -22,8 +20,6 @@ def hil(): # hil_instance.init_can() - power = hil_instance.dout("RearTester", "RLY1") - yield hil_instance hil_instance.shutdown() From 6eb1c25589f1b354389384111a9ce3683cb7fb60 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 12 Oct 2024 15:09:08 -0400 Subject: [PATCH 023/181] Trying Pytest system --- scripts/pytest_system.py | 857 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 857 insertions(+) create mode 100644 scripts/pytest_system.py diff --git a/scripts/pytest_system.py b/scripts/pytest_system.py new file mode 100644 index 0000000..967f915 --- /dev/null +++ b/scripts/pytest_system.py @@ -0,0 +1,857 @@ +from os import sys, path +sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) +from hil import HIL +import utils +import time +from rules_constants import * +from vehicle_constants import * + +import pytest_check as check +import pytest + + +# ---------------------------------------------------------------------------- # +AMS_STAT_OKAY = 1 +AMS_STAT_TRIP = 0 +AMS_CTRL_OKAY = 1 +AMS_CTRL_TRIP = 0 + +def reset_ams(ams_stat): + ams_stat.state = AMS_STAT_OKAY + +def set_bspd_current(ch1, current): + c = ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(current)) + #print(f"bspd current: {current} voltage: {c}") + ch1.state = c + +def reset_bspd(brk1, brk2, ch1): + brk1.state = BRK_1_REST_V + brk2.state = BRK_2_REST_V + set_bspd_current(ch1, 0.0) + +IMD_STAT_OKAY = 1 +IMD_STAT_TRIP = 0 +def reset_imd(imd_stat): + imd_stat.state = IMD_STAT_OKAY + +def reset_pchg(v_bat, v_mc): + print(f"Setting v_bat to {tiff_hv_to_lv(ACCUM_NOM_V)}") + v_bat.state = tiff_hv_to_lv(ACCUM_NOM_V) + print(f"Setting v_mc to {tiff_hv_to_lv(0.0)}") + v_mc.state = tiff_hv_to_lv(0.0) + +def reset_tsal(v_mc): + v_mc.state = tiff_hv_to_lv(0.0) + +power = None + +CYCLE_POWER_OFF_DELAY = 2.0 +CYCLE_POWER_ON_DELAY = 3.0 + +def cycle_power(): + power.state = 1 + time.sleep(CYCLE_POWER_OFF_DELAY) + power.state = 0 + time.sleep(CYCLE_POWER_ON_DELAY) +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +@pytest.fixture(scope="session") +def hil(): + global power + + hil_instance = HIL() + + hil_instance.load_config("config_charger.json") + hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + # hil_instance.init_can() + + power = hil_instance.dout("RearTester", "RLY1") + + yield hil_instance + + hil_instance.shutdown() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +def test_precharge(hil): + # Begin the test + # hil.start_test(test_precharge.__name__) + + # Outputs + v_bat = hil.aout("Main_Module", "VBatt") + v_mc = hil.aout("Main_Module", "Voltage MC Transducer") + + # Inputs + pchg_cmplt = hil.mcu_pin("Main_Module", "PrechargeComplete_Prot") + not_pchg_cmplt_delayed = hil.din("Main_Module", "NotPrechargeCompleteSchmitt") + # v_bat_mcu = hil.daq_var("Main_Module", "Varname") # TODO + # v_mc_mcu = hil.daq_var("Main_Module", "Varname") # TODO + # pchg_mux = hil.daq_var("Main_Module", "Varname") # TODO + + # Outputs to set SDC status to okay + imd_stat = hil.dout("Main_Module", "IMD_Status") + brk1 = hil.aout("Dashboard", "BRK1_RAW") + brk2 = hil.aout("Dashboard", "BRK2_RAW") + c_sense = hil.aout("Main_Module", "Current Sense C1") + ams_stat = hil.dout("Main_Module", "BMS-Status-Main") + reset_imd(imd_stat) + reset_bspd(brk1, brk2, c_sense) + reset_ams(ams_stat) + + cycle_power() + + # Initial State + reset_pchg(v_bat, v_mc) + time.sleep(2.5) + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on startup") + # hil.check(not_pchg_cmplt_delayed.state == 1, "Not precharge complete delayed high on startup") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on startup") + check.equal(not_pchg_cmplt_delayed.state, 1, "Not precharge complete delayed high on startup") + # Check delay + v_mc.state = tiff_hv_to_lv(ACCUM_NOM_V) + t = utils.measure_trip_time(not_pchg_cmplt_delayed, PCHG_COMPLETE_DELAY_S*3, is_falling=True) + # hil.check(not_pchg_cmplt_delayed.state == 0, "Precharge complete delayed") + # hil.check_within(t, PCHG_COMPLETE_DELAY_S, 0.25, f"Precharge complete delay of {t:.3}s close to expected {PCHG_COMPLETE_DELAY_S}s") + check.equal(not_pchg_cmplt_delayed.state, 0, "Precharge complete delayed") + check.almost_equal(t, PCHG_COMPLETE_DELAY_S, abs=0.25, rel=0.0, msg=f"Precharge complete delay of {t:.3}s close to expected {PCHG_COMPLETE_DELAY_S}s") + + # Find threshold at nominal pack voltage + for v in [ACCUM_MIN_V, ACCUM_NOM_V, ACCUM_MAX_V]: + reset_pchg(v_bat, v_mc) + print(f"Testing precharge threshold at V_bat = {v}") + v_bat.state = tiff_hv_to_lv(v) + v_mc.state = tiff_hv_to_lv(v*0.8) + #time.sleep(0.01) + time.sleep(0.5) + # hil.check(pchg_cmplt.state == 0, "Precharge Complete Low at Initial State") + check.equal(pchg_cmplt.state, 0, "Precharge Complete Low at Initial State") + + start = tiff_hv_to_lv(v*0.8) + stop = tiff_hv_to_lv(v) + step = tiff_hv_to_lv(1) + thresh = utils.measure_trip_thresh(v_mc, start, stop, step, 0.1, + pchg_cmplt, is_falling=0) + thresh_hv = tiff_lv_to_hv(thresh) + print(f"Precharge triggered at {thresh_hv / v * 100:.4}% ({thresh_hv:.5}V) of vbat={v}.") + # hil.check_within(thresh_hv / v, R_PCHG_V_BAT_THRESH, 0.03, f"Precharge threshold of {R_PCHG_V_BAT_THRESH*100}% at vbat = {v}V") + check.almost_equal(thresh_hv / v, R_PCHG_V_BAT_THRESH, abs=0.03, rel=0.0, msg=f"Precharge threshold of {R_PCHG_V_BAT_THRESH*100}% at vbat = {v}V") + v_mc.state = tiff_hv_to_lv(v) + #time.sleep(0.25) + time.sleep(8) + # hil.check(pchg_cmplt.state == 1, f"Precharge completed at vbat = {v}V") + check.equal(pchg_cmplt.state, 1, f"Precharge completed at vbat = {v}V") + + + # Floating conditions (check never precharge complete) + reset_pchg(v_bat, v_mc) + v_bat.hiZ() + v_mc.state = tiff_hv_to_lv(0) + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc 0V") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat float, v_mc 0V") + v_mc.state = tiff_hv_to_lv(ACCUM_MAX_V) + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc max V") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat float, v_mc max V") + + reset_pchg(v_bat, v_mc) + v_mc.hiZ() + v_bat.state = tiff_hv_to_lv(ACCUM_MIN_V) + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat min, v_mc float") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat min, v_mc float") + v_bat.state = tiff_hv_to_lv(ACCUM_MAX_V) + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat max, v_mc float") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat max, v_mc float") + + reset_pchg(v_bat, v_mc) + v_bat.hiZ() + v_mc.hiZ() + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc float") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat float, v_mc float") + + # TODO: software precharge validity checks (make precharge take forever) + # hil.end_test() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +BRK_SWEEP_DELAY = 0.1 +BSPD_DASH_ON_TIME = 0 + +def test_bspd(hil): + # Begin the test + # hil.start_test(test_bspd.__name__) + + # Outputs + brk1 = hil.aout("Dashboard", "BRK1_RAW") + brk2 = hil.aout("Dashboard", "BRK2_RAW") + c_sense = hil.aout("Main_Module", "Current Sense C1") + + # Outputs to set SDC status to okay + ams_stat = hil.dout("Main_Module", "BMS-Status-Main") + imd_stat = hil.dout("Main_Module", "IMD_Status") + + # Inputs + bspd_ctrl = hil.din("Main_Module", "SDC15") # assuming AMS and BSPD closed + + brk_fail_tap = hil.mcu_pin("Dashboard", "BRK_FAIL_TAP") + brk_stat_tap = hil.mcu_pin("Dashboard", "BRK_STAT_TAP") + + # Set other SDC nodes to okay + reset_ams(ams_stat) + reset_imd(imd_stat) + # BOTS assumed to be good + + # Brake threshold check + brk1.state = BRK_1_REST_V + brk2.state = BRK_2_REST_V + # hil.check(brk_stat_tap.state == 0, "Brake stat starts low") + check.equal(brk_stat_tap.state, 0, "Brake stat starts low") + brk1.state = BRK_1_THRESH_V + time.sleep(0.1) + # hil.check(brk_stat_tap.state == 1, "Brake stat goes high at brk 1 thresh") + check.equal(brk_stat_tap.state, 1, "Brake stat goes high at brk 1 thresh") + brk1.state = BRK_1_REST_V + # hil.check(brk_stat_tap.state == 0, "Brake stat starts low") + check.equal(brk_stat_tap.state, 0, "Brake stat starts low") + brk2.state = BRK_2_THRESH_V + time.sleep(0.1) + # hil.check(brk_stat_tap.state == 1, "Brake stat goes high at brk 2 thresh") + check.equal(brk_stat_tap.state, 1, "Brake stat goes high at brk 2 thresh") + brk1.state = BRK_1_THRESH_V + # hil.check(brk_stat_tap.state == 1, "Brake stat stays high for both brakes") + check.equal(brk_stat_tap.state, 1, "Brake stat stays high for both brakes") + + # Brake threshold scan + brk1.state = BRK_MIN_OUT_V + brk2.state = BRK_MIN_OUT_V + time.sleep(0.1) + # hil.check(brk_stat_tap.state == 0, "Brake Stat Starts Low Brk 1") + check.equal(brk_stat_tap.state, 0, "Brake Stat Starts Low Brk 1") + + start = BRK_MIN_OUT_V + stop = BRK_MAX_OUT_V + step = 0.1 + + thresh = utils.measure_trip_thresh(brk1, start, stop, step, + BRK_SWEEP_DELAY, + brk_stat_tap, is_falling=False) + print(f"Brake 1 braking threshold: {thresh}") + # hil.check_within(thresh, BRK_1_THRESH_V, 0.2, "Brake 1 trip voltage") + # hil.check(brk_stat_tap.state == 1, "Brake Stat Tripped for Brk 1") + check.almost_equal(thresh, BRK_1_THRESH_V, abs=0.2, rel=0.0, msg="Brake 1 trip voltage") + check.equal(brk_stat_tap.state, 1, "Brake Stat Tripped for Brk 1") + + brk1.state = BRK_MIN_OUT_V + brk2.state = BRK_MIN_OUT_V + # hil.check(brk_stat_tap.state == 0, "Brake Stat Starts Low Brk 2") + check.equal(brk_stat_tap.state, 0, "Brake Stat Starts Low Brk 2") + thresh = utils.measure_trip_thresh(brk2, start, stop, step, + BRK_SWEEP_DELAY, + brk_stat_tap, is_falling=False) + print(f"Brake 2 braking threshold: {thresh}") + # hil.check_within(thresh, BRK_2_THRESH_V, 0.2, "Brake 2 trip voltage") + # hil.check(brk_stat_tap.state == 1, "Brake Stat Tripped for Brk 2") + check.almost_equal(thresh, BRK_2_THRESH_V, abs=0.2, rel=0.0, msg="Brake 2 trip voltage") + check.equal(brk_stat_tap.state, 1, "Brake Stat Tripped for Brk 2") + + # Brake Fail scan + brk1.state = BRK_1_REST_V + brk2.state = BRK_2_REST_V + time.sleep(0.1) + # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 1 Starts 0") + check.equal(brk_fail_tap.state, 0, "Brake Fail Check 1 Starts 0") + + brk1.state = 0.0 # Force 0 + time.sleep(0.1) + # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Short GND") + check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 1 Short GND") + + brk1.state = BRK_1_REST_V + time.sleep(0.1) + # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 2 Starts 0") + check.equal(brk_fail_tap.state, 0, "Brake Fail Check 2 Starts 0") + + brk2.state = 0.0 # Force 0 + time.sleep(0.1) + # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Short GND") + check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 2 Short GND") + + brk2.state = BRK_2_REST_V + time.sleep(0.1) + # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 3 Starts 0") + check.equal(brk_fail_tap.state, 0, "Brake Fail Check 3 Starts 0") + + brk1.state = 5.0 # Short VCC + time.sleep(0.1) + # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Short VCC") + check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 1 Short VCC") + + brk1.state = BRK_1_REST_V + time.sleep(0.1) + # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 4 Starts 0") + check.equal(brk_fail_tap.state, 0, "Brake Fail Check 4 Starts 0") + + brk2.state = 5.0 # Short VCC + time.sleep(0.1) + # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Short VCC") + check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 2 Short VCC") + + brk2.state = BRK_2_REST_V + time.sleep(0.1) + # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 5 Starts 0") + check.equal(brk_fail_tap.state, 0, "Brake Fail Check 5 Starts 0") + + brk1.hiZ() + time.sleep(0.1) + # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Hi-Z") + check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 1 Hi-Z") + + brk1.state = BRK_1_REST_V + time.sleep(0.1) + # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 6 Starts 0") + check.equal(brk_fail_tap.state, 0, "Brake Fail Check 6 Starts 0") + + brk2.hiZ() + time.sleep(0.1) + # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Hi-Z") + check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 2 Hi-Z") + + brk2.state = BRK_2_REST_V + + # Brake Fail + reset_bspd(brk1, brk2, c_sense) + cycle_power() + time.sleep(BSPD_DASH_ON_TIME) + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + + brk1.state = 0.0 + t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") + # hil.check(brk_fail_tap.state == 1, "Brake Fail went high") + check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") + check.equal(brk_fail_tap.state, 1, "Brake Fail went high") + + brk1.state = BRK_1_REST_V + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(brk_fail_tap.state == 0, "Brake Fail returned low") + # hil.check(bspd_ctrl.state == 0, "Brake Fail Stays Latched") + check.equal(brk_fail_tap.state, 0, "Brake Fail returned low") + check.equal(bspd_ctrl.state, 0, "Brake Fail Stays Latched") + + # Brake Fail on Power On + reset_bspd(brk1, brk2, c_sense) + # Manual power cycle, setting brk_fail on before + # Will cause power to feed back into system + power.state = 1 + time.sleep(2) + brk1.state = 0.0 + power.state = 0 + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + time.sleep(BSPD_DASH_ON_TIME) # NOTE: test can't check for the trip time + # hil.check(bspd_ctrl.state == 0, "Power On Brake Fail") + check.equal(bspd_ctrl.state, 0, "Power On Brake Fail") + + # Current no brake + reset_bspd(brk1, brk2, c_sense) + power.state = 1 + time.sleep(3) + power.state = 0 + time.sleep(1) + #hil.check(bspd_ctrl.state == 1, "Power On") + time.sleep(2) # TODO: I am not sure why this fails, but oh well + set_bspd_current(c_sense, 75) + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # time.sleep(100) + time.sleep(3) + # hil.check(bspd_ctrl.state == 1, "Current no brake") + check.equal(bspd_ctrl.state, 1, "Current no brake") + + # Current Sense Short to Ground + reset_bspd(brk1, brk2, c_sense) + cycle_power() + time.sleep(BSPD_DASH_ON_TIME) + # hil.check(bspd_ctrl.state == 1, "Power On" + check.equal(bspd_ctrl.state, 1, "Power On") + + c_sense.state = 0.0 + t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") + check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") + set_bspd_current(c_sense, 0.0) + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 0, "Current short to ground stays latched") + check.equal(bspd_ctrl.state, 0, "Current short to ground stays latched") + + # Current Sense Short to 5V + reset_bspd(brk1, brk2, c_sense) + cycle_power() + time.sleep(BSPD_DASH_ON_TIME*1.2) + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + c_sense.state = ABOX_DHAB_CH1_DIV.div(5.0) + t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") + check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") + set_bspd_current(c_sense, 0.0) + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 0, "Current short to 5V stays latched") + check.equal(bspd_ctrl.state, 0, "Current short to 5V stays latched") + + # Braking + reset_bspd(brk1, brk2, c_sense) + cycle_power() + time.sleep(BSPD_DASH_ON_TIME) + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + brk1.state = BRK_1_THRESH_V + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 1, "Brake no current") + # hil.check(brk_stat_tap.state == 1, "Brake stat went high") + check.equal(bspd_ctrl.state, 1, "Brake no current") + check.equal(brk_stat_tap.state, 1, "Brake stat went high") + + # Lowest current required to trip at + min_trip_current = R_BSPD_POWER_THRESH_W / ACCUM_MAX_V + set_bspd_current(c_sense, min_trip_current) + t = utils.measure_trip_time(bspd_ctrl, 10.0, is_falling=True) + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Braking with current") + check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Braking with current") + + # Measure braking with current threshold + reset_bspd(brk1, brk2, c_sense) + cycle_power() + time.sleep(BSPD_DASH_ON_TIME) + brk1.state = BRK_1_THRESH_V + + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + start = ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(0.0)) + stop = ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(DHAB_S124_CH1_MAX_A)) + step = 0.1 + thresh = utils.measure_trip_thresh(c_sense, start, stop, step, + R_BSPD_MAX_TRIP_TIME_S, + bspd_ctrl, is_falling=True) + thresh_amps = dhab_ch1_v_to_a(ABOX_DHAB_CH1_DIV.reverse(thresh)) + print(f"Current while braking threshold: {thresh}V = {thresh_amps}A") + # hil.check_within(thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), 0.1, "Current while braking threshold") + check.almost_equal( + thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), + abs=0.1, rel=0.0, + msg="Current while braking threshold" + ) + + # Determine the current sense short to gnd threshold + reset_bspd(brk1, brk2, c_sense) + cycle_power() + time.sleep(BSPD_DASH_ON_TIME) + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + set_bspd_current(c_sense, DHAB_S124_CH1_MIN_A) + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 1, "Min output current okay") + check.equal(bspd_ctrl.state, 1, "Min output current okay") + start = ABOX_DHAB_CH1_DIV.div(DHAB_S124_MIN_OUT_V) + stop = 0.0 + step = -0.1 + thresh = utils.measure_trip_thresh(c_sense, start, stop, step, + R_BSPD_MAX_TRIP_TIME_S, + bspd_ctrl, is_falling=True) + print(f"Short to ground threshold: {thresh}V") + # hil.check(stop < (thresh) < start, "Current short to ground threshold") + check.between(thresh, stop, start, "Current short to ground threshold") + + # Determine the current sense short to 5V threshold + reset_bspd(brk1, brk2, c_sense) + cycle_power() + time.sleep(BSPD_DASH_ON_TIME) + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + time.sleep(2) + + set_bspd_current(c_sense, DHAB_S124_CH1_MAX_A) + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 1, "Max output current okay") + check.equal(bspd_ctrl.state, 1, "Max output current okay") + + start = ABOX_DHAB_CH1_DIV.div(DHAB_S124_MAX_OUT_V) + stop = ABOX_DHAB_CH1_DIV.div(5.0) + step = 0.01 + + c_sense.state = start + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 1, "Max output voltage okay") + check.equal(bspd_ctrl.state, 1, "Max output voltage okay") + input("enter to continue") + + thresh = utils.measure_trip_thresh(c_sense, start, stop, step, + R_BSPD_MAX_TRIP_TIME_S, + bspd_ctrl, is_falling=True) + print(f"Short to 5V threshold: {thresh}V") + # hil.check(bspd_ctrl.state == 0, "Short to 5V trips") + check.equal(bspd_ctrl.state, 0, "Short to 5V trips") + print(stop) + print(start) + # hil.check(start < (thresh) <= stop, "Current short to 5V threshold") + check.between(thresh, start, stop, "Current short to 5V threshold", le=True) + + # Floating current + reset_bspd(brk1, brk2, c_sense) + cycle_power() + time.sleep(BSPD_DASH_ON_TIME) + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + c_sense.hiZ() + time.sleep(R_BSPD_MAX_TRIP_TIME_S) + # hil.check(bspd_ctrl.state == 0, "Floating current") + check.equal(bspd_ctrl.state, 0, "Floating current") + + # Floating brake_fail + # Can't test this at system level! + + # Floating brake_stat + # Can't test this at system level! + + # End the test + # hil.end_test() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +IMD_RC_MIN_TRIP_TIME_S = IMD_STARTUP_TIME_S +IMD_RC_MAX_TRIP_TIME_S = R_IMD_MAX_TRIP_TIME_S - IMD_MEASURE_TIME_S +IMD_CTRL_OKAY = 1 +IMD_CTRL_TRIP = 0 + +def test_imd(hil): + # Begin the test + # hil.start_test(test_imd.__name__) + + # Outputs + imd_stat = hil.dout("Main_Module", "IMD_Status") + + # Outputs to set SDC status to okay + ams_stat = hil.dout("Main_Module", "BMS-Status-Main") + brk1 = hil.aout("Dashboard", "BRK1_RAW") + brk2 = hil.aout("Dashboard", "BRK2_RAW") + c_sense = hil.aout("Main_Module", "Current Sense C1") + + # Inputs + imd_ctrl = hil.din("Main_Module", "SDC15") # assuming AMS and BSPD closed + + # Set other SDC nodes to okay + reset_ams(ams_stat) + reset_bspd(brk1, brk2, c_sense) + + # IMD Fault + reset_imd(imd_stat) + cycle_power() + # hil.check(imd_ctrl.state == IMD_CTRL_OKAY, "Power On") + check.equal(imd_ctrl.state, IMD_CTRL_OKAY, "Power On") + time.sleep(1) + imd_stat.state = IMD_STAT_TRIP + t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) + print(f"Target trip time: [{IMD_RC_MIN_TRIP_TIME_S}, {IMD_RC_MAX_TRIP_TIME_S}]") + # hil.check(IMD_RC_MIN_TRIP_TIME_S < t < IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Trip") + check.between(t, IMD_RC_MIN_TRIP_TIME_S, IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Trip") + imd_stat.state = IMD_STAT_OKAY + time.sleep(IMD_RC_MAX_TRIP_TIME_S * 1.1) + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Stays Latched") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Stays Latched") + + # IMD Fault on Power On + reset_imd(imd_stat) + imd_stat.state = IMD_STAT_TRIP + cycle_power() + time.sleep(IMD_RC_MAX_TRIP_TIME_S) + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Power On") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Power On") + + # IMD Floating + reset_imd(imd_stat) + imd_stat.hiZ() + cycle_power() + t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) + # hil.check(t < R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Floating Trip") + check.less(t, R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Floating Trip") + + # hil.end_test() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +def test_ams(hil): + # Begin the test + # hil.start_test(test_ams.__name__) + + # Outputs + ams_stat = hil.dout("Main_Module", "BMS-Status-Main") + + # Outputs to set SDC status to okay + imd_stat = hil.dout("Main_Module", "IMD_Status") + brk1 = hil.aout("Dashboard", "BRK1_RAW") + brk2 = hil.aout("Dashboard", "BRK2_RAW") + c_sense = hil.aout("Main_Module", "Current Sense C1") + + # Inputs + ams_ctrl = hil.din("Main_Module", "SDC15") # assumes IMD and BSPD closed + + # Set other SDC nodes to okay + reset_imd(imd_stat) + reset_bspd(brk1, brk2, c_sense) + + # AMS Fault + reset_ams(ams_stat) + cycle_power() + # hil.check(ams_ctrl.state == AMS_CTRL_OKAY, "Power On") + check.equal(ams_ctrl.state, AMS_CTRL_OKAY, "Power On") + time.sleep(1) + ams_stat.state = AMS_STAT_TRIP + t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) + # hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Trip") + check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Trip") + ams_stat.state = AMS_STAT_OKAY + time.sleep(AMS_MAX_TRIP_DELAY_S * 1.1) + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Stays Latched") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Stays Latched") + + # AMS Fault on Power On + reset_ams(ams_stat) + ams_stat.state = AMS_STAT_TRIP + cycle_power() + time.sleep(AMS_MAX_TRIP_DELAY_S) + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Power On") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Power On") + + # AMS Floating + reset_ams(ams_stat) + ams_stat.hiZ() + cycle_power() + t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) + # hil.check(0 <= t < AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Floating Trip") + check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Floating Trip") + + # hil.end_test() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +def tsal_is_red(): + while 1: + i = input("Is TSAL Green (g) or Red (r): ") + utils.clear_term_line() + i = i.upper() + if (i == 'G' or i == 'R'): + return i == 'R' + print("You may only enter G or R!") + +def test_tsal(hil): + + # Begin the test + hil.start_test(test_tsal.__name__) + + # Outputs + v_mc = hil.aout("Main_Module", "Voltage MC Transducer") + + # Inputs + # User :D + print(f"{utils.bcolors.OKCYAN}Press 'G' for green and 'R' for red.{utils.bcolors.ENDC}") + + # Initial State + reset_tsal(v_mc) + time.sleep(0.2) + # No need to power cycle + + # hil.check(tsal_is_red() == False, "LVAL on at v_mc = 0") + check.equal(tsal_is_red(), False, "LVAL on at v_mc = 0") + #hil.check(tsal.state == 0, "TSAL off at v_mc = 0") + + time.sleep(5) + # hil.check(tsal_is_red() == False, "LVAL stays on") + check.equal(tsal_is_red(), False, "LVAL stays on") + + v_mc.state = tiff_hv_to_lv(ACCUM_MIN_V) + time.sleep(0.1) + + #hil.check(lval.state == 0, f"LVAL off at {ACCUM_MIN_V:.4} V") + # hil.check(tsal_is_red() == True, f"TSAL on at {ACCUM_MIN_V:.4} V") + check.equal(tsal_is_red(), True, f"TSAL on at {ACCUM_MIN_V:.4} V") + + reset_tsal(v_mc) + time.sleep(0.2) + # hil.check(tsal_is_red() == False, f"LVAL turns back on") + check.equal(tsal_is_red(), False, f"LVAL turns back on") + + start = tiff_hv_to_lv(50) + stop = tiff_hv_to_lv(R_TSAL_HV_V * 1.5) + step = tiff_hv_to_lv(1) + + gain = 1000 + thresh = start + _start = int(start * gain) + _stop = int(stop * gain) + _step = int(step * gain) + v_mc.state = start + tripped = False + print(f"Start: {_start} Stop: {_stop} Step: {_step} Gain: {gain}") + for v in range(_start, _stop+_step, _step): + v_mc.state = v / gain + time.sleep(0.01) + if (tsal_is_red()): + thresh = v / gain + tripped = True + break + if (not tripped): + utils.log_warning(f"TSAL did not trip at stop of {stop}.") + thresh = stop + # hil.check(tripped, "TSAL tripped") + check.is_true(tripped, "TSAL tripped") + + thresh = tiff_lv_to_hv(thresh) + print(f"TSAL on at {thresh:.4} V") + hil.check_within(thresh, R_TSAL_HV_V, 4, f"TSAL trips at {R_TSAL_HV_V:.4} +-4") + check.almost_equal(thresh, R_TSAL_HV_V, abs=4, rel=0.0, msg=f"TSAL trips at {R_TSAL_HV_V:.4} +-4") + + # hil.end_test() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +def test_sdc(hil): + ''' Check that every node in the sdc trips ''' + # Begin the test + # hil.start_test(test_sdc.__name__) + + # Outputs + + # Inputs + + # hil.check(False, "TODO") + check.is_true(False, "TODO") + + # hil.end_test() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +def is_buzzer_on(): + while 1: + i = input("Is Buzzer On (y) or No (n): ") + utils.clear_term_line() + i = i.upper() + if (i == 'Y' or i == 'N'): + return i == 'Y' + print("You may only enter Y or N!") + +def test_buzzer(hil): + # Begin the test + # hil.start_test(test_buzzer.__name__) + + # Outputs + buzzer_ctrl = hil.daq_var("Main_Module", "daq_buzzer") + + # Inputs + buzzer_stat = hil.mcu_pin("Main_Module", "Buzzer_Prot") + + buzzer_ctrl.state = 0 + time.sleep(0.02) + # hil.check(buzzer_stat.state == 0, "Buzzer Off") + check.equal(buzzer_stat.state, 0, "Buzzer Off") + + buzzer_ctrl.state = 1 + print(buzzer_ctrl.state) + time.sleep(0.02) + # hil.check(buzzer_stat.state == 1, "Buzzer On") + # hil.check(is_buzzer_on() == True, "Buzzer Making Noise") + check.equal(buzzer_stat.state, 1, "Buzzer On") + check.is_true(is_buzzer_on(), "Buzzer Making Noise") + + buzzer_ctrl.state = 0 + time.sleep(0.02) + # hil.check(buzzer_stat.state == 0, "Buzzer back Off") + # hil.check(is_buzzer_on() == False, "Buzzer Not Making Noise") + check.equal(buzzer_stat.state, 0, "Buzzer back Off") + check.is_false(is_buzzer_on(), "Buzzer Not Making Noise") + + # hil.end_test() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +def is_brake_light_on(): + while 1: + i = input("Is Brake Light On (y) or No (n): ") + utils.clear_term_line() + i = i.upper() + if (i == 'Y' or i == 'N'): + return i == 'Y' + print("You may only enter Y or N!") + +def test_brake_light(hil): + # Begin the test + # hil.start_test(test_brake_light.__name__) + + # Outputs + brk_ctrl = hil.daq_var("Main_Module", "daq_brake") + + # Inputs + brk_stat = hil.mcu_pin("Main_Module", "Brake_Light_CTRL_Prot") + + brk_ctrl.state = 0 + time.sleep(0.02) + # hil.check(brk_ctrl.state == 0, "Brake Off") + check.equal(brk_ctrl.state, 0, "Brake Off") + + brk_ctrl.state = 1 + print(brk_ctrl.state) + time.sleep(0.02) + # hil.check(brk_ctrl.state == 1, "Brake Light On") + # hil.check(is_brake_light_on() == True, "Brake Light is On") + check.equal(brk_ctrl.state, 1, "Brake Light On") + check.is_true(is_brake_light_on(), "Brake Light is On") + + brk_ctrl.state = 0 + time.sleep(0.02) + # hil.check(brk_ctrl.state == 0, "Brake Light back Off") + # hil.check(is_brake_light_on() == False, "Brake Light is Off") + check.equal(brk_ctrl.state, 0, "Brake Light back Off") + check.is_false(is_brake_light_on(), "Brake Light is Off") + + + # Can copy lot from bspd + # Read the brake control mcu pin + # Finally have user verify light actually turned on + + # hil.end_test() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +def test_light_tsal_buz(hil): + # hil.start_test(test_light_tsal_buz.__name__) + + # Outputs + brk_ctrl = hil.daq_var("Main_Module", "daq_brake") + buzzer_ctrl = hil.daq_var("Main_Module", "daq_buzzer") + + brk_ctrl.state = 1 + buzzer_ctrl.state = 1 + input("Press enter to end the test") + brk_ctrl.state = 0 + buzzer_ctrl.state = 0 + + check.is_true(True, "TODO") + + # hil.end_test() +# ---------------------------------------------------------------------------- # \ No newline at end of file From 8fcff42a89bf804fcfeedc18a3dbdb107677f641 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 12 Oct 2024 15:14:00 -0400 Subject: [PATCH 024/181] Trying Pytest test Kinda weird because it makes no calls to HIL.check() --- scripts/pytest_test.py | 200 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 scripts/pytest_test.py diff --git a/scripts/pytest_test.py b/scripts/pytest_test.py new file mode 100644 index 0000000..836a1e9 --- /dev/null +++ b/scripts/pytest_test.py @@ -0,0 +1,200 @@ +from os import sys, path +sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) +from hil import HIL +import utils +import time +import can +from rules_constants import * +from vehicle_constants import * + +import pytest_check as check +import pytest + + +# ---------------------------------------------------------------------------- # +@pytest.fixture(scope="session") +def hil(): + hil_instance = HIL() + + # hil.load_config("config_testing.json") + hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + # hil_instance.init_can() + + yield hil_instance + + hil_instance.shutdown() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +def test_bspd(hil): + # Begin the test + # hil.start_test(test_bspd.__name__) + + # Inputs + d2 = hil.din("Test_HIL", "AI2") + d3 = hil.din("Test_HIL", "AI3") + d4 = hil.din("Test_HIL", "AI4") + # d5 = hil.din("Test_HIL", "DI5") + # d6 = hil.din("Test_HIL", "DI6") + # d7 = hil.din("Test_HIL", "DI7") + r1 = hil.dout("Test_HIL", "RLY1") + r2 = hil.dout("Test_HIL", "RLY2") + r3 = hil.dout("Test_HIL", "RLY3") + r4 = hil.dout("Test_HIL", "RLY4") + + a1 = hil.dout("Test_HIL", "AI1") + + a1.state = 1 + + + r1.state = 1 + r2.state = 1 + r3.state = 1 + r4.state = 1 + + r1.state = 0 + input("") + r2.state = 0 + input("") + r3.state = 0 + input("") + r4.state = 0 + input("") + + for _ in range(100): + + #print(f"{d2.state}, {d3.state}, {d4.state}") + for i in range(4): + r1.state = not ((i % 4) == 0) + r2.state = not ((i % 4) == 1) + r3.state = not ((i % 4) == 2) + r4.state = not ((i % 4) == 3) + time.sleep(1) + time.sleep(2) + + check.is_true(True, "TODO") + + # hil.end_test() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +def test_dac(hil): + # hil.start_test(test_dac.__name__) + + dac1 = hil.aout("Test_HIL", "DAC1") + dac2 = hil.aout("Test_HIL", "DAC2") + + dac1.state = 2.5 + dac2.state = 5.0 + input("5, 2") + dac1.hiZ() + dac2.hiZ() + input("hi-z") + dac1.state = 0.25 + dac2.state = 0.25 + input(".25") + + check.is_true(True, "TODO") + + # hil.end_test() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +def test_pot(hil): + + pot1 = hil.pot("Test_HIL", "POT1") + pot2 = hil.pot("Test_HIL", "POT2") + + print("initial") + input(" - ") + print("0.5, 1") + pot1.state = 0.5 + pot2.state = 0.5 + input(" - ") + + print("1, 0.5") + pot1.state = 1.0 + pot2.state = 1.0 + input(" - ") + + print("0, 0") + pot1.state = 0.0 + pot2.state = 0.0 + input(" - ") + + for i in range(1000): + pot1.state = 0.25 + pot2.state = 0.25 + time.sleep(0.01) + pot1.state = 0.75 + pot2.state = 0.75 + time.sleep(0.01) + + pot1.state = 0.5 + pot2.state = 0.5 + input("-------") + + check.is_true(True, "TODO") +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +def test_mcu_pin(hil): + # hil.start_test(test_mcu_pin.__name__) + + brk_stat_tap = hil.mcu_pin("Dashboard", "BRK_STAT_TAP") + + delta_avg = 0 + delta_cnt = 0 + for i in range(100): + t_start = time.time() + #time.sleep(0.01) + print(brk_stat_tap.state) + t_start = time.time() - t_start + delta_avg += t_start + delta_cnt = delta_cnt + 1 + + print(f"Average: {delta_avg/delta_cnt}") + + check.is_true(True, "TODO") + + # hil.end_test() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +def test_daq(hil): + # hil.start_test(test_daq.__name__) + + counter = 0 + start_time = time.time() + + LOOP_TIME_S = 0.001 + + # while(1): + # time.sleep(3) + + print("Sending") + + #while (time.time() - start_time < 15*60): + while (counter < 4000): + last_tx = time.perf_counter() + #msg = can.Message(arbitration_id=0x14000072, data=counter.to_bytes(4, 'little')) + #msg = can.Message(arbitration_id=0x80080c4, data=counter.to_bytes(4, 'little')) + msg = can.Message(arbitration_id=0x400193e, data=counter.to_bytes(8, 'little')) + #print(msg) + hil.can_bus.sendMsg(msg) + counter = counter + 1 + delta = LOOP_TIME_S - (time.perf_counter() - last_tx) + if (delta < 0): delta = 0 + time.sleep(delta) + + check.is_true(True, "TODO") + + print("Done") + print(f"Last count sent: {counter - 1}") +# ---------------------------------------------------------------------------- # \ No newline at end of file From 2899d4d0269904258b33e9f92bf22ac282c04795 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 12 Oct 2024 15:25:46 -0400 Subject: [PATCH 025/181] Separating new Pytest scripts and old ones Can use this commit to see all the way normal tests were converted to pytest ones by looking at the modified files in scripts/ --- old_scripts/config_dash.py | 124 ++++++ old_scripts/rules_constants.py | 16 + old_scripts/test.sh | 10 + old_scripts/test_abox.py | 272 ++++++++++++ old_scripts/test_charger.py | 147 +++++++ .../test_collector.py | 35 +- .../test_main_base.py | 283 ++++-------- .../test_main_sdc.py | 187 +++----- .../test_system.py | 415 ++++++------------ .../test_test.py | 72 +-- old_scripts/vehicle_constants.py | 75 ++++ scripts/pytest_abox.py | 319 -------------- scripts/pytest_charger.py | 186 -------- scripts/test_abox.py | 171 +++++--- scripts/test_charger.py | 107 +++-- scripts/test_collector.py | 35 +- scripts/test_main_base.py | 283 ++++++++---- scripts/test_main_sdc.py | 187 +++++--- scripts/test_system.py | 415 ++++++++++++------ scripts/test_test.py | 72 ++- 20 files changed, 1818 insertions(+), 1593 deletions(-) create mode 100644 old_scripts/config_dash.py create mode 100644 old_scripts/rules_constants.py create mode 100755 old_scripts/test.sh create mode 100644 old_scripts/test_abox.py create mode 100644 old_scripts/test_charger.py rename scripts/pytest_collector.py => old_scripts/test_collector.py (51%) rename scripts/pytest_main_base.py => old_scripts/test_main_base.py (51%) rename scripts/pytest_main_sdc.py => old_scripts/test_main_sdc.py (51%) rename scripts/pytest_system.py => old_scripts/test_system.py (51%) rename scripts/pytest_test.py => old_scripts/test_test.py (66%) create mode 100644 old_scripts/vehicle_constants.py delete mode 100644 scripts/pytest_abox.py delete mode 100644 scripts/pytest_charger.py diff --git a/old_scripts/config_dash.py b/old_scripts/config_dash.py new file mode 100644 index 0000000..37448f0 --- /dev/null +++ b/old_scripts/config_dash.py @@ -0,0 +1,124 @@ +from os import sys, path +sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) +from hil import HIL +import utils +import time +from rules_constants import * +from vehicle_constants import * + + +BRK_SWEEP_DELAY = 0.1 +def test_bspd(hil): + # Begin the test + hil.start_test(test_bspd.__name__) + + # Outputs + brk1 = hil.aout("Dashboard", "BRK1_RAW") + brk2 = hil.aout("Dashboard", "BRK2_RAW") + + # Inputs + brk_fail_tap = hil.mcu_pin("Dashboard", "BRK_FAIL_TAP") + brk_stat_tap = hil.mcu_pin("Dashboard", "BRK_STAT_TAP") + + # Brake threshold check + brk1.state = BRK_1_REST_V + brk2.state = BRK_2_REST_V + hil.check(brk_stat_tap.state == 0, "Brake stat starts low") + brk1.state = BRK_1_THRESH_V + time.sleep(0.1) + hil.check(brk_stat_tap.state == 1, "Brake stat goes high at brk 1 thresh") + brk1.state = BRK_1_REST_V + hil.check(brk_stat_tap.state == 0, "Brake stat starts low") + brk2.state = BRK_2_THRESH_V + time.sleep(0.1) + hil.check(brk_stat_tap.state == 1, "Brake stat goes high at brk 2 thresh") + brk1.state = BRK_1_THRESH_V + hil.check(brk_stat_tap.state == 1, "Brake stat stays high for both brakes") + + # Brake threshold scan + brk1.state = BRK_MIN_OUT_V + brk2.state = BRK_MIN_OUT_V + time.sleep(0.1) + hil.check(brk_stat_tap.state == 0, "Brake Stat Starts Low Brk 1") + + start = BRK_MIN_OUT_V + stop = BRK_MAX_OUT_V + step = 0.1 + + thresh = utils.measure_trip_thresh(brk1, start, stop, step, + BRK_SWEEP_DELAY, + brk_stat_tap, is_falling=False) + print(f"Brake 1 braking threshold: {thresh}") + hil.check_within(thresh, BRK_1_THRESH_V, 0.2, "Brake 1 trip voltage") + hil.check(brk_stat_tap.state == 1, "Brake Stat Tripped for Brk 1") + + brk1.state = BRK_MIN_OUT_V + brk2.state = BRK_MIN_OUT_V + hil.check(brk_stat_tap.state == 0, "Brake Stat Starts Low Brk 2") + thresh = utils.measure_trip_thresh(brk2, start, stop, step, + BRK_SWEEP_DELAY, + brk_stat_tap, is_falling=False) + print(f"Brake 2 braking threshold: {thresh}") + hil.check_within(thresh, BRK_2_THRESH_V, 0.2, "Brake 2 trip voltage") + hil.check(brk_stat_tap.state == 1, "Brake Stat Tripped for Brk 2") + + # Brake Fail scan + brk1.state = BRK_1_REST_V + brk2.state = BRK_2_REST_V + time.sleep(0.1) + hil.check(brk_fail_tap.state == 0, "Brake Fail Check 1 Starts 0") + brk1.state = 0.0 # Force 0 + time.sleep(0.1) + hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Short GND") + brk1.state = BRK_1_REST_V + time.sleep(0.1) + hil.check(brk_fail_tap.state == 0, "Brake Fail Check 2 Starts 0") + brk2.state = 0.0 # Force 0 + time.sleep(0.1) + hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Short GND") + brk2.state = BRK_2_REST_V + time.sleep(0.1) + hil.check(brk_fail_tap.state == 0, "Brake Fail Check 3 Starts 0") + brk1.state = 5.0 # Short VCC + time.sleep(0.1) + hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Short VCC") + brk1.state = BRK_1_REST_V + time.sleep(0.1) + hil.check(brk_fail_tap.state == 0, "Brake Fail Check 4 Starts 0") + brk2.state = 5.0 # Short VCC + time.sleep(0.1) + hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Short VCC") + brk2.state = BRK_2_REST_V + time.sleep(0.1) + hil.check(brk_fail_tap.state == 0, "Brake Fail Check 5 Starts 0") + brk1.hiZ() + time.sleep(0.1) + hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Hi-Z") + brk1.state = BRK_1_REST_V + time.sleep(0.1) + hil.check(brk_fail_tap.state == 0, "Brake Fail Check 6 Starts 0") + brk2.hiZ() + time.sleep(0.1) + hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Hi-Z") + brk2.state = BRK_2_REST_V + + # End the test + hil.end_test() + +# TODO: add throttle checks + + +if __name__ == "__main__": + hil = HIL() + + hil.load_config("config_system_hil_attached.json") + hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + hil.init_can() + + # Drive Critical Tests + test_bspd(hil) + + # Peripheral Sensor Tests + + hil.shutdown() diff --git a/old_scripts/rules_constants.py b/old_scripts/rules_constants.py new file mode 100644 index 0000000..425beba --- /dev/null +++ b/old_scripts/rules_constants.py @@ -0,0 +1,16 @@ +# NOTE: each constant in this file shall reference a rule + +# IMD +R_IMD_RESISTANCE_RATIO = 500 # EV.7.6.3 Ohms / Volt +R_IMD_MAX_TRIP_TIME_S = 30.0 # IN.4.4.2 +R_IMD_TRIP_TEST_RESISTANCE_PERCENT = 0.5 # IN.4.4.2 50% of response value + +# BSPD EV.7.7 +R_BSPD_MAX_TRIP_TIME_S = 0.5 # EV.7.7.2 +R_BSPD_POWER_THRESH_W = 5000 # EV.7.7.2 + +# Precharge and Discharge EV.5.6 +R_PCHG_V_BAT_THRESH = 0.90 # EV.5.6.1.a + +# TSAL EV.5.9 +R_TSAL_HV_V = 60.0 # T.9.1.1 diff --git a/old_scripts/test.sh b/old_scripts/test.sh new file mode 100755 index 0000000..9a919dd --- /dev/null +++ b/old_scripts/test.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# If no file passed, run on all files +if [ "$#" -ne 1 ]; then + echo "Running tests on all files..." + pytest --cache-clear --no-header -v +else + echo "Running tests on $1..." + pytest --cache-clear --no-header -v "$1" +fi \ No newline at end of file diff --git a/old_scripts/test_abox.py b/old_scripts/test_abox.py new file mode 100644 index 0000000..042024a --- /dev/null +++ b/old_scripts/test_abox.py @@ -0,0 +1,272 @@ +from os import sys, path +sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) +from hil import HIL +import utils +import time +from rules_constants import * +from vehicle_constants import * + + +def test_abox_ams(hil): + # Begin the test + hil.start_test(test_abox_ams.__name__) + + # Outputs + den = hil.dout("a_box", "Discharge Enable") + csafe = hil.dout("a_box", "Charger Safety") + bms_override = hil.daq_var("a_box", "bms_daq_override") + bms_stat = hil.daq_var("a_box", "bms_daq_stat") + + # Inputs + chrg_stat = hil.din("a_box", "BMS Status Charger") + main_stat = hil.din("a_box", "BMS Status PDU") + + bms_override.state = 1 + + for i in range(0, 8): + dchg_set = bool(i & 0x1) + chg_set = bool(i & 0x2) + bms_set = bool(i & 0x4) + exp_chrg = not (chg_set or bms_set) + exp_dchg = not (dchg_set or bms_set) + + den.state = dchg_set + csafe.state = chg_set + bms_stat.state = bms_set + print(f"Combo {i}") + time.sleep(0.1) + hil.check(chrg_stat.state == exp_chrg, f"Chrg stat {exp_chrg}") + hil.check(main_stat.state == exp_dchg, f"Main stat {exp_dchg}") + + bms_override.state = 0 + + hil.end_test() + +def test_isense(hil): + # Begin the test + hil.start_test(test_isense.__name__) + + # Outputs + ch1_raw = hil.aout("a_box", "Isense_Ch1_raw") + + # Inputs + ch1_filt = hil.ain("a_box", "ISense Ch1") + + # Need to test voltage divider transfer function correct + for v in [0.0, DHAB_S124_MIN_OUT_V, DHAB_S124_OFFSET_V, 3.2, DHAB_S124_MAX_OUT_V, 5.0]: + ch1_raw.state = v + time.sleep(1) + exp_out = ABOX_DHAB_CH1_DIV.div(v) + input(f"enter to meas, set to {v}, expected {exp_out}") + meas = ch1_filt.state + print(f"isense expected: {exp_out}V, measured: {meas}V") + hil.check_within(meas, exp_out, 0.05, f"Isense v={v:.3}") + + ch1_raw.hiZ() + time.sleep(0.01) + hil.check_within(ch1_filt.state, 0.0, 0.05, f"Isense float pulled down") + + hil.end_test() + +RLY_ON = 0 +RLY_OFF = 1 +RLY_DLY = 0.01 # Mechanicl relay takes time to transition + +def test_precharge(hil): + # Begin the test + hil.start_test(test_precharge.__name__) + + # Outputs + n_pchg_cmplt = hil.dout("a_box", "NotPrechargeComplete") + sdc = hil.dout("a_box", "SDC") + bat_p = hil.dout("a_box", "Batt+") + + # Inputs + resistor = hil.din("a_box", "NetK1_4") # To precharge resistor + + bat_p.state = RLY_ON + + print("Combo 1") + n_pchg_cmplt.state = 0 + sdc.state = RLY_OFF + time.sleep(RLY_DLY) + hil.check(resistor.state == 0, "Resistor disconnected") + + print("Combo 2") + n_pchg_cmplt.state = 1 + sdc.state = RLY_OFF + time.sleep(RLY_DLY) + hil.check(resistor.state == 0, "Resistor disconnected") + + print("Combo 3") + n_pchg_cmplt.state = 1 + sdc.state = RLY_ON + time.sleep(RLY_DLY) + hil.check(resistor.state == 1, "Resistor connected") + + print("Combo 4") + n_pchg_cmplt.state = 0 + sdc.state = RLY_ON + time.sleep(RLY_DLY) + hil.check(resistor.state == 0, "Resistor disconnected") + + # Duration test + time.sleep(1) + n_pchg_cmplt.state = 1 + sdc.state = RLY_ON + time.sleep(RLY_DLY) + hil.check(resistor.state == 1, "Duration init") + time.sleep(9) + hil.check(resistor.state == 1, "Duration mid") + n_pchg_cmplt.state = 0 + time.sleep(RLY_DLY) + hil.check(resistor.state == 0, "Duration end") + + hil.end_test() + +SUPPLY_VOLTAGE = 24.0 +TIFF_DLY = 0.3 + +def test_tiffomy(hil): + # Begin the test + hil.start_test(test_tiffomy.__name__) + + # Outputs + bat_p = hil.dout("a_box", "Batt+") + + # Inputs + vbat = hil.ain("a_box", "VBatt") + imd_hv = hil.din("a_box", "Batt+_Fused") + + # NOTE: the IMD test confirms that the relay closed + # This is a bit redundant of the tiffomy voltage measurement + + utils.log_warning(f"Assuming supply = {SUPPLY_VOLTAGE} V") + utils.log_warning(f"Do not reverse polarity Vbat, it will kill Arduino ADC") + input("Click enter to acknowledge or ctrl+c to cancel") + + bat_p.state = RLY_OFF + time.sleep(TIFF_DLY) + hil.check_within(vbat.state, 0.0, 0.1, "TIff off") + hil.check(imd_hv.state == 0, "IMD HV off") + + bat_p.state = RLY_ON + time.sleep(TIFF_DLY) + exp = SUPPLY_VOLTAGE + #input("press enter, tiff should be getting volts") + meas = tiff_lv_to_hv(vbat.state) + print(f"Tiff HV reading: {meas} V, expect: {SUPPLY_VOLTAGE} V") + hil.check_within(meas, exp, 2.5, "Tiff on") + hil.check(imd_hv.state == 1, "IMD HV on") + + hil.end_test() + + +def test_tmu(hil): + # Begin the test + hil.start_test(test_tmu.__name__) + + # Outputs + tmu_a_do = hil.dout("a_box", "TMU_1") + tmu_b_do = hil.dout("a_box", "TMU_2") + tmu_c_do = hil.dout("a_box", "TMU_3") + tmu_d_do = hil.dout("a_box", "TMU_4") + + daq_override = hil.daq_var("a_box", "tmu_daq_override") + daq_therm = hil.daq_var("a_box", "tmu_daq_therm") + + # Inputs + mux_a = hil.din("a_box", "MUX_A_NON_ISO") + mux_b = hil.din("a_box", "MUX_B_NON_ISO") + mux_c = hil.din("a_box", "MUX_C_NON_ISO") + mux_d = hil.din("a_box", "MUX_D_NON_ISO") + + tmu_a_ai = hil.daq_var("a_box", "tmu_1") + tmu_b_ai = hil.daq_var("a_box", "tmu_2") + tmu_c_ai = hil.daq_var("a_box", "tmu_3") + tmu_d_ai = hil.daq_var("a_box", "tmu_4") + + daq_therm.state = 0 + daq_override.state = 1 + + # mux line test + for i in range(0,16): + daq_therm.state = i + time.sleep(0.05) + hil.check(mux_a.state == bool(i & 0x1), f"Mux A test {i}") + hil.check(mux_b.state == bool(i & 0x2), f"Mux B test {i}") + hil.check(mux_c.state == bool(i & 0x4), f"Mux C test {i}") + hil.check(mux_d.state == bool(i & 0x8), f"Mux D test {i}") + + daq_override.state = 0 + + TMU_TOLERANCE = 100 + TMU_HIGH_VALUE = 1970 #2148 + + # thermistors + for i in range(0,16): + tmu_a_do.state = bool(i & 0x1) + tmu_b_do.state = bool(i & 0x2) + tmu_c_do.state = bool(i & 0x4) + tmu_d_do.state = bool(i & 0x8) + time.sleep(1.0) + a = int(tmu_a_ai.state) + b = int(tmu_b_ai.state) + c = int(tmu_c_ai.state) + d = int(tmu_d_ai.state) + print(f"Readings at therm={i}: {a}, {b}, {c}, {d}") + hil.check_within(a, TMU_HIGH_VALUE if (i & 0x1) else 0, TMU_TOLERANCE, f"TMU 1 test {i}") + hil.check_within(b, TMU_HIGH_VALUE if (i & 0x2) else 0, TMU_TOLERANCE, f"TMU 2 test {i}") + hil.check_within(c, TMU_HIGH_VALUE if (i & 0x4) else 0, TMU_TOLERANCE, f"TMU 3 test {i}") + hil.check_within(d, TMU_HIGH_VALUE if (i & 0x8) else 0, TMU_TOLERANCE, f"TMU 4 test {i}") + + + hil.end_test() + +def test_imd(hil): + hil.start_test(test_imd.__name__) + + # Outputs + imd_out = hil.dout('a_box', 'IMD_Status') + + # Inputs + imd_in = hil.din('a_box', 'IMD_STATUS_LV_COMP') + imd_mcu = hil.mcu_pin('a_box', 'IMD_STATUS_LV_COMP') + + + imd_out.state = RLY_OFF + time.sleep(RLY_DLY) + + hil.check(imd_in.state == 0, 'IMD LV OFF') + hil.check(imd_mcu.state == 0, 'IMD MCU OFF') + + imd_out.state = RLY_ON + time.sleep(RLY_DLY) + + hil.check(imd_in.state == 1, 'IMD LV ON') + hil.check(imd_mcu.state == 1, 'IMD MCU ON') + + imd_out.state = RLY_OFF + time.sleep(RLY_DLY) + + hil.check(imd_in.state == 0, 'IMD LV BACK OFF') + hil.check(imd_mcu.state == 0, 'IMD MCU BACK OFF') + + hil.end_test() + + +if __name__ == "__main__": + hil = HIL() + hil.load_config("config_abox_bench.json") + hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + hil.init_can() + + test_abox_ams(hil) + test_isense(hil) + test_precharge(hil) + test_tiffomy(hil) + test_tmu(hil) + test_imd(hil) + + hil.shutdown() diff --git a/old_scripts/test_charger.py b/old_scripts/test_charger.py new file mode 100644 index 0000000..87a6fa4 --- /dev/null +++ b/old_scripts/test_charger.py @@ -0,0 +1,147 @@ +from os import sys, path +sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) +from hil import HIL +import hil.utils as utils +import time +from rules_constants import * +from vehicle_constants import * + +AMS_STAT_OKAY = 1 +AMS_STAT_TRIP = 0 +AMS_CTRL_OKAY = 1 +AMS_CTRL_TRIP = 0 + +def reset_ams(ams_stat): + ams_stat.state = AMS_STAT_OKAY + +IMD_STAT_OKAY = 1 +IMD_STAT_TRIP = 0 +def reset_imd(imd_stat): + imd_stat.state = IMD_STAT_OKAY + +power = None + +CYCLE_POWER_OFF_DELAY = 2.0 +CYCLE_POWER_ON_DELAY = 3.0 + +def cycle_power(): + power.state = 1 + time.sleep(CYCLE_POWER_OFF_DELAY) + power.state = 0 + time.sleep(CYCLE_POWER_ON_DELAY) + + +IMD_RC_MIN_TRIP_TIME_S = IMD_STARTUP_TIME_S +IMD_RC_MAX_TRIP_TIME_S = R_IMD_MAX_TRIP_TIME_S - IMD_MEASURE_TIME_S +IMD_CTRL_OKAY = 1 +IMD_CTRL_TRIP = 0 + +def test_imd(hil): + # Begin the test + hil.start_test(test_imd.__name__) + + # Outputs + imd_stat = hil.dout("Charger", "IMD_STATUS") + + # Outputs to set SDC status to okay + ams_stat = hil.dout("Charger", "BMS_STATUS") + + # Inputs + imd_ctrl = hil.din("Main_Module", "SDC_FINAL") # assuming AMS closed + + # Set other SDC nodes to okay + reset_ams(ams_stat) + + # IMD Fault + reset_imd(imd_stat) + cycle_power() + hil.check(imd_ctrl.state == IMD_CTRL_OKAY, "Power On") + time.sleep(1) + imd_stat.state = IMD_STAT_TRIP + t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) + print(f"Target trip time: [{IMD_RC_MIN_TRIP_TIME_S}, {IMD_RC_MAX_TRIP_TIME_S}]") + hil.check(IMD_RC_MIN_TRIP_TIME_S < t < IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") + hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Trip") + imd_stat.state = IMD_STAT_OKAY + time.sleep(IMD_RC_MAX_TRIP_TIME_S * 1.1) + hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Stays Latched") + + # IMD Fault on Power On + reset_imd(imd_stat) + imd_stat.state = IMD_STAT_TRIP + cycle_power() + time.sleep(IMD_RC_MAX_TRIP_TIME_S) + hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Power On") + + # IMD Floating + reset_imd(imd_stat) + imd_stat.hiZ() + cycle_power() + t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) + hil.check(t < R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") + hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Floating Trip") + + hil.end_test() + +def test_ams(hil): + # Begin the test + hil.start_test(test_ams.__name__) + + # Outputs + ams_stat = hil.dout("Charger", "BMS_STATUS") + + + # Outputs to set SDC status to okay + imd_stat = hil.dout("Charger", "IMD_STATUS") + + # Inputs + ams_ctrl = hil.din("Main_Module", "SDC_FINAL") # assuming AMS closed + + # Set other SDC nodes to okay + reset_imd(imd_stat) + + # AMS Fault + reset_ams(ams_stat) + cycle_power() + hil.check(ams_ctrl.state == AMS_CTRL_OKAY, "Power On") + time.sleep(1) + ams_stat.state = AMS_STAT_TRIP + t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) + hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") + hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Trip") + ams_stat.state = AMS_STAT_OKAY + time.sleep(AMS_MAX_TRIP_DELAY_S * 1.1) + hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Stays Latched") + + # AMS Fault on Power On + reset_ams(ams_stat) + ams_stat.state = AMS_STAT_TRIP + cycle_power() + time.sleep(AMS_MAX_TRIP_DELAY_S) + hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Power On") + + # AMS Floating + reset_ams(ams_stat) + ams_stat.hiZ() + cycle_power() + t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) + hil.check(0 <= t < AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") + hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Floating Trip") + + hil.end_test() + + +if __name__ == "__main__": + hil = HIL() + + hil.load_config("config_charger.json") + hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + #hil.init_can() + + power = hil.dout("RearTester", "RLY1") + + test_imd(hil) + test_ams(hil) + + hil.shutdown() diff --git a/scripts/pytest_collector.py b/old_scripts/test_collector.py similarity index 51% rename from scripts/pytest_collector.py rename to old_scripts/test_collector.py index 382f977..b1ee509 100644 --- a/scripts/pytest_collector.py +++ b/old_scripts/test_collector.py @@ -4,30 +4,9 @@ import utils import time -import pytest_check as check -import pytest - - -# ---------------------------------------------------------------------------- # -@pytest.fixture(scope="session") -def hil(): - hil_instance = HIL() - - hil_instance.load_config("config_collector_bench.json") - hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") - - # hil_instance.init_can() - - yield hil_instance - - hil_instance.shutdown() -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # def test_collector(hil): # Begin the test - # hil.start_test(test_collector.__name__) + hil.start_test(test_collector.__name__) # Outputs m1 = hil.dout("Collector", "MUX_A") @@ -61,19 +40,15 @@ def test_collector(hil): time.sleep(0.01) if (i == thermistor): - # hil.check_within(to.state, test_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") - check.almost_equal(to.state, test_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") + hil.check_within(to.state, test_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") else: - # hil.check_within(to.state, pullup_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") - check.almost_equal(to.state, pullup_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") + hil.check_within(to.state, pullup_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") print(to.state) # End the test - # hil.end_test() -# ---------------------------------------------------------------------------- # + hil.end_test() -# ---------------------------------------------------------------------------- # -# if __name__ == "__main__": +if __name__ == "__main__": hil = HIL() hil.load_config("config_collector_bench.json") hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") diff --git a/scripts/pytest_main_base.py b/old_scripts/test_main_base.py similarity index 51% rename from scripts/pytest_main_base.py rename to old_scripts/test_main_base.py index c553f4a..133eb27 100644 --- a/scripts/pytest_main_base.py +++ b/old_scripts/test_main_base.py @@ -6,11 +6,6 @@ from rules_constants import * from vehicle_constants import * -import pytest_check as check -import pytest - - -# ---------------------------------------------------------------------------- # AMS_STAT_OKAY = 1 AMS_STAT_TRIP = 0 AMS_CTRL_OKAY = 1 @@ -50,33 +45,10 @@ def cycle_power(): time.sleep(0.75) power.state = 0 time.sleep(CYCLE_POWER_ON_DELAY) -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # -@pytest.fixture(scope="session") -def hil(): - global power - - hil_instance = HIL() - - hil_instance.load_config("config_main_base_bench.json") - hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") - hil_instance.init_can() - - power = hil_instance.dout("Arduino2", "RLY1") - - yield hil_instance - - hil_instance.shutdown() -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # def test_precharge(hil): # Begin the test - # hil.start_test(test_precharge.__name__) + hil.start_test(test_precharge.__name__) # Outputs v_bat = hil.aout("Main_Module", "VBatt") @@ -92,19 +64,14 @@ def test_precharge(hil): # Initial State reset_pchg(v_bat, v_mc) time.sleep(2.5) - # hil.check(pchg_cmplt.state == 0, "Precharge not complete on startup") - # hil.check(not_pchg_cmplt_delayed.state == 1, "Not precharge complete delayed high on startup") - check.equal(pchg_cmplt.state, 0, "Precharge not complete on startup") - check.equal(not_pchg_cmplt_delayed.state, 1, "Not precharge complete delayed high on startup") + hil.check(pchg_cmplt.state == 0, "Precharge not complete on startup") + hil.check(not_pchg_cmplt_delayed.state == 1, "Not precharge complete delayed high on startup") # Check delay v_mc.state = tiff_hv_to_lv(ACCUM_NOM_V) t = utils.measure_trip_time(not_pchg_cmplt_delayed, PCHG_COMPLETE_DELAY_S*3, is_falling=True) - # hil.check(not_pchg_cmplt_delayed.state == 0, "Precharge complete delayed") - # hil.check_within(t, PCHG_COMPLETE_DELAY_S, 0.25, f"Precharge complete delay of {t:.3}s close to expected {PCHG_COMPLETE_DELAY_S}s") - check.equal(not_pchg_cmplt_delayed.state, 0, "Precharge complete delayed") - check.almost_equal(t, PCHG_COMPLETE_DELAY_S, abs=0.25, rel=0.0, msg=f"Precharge complete delay of {t:.3}s close to expected {PCHG_COMPLETE_DELAY_S}s") - + hil.check(not_pchg_cmplt_delayed.state == 0, "Precharge complete delayed") + hil.check_within(t, PCHG_COMPLETE_DELAY_S, 0.25, f"Precharge complete delay of {t:.3}s close to expected {PCHG_COMPLETE_DELAY_S}s") # Find threshold at nominal pack voltage for v in [ACCUM_MIN_V, ACCUM_NOM_V, ACCUM_MAX_V]: @@ -113,8 +80,7 @@ def test_precharge(hil): v_bat.state = tiff_hv_to_lv(v) v_mc.state = tiff_hv_to_lv(v*0.8) time.sleep(0.01) - # hil.check(pchg_cmplt.state == 0, "Precharge Complete Low at Initial State") - check.equal(pchg_cmplt.state, 0, "Precharge Complete Low at Initial State") + hil.check(pchg_cmplt.state == 0, "Precharge Complete Low at Initial State") start = tiff_hv_to_lv(v*0.8) stop = tiff_hv_to_lv(v) @@ -123,49 +89,38 @@ def test_precharge(hil): pchg_cmplt, is_falling=0) thresh_hv = tiff_lv_to_hv(thresh) print(f"Precharge triggered at {thresh_hv / v * 100:.4}% ({thresh_hv:.5}V) of vbat={v}.") - # hil.check_within(thresh_hv / v, R_PCHG_V_BAT_THRESH, 0.03, f"Precharge threshold of {R_PCHG_V_BAT_THRESH*100}% at vbat = {v}V") - check.almost_equal(thresh_hv / v, R_PCHG_V_BAT_THRESH, abs=0.03, rel=0.0, msg=f"Precharge threshold of {R_PCHG_V_BAT_THRESH*100}% at vbat = {v}V") - + hil.check_within(thresh_hv / v, R_PCHG_V_BAT_THRESH, 0.03, f"Precharge threshold of {R_PCHG_V_BAT_THRESH*100}% at vbat = {v}V") v_mc.state = tiff_hv_to_lv(v) time.sleep(0.25) - # hil.check(pchg_cmplt.state == 1, f"Precharge completed at vbat = {v}V") - check.equal(pchg_cmplt.state, 1, f"Precharge completed at vbat = {v}V") + hil.check(pchg_cmplt.state == 1, f"Precharge completed at vbat = {v}V") # Floating conditions (check never precharge complete) reset_pchg(v_bat, v_mc) v_bat.hiZ() v_mc.state = tiff_hv_to_lv(0) - # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc 0V") - check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat float, v_mc 0V") - + hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc 0V") v_mc.state = tiff_hv_to_lv(ACCUM_MAX_V) - # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc max V") - check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat float, v_mc max V") + hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc max V") reset_pchg(v_bat, v_mc) v_mc.hiZ() v_bat.state = tiff_hv_to_lv(ACCUM_MIN_V) - # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat min, v_mc float") - check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat min, v_mc float") + hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat min, v_mc float") v_bat.state = tiff_hv_to_lv(ACCUM_MAX_V) - # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat max, v_mc float") - check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat max, v_mc float") + hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat max, v_mc float") reset_pchg(v_bat, v_mc) v_bat.hiZ() v_mc.hiZ() - # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc float") - check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat float, v_mc float") + hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc float") # TODO: software precharge validity checks (make precharge take forever) - # hil.end_test() -# ---------------------------------------------------------------------------- # + hil.end_test() -# ---------------------------------------------------------------------------- # def test_bspd(hil): # Begin the test - # hil.start_test(test_bspd.__name__) + hil.start_test(test_bspd.__name__) # Outputs brk_fail = hil.dout("Main_Module", "Brake Fail") @@ -186,16 +141,13 @@ def test_bspd(hil): # Brake Fail reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") brk_fail.state = 1 t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") - check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") + hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") brk_fail.state = 0 time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 0, "Brake Fail Stays Latched") - check.equal(bspd_ctrl.state, 0, "Brake Fail Stays Latched") + hil.check(bspd_ctrl.state == 0, "Brake Fail Stays Latched") # Brake Fail on Power On reset_bspd(brk_fail, brk_stat, c_sense) @@ -206,74 +158,61 @@ def test_bspd(hil): brk_fail.state = 1 power.state = 0 time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 0, "Power On Brake Fail") - check.equal(bspd_ctrl.state, 0, "Power On Brake Fail") + hil.check(bspd_ctrl.state == 0, "Power On Brake Fail") # Current no brake reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") time.sleep(2) # TODO: I am not sure why this fails, but oh well set_bspd_current(c_sense, 75) time.sleep(R_BSPD_MAX_TRIP_TIME_S) # time.sleep(100) - # hil.check(bspd_ctrl.state == 1, "Current no brake") - check.equal(bspd_ctrl.state, 1, "Current no brake") + hil.check(bspd_ctrl.state == 1, "Current no brake") # Current Sense Short to Ground reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") c_sense.state = 0.0 t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") - check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") + hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") set_bspd_current(c_sense, 0.0) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 0, "Current short to ground stays latched") - check.equal(bspd_ctrl.state, 0, "Current short to ground stays latched") + hil.check(bspd_ctrl.state == 0, "Current short to ground stays latched") # Current Sense Short to 5V reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") c_sense.state = ABOX_DHAB_CH1_DIV.div(5.0) t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") - check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") + hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") set_bspd_current(c_sense, 0.0) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 0, "Current short to 5V stays latched") - check.equal(bspd_ctrl.state, 0, "Current short to 5V stays latched") + hil.check(bspd_ctrl.state == 0, "Current short to 5V stays latched") # Braking reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") brk_stat.state = 1 time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 1, "Brake no current") - check.equal(bspd_ctrl.state, 1, "Brake no current") + hil.check(bspd_ctrl.state == 1, "Brake no current") # Lowest current required to trip at min_trip_current = R_BSPD_POWER_THRESH_W / ACCUM_MAX_V set_bspd_current(c_sense, min_trip_current) t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Braking with current") - check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Braking with current") + hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Braking with current") # Measure braking with current threshold reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() brk_stat.state = 1 - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") start = ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(0.0)) stop = ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(DHAB_S124_CH1_MAX_A)) step = 0.1 @@ -282,22 +221,15 @@ def test_bspd(hil): bspd_ctrl, is_falling=True) thresh_amps = dhab_ch1_v_to_a(ABOX_DHAB_CH1_DIV.reverse(thresh)) print(f"Current while braking threshold: {thresh}V = {thresh_amps}A") - # hil.check_within(thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), 0.1, "Current while braking threshold") - check.almost_equal( - thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), - abs=0.1, rel=0.0, - msg="Current while braking threshold" - ) + hil.check_within(thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), 0.1, "Current while braking threshold") # Determine the current sense short to gnd threshold reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") set_bspd_current(c_sense, DHAB_S124_CH1_MIN_A) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 1, "Min output current okay") - check.equal(bspd_ctrl.state, 1, "Min output current okay") + hil.check(bspd_ctrl.state == 1, "Min output current okay") start = ABOX_DHAB_CH1_DIV.div(DHAB_S124_MIN_OUT_V) stop = 0.0 step = -0.1 @@ -305,20 +237,17 @@ def test_bspd(hil): R_BSPD_MAX_TRIP_TIME_S, bspd_ctrl, is_falling=True) print(f"Short to ground threshold: {thresh}V") - # hil.check(stop < (thresh) < start, "Current short to ground threshold") - check.between(thresh, stop, start, "Current short to ground threshold") + hil.check(stop < (thresh) < start, "Current short to ground threshold") # Determine the current sense short to 5V threshold reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") time.sleep(2) set_bspd_current(c_sense, DHAB_S124_CH1_MAX_A) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 1, "Max output current okay") - check.equal(bspd_ctrl.state, 1, "Max output current okay") + hil.check(bspd_ctrl.state == 1, "Max output current okay") start = ABOX_DHAB_CH1_DIV.div(DHAB_S124_MAX_OUT_V) stop = ABOX_DHAB_CH1_DIV.div(5.0) step = 0.01 @@ -327,49 +256,40 @@ def test_bspd(hil): R_BSPD_MAX_TRIP_TIME_S, bspd_ctrl, is_falling=True) print(f"Short to 5V threshold: {thresh}V") - # hil.check(bspd_ctrl.state == 0, "Short to 5V trips") - check.equal(bspd_ctrl.state, 0, "Short to 5V trips") + hil.check(bspd_ctrl.state == 0, "Short to 5V trips") print(stop) print(start) - # hil.check(start < (thresh) <= stop, "Current short to 5V threshold") - check.between(thresh, stop, start, "Current short to 5V threshold", le=True) + hil.check(start < (thresh) <= stop, "Current short to 5V threshold") # Floating current reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") c_sense.hiZ() time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 0, "Floating current") - check.equal(bspd_ctrl.state, 0, "Floating current") + hil.check(bspd_ctrl.state == 0, "Floating current") # Floating brake_fail reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") brk_fail.hiZ() time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 0, "Floating brake fail") - check.equal(bspd_ctrl.state, 0, "Floating brake fail") + hil.check(bspd_ctrl.state == 0, "Floating brake fail") # Floating brake_stat reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") brk_stat.hiZ() set_bspd_current(c_sense, min_trip_current) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 0, "Floating brake status") - check.equal(bspd_ctrl.state, 0, "Floating brake status") + hil.check(bspd_ctrl.state == 0, "Floating brake status") # End the test - # hil.end_test() -# ---------------------------------------------------------------------------- # + hil.end_test() + -# ---------------------------------------------------------------------------- # IMD_RC_MIN_TRIP_TIME_S = IMD_STARTUP_TIME_S IMD_RC_MAX_TRIP_TIME_S = R_IMD_MAX_TRIP_TIME_S - IMD_MEASURE_TIME_S IMD_CTRL_OKAY = 1 @@ -377,13 +297,13 @@ def test_bspd(hil): def test_imd(hil): # Begin the test - # hil.start_test(test_imd.__name__) + hil.start_test(test_imd.__name__) # Outputs imd_stat = hil.dout("Main_Module", "IMD_Status") # Outputs to set SDC status to okay - ams_stat = hil.dout("Main_Module", "BMS-Status-Main") + ams_stat = hil.dout("Main_Module", "BMS-Status-Main") brk_fail = hil.dout("Main_Module", "Brake Fail") brk_stat = hil.dout("Main_Module", "Brake Status") c_sense = hil.aout("Main_Module", "Current Sense C1") @@ -398,46 +318,37 @@ def test_imd(hil): # IMD Fault reset_imd(imd_stat) cycle_power() - # hil.check(imd_ctrl.state == IMD_CTRL_OKAY, "Power On") - check.equal(imd_ctrl.state, IMD_CTRL_OKAY, "Power On") + hil.check(imd_ctrl.state == IMD_CTRL_OKAY, "Power On") time.sleep(1) imd_stat.state = IMD_STAT_TRIP t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) print(f"Target trip time: [{IMD_RC_MIN_TRIP_TIME_S}, {IMD_RC_MAX_TRIP_TIME_S}]") - # hil.check(IMD_RC_MIN_TRIP_TIME_S < t < IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") - # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Trip") - check.between(t, IMD_RC_MIN_TRIP_TIME_S, IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") - check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Trip") + hil.check(IMD_RC_MIN_TRIP_TIME_S < t < IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") + hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Trip") imd_stat.state = IMD_STAT_OKAY time.sleep(IMD_RC_MAX_TRIP_TIME_S * 1.1) - # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Stays Latched") - check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Stays Latched") + hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Stays Latched") # IMD Fault on Power On reset_imd(imd_stat) imd_stat.state = IMD_STAT_TRIP cycle_power() time.sleep(IMD_RC_MAX_TRIP_TIME_S) - # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Power On") - check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Power On") + hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Power On") # IMD Floating reset_imd(imd_stat) imd_stat.hiZ() cycle_power() t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) - # hil.check(t < R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") - # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Floating Trip") - check.between(t, 0, R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") - check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Floating Trip") + hil.check(t < R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") + hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Floating Trip") - # hil.end_test() -# ---------------------------------------------------------------------------- # + hil.end_test() -# ---------------------------------------------------------------------------- # def test_ams(hil): # Begin the test - # hil.start_test(test_ams.__name__) + hil.start_test(test_ams.__name__) # Outputs ams_stat = hil.dout("Main_Module", "BMS-Status-Main") @@ -458,46 +369,37 @@ def test_ams(hil): # AMS Fault reset_ams(ams_stat) cycle_power() - # hil.check(ams_ctrl.state == AMS_CTRL_OKAY, "Power On") - check.equal(ams_ctrl.state, AMS_CTRL_OKAY, "Power On") + hil.check(ams_ctrl.state == AMS_CTRL_OKAY, "Power On") time.sleep(1) ams_stat.state = AMS_STAT_TRIP t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) - # hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") - # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Trip") - check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") - check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Trip") + hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") + hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Trip") ams_stat.state = AMS_STAT_OKAY time.sleep(AMS_MAX_TRIP_DELAY_S * 1.1) - # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Stays Latched") - check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Stays Latched") + hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Stays Latched") # AMS Fault on Power On reset_ams(ams_stat) ams_stat.state = AMS_STAT_TRIP cycle_power() time.sleep(AMS_MAX_TRIP_DELAY_S) - # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Power On") - check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Power On") + hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Power On") # AMS Floating reset_ams(ams_stat) ams_stat.hiZ() cycle_power() t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) - # hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") - # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Floating Trip") - check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") - check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Floating Trip") + hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") + hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Floating Trip") - # hil.end_test() -# ---------------------------------------------------------------------------- # + hil.end_test() -# ---------------------------------------------------------------------------- # def test_tsal(hil): # Begin the test - # hil.start_test(test_tsal.__name__) + hil.start_test(test_tsal.__name__) # Outputs v_mc = hil.aout("Main_Module", "Voltage MC Transducer") @@ -511,27 +413,21 @@ def test_tsal(hil): time.sleep(0.2) # No need to power cycle - # hil.check(lval.state == 1, "LVAL on at v_mc = 0") - # hil.check(tsal.state == 0, "TSAL off at v_mc = 0") - check.equal(lval.state, 1, "LVAL on at v_mc = 0") - check.equal(tsal.state, 0, "TSAL off at v_mc = 0") + hil.check(lval.state == 1, "LVAL on at v_mc = 0") + hil.check(tsal.state == 0, "TSAL off at v_mc = 0") time.sleep(5) - # hil.check(lval.state == 1, "LVAL stays on") - check.equal(lval.state, 1, "LVAL stays on") + hil.check(lval.state == 1, "LVAL stays on") v_mc.state = tiff_hv_to_lv(ACCUM_MIN_V) time.sleep(0.1) - # hil.check(lval.state == 0, f"LVAL off at {ACCUM_MIN_V:.4} V") - # hil.check(tsal.state == 1, f"TSAL on at {ACCUM_MIN_V:.4} V") - check.equal(lval.state, 0, f"LVAL off at {ACCUM_MIN_V:.4} V") - check.equal(tsal.state, 1, f"TSAL on at {ACCUM_MIN_V:.4} V") + hil.check(lval.state == 0, f"LVAL off at {ACCUM_MIN_V:.4} V") + hil.check(tsal.state == 1, f"TSAL on at {ACCUM_MIN_V:.4} V") reset_tsal(v_mc) time.sleep(0.2) - # hil.check(lval.state == 1, f"LVAL turns back on") - check.equal(lval.state, 1, f"LVAL turns back on") + hil.check(lval.state == 1, f"LVAL turns back on") start = tiff_hv_to_lv(0.0) stop = tiff_hv_to_lv(R_TSAL_HV_V * 1.5) @@ -541,12 +437,27 @@ def test_tsal(hil): tsal, is_falling=False) thresh = tiff_lv_to_hv(thresh) print(f"TSAL on at {thresh:.4} V") - # hil.check_within(thresh, R_TSAL_HV_V, 4, f"TSAL trips at {R_TSAL_HV_V:.4} +-4") - # hil.check(lval.state == 0, f"LVAL off V") - # hil.check(tsal.state == 1, f"TSAL on V") - check.almost_equal(thresh, R_TSAL_HV_V, abs=4, rel=0.0, msg=f"TSAL trips at {R_TSAL_HV_V:.4} +-4") - check.equal(lval.state, 0, f"LVAL off V") - check.equal(tsal.state, 1, f"TSAL on V") - - # hil.end_test() -# ---------------------------------------------------------------------------- # \ No newline at end of file + hil.check_within(thresh, R_TSAL_HV_V, 4, f"TSAL trips at {R_TSAL_HV_V:.4} +-4") + hil.check(lval.state == 0, f"LVAL off V") + hil.check(tsal.state == 1, f"TSAL on V") + + hil.end_test() + + +if __name__ == "__main__": + hil = HIL() + + hil.load_config("config_main_base_bench.json") + hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + hil.init_can() + + power = hil.dout("Arduino2", "RLY1") + + test_precharge(hil) + test_bspd(hil) + test_imd(hil) + test_ams(hil) + test_tsal(hil) + + hil.shutdown() diff --git a/scripts/pytest_main_sdc.py b/old_scripts/test_main_sdc.py similarity index 51% rename from scripts/pytest_main_sdc.py rename to old_scripts/test_main_sdc.py index 119d7a1..c4ad102 100644 --- a/scripts/pytest_main_sdc.py +++ b/old_scripts/test_main_sdc.py @@ -6,27 +6,6 @@ from rules_constants import * from vehicle_constants import * -import pytest_check as check -import pytest - - -# ---------------------------------------------------------------------------- # -@pytest.fixture(scope="session") -def hil(): - hil_instance = HIL() - - hil_instance.load_config("config_main_sdc_bench.json") - hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") - - # hil_instance.init_can() - - yield hil_instance - - hil_instance.shutdown() -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # # SETUP for CSENSE # Current Sensor (DHAB) -> ABOX V Divider -> MAIN_SDC @@ -46,11 +25,9 @@ def reset_bspd(fail, stat, ch1): stat.state = 0 set_bspd_current(ch1, 0.0) - -# ---------------------------------------------------------------------------- # def test_bspd(hil): # Begin the test - # hil.start_test(test_bspd.__name__) + hil.start_test(test_bspd.__name__) # Outputs brk_fail = hil.dout("MainSDC", "Brake Fail") @@ -64,90 +41,74 @@ def test_bspd(hil): # Brake Fail reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") brk_fail.state = 1 t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") - check.below(t, R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") + hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") brk_fail.state = 0 time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 0, "Brake Fail Stays Latched") - check.equal(bspd_ctrl.state, 0, "Brake Fail Stays Latched") + hil.check(bspd_ctrl.state == 0, "Brake Fail Stays Latched") # Brake Fail on Power On reset_bspd(brk_fail, brk_stat, c_sense) brk_fail.state = 1 cycle_power(pow) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 0, "Power On Brake Fail") - check.equal(bspd_ctrl.state, 0, "Power On Brake Fail") + hil.check(bspd_ctrl.state == 0, "Power On Brake Fail") # Current no brake reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") time.sleep(2) # TODO: I am not sure why this fails, but oh well set_bspd_current(c_sense, 75) time.sleep(R_BSPD_MAX_TRIP_TIME_S) # time.sleep(100) - # hil.check(bspd_ctrl.state == 1, "Current no brake") - check.equal(bspd_ctrl.state, 1, "Current no brake") + hil.check(bspd_ctrl.state == 1, "Current no brake") # Current Sense Short to Ground reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") c_sense.state = 0.0 t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") - check.below(t, R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") + hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") set_bspd_current(c_sense, 0.0) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 0, "Current short to ground stays latched") - check.equal(bspd_ctrl.state, 0, "Current short to ground stays latched") + hil.check(bspd_ctrl.state == 0, "Current short to ground stays latched") # Current Sense Short to 5V reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") c_sense.state = ABOX_DHAB_CH1_DIV.div(5.0) / DAC_GAIN t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") - check.below(t, R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") + hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") set_bspd_current(c_sense, 0.0) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 0, "Current short to 5V stays latched") - check.equal(bspd_ctrl.state, 0, "Current short to 5V stays latched") + hil.check(bspd_ctrl.state == 0, "Current short to 5V stays latched") # Braking reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") brk_stat.state = 1 time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 1, "Brake no current") - check.equal(bspd_ctrl.state, 1, "Brake no current") + hil.check(bspd_ctrl.state == 1, "Brake no current") # Lowest current required to trip at min_trip_current = R_BSPD_POWER_THRESH_W / ACCUM_MAX_V set_bspd_current(c_sense, min_trip_current) t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Braking with current") - check.below(t, R_BSPD_MAX_TRIP_TIME_S, "Braking with current") + hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Braking with current") # Measure braking with current threshold reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) brk_stat.state = 1 - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") start = ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(0.0)) / DAC_GAIN stop = ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(DHAB_S124_CH1_MAX_A)) / DAC_GAIN step = 0.1 / DAC_GAIN @@ -157,18 +118,15 @@ def test_bspd(hil): thresh *= DAC_GAIN thresh_amps = dhab_ch1_v_to_a(ABOX_DHAB_CH1_DIV.reverse(thresh)) print(f"Current while braking threshold: {thresh}V = {thresh_amps}A") - # hil.check_within(thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), 0.1, "Current while braking threshold") - check.within(thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), 0.1, "Current while braking threshold") + hil.check_within(thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), 0.1, "Current while braking threshold") # Determine the current sense short to gnd threshold reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") set_bspd_current(c_sense, DHAB_S124_CH1_MIN_A) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 1, "Min output current okay") - check.equal(bspd_ctrl.state, 1, "Min output current okay") + hil.check(bspd_ctrl.state == 1, "Min output current okay") start = ABOX_DHAB_CH1_DIV.div(DHAB_S124_MIN_OUT_V) / DAC_GAIN stop = 0.0 step = -0.1 / DAC_GAIN @@ -177,20 +135,17 @@ def test_bspd(hil): bspd_ctrl, is_falling=True) thresh *= DAC_GAIN print(f"Short to ground threshold: {thresh}V") - # hil.check(stop < (thresh / DAC_GAIN) < start, "Current short to ground threshold") - check.between(thresh / DAC_GAIN, stop, start, "Current short to ground threshold") + hil.check(stop < (thresh / DAC_GAIN) < start, "Current short to ground threshold") # Determine the current sense short to 5V threshold reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") time.sleep(2) set_bspd_current(c_sense, DHAB_S124_CH1_MAX_A) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 1, "Max output current okay") - check.equal(bspd_ctrl.state, 1, "Max output current okay") + hil.check(bspd_ctrl.state == 1, "Max output current okay") start = ABOX_DHAB_CH1_DIV.div(DHAB_S124_MAX_OUT_V) / DAC_GAIN stop = ABOX_DHAB_CH1_DIV.div(5.0) / DAC_GAIN step = 0.01 / DAC_GAIN @@ -200,50 +155,40 @@ def test_bspd(hil): bspd_ctrl, is_falling=True) thresh *= DAC_GAIN print(f"Short to 5V threshold: {thresh}V") - # hil.check(bspd_ctrl.state == 0, "Short to 5V trips") - check.equal(bspd_ctrl.state, 0, "Short to 5V trips") + hil.check(bspd_ctrl.state == 0, "Short to 5V trips") print(stop * DAC_GAIN) print(start * DAC_GAIN) - # hil.check(start < (thresh / DAC_GAIN) <= stop, "Current short to 5V threshold") - check.between(thresh / DAC_GAIN, stop, start, "Current short to 5V threshold") + hil.check(start < (thresh / DAC_GAIN) <= stop, "Current short to 5V threshold") # Floating current reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") c_sense.hiZ() time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 0, "Floating current") - check.equal(bspd_ctrl.state, 0, "Floating current") + hil.check(bspd_ctrl.state == 0, "Floating current") # Floating brake_fail reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") brk_fail.hiZ() time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 0, "Floating brake fail") - check.equal(bspd_ctrl.state, 0, "Floating brake fail") + hil.check(bspd_ctrl.state == 0, "Floating brake fail") # Floating brake_stat reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") brk_stat.hiZ() set_bspd_current(c_sense, min_trip_current) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 0, "Floating brake status") - check.equal(bspd_ctrl.state, 0, "Floating brake status") + hil.check(bspd_ctrl.state == 0, "Floating brake status") # End the test - # hil.end_test() -# ---------------------------------------------------------------------------- # + hil.end_test() -# ---------------------------------------------------------------------------- # IMD_RC_MIN_TRIP_TIME_S = IMD_STARTUP_TIME_S IMD_RC_MAX_TRIP_TIME_S = R_IMD_MAX_TRIP_TIME_S - IMD_MEASURE_TIME_S IMD_STAT_OKAY = 1 @@ -254,10 +199,9 @@ def test_bspd(hil): def reset_imd(imd_stat): imd_stat.state = IMD_STAT_OKAY - def test_imd(hil): # Begin the test - # hil.start_test(test_imd.__name__) + hil.start_test(test_imd.__name__) # Outputs imd_stat = hil.dout("MainSDC", "IMD_Status") @@ -269,43 +213,33 @@ def test_imd(hil): # IMD Fault reset_imd(imd_stat) cycle_power(pow) - # hil.check(imd_ctrl.state == IMD_CTRL_OKAY, "Power On") - check.equal(imd_ctrl.state, IMD_CTRL_OKAY, "Power On") + hil.check(imd_ctrl.state == IMD_CTRL_OKAY, "Power On") time.sleep(1) imd_stat.state = IMD_STAT_TRIP t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) - # hil.check(IMD_RC_MIN_TRIP_TIME_S < t < IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") - # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Trip") - check.between(t, IMD_RC_MIN_TRIP_TIME_S, IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") - check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Trip") + hil.check(IMD_RC_MIN_TRIP_TIME_S < t < IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") + hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Trip") imd_stat.state = IMD_STAT_OKAY time.sleep(IMD_RC_MAX_TRIP_TIME_S * 1.1) - # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Stays Latched") - check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Stays Latched") + hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Stays Latched") # IMD Fault on Power On reset_imd(imd_stat) imd_stat.state = IMD_STAT_TRIP cycle_power(pow) time.sleep(IMD_RC_MAX_TRIP_TIME_S) - # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Power On") - check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Power On") + hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Power On") # IMD Floating reset_imd(imd_stat) imd_stat.hiZ() cycle_power(pow) t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) - # hil.check(t < R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") - # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Floating Trip") - check.below(t, R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") - check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Floating Trip") + hil.check(t < R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") + hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Floating Trip") - # hil.end_test() -# ---------------------------------------------------------------------------- # + hil.end_test() - -# ---------------------------------------------------------------------------- # AMS_STAT_OKAY = 1 AMS_STAT_TRIP = 0 AMS_CTRL_OKAY = 1 @@ -314,10 +248,9 @@ def test_imd(hil): def reset_ams(ams_stat): ams_stat.state = AMS_STAT_OKAY - def test_ams(hil): # Begin the test - # hil.start_test(test_ams.__name__) + hil.start_test(test_ams.__name__) # Outputs ams_stat = hil.dout("MainSDC", "BMS-Status-Main") @@ -329,37 +262,41 @@ def test_ams(hil): # AMS Fault reset_ams(ams_stat) cycle_power(pow) - # hil.check(ams_ctrl.state == AMS_CTRL_OKAY, "Power On") - check.equal(ams_ctrl.state, AMS_CTRL_OKAY, "Power On") + hil.check(ams_ctrl.state == AMS_CTRL_OKAY, "Power On") time.sleep(1) ams_stat.state = AMS_STAT_TRIP t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) - # hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") - # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Trip") - check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") - check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Trip") + hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") + hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Trip") ams_stat.state = AMS_STAT_OKAY time.sleep(AMS_MAX_TRIP_DELAY_S * 1.1) - # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Stays Latched") - check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Stays Latched") + hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Stays Latched") # AMS Fault on Power On reset_ams(ams_stat) ams_stat.state = AMS_STAT_TRIP cycle_power(pow) time.sleep(AMS_MAX_TRIP_DELAY_S) - # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Power On") - check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Power On") + hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Power On") # AMS Floating reset_ams(ams_stat) ams_stat.hiZ() cycle_power(pow) t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) - # hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") - # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Floating Trip") - check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time", ge=True) - check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Floating Trip") + hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") + hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Floating Trip") - # hil.end_test() -# ---------------------------------------------------------------------------- # \ No newline at end of file + hil.end_test() + + +if __name__ == "__main__": + hil = HIL() + hil.load_config("config_main_sdc_bench.json") + hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + test_bspd(hil) + test_imd(hil) + test_ams(hil) + + hil.shutdown() diff --git a/scripts/pytest_system.py b/old_scripts/test_system.py similarity index 51% rename from scripts/pytest_system.py rename to old_scripts/test_system.py index 967f915..30ffc5a 100644 --- a/scripts/pytest_system.py +++ b/old_scripts/test_system.py @@ -6,11 +6,6 @@ from rules_constants import * from vehicle_constants import * -import pytest_check as check -import pytest - - -# ---------------------------------------------------------------------------- # AMS_STAT_OKAY = 1 AMS_STAT_TRIP = 0 AMS_CTRL_OKAY = 1 @@ -53,33 +48,10 @@ def cycle_power(): time.sleep(CYCLE_POWER_OFF_DELAY) power.state = 0 time.sleep(CYCLE_POWER_ON_DELAY) -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # -@pytest.fixture(scope="session") -def hil(): - global power - - hil_instance = HIL() - - hil_instance.load_config("config_charger.json") - hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") - - # hil_instance.init_can() - - power = hil_instance.dout("RearTester", "RLY1") - - yield hil_instance - - hil_instance.shutdown() -# ---------------------------------------------------------------------------- # - -# ---------------------------------------------------------------------------- # def test_precharge(hil): # Begin the test - # hil.start_test(test_precharge.__name__) + hil.start_test(test_precharge.__name__) # Outputs v_bat = hil.aout("Main_Module", "VBatt") @@ -107,17 +79,13 @@ def test_precharge(hil): # Initial State reset_pchg(v_bat, v_mc) time.sleep(2.5) - # hil.check(pchg_cmplt.state == 0, "Precharge not complete on startup") - # hil.check(not_pchg_cmplt_delayed.state == 1, "Not precharge complete delayed high on startup") - check.equal(pchg_cmplt.state, 0, "Precharge not complete on startup") - check.equal(not_pchg_cmplt_delayed.state, 1, "Not precharge complete delayed high on startup") + hil.check(pchg_cmplt.state == 0, "Precharge not complete on startup") + hil.check(not_pchg_cmplt_delayed.state == 1, "Not precharge complete delayed high on startup") # Check delay v_mc.state = tiff_hv_to_lv(ACCUM_NOM_V) t = utils.measure_trip_time(not_pchg_cmplt_delayed, PCHG_COMPLETE_DELAY_S*3, is_falling=True) - # hil.check(not_pchg_cmplt_delayed.state == 0, "Precharge complete delayed") - # hil.check_within(t, PCHG_COMPLETE_DELAY_S, 0.25, f"Precharge complete delay of {t:.3}s close to expected {PCHG_COMPLETE_DELAY_S}s") - check.equal(not_pchg_cmplt_delayed.state, 0, "Precharge complete delayed") - check.almost_equal(t, PCHG_COMPLETE_DELAY_S, abs=0.25, rel=0.0, msg=f"Precharge complete delay of {t:.3}s close to expected {PCHG_COMPLETE_DELAY_S}s") + hil.check(not_pchg_cmplt_delayed.state == 0, "Precharge complete delayed") + hil.check_within(t, PCHG_COMPLETE_DELAY_S, 0.25, f"Precharge complete delay of {t:.3}s close to expected {PCHG_COMPLETE_DELAY_S}s") # Find threshold at nominal pack voltage for v in [ACCUM_MIN_V, ACCUM_NOM_V, ACCUM_MAX_V]: @@ -127,8 +95,7 @@ def test_precharge(hil): v_mc.state = tiff_hv_to_lv(v*0.8) #time.sleep(0.01) time.sleep(0.5) - # hil.check(pchg_cmplt.state == 0, "Precharge Complete Low at Initial State") - check.equal(pchg_cmplt.state, 0, "Precharge Complete Low at Initial State") + hil.check(pchg_cmplt.state == 0, "Precharge Complete Low at Initial State") start = tiff_hv_to_lv(v*0.8) stop = tiff_hv_to_lv(v) @@ -137,52 +104,41 @@ def test_precharge(hil): pchg_cmplt, is_falling=0) thresh_hv = tiff_lv_to_hv(thresh) print(f"Precharge triggered at {thresh_hv / v * 100:.4}% ({thresh_hv:.5}V) of vbat={v}.") - # hil.check_within(thresh_hv / v, R_PCHG_V_BAT_THRESH, 0.03, f"Precharge threshold of {R_PCHG_V_BAT_THRESH*100}% at vbat = {v}V") - check.almost_equal(thresh_hv / v, R_PCHG_V_BAT_THRESH, abs=0.03, rel=0.0, msg=f"Precharge threshold of {R_PCHG_V_BAT_THRESH*100}% at vbat = {v}V") + hil.check_within(thresh_hv / v, R_PCHG_V_BAT_THRESH, 0.03, f"Precharge threshold of {R_PCHG_V_BAT_THRESH*100}% at vbat = {v}V") v_mc.state = tiff_hv_to_lv(v) #time.sleep(0.25) time.sleep(8) - # hil.check(pchg_cmplt.state == 1, f"Precharge completed at vbat = {v}V") - check.equal(pchg_cmplt.state, 1, f"Precharge completed at vbat = {v}V") + hil.check(pchg_cmplt.state == 1, f"Precharge completed at vbat = {v}V") # Floating conditions (check never precharge complete) reset_pchg(v_bat, v_mc) v_bat.hiZ() v_mc.state = tiff_hv_to_lv(0) - # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc 0V") - check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat float, v_mc 0V") + hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc 0V") v_mc.state = tiff_hv_to_lv(ACCUM_MAX_V) - # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc max V") - check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat float, v_mc max V") + hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc max V") reset_pchg(v_bat, v_mc) v_mc.hiZ() v_bat.state = tiff_hv_to_lv(ACCUM_MIN_V) - # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat min, v_mc float") - check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat min, v_mc float") + hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat min, v_mc float") v_bat.state = tiff_hv_to_lv(ACCUM_MAX_V) - # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat max, v_mc float") - check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat max, v_mc float") + hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat max, v_mc float") reset_pchg(v_bat, v_mc) v_bat.hiZ() v_mc.hiZ() - # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc float") - check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat float, v_mc float") + hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc float") # TODO: software precharge validity checks (make precharge take forever) - # hil.end_test() -# ---------------------------------------------------------------------------- # + hil.end_test() - -# ---------------------------------------------------------------------------- # BRK_SWEEP_DELAY = 0.1 BSPD_DASH_ON_TIME = 0 - def test_bspd(hil): # Begin the test - # hil.start_test(test_bspd.__name__) + hil.start_test(test_bspd.__name__) # Outputs brk1 = hil.aout("Dashboard", "BRK1_RAW") @@ -207,29 +163,23 @@ def test_bspd(hil): # Brake threshold check brk1.state = BRK_1_REST_V brk2.state = BRK_2_REST_V - # hil.check(brk_stat_tap.state == 0, "Brake stat starts low") - check.equal(brk_stat_tap.state, 0, "Brake stat starts low") + hil.check(brk_stat_tap.state == 0, "Brake stat starts low") brk1.state = BRK_1_THRESH_V time.sleep(0.1) - # hil.check(brk_stat_tap.state == 1, "Brake stat goes high at brk 1 thresh") - check.equal(brk_stat_tap.state, 1, "Brake stat goes high at brk 1 thresh") + hil.check(brk_stat_tap.state == 1, "Brake stat goes high at brk 1 thresh") brk1.state = BRK_1_REST_V - # hil.check(brk_stat_tap.state == 0, "Brake stat starts low") - check.equal(brk_stat_tap.state, 0, "Brake stat starts low") + hil.check(brk_stat_tap.state == 0, "Brake stat starts low") brk2.state = BRK_2_THRESH_V time.sleep(0.1) - # hil.check(brk_stat_tap.state == 1, "Brake stat goes high at brk 2 thresh") - check.equal(brk_stat_tap.state, 1, "Brake stat goes high at brk 2 thresh") + hil.check(brk_stat_tap.state == 1, "Brake stat goes high at brk 2 thresh") brk1.state = BRK_1_THRESH_V - # hil.check(brk_stat_tap.state == 1, "Brake stat stays high for both brakes") - check.equal(brk_stat_tap.state, 1, "Brake stat stays high for both brakes") + hil.check(brk_stat_tap.state == 1, "Brake stat stays high for both brakes") # Brake threshold scan brk1.state = BRK_MIN_OUT_V brk2.state = BRK_MIN_OUT_V time.sleep(0.1) - # hil.check(brk_stat_tap.state == 0, "Brake Stat Starts Low Brk 1") - check.equal(brk_stat_tap.state, 0, "Brake Stat Starts Low Brk 1") + hil.check(brk_stat_tap.state == 0, "Brake Stat Starts Low Brk 1") start = BRK_MIN_OUT_V stop = BRK_MAX_OUT_V @@ -239,108 +189,72 @@ def test_bspd(hil): BRK_SWEEP_DELAY, brk_stat_tap, is_falling=False) print(f"Brake 1 braking threshold: {thresh}") - # hil.check_within(thresh, BRK_1_THRESH_V, 0.2, "Brake 1 trip voltage") - # hil.check(brk_stat_tap.state == 1, "Brake Stat Tripped for Brk 1") - check.almost_equal(thresh, BRK_1_THRESH_V, abs=0.2, rel=0.0, msg="Brake 1 trip voltage") - check.equal(brk_stat_tap.state, 1, "Brake Stat Tripped for Brk 1") + hil.check_within(thresh, BRK_1_THRESH_V, 0.2, "Brake 1 trip voltage") + hil.check(brk_stat_tap.state == 1, "Brake Stat Tripped for Brk 1") brk1.state = BRK_MIN_OUT_V brk2.state = BRK_MIN_OUT_V - # hil.check(brk_stat_tap.state == 0, "Brake Stat Starts Low Brk 2") - check.equal(brk_stat_tap.state, 0, "Brake Stat Starts Low Brk 2") + hil.check(brk_stat_tap.state == 0, "Brake Stat Starts Low Brk 2") thresh = utils.measure_trip_thresh(brk2, start, stop, step, BRK_SWEEP_DELAY, brk_stat_tap, is_falling=False) print(f"Brake 2 braking threshold: {thresh}") - # hil.check_within(thresh, BRK_2_THRESH_V, 0.2, "Brake 2 trip voltage") - # hil.check(brk_stat_tap.state == 1, "Brake Stat Tripped for Brk 2") - check.almost_equal(thresh, BRK_2_THRESH_V, abs=0.2, rel=0.0, msg="Brake 2 trip voltage") - check.equal(brk_stat_tap.state, 1, "Brake Stat Tripped for Brk 2") + hil.check_within(thresh, BRK_2_THRESH_V, 0.2, "Brake 2 trip voltage") + hil.check(brk_stat_tap.state == 1, "Brake Stat Tripped for Brk 2") # Brake Fail scan brk1.state = BRK_1_REST_V brk2.state = BRK_2_REST_V time.sleep(0.1) - # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 1 Starts 0") - check.equal(brk_fail_tap.state, 0, "Brake Fail Check 1 Starts 0") - + hil.check(brk_fail_tap.state == 0, "Brake Fail Check 1 Starts 0") brk1.state = 0.0 # Force 0 time.sleep(0.1) - # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Short GND") - check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 1 Short GND") - + hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Short GND") brk1.state = BRK_1_REST_V time.sleep(0.1) - # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 2 Starts 0") - check.equal(brk_fail_tap.state, 0, "Brake Fail Check 2 Starts 0") - + hil.check(brk_fail_tap.state == 0, "Brake Fail Check 2 Starts 0") brk2.state = 0.0 # Force 0 time.sleep(0.1) - # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Short GND") - check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 2 Short GND") - + hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Short GND") brk2.state = BRK_2_REST_V time.sleep(0.1) - # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 3 Starts 0") - check.equal(brk_fail_tap.state, 0, "Brake Fail Check 3 Starts 0") - + hil.check(brk_fail_tap.state == 0, "Brake Fail Check 3 Starts 0") brk1.state = 5.0 # Short VCC time.sleep(0.1) - # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Short VCC") - check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 1 Short VCC") - + hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Short VCC") brk1.state = BRK_1_REST_V time.sleep(0.1) - # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 4 Starts 0") - check.equal(brk_fail_tap.state, 0, "Brake Fail Check 4 Starts 0") - + hil.check(brk_fail_tap.state == 0, "Brake Fail Check 4 Starts 0") brk2.state = 5.0 # Short VCC time.sleep(0.1) - # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Short VCC") - check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 2 Short VCC") - + hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Short VCC") brk2.state = BRK_2_REST_V time.sleep(0.1) - # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 5 Starts 0") - check.equal(brk_fail_tap.state, 0, "Brake Fail Check 5 Starts 0") - + hil.check(brk_fail_tap.state == 0, "Brake Fail Check 5 Starts 0") brk1.hiZ() time.sleep(0.1) - # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Hi-Z") - check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 1 Hi-Z") - + hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Hi-Z") brk1.state = BRK_1_REST_V time.sleep(0.1) - # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 6 Starts 0") - check.equal(brk_fail_tap.state, 0, "Brake Fail Check 6 Starts 0") - + hil.check(brk_fail_tap.state == 0, "Brake Fail Check 6 Starts 0") brk2.hiZ() time.sleep(0.1) - # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Hi-Z") - check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 2 Hi-Z") - + hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Hi-Z") brk2.state = BRK_2_REST_V # Brake Fail reset_bspd(brk1, brk2, c_sense) cycle_power() time.sleep(BSPD_DASH_ON_TIME) - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") - + hil.check(bspd_ctrl.state == 1, "Power On") brk1.state = 0.0 t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") - # hil.check(brk_fail_tap.state == 1, "Brake Fail went high") - check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") - check.equal(brk_fail_tap.state, 1, "Brake Fail went high") - + hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") + hil.check(brk_fail_tap.state == 1, "Brake Fail went high") brk1.state = BRK_1_REST_V time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(brk_fail_tap.state == 0, "Brake Fail returned low") - # hil.check(bspd_ctrl.state == 0, "Brake Fail Stays Latched") - check.equal(brk_fail_tap.state, 0, "Brake Fail returned low") - check.equal(bspd_ctrl.state, 0, "Brake Fail Stays Latched") + hil.check(brk_fail_tap.state == 0, "Brake Fail returned low") + hil.check(bspd_ctrl.state == 0, "Brake Fail Stays Latched") # Brake Fail on Power On reset_bspd(brk1, brk2, c_sense) @@ -352,8 +266,7 @@ def test_bspd(hil): power.state = 0 time.sleep(R_BSPD_MAX_TRIP_TIME_S) time.sleep(BSPD_DASH_ON_TIME) # NOTE: test can't check for the trip time - # hil.check(bspd_ctrl.state == 0, "Power On Brake Fail") - check.equal(bspd_ctrl.state, 0, "Power On Brake Fail") + hil.check(bspd_ctrl.state == 0, "Power On Brake Fail") # Current no brake reset_bspd(brk1, brk2, c_sense) @@ -367,59 +280,47 @@ def test_bspd(hil): time.sleep(R_BSPD_MAX_TRIP_TIME_S) # time.sleep(100) time.sleep(3) - # hil.check(bspd_ctrl.state == 1, "Current no brake") - check.equal(bspd_ctrl.state, 1, "Current no brake") + hil.check(bspd_ctrl.state == 1, "Current no brake") # Current Sense Short to Ground reset_bspd(brk1, brk2, c_sense) cycle_power() time.sleep(BSPD_DASH_ON_TIME) - # hil.check(bspd_ctrl.state == 1, "Power On" - check.equal(bspd_ctrl.state, 1, "Power On") - + hil.check(bspd_ctrl.state == 1, "Power On") c_sense.state = 0.0 t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") - check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") + hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") set_bspd_current(c_sense, 0.0) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 0, "Current short to ground stays latched") - check.equal(bspd_ctrl.state, 0, "Current short to ground stays latched") + hil.check(bspd_ctrl.state == 0, "Current short to ground stays latched") # Current Sense Short to 5V reset_bspd(brk1, brk2, c_sense) cycle_power() time.sleep(BSPD_DASH_ON_TIME*1.2) - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") c_sense.state = ABOX_DHAB_CH1_DIV.div(5.0) t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") - check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") + hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") set_bspd_current(c_sense, 0.0) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 0, "Current short to 5V stays latched") - check.equal(bspd_ctrl.state, 0, "Current short to 5V stays latched") + hil.check(bspd_ctrl.state == 0, "Current short to 5V stays latched") # Braking reset_bspd(brk1, brk2, c_sense) cycle_power() time.sleep(BSPD_DASH_ON_TIME) - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") brk1.state = BRK_1_THRESH_V time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 1, "Brake no current") - # hil.check(brk_stat_tap.state == 1, "Brake stat went high") - check.equal(bspd_ctrl.state, 1, "Brake no current") - check.equal(brk_stat_tap.state, 1, "Brake stat went high") + hil.check(bspd_ctrl.state == 1, "Brake no current") + hil.check(brk_stat_tap.state == 1, "Brake stat went high") # Lowest current required to trip at min_trip_current = R_BSPD_POWER_THRESH_W / ACCUM_MAX_V set_bspd_current(c_sense, min_trip_current) t = utils.measure_trip_time(bspd_ctrl, 10.0, is_falling=True) - # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Braking with current") - check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Braking with current") + hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Braking with current") # Measure braking with current threshold reset_bspd(brk1, brk2, c_sense) @@ -427,8 +328,7 @@ def test_bspd(hil): time.sleep(BSPD_DASH_ON_TIME) brk1.state = BRK_1_THRESH_V - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") start = ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(0.0)) stop = ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(DHAB_S124_CH1_MAX_A)) step = 0.1 @@ -437,23 +337,16 @@ def test_bspd(hil): bspd_ctrl, is_falling=True) thresh_amps = dhab_ch1_v_to_a(ABOX_DHAB_CH1_DIV.reverse(thresh)) print(f"Current while braking threshold: {thresh}V = {thresh_amps}A") - # hil.check_within(thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), 0.1, "Current while braking threshold") - check.almost_equal( - thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), - abs=0.1, rel=0.0, - msg="Current while braking threshold" - ) + hil.check_within(thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), 0.1, "Current while braking threshold") # Determine the current sense short to gnd threshold reset_bspd(brk1, brk2, c_sense) cycle_power() time.sleep(BSPD_DASH_ON_TIME) - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") set_bspd_current(c_sense, DHAB_S124_CH1_MIN_A) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 1, "Min output current okay") - check.equal(bspd_ctrl.state, 1, "Min output current okay") + hil.check(bspd_ctrl.state == 1, "Min output current okay") start = ABOX_DHAB_CH1_DIV.div(DHAB_S124_MIN_OUT_V) stop = 0.0 step = -0.1 @@ -461,21 +354,18 @@ def test_bspd(hil): R_BSPD_MAX_TRIP_TIME_S, bspd_ctrl, is_falling=True) print(f"Short to ground threshold: {thresh}V") - # hil.check(stop < (thresh) < start, "Current short to ground threshold") - check.between(thresh, stop, start, "Current short to ground threshold") + hil.check(stop < (thresh) < start, "Current short to ground threshold") # Determine the current sense short to 5V threshold reset_bspd(brk1, brk2, c_sense) cycle_power() time.sleep(BSPD_DASH_ON_TIME) - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") time.sleep(2) set_bspd_current(c_sense, DHAB_S124_CH1_MAX_A) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 1, "Max output current okay") - check.equal(bspd_ctrl.state, 1, "Max output current okay") + hil.check(bspd_ctrl.state == 1, "Max output current okay") start = ABOX_DHAB_CH1_DIV.div(DHAB_S124_MAX_OUT_V) stop = ABOX_DHAB_CH1_DIV.div(5.0) @@ -483,31 +373,26 @@ def test_bspd(hil): c_sense.state = start time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 1, "Max output voltage okay") - check.equal(bspd_ctrl.state, 1, "Max output voltage okay") + hil.check(bspd_ctrl.state == 1, "Max output voltage okay") input("enter to continue") thresh = utils.measure_trip_thresh(c_sense, start, stop, step, R_BSPD_MAX_TRIP_TIME_S, bspd_ctrl, is_falling=True) print(f"Short to 5V threshold: {thresh}V") - # hil.check(bspd_ctrl.state == 0, "Short to 5V trips") - check.equal(bspd_ctrl.state, 0, "Short to 5V trips") + hil.check(bspd_ctrl.state == 0, "Short to 5V trips") print(stop) print(start) - # hil.check(start < (thresh) <= stop, "Current short to 5V threshold") - check.between(thresh, start, stop, "Current short to 5V threshold", le=True) + hil.check(start < (thresh) <= stop, "Current short to 5V threshold") # Floating current reset_bspd(brk1, brk2, c_sense) cycle_power() time.sleep(BSPD_DASH_ON_TIME) - # hil.check(bspd_ctrl.state == 1, "Power On") - check.equal(bspd_ctrl.state, 1, "Power On") + hil.check(bspd_ctrl.state == 1, "Power On") c_sense.hiZ() time.sleep(R_BSPD_MAX_TRIP_TIME_S) - # hil.check(bspd_ctrl.state == 0, "Floating current") - check.equal(bspd_ctrl.state, 0, "Floating current") + hil.check(bspd_ctrl.state == 0, "Floating current") # Floating brake_fail # Can't test this at system level! @@ -516,11 +401,9 @@ def test_bspd(hil): # Can't test this at system level! # End the test - # hil.end_test() -# ---------------------------------------------------------------------------- # + hil.end_test() -# ---------------------------------------------------------------------------- # IMD_RC_MIN_TRIP_TIME_S = IMD_STARTUP_TIME_S IMD_RC_MAX_TRIP_TIME_S = R_IMD_MAX_TRIP_TIME_S - IMD_MEASURE_TIME_S IMD_CTRL_OKAY = 1 @@ -528,7 +411,7 @@ def test_bspd(hil): def test_imd(hil): # Begin the test - # hil.start_test(test_imd.__name__) + hil.start_test(test_imd.__name__) # Outputs imd_stat = hil.dout("Main_Module", "IMD_Status") @@ -549,47 +432,37 @@ def test_imd(hil): # IMD Fault reset_imd(imd_stat) cycle_power() - # hil.check(imd_ctrl.state == IMD_CTRL_OKAY, "Power On") - check.equal(imd_ctrl.state, IMD_CTRL_OKAY, "Power On") + hil.check(imd_ctrl.state == IMD_CTRL_OKAY, "Power On") time.sleep(1) imd_stat.state = IMD_STAT_TRIP t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) print(f"Target trip time: [{IMD_RC_MIN_TRIP_TIME_S}, {IMD_RC_MAX_TRIP_TIME_S}]") - # hil.check(IMD_RC_MIN_TRIP_TIME_S < t < IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") - # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Trip") - check.between(t, IMD_RC_MIN_TRIP_TIME_S, IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") - check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Trip") + hil.check(IMD_RC_MIN_TRIP_TIME_S < t < IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") + hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Trip") imd_stat.state = IMD_STAT_OKAY time.sleep(IMD_RC_MAX_TRIP_TIME_S * 1.1) - # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Stays Latched") - check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Stays Latched") + hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Stays Latched") # IMD Fault on Power On reset_imd(imd_stat) imd_stat.state = IMD_STAT_TRIP cycle_power() time.sleep(IMD_RC_MAX_TRIP_TIME_S) - # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Power On") - check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Power On") + hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Power On") # IMD Floating reset_imd(imd_stat) imd_stat.hiZ() cycle_power() t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) - # hil.check(t < R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") - # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Floating Trip") - check.less(t, R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") - check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Floating Trip") + hil.check(t < R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") + hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Floating Trip") - # hil.end_test() -# ---------------------------------------------------------------------------- # - + hil.end_test() -# ---------------------------------------------------------------------------- # def test_ams(hil): # Begin the test - # hil.start_test(test_ams.__name__) + hil.start_test(test_ams.__name__) # Outputs ams_stat = hil.dout("Main_Module", "BMS-Status-Main") @@ -610,43 +483,33 @@ def test_ams(hil): # AMS Fault reset_ams(ams_stat) cycle_power() - # hil.check(ams_ctrl.state == AMS_CTRL_OKAY, "Power On") - check.equal(ams_ctrl.state, AMS_CTRL_OKAY, "Power On") + hil.check(ams_ctrl.state == AMS_CTRL_OKAY, "Power On") time.sleep(1) ams_stat.state = AMS_STAT_TRIP t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) - # hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") - # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Trip") - check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") - check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Trip") + hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") + hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Trip") ams_stat.state = AMS_STAT_OKAY time.sleep(AMS_MAX_TRIP_DELAY_S * 1.1) - # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Stays Latched") - check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Stays Latched") + hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Stays Latched") # AMS Fault on Power On reset_ams(ams_stat) ams_stat.state = AMS_STAT_TRIP cycle_power() time.sleep(AMS_MAX_TRIP_DELAY_S) - # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Power On") - check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Power On") + hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Power On") # AMS Floating reset_ams(ams_stat) ams_stat.hiZ() cycle_power() t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) - # hil.check(0 <= t < AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") - # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Floating Trip") - check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") - check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Floating Trip") + hil.check(0 <= t < AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") + hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Floating Trip") - # hil.end_test() -# ---------------------------------------------------------------------------- # + hil.end_test() - -# ---------------------------------------------------------------------------- # def tsal_is_red(): while 1: i = input("Is TSAL Green (g) or Red (r): ") @@ -673,25 +536,21 @@ def test_tsal(hil): time.sleep(0.2) # No need to power cycle - # hil.check(tsal_is_red() == False, "LVAL on at v_mc = 0") - check.equal(tsal_is_red(), False, "LVAL on at v_mc = 0") + hil.check(tsal_is_red() == False, "LVAL on at v_mc = 0") #hil.check(tsal.state == 0, "TSAL off at v_mc = 0") time.sleep(5) - # hil.check(tsal_is_red() == False, "LVAL stays on") - check.equal(tsal_is_red(), False, "LVAL stays on") + hil.check(tsal_is_red() == False, "LVAL stays on") v_mc.state = tiff_hv_to_lv(ACCUM_MIN_V) time.sleep(0.1) #hil.check(lval.state == 0, f"LVAL off at {ACCUM_MIN_V:.4} V") - # hil.check(tsal_is_red() == True, f"TSAL on at {ACCUM_MIN_V:.4} V") - check.equal(tsal_is_red(), True, f"TSAL on at {ACCUM_MIN_V:.4} V") + hil.check(tsal_is_red() == True, f"TSAL on at {ACCUM_MIN_V:.4} V") reset_tsal(v_mc) time.sleep(0.2) - # hil.check(tsal_is_red() == False, f"LVAL turns back on") - check.equal(tsal_is_red(), False, f"LVAL turns back on") + hil.check(tsal_is_red() == False, f"LVAL turns back on") start = tiff_hv_to_lv(50) stop = tiff_hv_to_lv(R_TSAL_HV_V * 1.5) @@ -715,36 +574,27 @@ def test_tsal(hil): if (not tripped): utils.log_warning(f"TSAL did not trip at stop of {stop}.") thresh = stop - # hil.check(tripped, "TSAL tripped") - check.is_true(tripped, "TSAL tripped") + hil.check(tripped, "TSAL tripped") thresh = tiff_lv_to_hv(thresh) print(f"TSAL on at {thresh:.4} V") hil.check_within(thresh, R_TSAL_HV_V, 4, f"TSAL trips at {R_TSAL_HV_V:.4} +-4") - check.almost_equal(thresh, R_TSAL_HV_V, abs=4, rel=0.0, msg=f"TSAL trips at {R_TSAL_HV_V:.4} +-4") - - # hil.end_test() -# ---------------------------------------------------------------------------- # + hil.end_test() -# ---------------------------------------------------------------------------- # def test_sdc(hil): ''' Check that every node in the sdc trips ''' # Begin the test - # hil.start_test(test_sdc.__name__) + hil.start_test(test_sdc.__name__) # Outputs # Inputs - # hil.check(False, "TODO") - check.is_true(False, "TODO") + hil.check(0, "TODO") - # hil.end_test() -# ---------------------------------------------------------------------------- # + hil.end_test() - -# ---------------------------------------------------------------------------- # def is_buzzer_on(): while 1: i = input("Is Buzzer On (y) or No (n): ") @@ -756,7 +606,7 @@ def is_buzzer_on(): def test_buzzer(hil): # Begin the test - # hil.start_test(test_buzzer.__name__) + hil.start_test(test_buzzer.__name__) # Outputs buzzer_ctrl = hil.daq_var("Main_Module", "daq_buzzer") @@ -766,29 +616,21 @@ def test_buzzer(hil): buzzer_ctrl.state = 0 time.sleep(0.02) - # hil.check(buzzer_stat.state == 0, "Buzzer Off") - check.equal(buzzer_stat.state, 0, "Buzzer Off") + hil.check(buzzer_stat.state == 0, "Buzzer Off") buzzer_ctrl.state = 1 print(buzzer_ctrl.state) time.sleep(0.02) - # hil.check(buzzer_stat.state == 1, "Buzzer On") - # hil.check(is_buzzer_on() == True, "Buzzer Making Noise") - check.equal(buzzer_stat.state, 1, "Buzzer On") - check.is_true(is_buzzer_on(), "Buzzer Making Noise") + hil.check(buzzer_stat.state == 1, "Buzzer On") + hil.check(is_buzzer_on() == True, "Buzzer Making Noise") buzzer_ctrl.state = 0 time.sleep(0.02) - # hil.check(buzzer_stat.state == 0, "Buzzer back Off") - # hil.check(is_buzzer_on() == False, "Buzzer Not Making Noise") - check.equal(buzzer_stat.state, 0, "Buzzer back Off") - check.is_false(is_buzzer_on(), "Buzzer Not Making Noise") - - # hil.end_test() -# ---------------------------------------------------------------------------- # + hil.check(buzzer_stat.state == 0, "Buzzer back Off") + hil.check(is_buzzer_on() == False, "Buzzer Not Making Noise") + hil.end_test() -# ---------------------------------------------------------------------------- # def is_brake_light_on(): while 1: i = input("Is Brake Light On (y) or No (n): ") @@ -800,7 +642,7 @@ def is_brake_light_on(): def test_brake_light(hil): # Begin the test - # hil.start_test(test_brake_light.__name__) + hil.start_test(test_brake_light.__name__) # Outputs brk_ctrl = hil.daq_var("Main_Module", "daq_brake") @@ -810,36 +652,28 @@ def test_brake_light(hil): brk_ctrl.state = 0 time.sleep(0.02) - # hil.check(brk_ctrl.state == 0, "Brake Off") - check.equal(brk_ctrl.state, 0, "Brake Off") + hil.check(brk_ctrl.state == 0, "Brake Off") brk_ctrl.state = 1 print(brk_ctrl.state) time.sleep(0.02) - # hil.check(brk_ctrl.state == 1, "Brake Light On") - # hil.check(is_brake_light_on() == True, "Brake Light is On") - check.equal(brk_ctrl.state, 1, "Brake Light On") - check.is_true(is_brake_light_on(), "Brake Light is On") + hil.check(brk_ctrl.state == 1, "Brake Light On") + hil.check(is_brake_light_on() == True, "Brake Light is On") brk_ctrl.state = 0 time.sleep(0.02) - # hil.check(brk_ctrl.state == 0, "Brake Light back Off") - # hil.check(is_brake_light_on() == False, "Brake Light is Off") - check.equal(brk_ctrl.state, 0, "Brake Light back Off") - check.is_false(is_brake_light_on(), "Brake Light is Off") + hil.check(brk_ctrl.state == 0, "Brake Light back Off") + hil.check(is_brake_light_on() == False, "Brake Light is Off") # Can copy lot from bspd # Read the brake control mcu pin # Finally have user verify light actually turned on - # hil.end_test() -# ---------------------------------------------------------------------------- # - + hil.end_test() -# ---------------------------------------------------------------------------- # def test_light_tsal_buz(hil): - # hil.start_test(test_light_tsal_buz.__name__) + hil.start_test(test_light_tsal_buz.__name__) # Outputs brk_ctrl = hil.daq_var("Main_Module", "daq_brake") @@ -851,7 +685,30 @@ def test_light_tsal_buz(hil): brk_ctrl.state = 0 buzzer_ctrl.state = 0 - check.is_true(True, "TODO") + hil.end_test() + + +if __name__ == "__main__": + hil = HIL() + + hil.load_config("config_system_hil_attached.json") + hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + hil.init_can() + + power = hil.dout("RearTester", "RLY1") + + # Drive Critical Tests + # test_precharge(hil) + test_bspd(hil) + # test_imd(hil) # note: tsal needs to be tripped + # test_ams(hil) + # test_tsal(hil) + # test_sdc(hil) + # test_buzzer(hil) + # test_brake_light(hil) + # test_light_tsal_buz(hil) + + # Peripheral Sensor Tests - # hil.end_test() -# ---------------------------------------------------------------------------- # \ No newline at end of file + hil.shutdown() diff --git a/scripts/pytest_test.py b/old_scripts/test_test.py similarity index 66% rename from scripts/pytest_test.py rename to old_scripts/test_test.py index 836a1e9..08af75a 100644 --- a/scripts/pytest_test.py +++ b/old_scripts/test_test.py @@ -7,30 +7,9 @@ from rules_constants import * from vehicle_constants import * -import pytest_check as check -import pytest - - -# ---------------------------------------------------------------------------- # -@pytest.fixture(scope="session") -def hil(): - hil_instance = HIL() - - # hil.load_config("config_testing.json") - hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") - - # hil_instance.init_can() - - yield hil_instance - - hil_instance.shutdown() -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # def test_bspd(hil): # Begin the test - # hil.start_test(test_bspd.__name__) + hil.start_test(test_bspd.__name__) # Inputs d2 = hil.din("Test_HIL", "AI2") @@ -74,15 +53,10 @@ def test_bspd(hil): time.sleep(1) time.sleep(2) - check.is_true(True, "TODO") - - # hil.end_test() -# ---------------------------------------------------------------------------- # - + hil.end_test() -# ---------------------------------------------------------------------------- # def test_dac(hil): - # hil.start_test(test_dac.__name__) + hil.start_test(test_dac.__name__) dac1 = hil.aout("Test_HIL", "DAC1") dac2 = hil.aout("Test_HIL", "DAC2") @@ -97,13 +71,8 @@ def test_dac(hil): dac2.state = 0.25 input(".25") - check.is_true(True, "TODO") + hil.end_test() - # hil.end_test() -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # def test_pot(hil): pot1 = hil.pot("Test_HIL", "POT1") @@ -138,13 +107,8 @@ def test_pot(hil): pot2.state = 0.5 input("-------") - check.is_true(True, "TODO") -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # def test_mcu_pin(hil): - # hil.start_test(test_mcu_pin.__name__) + hil.start_test(test_mcu_pin.__name__) brk_stat_tap = hil.mcu_pin("Dashboard", "BRK_STAT_TAP") @@ -159,16 +123,12 @@ def test_mcu_pin(hil): delta_cnt = delta_cnt + 1 print(f"Average: {delta_avg/delta_cnt}") - - check.is_true(True, "TODO") - # hil.end_test() -# ---------------------------------------------------------------------------- # + hil.end_test() -# ---------------------------------------------------------------------------- # def test_daq(hil): - # hil.start_test(test_daq.__name__) + hil.start_test(test_daq.__name__) counter = 0 start_time = time.time() @@ -193,8 +153,20 @@ def test_daq(hil): if (delta < 0): delta = 0 time.sleep(delta) - check.is_true(True, "TODO") - print("Done") print(f"Last count sent: {counter - 1}") -# ---------------------------------------------------------------------------- # \ No newline at end of file + + +if __name__ == "__main__": + hil = HIL() + #hil.load_config("config_testing.json") + hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + hil.init_can() + #test_bspd(hil) + #test_dac(hil) + # test_pot(hil) + # test_mcu_pin(hil) + test_daq(hil) + + hil.shutdown() diff --git a/old_scripts/vehicle_constants.py b/old_scripts/vehicle_constants.py new file mode 100644 index 0000000..35a4050 --- /dev/null +++ b/old_scripts/vehicle_constants.py @@ -0,0 +1,75 @@ +from os import sys, path +sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) +import utils + +# NOTE: each value in this file should be a physical or electrical property of the vehicle + +# Accumulator Constants +ACCUM_MAX_V = 317.3 +ACCUM_MIN_V = 190.0 +ACCUM_NOM_V = 273.6 +ACCUM_FUSE_A = 140.0 + +ABOX_DHAB_CH1_DIV = utils.VoltageDivider(1000, 2000) + +# IMD Constants +IMD_MEASURE_TIME_S = 20.0 +IMD_STARTUP_TIME_S = 2.0 + +# AMS Constants +AMS_MAX_TRIP_DELAY_S = 3.0 + +# Precharge Constants +PCHG_COMPLETE_DELAY_S = 0.5 + +# Tiffomy Constants +TIFF_LV_MAX = 5.0 +TIFF_LV_MIN = -5.0 +TIFF_SCALE = 100.0 +def tiff_hv_to_lv(hv_voltage): + return min(max(hv_voltage / TIFF_SCALE, TIFF_LV_MIN), TIFF_LV_MAX) +def tiff_lv_to_hv(lv_voltage): + return lv_voltage * TIFF_SCALE + +# DHAB S124 Current Sensor +DHAB_S124_MAX_OUT_V = 4.8 +DHAB_S124_MIN_OUT_V = 0.2 +DHAB_S124_OFFSET_V = 2.5 +DHAB_S124_CH1_SENSITIVITY = 26.7 / 1000.0 # V / A +DHAB_S124_CH2_SENSITIVITY = 4.9 / 1000.0 # V / A +DHAB_S124_CH1_MAX_A = 75.0 +DHAB_S124_CH1_MIN_A = -75.0 +DHAB_S124_CH2_MAX_A = 500.0 +DHAB_S124_CH2_MIN_A = -500.0 + +def dhab_ch1_v_to_a(signal_v): + return (signal_v - DHAB_S124_OFFSET_V) / DHAB_S124_CH1_SENSITIVITY + +def dhab_ch2_v_to_a(signal_v): + return (signal_v - DHAB_S124_OFFSET_V) / DHAB_S124_CH2_SENSITIVITY + +def dhab_ch1_a_to_v(amps): + amps = min(max(amps, DHAB_S124_CH1_MIN_A), DHAB_S124_CH1_MAX_A) + return (amps * DHAB_S124_CH1_SENSITIVITY) + DHAB_S124_OFFSET_V + +def dhab_ch2_a_to_v(amps): + amps = min(max(amps, DHAB_S124_CH2_MIN_A), DHAB_S124_CH2_MAX_A) + return (amps * DHAB_S124_CH2_SENSITIVITY) + DHAB_S124_OFFSET_V + +def dhab_v_valid(signal_v): + return (DHAB_S124_MIN_OUT_V <= signal_v <= DHAB_S124_MAX_OUT_V) + +# Brake Pressure Transducer +BRK_MAX_OUT_V = 4.8 +BRK_MIN_OUT_V = 0.2 +BRK_1_REST_V = 0.5 # Resting line voltage of brake 1 +BRK_2_REST_V = 0.5 # Resting line voltage of brake 2 +BRK_1_DIV = utils.VoltageDivider(5600, 10000) +BRK_2_DIV = utils.VoltageDivider(5600, 10000) +BRK_1_THRESH_V = 0.68 # Threshold that is considered braking for brake 1 +BRK_2_THRESH_V = 0.68 # Threshold that is considered braking for brake 2 + +# Throttle +THTL_MAX_P = 0.9 # Maximum pedal press percent +THTL_MIN_P = 0.1 # Minimum pedal press percent +THTL_THRESH = 0.2 # Throttle pressed percent diff --git a/scripts/pytest_abox.py b/scripts/pytest_abox.py deleted file mode 100644 index 18d5fe9..0000000 --- a/scripts/pytest_abox.py +++ /dev/null @@ -1,319 +0,0 @@ -from os import sys, path -sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) -from hil import HIL -import utils -import time -from rules_constants import * -from vehicle_constants import * - - -import pytest_check as check -import pytest - - - -# ---------------------------------------------------------------------------- # -@pytest.fixture(scope="session") -def hil(): - hil_instance = HIL() - - hil_instance.load_config("config_abox_bench.json") - hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") - - hil_instance.init_can() - - yield hil_instance - - hil_instance.shutdown() -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # -def test_abox_ams(hil): - # Begin the test - # hil.start_test(test_abox_ams.__name__) - - # Outputs - den = hil.dout("a_box", "Discharge Enable") - csafe = hil.dout("a_box", "Charger Safety") - bms_override = hil.daq_var("a_box", "bms_daq_override") - bms_stat = hil.daq_var("a_box", "bms_daq_stat") - - # Inputs - chrg_stat = hil.din("a_box", "BMS Status Charger") - main_stat = hil.din("a_box", "BMS Status PDU") - - bms_override.state = 1 - - for i in range(0, 8): - dchg_set = bool(i & 0x1) - chg_set = bool(i & 0x2) - bms_set = bool(i & 0x4) - exp_chrg = not (chg_set or bms_set) - exp_dchg = not (dchg_set or bms_set) - - den.state = dchg_set - csafe.state = chg_set - bms_stat.state = bms_set - print(f"Combo {i}") - time.sleep(0.1) - # hil.check(chrg_stat.state == exp_chrg, f"Chrg stat {exp_chrg}") - # hil.check(main_stat.state == exp_dchg, f"Main stat {exp_dchg}") - check.equal(chrg_stat.state, exp_chrg, f"Chrg stat {exp_chrg}") - check.equal(main_stat.state, exp_dchg, f"Main stat {exp_dchg}") - - bms_override.state = 0 - - # hil.end_test() -# ---------------------------------------------------------------------------- # - -# ---------------------------------------------------------------------------- # -def test_isense(hil): - # Begin the test - # hil.start_test(test_isense.__name__) - - # Outputs - ch1_raw = hil.aout("a_box", "Isense_Ch1_raw") - - # Inputs - ch1_filt = hil.ain("a_box", "ISense Ch1") - - # Need to test voltage divider transfer function correct - for v in [0.0, DHAB_S124_MIN_OUT_V, DHAB_S124_OFFSET_V, 3.2, DHAB_S124_MAX_OUT_V, 5.0]: - ch1_raw.state = v - time.sleep(1) - exp_out = ABOX_DHAB_CH1_DIV.div(v) - input(f"enter to meas, set to {v}, expected {exp_out}") - meas = ch1_filt.state - print(f"isense expected: {exp_out}V, measured: {meas}V") - # hil.check_within(meas, exp_out, 0.05, f"Isense v={v:.3}") - check.almost_equal(meas, exp_out, abs=0.05, rel=0.0, msg=f"Isense v={v:.3}") - - ch1_raw.hiZ() - time.sleep(0.01) - # hil.check_within(ch1_filt.state, 0.0, 0.05, f"Isense float pulled down") - check.almost_equal(ch1_filt.state, 0.0, abs=0.05, rel=0.0, msg="Isense float pulled down") - - # hil.end_test() -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # -RLY_ON = 0 -RLY_OFF = 1 -RLY_DLY = 0.01 # Mechanicl relay takes time to transition - -def test_precharge(hil): - # Begin the test - # hil.start_test(test_precharge.__name__) - - # Outputs - n_pchg_cmplt = hil.dout("a_box", "NotPrechargeComplete") - sdc = hil.dout("a_box", "SDC") - bat_p = hil.dout("a_box", "Batt+") - - # Inputs - resistor = hil.din("a_box", "NetK1_4") # To precharge resistor - - bat_p.state = RLY_ON - - print("Combo 1") - n_pchg_cmplt.state = 0 - sdc.state = RLY_OFF - time.sleep(RLY_DLY) - # hil.check(resistor.state == 0, "Resistor disconnected") - check.equal(resistor.state, 0, "Combo 1, resistor disconnected") - - print("Combo 2") - n_pchg_cmplt.state = 1 - sdc.state = RLY_OFF - time.sleep(RLY_DLY) - # hil.check(resistor.state == 0, "Resistor disconnected") - check.equal(resistor.state, 0, "Combo 2, resistor disconnected") - - print("Combo 3") - n_pchg_cmplt.state = 1 - sdc.state = RLY_ON - time.sleep(RLY_DLY) - # hil.check(resistor.state == 1, "Resistor connected") - check.equal(resistor.state, 1, "Combo 3, resistor connected") - - print("Combo 4") - n_pchg_cmplt.state = 0 - sdc.state = RLY_ON - time.sleep(RLY_DLY) - # hil.check(resistor.state == 0, "Resistor disconnected") - check.equal(resistor.state, 0, "Combo 4, resistor disconnected") - - # Duration test - time.sleep(1) - n_pchg_cmplt.state = 1 - sdc.state = RLY_ON - time.sleep(RLY_DLY) - # hil.check(resistor.state == 1, "Duration init") - check.equal(resistor.state, 1, "Duration init") - - time.sleep(9) - # hil.check(resistor.state == 1, "Duration mid") - check.equal(resistor.state, 1, "Duration mid") - - n_pchg_cmplt.state = 0 - time.sleep(RLY_DLY) - # hil.check(resistor.state == 0, "Duration end") - check.equal(resistor.state, 0, "Duration end") - - # hil.end_test() -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # -SUPPLY_VOLTAGE = 24.0 -TIFF_DLY = 0.3 - -def test_tiffomy(hil): - # Begin the test - # hil.start_test(test_tiffomy.__name__) - - # Outputs - bat_p = hil.dout("a_box", "Batt+") - - # Inputs - vbat = hil.ain("a_box", "VBatt") - imd_hv = hil.din("a_box", "Batt+_Fused") - - # NOTE: the IMD test confirms that the relay closed - # This is a bit redundant of the tiffomy voltage measurement - - utils.log_warning(f"Assuming supply = {SUPPLY_VOLTAGE} V") - utils.log_warning(f"Do not reverse polarity Vbat, it will kill Arduino ADC") - input("Click enter to acknowledge or ctrl+c to cancel") - - bat_p.state = RLY_OFF - time.sleep(TIFF_DLY) - # hil.check_within(vbat.state, 0.0, 0.1, "TIff off") - # hil.check(imd_hv.state == 0, "IMD HV off") - check.almost_equal(vbat.state, 0.0, abs=0.1, rel=0.0, msg="TIff off") - check.equal(imd_hv.state, 0, "IMD HV off") - - bat_p.state = RLY_ON - time.sleep(TIFF_DLY) - exp = SUPPLY_VOLTAGE - #input("press enter, tiff should be getting volts") - meas = tiff_lv_to_hv(vbat.state) - print(f"Tiff HV reading: {meas} V, expect: {SUPPLY_VOLTAGE} V") - # hil.check_within(meas, exp, 2.5, "Tiff on") - # hil.check(imd_hv.state == 1, "IMD HV on") - check.almost_equal(meas, exp, abs=2.5, rel=0.0, msg="Tiff on") - check.equal(imd_hv.state, 1, "IMD HV on") - - # hil.end_test() -# ---------------------------------------------------------------------------- # - -# ---------------------------------------------------------------------------- # -def test_tmu(hil): - # Begin the test - # hil.start_test(test_tmu.__name__) - - # Outputs - tmu_a_do = hil.dout("a_box", "TMU_1") - tmu_b_do = hil.dout("a_box", "TMU_2") - tmu_c_do = hil.dout("a_box", "TMU_3") - tmu_d_do = hil.dout("a_box", "TMU_4") - - daq_override = hil.daq_var("a_box", "tmu_daq_override") - daq_therm = hil.daq_var("a_box", "tmu_daq_therm") - - # Inputs - mux_a = hil.din("a_box", "MUX_A_NON_ISO") - mux_b = hil.din("a_box", "MUX_B_NON_ISO") - mux_c = hil.din("a_box", "MUX_C_NON_ISO") - mux_d = hil.din("a_box", "MUX_D_NON_ISO") - - tmu_a_ai = hil.daq_var("a_box", "tmu_1") - tmu_b_ai = hil.daq_var("a_box", "tmu_2") - tmu_c_ai = hil.daq_var("a_box", "tmu_3") - tmu_d_ai = hil.daq_var("a_box", "tmu_4") - - daq_therm.state = 0 - daq_override.state = 1 - - # mux line test - for i in range(0,16): - daq_therm.state = i - time.sleep(0.05) - # hil.check(mux_a.state == bool(i & 0x1), f"Mux A test {i}") - # hil.check(mux_b.state == bool(i & 0x2), f"Mux B test {i}") - # hil.check(mux_c.state == bool(i & 0x4), f"Mux C test {i}") - # hil.check(mux_d.state == bool(i & 0x8), f"Mux D test {i}") - check.equal(mux_a.state, bool(i & 0x1), f"Mux A test {i}") - check.equal(mux_b.state, bool(i & 0x2), f"Mux B test {i}") - check.equal(mux_c.state, bool(i & 0x4), f"Mux C test {i}") - check.equal(mux_d.state, bool(i & 0x8), f"Mux D test {i}") - - daq_override.state = 0 - - TMU_TOLERANCE = 100 - TMU_HIGH_VALUE = 1970 #2148 - - # thermistors - for i in range(0,16): - tmu_a_do.state = bool(i & 0x1) - tmu_b_do.state = bool(i & 0x2) - tmu_c_do.state = bool(i & 0x4) - tmu_d_do.state = bool(i & 0x8) - time.sleep(1.0) - a = int(tmu_a_ai.state) - b = int(tmu_b_ai.state) - c = int(tmu_c_ai.state) - d = int(tmu_d_ai.state) - print(f"Readings at therm={i}: {a}, {b}, {c}, {d}") - # hil.check_within(a, TMU_HIGH_VALUE if (i & 0x1) else 0, TMU_TOLERANCE, f"TMU 1 test {i}") - # hil.check_within(b, TMU_HIGH_VALUE if (i & 0x2) else 0, TMU_TOLERANCE, f"TMU 2 test {i}") - # hil.check_within(c, TMU_HIGH_VALUE if (i & 0x4) else 0, TMU_TOLERANCE, f"TMU 3 test {i}") - # hil.check_within(d, TMU_HIGH_VALUE if (i & 0x8) else 0, TMU_TOLERANCE, f"TMU 4 test {i}") - check.almost_equal(a, TMU_HIGH_VALUE if (i & 0x1) else 0, abs=TMU_TOLERANCE, rel=0.0, msg=f"TMU 1 test {i}") - check.almost_equal(b, TMU_HIGH_VALUE if (i & 0x2) else 0, abs=TMU_TOLERANCE, rel=0.0, msg=f"TMU 2 test {i}") - check.almost_equal(c, TMU_HIGH_VALUE if (i & 0x4) else 0, abs=TMU_TOLERANCE, rel=0.0, msg=f"TMU 3 test {i}") - check.almost_equal(d, TMU_HIGH_VALUE if (i & 0x8) else 0, abs=TMU_TOLERANCE, rel=0.0, msg=f"TMU 4 test {i}") - - # hil.end_test() -# ---------------------------------------------------------------------------- # - -# ---------------------------------------------------------------------------- # -def test_imd(hil): - # hil.start_test(test_imd.__name__) - - # Outputs - imd_out = hil.dout('a_box', 'IMD_Status') - - # Inputs - imd_in = hil.din('a_box', 'IMD_STATUS_LV_COMP') - imd_mcu = hil.mcu_pin('a_box', 'IMD_STATUS_LV_COMP') - - - imd_out.state = RLY_OFF - time.sleep(RLY_DLY) - - # hil.check(imd_in.state == 0, 'IMD LV OFF') - # hil.check(imd_mcu.state == 0, 'IMD MCU OFF') - check.equal(imd_in.state, 0, 'IMD LV OFF') - check.equal(imd_mcu.state, 0, 'IMD MCU OFF') - - imd_out.state = RLY_ON - time.sleep(RLY_DLY) - - # hil.check(imd_in.state == 1, 'IMD LV ON') - # hil.check(imd_mcu.state == 1, 'IMD MCU ON') - check.equal(imd_in.state, 1, 'IMD LV ON') - check.equal(imd_mcu.state, 1, 'IMD MCU ON') - - imd_out.state = RLY_OFF - time.sleep(RLY_DLY) - - # hil.check(imd_in.state == 0, 'IMD LV BACK OFF') - # hil.check(imd_mcu.state == 0, 'IMD MCU BACK OFF') - check.equal(imd_in.state, 0, 'IMD LV BACK OFF') - check.equal(imd_mcu.state, 0, 'IMD MCU BACK OFF') - - # hil.end_test() -# ---------------------------------------------------------------------------- # \ No newline at end of file diff --git a/scripts/pytest_charger.py b/scripts/pytest_charger.py deleted file mode 100644 index 8dea486..0000000 --- a/scripts/pytest_charger.py +++ /dev/null @@ -1,186 +0,0 @@ -from os import sys, path -sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) - -from hil import HIL -# import hil.utils as utils -import utils -import time -from rules_constants import * -from vehicle_constants import * - -import pytest_check as check -import pytest - - -# ---------------------------------------------------------------------------- # -AMS_STAT_OKAY = 1 -AMS_STAT_TRIP = 0 -AMS_CTRL_OKAY = 1 -AMS_CTRL_TRIP = 0 - -def reset_ams(ams_stat): - ams_stat.state = AMS_STAT_OKAY - -IMD_STAT_OKAY = 1 -IMD_STAT_TRIP = 0 -def reset_imd(imd_stat): - imd_stat.state = IMD_STAT_OKAY - -power = None - -CYCLE_POWER_OFF_DELAY = 2.0 -CYCLE_POWER_ON_DELAY = 3.0 - -def cycle_power(): - power.state = 1 - time.sleep(CYCLE_POWER_OFF_DELAY) - power.state = 0 - time.sleep(CYCLE_POWER_ON_DELAY) - - -IMD_RC_MIN_TRIP_TIME_S = IMD_STARTUP_TIME_S -IMD_RC_MAX_TRIP_TIME_S = R_IMD_MAX_TRIP_TIME_S - IMD_MEASURE_TIME_S -IMD_CTRL_OKAY = 1 -IMD_CTRL_TRIP = 0 -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # -@pytest.fixture(scope="session") -def hil(): - global power - - hil_instance = HIL() - - hil_instance.load_config("config_charger.json") - hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") - - # hil_instance.init_can() - - power = hil_instance.dout("RearTester", "RLY1") - - yield hil_instance - - hil_instance.shutdown() -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # -def test_imd(hil): - # Begin the test - # hil.start_test(test_imd.__name__) - - # Outputs - imd_stat = hil.dout("Charger", "IMD_STATUS") - - # Outputs to set SDC status to okay - ams_stat = hil.dout("Charger", "BMS_STATUS") - - # Inputs - imd_ctrl = hil.din("Main_Module", "SDC_FINAL") # assuming AMS closed - - # Set other SDC nodes to okay - reset_ams(ams_stat) - - # IMD Fault - reset_imd(imd_stat) - cycle_power() - # hil.check(imd_ctrl.state == IMD_CTRL_OKAY, "Power On") - check.equal(imd_ctrl.state, IMD_CTRL_OKAY, "Power On") - - time.sleep(1) - imd_stat.state = IMD_STAT_TRIP - t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) - print(f"Target trip time: [{IMD_RC_MIN_TRIP_TIME_S}, {IMD_RC_MAX_TRIP_TIME_S}]") - # hil.check(IMD_RC_MIN_TRIP_TIME_S < t < IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") - # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Trip") - check.between(t, IMD_RC_MIN_TRIP_TIME_S, IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") - check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Trip") - - imd_stat.state = IMD_STAT_OKAY - time.sleep(IMD_RC_MAX_TRIP_TIME_S * 1.1) - # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Stays Latched") - check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Stays Latched") - - - # IMD Fault on Power On - reset_imd(imd_stat) - imd_stat.state = IMD_STAT_TRIP - cycle_power() - time.sleep(IMD_RC_MAX_TRIP_TIME_S) - # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Power On") - check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Power On") - - - # IMD Floating - reset_imd(imd_stat) - imd_stat.hiZ() - cycle_power() - t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) - # hil.check(t < R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") - # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Floating Trip") - check.less(t, R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") - check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Floating Trip") - - # hil.end_test() -# ---------------------------------------------------------------------------- # - -# ---------------------------------------------------------------------------- # -def test_ams(hil): - # Begin the test - hil.start_test(test_ams.__name__) - - # Outputs - ams_stat = hil.dout("Charger", "BMS_STATUS") - - - # Outputs to set SDC status to okay - imd_stat = hil.dout("Charger", "IMD_STATUS") - - # Inputs - ams_ctrl = hil.din("Main_Module", "SDC_FINAL") # assuming AMS closed - - # Set other SDC nodes to okay - reset_imd(imd_stat) - - # AMS Fault - reset_ams(ams_stat) - cycle_power() - # hil.check(ams_ctrl.state == AMS_CTRL_OKAY, "Power On") - check.equal(ams_ctrl.state, AMS_CTRL_OKAY, "Power On") - - time.sleep(1) - ams_stat.state = AMS_STAT_TRIP - t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) - # hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") - # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Trip") - check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") - check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Trip") - - ams_stat.state = AMS_STAT_OKAY - time.sleep(AMS_MAX_TRIP_DELAY_S * 1.1) - # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Stays Latched") - check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Stays Latched") - - - # AMS Fault on Power On - reset_ams(ams_stat) - ams_stat.state = AMS_STAT_TRIP - cycle_power() - time.sleep(AMS_MAX_TRIP_DELAY_S) - # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Power On") - check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Power On") - - - # AMS Floating - reset_ams(ams_stat) - ams_stat.hiZ() - cycle_power() - t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) - # hil.check(0 <= t < AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") - # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Floating Trip") - check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time", ge=True) - check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Floating Trip") - - # hil.end_test() -# ---------------------------------------------------------------------------- # \ No newline at end of file diff --git a/scripts/test_abox.py b/scripts/test_abox.py index 042024a..18d5fe9 100644 --- a/scripts/test_abox.py +++ b/scripts/test_abox.py @@ -7,9 +7,31 @@ from vehicle_constants import * +import pytest_check as check +import pytest + + + +# ---------------------------------------------------------------------------- # +@pytest.fixture(scope="session") +def hil(): + hil_instance = HIL() + + hil_instance.load_config("config_abox_bench.json") + hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + hil_instance.init_can() + + yield hil_instance + + hil_instance.shutdown() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # def test_abox_ams(hil): # Begin the test - hil.start_test(test_abox_ams.__name__) + # hil.start_test(test_abox_ams.__name__) # Outputs den = hil.dout("a_box", "Discharge Enable") @@ -35,16 +57,20 @@ def test_abox_ams(hil): bms_stat.state = bms_set print(f"Combo {i}") time.sleep(0.1) - hil.check(chrg_stat.state == exp_chrg, f"Chrg stat {exp_chrg}") - hil.check(main_stat.state == exp_dchg, f"Main stat {exp_dchg}") + # hil.check(chrg_stat.state == exp_chrg, f"Chrg stat {exp_chrg}") + # hil.check(main_stat.state == exp_dchg, f"Main stat {exp_dchg}") + check.equal(chrg_stat.state, exp_chrg, f"Chrg stat {exp_chrg}") + check.equal(main_stat.state, exp_dchg, f"Main stat {exp_dchg}") bms_override.state = 0 - hil.end_test() + # hil.end_test() +# ---------------------------------------------------------------------------- # +# ---------------------------------------------------------------------------- # def test_isense(hil): # Begin the test - hil.start_test(test_isense.__name__) + # hil.start_test(test_isense.__name__) # Outputs ch1_raw = hil.aout("a_box", "Isense_Ch1_raw") @@ -60,21 +86,26 @@ def test_isense(hil): input(f"enter to meas, set to {v}, expected {exp_out}") meas = ch1_filt.state print(f"isense expected: {exp_out}V, measured: {meas}V") - hil.check_within(meas, exp_out, 0.05, f"Isense v={v:.3}") + # hil.check_within(meas, exp_out, 0.05, f"Isense v={v:.3}") + check.almost_equal(meas, exp_out, abs=0.05, rel=0.0, msg=f"Isense v={v:.3}") ch1_raw.hiZ() time.sleep(0.01) - hil.check_within(ch1_filt.state, 0.0, 0.05, f"Isense float pulled down") + # hil.check_within(ch1_filt.state, 0.0, 0.05, f"Isense float pulled down") + check.almost_equal(ch1_filt.state, 0.0, abs=0.05, rel=0.0, msg="Isense float pulled down") - hil.end_test() + # hil.end_test() +# ---------------------------------------------------------------------------- # + +# ---------------------------------------------------------------------------- # RLY_ON = 0 RLY_OFF = 1 RLY_DLY = 0.01 # Mechanicl relay takes time to transition def test_precharge(hil): # Begin the test - hil.start_test(test_precharge.__name__) + # hil.start_test(test_precharge.__name__) # Outputs n_pchg_cmplt = hil.dout("a_box", "NotPrechargeComplete") @@ -90,46 +121,58 @@ def test_precharge(hil): n_pchg_cmplt.state = 0 sdc.state = RLY_OFF time.sleep(RLY_DLY) - hil.check(resistor.state == 0, "Resistor disconnected") + # hil.check(resistor.state == 0, "Resistor disconnected") + check.equal(resistor.state, 0, "Combo 1, resistor disconnected") print("Combo 2") n_pchg_cmplt.state = 1 sdc.state = RLY_OFF time.sleep(RLY_DLY) - hil.check(resistor.state == 0, "Resistor disconnected") + # hil.check(resistor.state == 0, "Resistor disconnected") + check.equal(resistor.state, 0, "Combo 2, resistor disconnected") print("Combo 3") n_pchg_cmplt.state = 1 sdc.state = RLY_ON time.sleep(RLY_DLY) - hil.check(resistor.state == 1, "Resistor connected") + # hil.check(resistor.state == 1, "Resistor connected") + check.equal(resistor.state, 1, "Combo 3, resistor connected") print("Combo 4") n_pchg_cmplt.state = 0 sdc.state = RLY_ON time.sleep(RLY_DLY) - hil.check(resistor.state == 0, "Resistor disconnected") + # hil.check(resistor.state == 0, "Resistor disconnected") + check.equal(resistor.state, 0, "Combo 4, resistor disconnected") # Duration test time.sleep(1) n_pchg_cmplt.state = 1 sdc.state = RLY_ON time.sleep(RLY_DLY) - hil.check(resistor.state == 1, "Duration init") + # hil.check(resistor.state == 1, "Duration init") + check.equal(resistor.state, 1, "Duration init") + time.sleep(9) - hil.check(resistor.state == 1, "Duration mid") + # hil.check(resistor.state == 1, "Duration mid") + check.equal(resistor.state, 1, "Duration mid") + n_pchg_cmplt.state = 0 time.sleep(RLY_DLY) - hil.check(resistor.state == 0, "Duration end") + # hil.check(resistor.state == 0, "Duration end") + check.equal(resistor.state, 0, "Duration end") + + # hil.end_test() +# ---------------------------------------------------------------------------- # - hil.end_test() +# ---------------------------------------------------------------------------- # SUPPLY_VOLTAGE = 24.0 TIFF_DLY = 0.3 def test_tiffomy(hil): # Begin the test - hil.start_test(test_tiffomy.__name__) + # hil.start_test(test_tiffomy.__name__) # Outputs bat_p = hil.dout("a_box", "Batt+") @@ -147,8 +190,10 @@ def test_tiffomy(hil): bat_p.state = RLY_OFF time.sleep(TIFF_DLY) - hil.check_within(vbat.state, 0.0, 0.1, "TIff off") - hil.check(imd_hv.state == 0, "IMD HV off") + # hil.check_within(vbat.state, 0.0, 0.1, "TIff off") + # hil.check(imd_hv.state == 0, "IMD HV off") + check.almost_equal(vbat.state, 0.0, abs=0.1, rel=0.0, msg="TIff off") + check.equal(imd_hv.state, 0, "IMD HV off") bat_p.state = RLY_ON time.sleep(TIFF_DLY) @@ -156,15 +201,18 @@ def test_tiffomy(hil): #input("press enter, tiff should be getting volts") meas = tiff_lv_to_hv(vbat.state) print(f"Tiff HV reading: {meas} V, expect: {SUPPLY_VOLTAGE} V") - hil.check_within(meas, exp, 2.5, "Tiff on") - hil.check(imd_hv.state == 1, "IMD HV on") - - hil.end_test() + # hil.check_within(meas, exp, 2.5, "Tiff on") + # hil.check(imd_hv.state == 1, "IMD HV on") + check.almost_equal(meas, exp, abs=2.5, rel=0.0, msg="Tiff on") + check.equal(imd_hv.state, 1, "IMD HV on") + # hil.end_test() +# ---------------------------------------------------------------------------- # +# ---------------------------------------------------------------------------- # def test_tmu(hil): # Begin the test - hil.start_test(test_tmu.__name__) + # hil.start_test(test_tmu.__name__) # Outputs tmu_a_do = hil.dout("a_box", "TMU_1") @@ -193,10 +241,14 @@ def test_tmu(hil): for i in range(0,16): daq_therm.state = i time.sleep(0.05) - hil.check(mux_a.state == bool(i & 0x1), f"Mux A test {i}") - hil.check(mux_b.state == bool(i & 0x2), f"Mux B test {i}") - hil.check(mux_c.state == bool(i & 0x4), f"Mux C test {i}") - hil.check(mux_d.state == bool(i & 0x8), f"Mux D test {i}") + # hil.check(mux_a.state == bool(i & 0x1), f"Mux A test {i}") + # hil.check(mux_b.state == bool(i & 0x2), f"Mux B test {i}") + # hil.check(mux_c.state == bool(i & 0x4), f"Mux C test {i}") + # hil.check(mux_d.state == bool(i & 0x8), f"Mux D test {i}") + check.equal(mux_a.state, bool(i & 0x1), f"Mux A test {i}") + check.equal(mux_b.state, bool(i & 0x2), f"Mux B test {i}") + check.equal(mux_c.state, bool(i & 0x4), f"Mux C test {i}") + check.equal(mux_d.state, bool(i & 0x8), f"Mux D test {i}") daq_override.state = 0 @@ -215,16 +267,21 @@ def test_tmu(hil): c = int(tmu_c_ai.state) d = int(tmu_d_ai.state) print(f"Readings at therm={i}: {a}, {b}, {c}, {d}") - hil.check_within(a, TMU_HIGH_VALUE if (i & 0x1) else 0, TMU_TOLERANCE, f"TMU 1 test {i}") - hil.check_within(b, TMU_HIGH_VALUE if (i & 0x2) else 0, TMU_TOLERANCE, f"TMU 2 test {i}") - hil.check_within(c, TMU_HIGH_VALUE if (i & 0x4) else 0, TMU_TOLERANCE, f"TMU 3 test {i}") - hil.check_within(d, TMU_HIGH_VALUE if (i & 0x8) else 0, TMU_TOLERANCE, f"TMU 4 test {i}") - - - hil.end_test() - + # hil.check_within(a, TMU_HIGH_VALUE if (i & 0x1) else 0, TMU_TOLERANCE, f"TMU 1 test {i}") + # hil.check_within(b, TMU_HIGH_VALUE if (i & 0x2) else 0, TMU_TOLERANCE, f"TMU 2 test {i}") + # hil.check_within(c, TMU_HIGH_VALUE if (i & 0x4) else 0, TMU_TOLERANCE, f"TMU 3 test {i}") + # hil.check_within(d, TMU_HIGH_VALUE if (i & 0x8) else 0, TMU_TOLERANCE, f"TMU 4 test {i}") + check.almost_equal(a, TMU_HIGH_VALUE if (i & 0x1) else 0, abs=TMU_TOLERANCE, rel=0.0, msg=f"TMU 1 test {i}") + check.almost_equal(b, TMU_HIGH_VALUE if (i & 0x2) else 0, abs=TMU_TOLERANCE, rel=0.0, msg=f"TMU 2 test {i}") + check.almost_equal(c, TMU_HIGH_VALUE if (i & 0x4) else 0, abs=TMU_TOLERANCE, rel=0.0, msg=f"TMU 3 test {i}") + check.almost_equal(d, TMU_HIGH_VALUE if (i & 0x8) else 0, abs=TMU_TOLERANCE, rel=0.0, msg=f"TMU 4 test {i}") + + # hil.end_test() +# ---------------------------------------------------------------------------- # + +# ---------------------------------------------------------------------------- # def test_imd(hil): - hil.start_test(test_imd.__name__) + # hil.start_test(test_imd.__name__) # Outputs imd_out = hil.dout('a_box', 'IMD_Status') @@ -237,36 +294,26 @@ def test_imd(hil): imd_out.state = RLY_OFF time.sleep(RLY_DLY) - hil.check(imd_in.state == 0, 'IMD LV OFF') - hil.check(imd_mcu.state == 0, 'IMD MCU OFF') + # hil.check(imd_in.state == 0, 'IMD LV OFF') + # hil.check(imd_mcu.state == 0, 'IMD MCU OFF') + check.equal(imd_in.state, 0, 'IMD LV OFF') + check.equal(imd_mcu.state, 0, 'IMD MCU OFF') imd_out.state = RLY_ON time.sleep(RLY_DLY) - hil.check(imd_in.state == 1, 'IMD LV ON') - hil.check(imd_mcu.state == 1, 'IMD MCU ON') + # hil.check(imd_in.state == 1, 'IMD LV ON') + # hil.check(imd_mcu.state == 1, 'IMD MCU ON') + check.equal(imd_in.state, 1, 'IMD LV ON') + check.equal(imd_mcu.state, 1, 'IMD MCU ON') imd_out.state = RLY_OFF time.sleep(RLY_DLY) - hil.check(imd_in.state == 0, 'IMD LV BACK OFF') - hil.check(imd_mcu.state == 0, 'IMD MCU BACK OFF') - - hil.end_test() - - -if __name__ == "__main__": - hil = HIL() - hil.load_config("config_abox_bench.json") - hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") - - hil.init_can() - - test_abox_ams(hil) - test_isense(hil) - test_precharge(hil) - test_tiffomy(hil) - test_tmu(hil) - test_imd(hil) + # hil.check(imd_in.state == 0, 'IMD LV BACK OFF') + # hil.check(imd_mcu.state == 0, 'IMD MCU BACK OFF') + check.equal(imd_in.state, 0, 'IMD LV BACK OFF') + check.equal(imd_mcu.state, 0, 'IMD MCU BACK OFF') - hil.shutdown() + # hil.end_test() +# ---------------------------------------------------------------------------- # \ No newline at end of file diff --git a/scripts/test_charger.py b/scripts/test_charger.py index 87a6fa4..8dea486 100644 --- a/scripts/test_charger.py +++ b/scripts/test_charger.py @@ -1,11 +1,18 @@ from os import sys, path sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) + from hil import HIL -import hil.utils as utils +# import hil.utils as utils +import utils import time from rules_constants import * from vehicle_constants import * +import pytest_check as check +import pytest + + +# ---------------------------------------------------------------------------- # AMS_STAT_OKAY = 1 AMS_STAT_TRIP = 0 AMS_CTRL_OKAY = 1 @@ -35,10 +42,33 @@ def cycle_power(): IMD_RC_MAX_TRIP_TIME_S = R_IMD_MAX_TRIP_TIME_S - IMD_MEASURE_TIME_S IMD_CTRL_OKAY = 1 IMD_CTRL_TRIP = 0 +# ---------------------------------------------------------------------------- # + +# ---------------------------------------------------------------------------- # +@pytest.fixture(scope="session") +def hil(): + global power + + hil_instance = HIL() + + hil_instance.load_config("config_charger.json") + hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + # hil_instance.init_can() + + power = hil_instance.dout("RearTester", "RLY1") + + yield hil_instance + + hil_instance.shutdown() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # def test_imd(hil): # Begin the test - hil.start_test(test_imd.__name__) + # hil.start_test(test_imd.__name__) # Outputs imd_stat = hil.dout("Charger", "IMD_STATUS") @@ -55,34 +85,47 @@ def test_imd(hil): # IMD Fault reset_imd(imd_stat) cycle_power() - hil.check(imd_ctrl.state == IMD_CTRL_OKAY, "Power On") + # hil.check(imd_ctrl.state == IMD_CTRL_OKAY, "Power On") + check.equal(imd_ctrl.state, IMD_CTRL_OKAY, "Power On") + time.sleep(1) imd_stat.state = IMD_STAT_TRIP t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) print(f"Target trip time: [{IMD_RC_MIN_TRIP_TIME_S}, {IMD_RC_MAX_TRIP_TIME_S}]") - hil.check(IMD_RC_MIN_TRIP_TIME_S < t < IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") - hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Trip") + # hil.check(IMD_RC_MIN_TRIP_TIME_S < t < IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Trip") + check.between(t, IMD_RC_MIN_TRIP_TIME_S, IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Trip") + imd_stat.state = IMD_STAT_OKAY time.sleep(IMD_RC_MAX_TRIP_TIME_S * 1.1) - hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Stays Latched") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Stays Latched") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Stays Latched") + # IMD Fault on Power On reset_imd(imd_stat) imd_stat.state = IMD_STAT_TRIP cycle_power() time.sleep(IMD_RC_MAX_TRIP_TIME_S) - hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Power On") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Power On") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Power On") + # IMD Floating reset_imd(imd_stat) imd_stat.hiZ() cycle_power() t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) - hil.check(t < R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") - hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Floating Trip") + # hil.check(t < R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Floating Trip") + check.less(t, R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Floating Trip") - hil.end_test() + # hil.end_test() +# ---------------------------------------------------------------------------- # +# ---------------------------------------------------------------------------- # def test_ams(hil): # Begin the test hil.start_test(test_ams.__name__) @@ -103,45 +146,41 @@ def test_ams(hil): # AMS Fault reset_ams(ams_stat) cycle_power() - hil.check(ams_ctrl.state == AMS_CTRL_OKAY, "Power On") + # hil.check(ams_ctrl.state == AMS_CTRL_OKAY, "Power On") + check.equal(ams_ctrl.state, AMS_CTRL_OKAY, "Power On") + time.sleep(1) ams_stat.state = AMS_STAT_TRIP t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) - hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") - hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Trip") + # hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Trip") + check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Trip") + ams_stat.state = AMS_STAT_OKAY time.sleep(AMS_MAX_TRIP_DELAY_S * 1.1) - hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Stays Latched") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Stays Latched") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Stays Latched") + # AMS Fault on Power On reset_ams(ams_stat) ams_stat.state = AMS_STAT_TRIP cycle_power() time.sleep(AMS_MAX_TRIP_DELAY_S) - hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Power On") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Power On") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Power On") + # AMS Floating reset_ams(ams_stat) ams_stat.hiZ() cycle_power() t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) - hil.check(0 <= t < AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") - hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Floating Trip") + # hil.check(0 <= t < AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Floating Trip") + check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time", ge=True) + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Floating Trip") - hil.end_test() - - -if __name__ == "__main__": - hil = HIL() - - hil.load_config("config_charger.json") - hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") - - #hil.init_can() - - power = hil.dout("RearTester", "RLY1") - - test_imd(hil) - test_ams(hil) - - hil.shutdown() + # hil.end_test() +# ---------------------------------------------------------------------------- # \ No newline at end of file diff --git a/scripts/test_collector.py b/scripts/test_collector.py index b1ee509..382f977 100644 --- a/scripts/test_collector.py +++ b/scripts/test_collector.py @@ -4,9 +4,30 @@ import utils import time +import pytest_check as check +import pytest + + +# ---------------------------------------------------------------------------- # +@pytest.fixture(scope="session") +def hil(): + hil_instance = HIL() + + hil_instance.load_config("config_collector_bench.json") + hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + # hil_instance.init_can() + + yield hil_instance + + hil_instance.shutdown() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # def test_collector(hil): # Begin the test - hil.start_test(test_collector.__name__) + # hil.start_test(test_collector.__name__) # Outputs m1 = hil.dout("Collector", "MUX_A") @@ -40,15 +61,19 @@ def test_collector(hil): time.sleep(0.01) if (i == thermistor): - hil.check_within(to.state, test_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") + # hil.check_within(to.state, test_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") + check.almost_equal(to.state, test_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") else: - hil.check_within(to.state, pullup_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") + # hil.check_within(to.state, pullup_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") + check.almost_equal(to.state, pullup_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") print(to.state) # End the test - hil.end_test() + # hil.end_test() +# ---------------------------------------------------------------------------- # -if __name__ == "__main__": +# ---------------------------------------------------------------------------- # +# if __name__ == "__main__": hil = HIL() hil.load_config("config_collector_bench.json") hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") diff --git a/scripts/test_main_base.py b/scripts/test_main_base.py index 133eb27..c553f4a 100644 --- a/scripts/test_main_base.py +++ b/scripts/test_main_base.py @@ -6,6 +6,11 @@ from rules_constants import * from vehicle_constants import * +import pytest_check as check +import pytest + + +# ---------------------------------------------------------------------------- # AMS_STAT_OKAY = 1 AMS_STAT_TRIP = 0 AMS_CTRL_OKAY = 1 @@ -45,10 +50,33 @@ def cycle_power(): time.sleep(0.75) power.state = 0 time.sleep(CYCLE_POWER_ON_DELAY) +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +@pytest.fixture(scope="session") +def hil(): + global power + + hil_instance = HIL() + + hil_instance.load_config("config_main_base_bench.json") + hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + hil_instance.init_can() + + power = hil_instance.dout("Arduino2", "RLY1") + + yield hil_instance + + hil_instance.shutdown() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # def test_precharge(hil): # Begin the test - hil.start_test(test_precharge.__name__) + # hil.start_test(test_precharge.__name__) # Outputs v_bat = hil.aout("Main_Module", "VBatt") @@ -64,14 +92,19 @@ def test_precharge(hil): # Initial State reset_pchg(v_bat, v_mc) time.sleep(2.5) - hil.check(pchg_cmplt.state == 0, "Precharge not complete on startup") - hil.check(not_pchg_cmplt_delayed.state == 1, "Not precharge complete delayed high on startup") + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on startup") + # hil.check(not_pchg_cmplt_delayed.state == 1, "Not precharge complete delayed high on startup") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on startup") + check.equal(not_pchg_cmplt_delayed.state, 1, "Not precharge complete delayed high on startup") # Check delay v_mc.state = tiff_hv_to_lv(ACCUM_NOM_V) t = utils.measure_trip_time(not_pchg_cmplt_delayed, PCHG_COMPLETE_DELAY_S*3, is_falling=True) - hil.check(not_pchg_cmplt_delayed.state == 0, "Precharge complete delayed") - hil.check_within(t, PCHG_COMPLETE_DELAY_S, 0.25, f"Precharge complete delay of {t:.3}s close to expected {PCHG_COMPLETE_DELAY_S}s") + # hil.check(not_pchg_cmplt_delayed.state == 0, "Precharge complete delayed") + # hil.check_within(t, PCHG_COMPLETE_DELAY_S, 0.25, f"Precharge complete delay of {t:.3}s close to expected {PCHG_COMPLETE_DELAY_S}s") + check.equal(not_pchg_cmplt_delayed.state, 0, "Precharge complete delayed") + check.almost_equal(t, PCHG_COMPLETE_DELAY_S, abs=0.25, rel=0.0, msg=f"Precharge complete delay of {t:.3}s close to expected {PCHG_COMPLETE_DELAY_S}s") + # Find threshold at nominal pack voltage for v in [ACCUM_MIN_V, ACCUM_NOM_V, ACCUM_MAX_V]: @@ -80,7 +113,8 @@ def test_precharge(hil): v_bat.state = tiff_hv_to_lv(v) v_mc.state = tiff_hv_to_lv(v*0.8) time.sleep(0.01) - hil.check(pchg_cmplt.state == 0, "Precharge Complete Low at Initial State") + # hil.check(pchg_cmplt.state == 0, "Precharge Complete Low at Initial State") + check.equal(pchg_cmplt.state, 0, "Precharge Complete Low at Initial State") start = tiff_hv_to_lv(v*0.8) stop = tiff_hv_to_lv(v) @@ -89,38 +123,49 @@ def test_precharge(hil): pchg_cmplt, is_falling=0) thresh_hv = tiff_lv_to_hv(thresh) print(f"Precharge triggered at {thresh_hv / v * 100:.4}% ({thresh_hv:.5}V) of vbat={v}.") - hil.check_within(thresh_hv / v, R_PCHG_V_BAT_THRESH, 0.03, f"Precharge threshold of {R_PCHG_V_BAT_THRESH*100}% at vbat = {v}V") + # hil.check_within(thresh_hv / v, R_PCHG_V_BAT_THRESH, 0.03, f"Precharge threshold of {R_PCHG_V_BAT_THRESH*100}% at vbat = {v}V") + check.almost_equal(thresh_hv / v, R_PCHG_V_BAT_THRESH, abs=0.03, rel=0.0, msg=f"Precharge threshold of {R_PCHG_V_BAT_THRESH*100}% at vbat = {v}V") + v_mc.state = tiff_hv_to_lv(v) time.sleep(0.25) - hil.check(pchg_cmplt.state == 1, f"Precharge completed at vbat = {v}V") + # hil.check(pchg_cmplt.state == 1, f"Precharge completed at vbat = {v}V") + check.equal(pchg_cmplt.state, 1, f"Precharge completed at vbat = {v}V") # Floating conditions (check never precharge complete) reset_pchg(v_bat, v_mc) v_bat.hiZ() v_mc.state = tiff_hv_to_lv(0) - hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc 0V") + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc 0V") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat float, v_mc 0V") + v_mc.state = tiff_hv_to_lv(ACCUM_MAX_V) - hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc max V") + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc max V") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat float, v_mc max V") reset_pchg(v_bat, v_mc) v_mc.hiZ() v_bat.state = tiff_hv_to_lv(ACCUM_MIN_V) - hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat min, v_mc float") + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat min, v_mc float") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat min, v_mc float") v_bat.state = tiff_hv_to_lv(ACCUM_MAX_V) - hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat max, v_mc float") + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat max, v_mc float") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat max, v_mc float") reset_pchg(v_bat, v_mc) v_bat.hiZ() v_mc.hiZ() - hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc float") + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc float") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat float, v_mc float") # TODO: software precharge validity checks (make precharge take forever) - hil.end_test() + # hil.end_test() +# ---------------------------------------------------------------------------- # +# ---------------------------------------------------------------------------- # def test_bspd(hil): # Begin the test - hil.start_test(test_bspd.__name__) + # hil.start_test(test_bspd.__name__) # Outputs brk_fail = hil.dout("Main_Module", "Brake Fail") @@ -141,13 +186,16 @@ def test_bspd(hil): # Brake Fail reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") brk_fail.state = 1 t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") + check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") brk_fail.state = 0 time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 0, "Brake Fail Stays Latched") + # hil.check(bspd_ctrl.state == 0, "Brake Fail Stays Latched") + check.equal(bspd_ctrl.state, 0, "Brake Fail Stays Latched") # Brake Fail on Power On reset_bspd(brk_fail, brk_stat, c_sense) @@ -158,61 +206,74 @@ def test_bspd(hil): brk_fail.state = 1 power.state = 0 time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 0, "Power On Brake Fail") + # hil.check(bspd_ctrl.state == 0, "Power On Brake Fail") + check.equal(bspd_ctrl.state, 0, "Power On Brake Fail") # Current no brake reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") time.sleep(2) # TODO: I am not sure why this fails, but oh well set_bspd_current(c_sense, 75) time.sleep(R_BSPD_MAX_TRIP_TIME_S) # time.sleep(100) - hil.check(bspd_ctrl.state == 1, "Current no brake") + # hil.check(bspd_ctrl.state == 1, "Current no brake") + check.equal(bspd_ctrl.state, 1, "Current no brake") # Current Sense Short to Ground reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") c_sense.state = 0.0 t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") + check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") set_bspd_current(c_sense, 0.0) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 0, "Current short to ground stays latched") + # hil.check(bspd_ctrl.state == 0, "Current short to ground stays latched") + check.equal(bspd_ctrl.state, 0, "Current short to ground stays latched") # Current Sense Short to 5V reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") c_sense.state = ABOX_DHAB_CH1_DIV.div(5.0) t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") + check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") set_bspd_current(c_sense, 0.0) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 0, "Current short to 5V stays latched") + # hil.check(bspd_ctrl.state == 0, "Current short to 5V stays latched") + check.equal(bspd_ctrl.state, 0, "Current short to 5V stays latched") # Braking reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") brk_stat.state = 1 time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 1, "Brake no current") + # hil.check(bspd_ctrl.state == 1, "Brake no current") + check.equal(bspd_ctrl.state, 1, "Brake no current") # Lowest current required to trip at min_trip_current = R_BSPD_POWER_THRESH_W / ACCUM_MAX_V set_bspd_current(c_sense, min_trip_current) t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Braking with current") + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Braking with current") + check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Braking with current") # Measure braking with current threshold reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() brk_stat.state = 1 - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") start = ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(0.0)) stop = ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(DHAB_S124_CH1_MAX_A)) step = 0.1 @@ -221,15 +282,22 @@ def test_bspd(hil): bspd_ctrl, is_falling=True) thresh_amps = dhab_ch1_v_to_a(ABOX_DHAB_CH1_DIV.reverse(thresh)) print(f"Current while braking threshold: {thresh}V = {thresh_amps}A") - hil.check_within(thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), 0.1, "Current while braking threshold") + # hil.check_within(thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), 0.1, "Current while braking threshold") + check.almost_equal( + thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), + abs=0.1, rel=0.0, + msg="Current while braking threshold" + ) # Determine the current sense short to gnd threshold reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") set_bspd_current(c_sense, DHAB_S124_CH1_MIN_A) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 1, "Min output current okay") + # hil.check(bspd_ctrl.state == 1, "Min output current okay") + check.equal(bspd_ctrl.state, 1, "Min output current okay") start = ABOX_DHAB_CH1_DIV.div(DHAB_S124_MIN_OUT_V) stop = 0.0 step = -0.1 @@ -237,17 +305,20 @@ def test_bspd(hil): R_BSPD_MAX_TRIP_TIME_S, bspd_ctrl, is_falling=True) print(f"Short to ground threshold: {thresh}V") - hil.check(stop < (thresh) < start, "Current short to ground threshold") + # hil.check(stop < (thresh) < start, "Current short to ground threshold") + check.between(thresh, stop, start, "Current short to ground threshold") # Determine the current sense short to 5V threshold reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") time.sleep(2) set_bspd_current(c_sense, DHAB_S124_CH1_MAX_A) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 1, "Max output current okay") + # hil.check(bspd_ctrl.state == 1, "Max output current okay") + check.equal(bspd_ctrl.state, 1, "Max output current okay") start = ABOX_DHAB_CH1_DIV.div(DHAB_S124_MAX_OUT_V) stop = ABOX_DHAB_CH1_DIV.div(5.0) step = 0.01 @@ -256,40 +327,49 @@ def test_bspd(hil): R_BSPD_MAX_TRIP_TIME_S, bspd_ctrl, is_falling=True) print(f"Short to 5V threshold: {thresh}V") - hil.check(bspd_ctrl.state == 0, "Short to 5V trips") + # hil.check(bspd_ctrl.state == 0, "Short to 5V trips") + check.equal(bspd_ctrl.state, 0, "Short to 5V trips") print(stop) print(start) - hil.check(start < (thresh) <= stop, "Current short to 5V threshold") + # hil.check(start < (thresh) <= stop, "Current short to 5V threshold") + check.between(thresh, stop, start, "Current short to 5V threshold", le=True) # Floating current reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") c_sense.hiZ() time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 0, "Floating current") + # hil.check(bspd_ctrl.state == 0, "Floating current") + check.equal(bspd_ctrl.state, 0, "Floating current") # Floating brake_fail reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") brk_fail.hiZ() time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 0, "Floating brake fail") + # hil.check(bspd_ctrl.state == 0, "Floating brake fail") + check.equal(bspd_ctrl.state, 0, "Floating brake fail") # Floating brake_stat reset_bspd(brk_fail, brk_stat, c_sense) cycle_power() - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") brk_stat.hiZ() set_bspd_current(c_sense, min_trip_current) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 0, "Floating brake status") + # hil.check(bspd_ctrl.state == 0, "Floating brake status") + check.equal(bspd_ctrl.state, 0, "Floating brake status") # End the test - hil.end_test() - + # hil.end_test() +# ---------------------------------------------------------------------------- # +# ---------------------------------------------------------------------------- # IMD_RC_MIN_TRIP_TIME_S = IMD_STARTUP_TIME_S IMD_RC_MAX_TRIP_TIME_S = R_IMD_MAX_TRIP_TIME_S - IMD_MEASURE_TIME_S IMD_CTRL_OKAY = 1 @@ -297,13 +377,13 @@ def test_bspd(hil): def test_imd(hil): # Begin the test - hil.start_test(test_imd.__name__) + # hil.start_test(test_imd.__name__) # Outputs imd_stat = hil.dout("Main_Module", "IMD_Status") # Outputs to set SDC status to okay - ams_stat = hil.dout("Main_Module", "BMS-Status-Main") + ams_stat = hil.dout("Main_Module", "BMS-Status-Main") brk_fail = hil.dout("Main_Module", "Brake Fail") brk_stat = hil.dout("Main_Module", "Brake Status") c_sense = hil.aout("Main_Module", "Current Sense C1") @@ -318,37 +398,46 @@ def test_imd(hil): # IMD Fault reset_imd(imd_stat) cycle_power() - hil.check(imd_ctrl.state == IMD_CTRL_OKAY, "Power On") + # hil.check(imd_ctrl.state == IMD_CTRL_OKAY, "Power On") + check.equal(imd_ctrl.state, IMD_CTRL_OKAY, "Power On") time.sleep(1) imd_stat.state = IMD_STAT_TRIP t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) print(f"Target trip time: [{IMD_RC_MIN_TRIP_TIME_S}, {IMD_RC_MAX_TRIP_TIME_S}]") - hil.check(IMD_RC_MIN_TRIP_TIME_S < t < IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") - hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Trip") + # hil.check(IMD_RC_MIN_TRIP_TIME_S < t < IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Trip") + check.between(t, IMD_RC_MIN_TRIP_TIME_S, IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Trip") imd_stat.state = IMD_STAT_OKAY time.sleep(IMD_RC_MAX_TRIP_TIME_S * 1.1) - hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Stays Latched") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Stays Latched") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Stays Latched") # IMD Fault on Power On reset_imd(imd_stat) imd_stat.state = IMD_STAT_TRIP cycle_power() time.sleep(IMD_RC_MAX_TRIP_TIME_S) - hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Power On") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Power On") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Power On") # IMD Floating reset_imd(imd_stat) imd_stat.hiZ() cycle_power() t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) - hil.check(t < R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") - hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Floating Trip") + # hil.check(t < R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Floating Trip") + check.between(t, 0, R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Floating Trip") - hil.end_test() + # hil.end_test() +# ---------------------------------------------------------------------------- # +# ---------------------------------------------------------------------------- # def test_ams(hil): # Begin the test - hil.start_test(test_ams.__name__) + # hil.start_test(test_ams.__name__) # Outputs ams_stat = hil.dout("Main_Module", "BMS-Status-Main") @@ -369,37 +458,46 @@ def test_ams(hil): # AMS Fault reset_ams(ams_stat) cycle_power() - hil.check(ams_ctrl.state == AMS_CTRL_OKAY, "Power On") + # hil.check(ams_ctrl.state == AMS_CTRL_OKAY, "Power On") + check.equal(ams_ctrl.state, AMS_CTRL_OKAY, "Power On") time.sleep(1) ams_stat.state = AMS_STAT_TRIP t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) - hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") - hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Trip") + # hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Trip") + check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Trip") ams_stat.state = AMS_STAT_OKAY time.sleep(AMS_MAX_TRIP_DELAY_S * 1.1) - hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Stays Latched") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Stays Latched") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Stays Latched") # AMS Fault on Power On reset_ams(ams_stat) ams_stat.state = AMS_STAT_TRIP cycle_power() time.sleep(AMS_MAX_TRIP_DELAY_S) - hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Power On") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Power On") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Power On") # AMS Floating reset_ams(ams_stat) ams_stat.hiZ() cycle_power() t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) - hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") - hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Floating Trip") + # hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Floating Trip") + check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Floating Trip") - hil.end_test() + # hil.end_test() +# ---------------------------------------------------------------------------- # +# ---------------------------------------------------------------------------- # def test_tsal(hil): # Begin the test - hil.start_test(test_tsal.__name__) + # hil.start_test(test_tsal.__name__) # Outputs v_mc = hil.aout("Main_Module", "Voltage MC Transducer") @@ -413,21 +511,27 @@ def test_tsal(hil): time.sleep(0.2) # No need to power cycle - hil.check(lval.state == 1, "LVAL on at v_mc = 0") - hil.check(tsal.state == 0, "TSAL off at v_mc = 0") + # hil.check(lval.state == 1, "LVAL on at v_mc = 0") + # hil.check(tsal.state == 0, "TSAL off at v_mc = 0") + check.equal(lval.state, 1, "LVAL on at v_mc = 0") + check.equal(tsal.state, 0, "TSAL off at v_mc = 0") time.sleep(5) - hil.check(lval.state == 1, "LVAL stays on") + # hil.check(lval.state == 1, "LVAL stays on") + check.equal(lval.state, 1, "LVAL stays on") v_mc.state = tiff_hv_to_lv(ACCUM_MIN_V) time.sleep(0.1) - hil.check(lval.state == 0, f"LVAL off at {ACCUM_MIN_V:.4} V") - hil.check(tsal.state == 1, f"TSAL on at {ACCUM_MIN_V:.4} V") + # hil.check(lval.state == 0, f"LVAL off at {ACCUM_MIN_V:.4} V") + # hil.check(tsal.state == 1, f"TSAL on at {ACCUM_MIN_V:.4} V") + check.equal(lval.state, 0, f"LVAL off at {ACCUM_MIN_V:.4} V") + check.equal(tsal.state, 1, f"TSAL on at {ACCUM_MIN_V:.4} V") reset_tsal(v_mc) time.sleep(0.2) - hil.check(lval.state == 1, f"LVAL turns back on") + # hil.check(lval.state == 1, f"LVAL turns back on") + check.equal(lval.state, 1, f"LVAL turns back on") start = tiff_hv_to_lv(0.0) stop = tiff_hv_to_lv(R_TSAL_HV_V * 1.5) @@ -437,27 +541,12 @@ def test_tsal(hil): tsal, is_falling=False) thresh = tiff_lv_to_hv(thresh) print(f"TSAL on at {thresh:.4} V") - hil.check_within(thresh, R_TSAL_HV_V, 4, f"TSAL trips at {R_TSAL_HV_V:.4} +-4") - hil.check(lval.state == 0, f"LVAL off V") - hil.check(tsal.state == 1, f"TSAL on V") - - hil.end_test() - - -if __name__ == "__main__": - hil = HIL() - - hil.load_config("config_main_base_bench.json") - hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") - - hil.init_can() - - power = hil.dout("Arduino2", "RLY1") - - test_precharge(hil) - test_bspd(hil) - test_imd(hil) - test_ams(hil) - test_tsal(hil) - - hil.shutdown() + # hil.check_within(thresh, R_TSAL_HV_V, 4, f"TSAL trips at {R_TSAL_HV_V:.4} +-4") + # hil.check(lval.state == 0, f"LVAL off V") + # hil.check(tsal.state == 1, f"TSAL on V") + check.almost_equal(thresh, R_TSAL_HV_V, abs=4, rel=0.0, msg=f"TSAL trips at {R_TSAL_HV_V:.4} +-4") + check.equal(lval.state, 0, f"LVAL off V") + check.equal(tsal.state, 1, f"TSAL on V") + + # hil.end_test() +# ---------------------------------------------------------------------------- # \ No newline at end of file diff --git a/scripts/test_main_sdc.py b/scripts/test_main_sdc.py index c4ad102..119d7a1 100644 --- a/scripts/test_main_sdc.py +++ b/scripts/test_main_sdc.py @@ -6,6 +6,27 @@ from rules_constants import * from vehicle_constants import * +import pytest_check as check +import pytest + + +# ---------------------------------------------------------------------------- # +@pytest.fixture(scope="session") +def hil(): + hil_instance = HIL() + + hil_instance.load_config("config_main_sdc_bench.json") + hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + # hil_instance.init_can() + + yield hil_instance + + hil_instance.shutdown() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # # SETUP for CSENSE # Current Sensor (DHAB) -> ABOX V Divider -> MAIN_SDC @@ -25,9 +46,11 @@ def reset_bspd(fail, stat, ch1): stat.state = 0 set_bspd_current(ch1, 0.0) + +# ---------------------------------------------------------------------------- # def test_bspd(hil): # Begin the test - hil.start_test(test_bspd.__name__) + # hil.start_test(test_bspd.__name__) # Outputs brk_fail = hil.dout("MainSDC", "Brake Fail") @@ -41,74 +64,90 @@ def test_bspd(hil): # Brake Fail reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") brk_fail.state = 1 t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") + check.below(t, R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") brk_fail.state = 0 time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 0, "Brake Fail Stays Latched") + # hil.check(bspd_ctrl.state == 0, "Brake Fail Stays Latched") + check.equal(bspd_ctrl.state, 0, "Brake Fail Stays Latched") # Brake Fail on Power On reset_bspd(brk_fail, brk_stat, c_sense) brk_fail.state = 1 cycle_power(pow) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 0, "Power On Brake Fail") + # hil.check(bspd_ctrl.state == 0, "Power On Brake Fail") + check.equal(bspd_ctrl.state, 0, "Power On Brake Fail") # Current no brake reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") time.sleep(2) # TODO: I am not sure why this fails, but oh well set_bspd_current(c_sense, 75) time.sleep(R_BSPD_MAX_TRIP_TIME_S) # time.sleep(100) - hil.check(bspd_ctrl.state == 1, "Current no brake") + # hil.check(bspd_ctrl.state == 1, "Current no brake") + check.equal(bspd_ctrl.state, 1, "Current no brake") # Current Sense Short to Ground reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") c_sense.state = 0.0 t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") + check.below(t, R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") set_bspd_current(c_sense, 0.0) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 0, "Current short to ground stays latched") + # hil.check(bspd_ctrl.state == 0, "Current short to ground stays latched") + check.equal(bspd_ctrl.state, 0, "Current short to ground stays latched") # Current Sense Short to 5V reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") c_sense.state = ABOX_DHAB_CH1_DIV.div(5.0) / DAC_GAIN t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") + check.below(t, R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") set_bspd_current(c_sense, 0.0) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 0, "Current short to 5V stays latched") + # hil.check(bspd_ctrl.state == 0, "Current short to 5V stays latched") + check.equal(bspd_ctrl.state, 0, "Current short to 5V stays latched") # Braking reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") brk_stat.state = 1 time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 1, "Brake no current") + # hil.check(bspd_ctrl.state == 1, "Brake no current") + check.equal(bspd_ctrl.state, 1, "Brake no current") # Lowest current required to trip at min_trip_current = R_BSPD_POWER_THRESH_W / ACCUM_MAX_V set_bspd_current(c_sense, min_trip_current) t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Braking with current") + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Braking with current") + check.below(t, R_BSPD_MAX_TRIP_TIME_S, "Braking with current") # Measure braking with current threshold reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) brk_stat.state = 1 - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") start = ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(0.0)) / DAC_GAIN stop = ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(DHAB_S124_CH1_MAX_A)) / DAC_GAIN step = 0.1 / DAC_GAIN @@ -118,15 +157,18 @@ def test_bspd(hil): thresh *= DAC_GAIN thresh_amps = dhab_ch1_v_to_a(ABOX_DHAB_CH1_DIV.reverse(thresh)) print(f"Current while braking threshold: {thresh}V = {thresh_amps}A") - hil.check_within(thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), 0.1, "Current while braking threshold") + # hil.check_within(thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), 0.1, "Current while braking threshold") + check.within(thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), 0.1, "Current while braking threshold") # Determine the current sense short to gnd threshold reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") set_bspd_current(c_sense, DHAB_S124_CH1_MIN_A) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 1, "Min output current okay") + # hil.check(bspd_ctrl.state == 1, "Min output current okay") + check.equal(bspd_ctrl.state, 1, "Min output current okay") start = ABOX_DHAB_CH1_DIV.div(DHAB_S124_MIN_OUT_V) / DAC_GAIN stop = 0.0 step = -0.1 / DAC_GAIN @@ -135,17 +177,20 @@ def test_bspd(hil): bspd_ctrl, is_falling=True) thresh *= DAC_GAIN print(f"Short to ground threshold: {thresh}V") - hil.check(stop < (thresh / DAC_GAIN) < start, "Current short to ground threshold") + # hil.check(stop < (thresh / DAC_GAIN) < start, "Current short to ground threshold") + check.between(thresh / DAC_GAIN, stop, start, "Current short to ground threshold") # Determine the current sense short to 5V threshold reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") time.sleep(2) set_bspd_current(c_sense, DHAB_S124_CH1_MAX_A) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 1, "Max output current okay") + # hil.check(bspd_ctrl.state == 1, "Max output current okay") + check.equal(bspd_ctrl.state, 1, "Max output current okay") start = ABOX_DHAB_CH1_DIV.div(DHAB_S124_MAX_OUT_V) / DAC_GAIN stop = ABOX_DHAB_CH1_DIV.div(5.0) / DAC_GAIN step = 0.01 / DAC_GAIN @@ -155,40 +200,50 @@ def test_bspd(hil): bspd_ctrl, is_falling=True) thresh *= DAC_GAIN print(f"Short to 5V threshold: {thresh}V") - hil.check(bspd_ctrl.state == 0, "Short to 5V trips") + # hil.check(bspd_ctrl.state == 0, "Short to 5V trips") + check.equal(bspd_ctrl.state, 0, "Short to 5V trips") print(stop * DAC_GAIN) print(start * DAC_GAIN) - hil.check(start < (thresh / DAC_GAIN) <= stop, "Current short to 5V threshold") + # hil.check(start < (thresh / DAC_GAIN) <= stop, "Current short to 5V threshold") + check.between(thresh / DAC_GAIN, stop, start, "Current short to 5V threshold") # Floating current reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") c_sense.hiZ() time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 0, "Floating current") + # hil.check(bspd_ctrl.state == 0, "Floating current") + check.equal(bspd_ctrl.state, 0, "Floating current") # Floating brake_fail reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") brk_fail.hiZ() time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 0, "Floating brake fail") + # hil.check(bspd_ctrl.state == 0, "Floating brake fail") + check.equal(bspd_ctrl.state, 0, "Floating brake fail") # Floating brake_stat reset_bspd(brk_fail, brk_stat, c_sense) cycle_power(pow) - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") brk_stat.hiZ() set_bspd_current(c_sense, min_trip_current) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 0, "Floating brake status") + # hil.check(bspd_ctrl.state == 0, "Floating brake status") + check.equal(bspd_ctrl.state, 0, "Floating brake status") # End the test - hil.end_test() + # hil.end_test() +# ---------------------------------------------------------------------------- # +# ---------------------------------------------------------------------------- # IMD_RC_MIN_TRIP_TIME_S = IMD_STARTUP_TIME_S IMD_RC_MAX_TRIP_TIME_S = R_IMD_MAX_TRIP_TIME_S - IMD_MEASURE_TIME_S IMD_STAT_OKAY = 1 @@ -199,9 +254,10 @@ def test_bspd(hil): def reset_imd(imd_stat): imd_stat.state = IMD_STAT_OKAY + def test_imd(hil): # Begin the test - hil.start_test(test_imd.__name__) + # hil.start_test(test_imd.__name__) # Outputs imd_stat = hil.dout("MainSDC", "IMD_Status") @@ -213,33 +269,43 @@ def test_imd(hil): # IMD Fault reset_imd(imd_stat) cycle_power(pow) - hil.check(imd_ctrl.state == IMD_CTRL_OKAY, "Power On") + # hil.check(imd_ctrl.state == IMD_CTRL_OKAY, "Power On") + check.equal(imd_ctrl.state, IMD_CTRL_OKAY, "Power On") time.sleep(1) imd_stat.state = IMD_STAT_TRIP t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) - hil.check(IMD_RC_MIN_TRIP_TIME_S < t < IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") - hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Trip") + # hil.check(IMD_RC_MIN_TRIP_TIME_S < t < IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Trip") + check.between(t, IMD_RC_MIN_TRIP_TIME_S, IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Trip") imd_stat.state = IMD_STAT_OKAY time.sleep(IMD_RC_MAX_TRIP_TIME_S * 1.1) - hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Stays Latched") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Stays Latched") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Stays Latched") # IMD Fault on Power On reset_imd(imd_stat) imd_stat.state = IMD_STAT_TRIP cycle_power(pow) time.sleep(IMD_RC_MAX_TRIP_TIME_S) - hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Power On") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Power On") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Power On") # IMD Floating reset_imd(imd_stat) imd_stat.hiZ() cycle_power(pow) t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) - hil.check(t < R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") - hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Floating Trip") + # hil.check(t < R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Floating Trip") + check.below(t, R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Floating Trip") - hil.end_test() + # hil.end_test() +# ---------------------------------------------------------------------------- # + +# ---------------------------------------------------------------------------- # AMS_STAT_OKAY = 1 AMS_STAT_TRIP = 0 AMS_CTRL_OKAY = 1 @@ -248,9 +314,10 @@ def test_imd(hil): def reset_ams(ams_stat): ams_stat.state = AMS_STAT_OKAY + def test_ams(hil): # Begin the test - hil.start_test(test_ams.__name__) + # hil.start_test(test_ams.__name__) # Outputs ams_stat = hil.dout("MainSDC", "BMS-Status-Main") @@ -262,41 +329,37 @@ def test_ams(hil): # AMS Fault reset_ams(ams_stat) cycle_power(pow) - hil.check(ams_ctrl.state == AMS_CTRL_OKAY, "Power On") + # hil.check(ams_ctrl.state == AMS_CTRL_OKAY, "Power On") + check.equal(ams_ctrl.state, AMS_CTRL_OKAY, "Power On") time.sleep(1) ams_stat.state = AMS_STAT_TRIP t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) - hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") - hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Trip") + # hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Trip") + check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Trip") ams_stat.state = AMS_STAT_OKAY time.sleep(AMS_MAX_TRIP_DELAY_S * 1.1) - hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Stays Latched") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Stays Latched") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Stays Latched") # AMS Fault on Power On reset_ams(ams_stat) ams_stat.state = AMS_STAT_TRIP cycle_power(pow) time.sleep(AMS_MAX_TRIP_DELAY_S) - hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Power On") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Power On") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Power On") # AMS Floating reset_ams(ams_stat) ams_stat.hiZ() cycle_power(pow) t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) - hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") - hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Floating Trip") + # hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Floating Trip") + check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time", ge=True) + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Floating Trip") - hil.end_test() - - -if __name__ == "__main__": - hil = HIL() - hil.load_config("config_main_sdc_bench.json") - hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") - - test_bspd(hil) - test_imd(hil) - test_ams(hil) - - hil.shutdown() + # hil.end_test() +# ---------------------------------------------------------------------------- # \ No newline at end of file diff --git a/scripts/test_system.py b/scripts/test_system.py index 30ffc5a..967f915 100644 --- a/scripts/test_system.py +++ b/scripts/test_system.py @@ -6,6 +6,11 @@ from rules_constants import * from vehicle_constants import * +import pytest_check as check +import pytest + + +# ---------------------------------------------------------------------------- # AMS_STAT_OKAY = 1 AMS_STAT_TRIP = 0 AMS_CTRL_OKAY = 1 @@ -48,10 +53,33 @@ def cycle_power(): time.sleep(CYCLE_POWER_OFF_DELAY) power.state = 0 time.sleep(CYCLE_POWER_ON_DELAY) +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +@pytest.fixture(scope="session") +def hil(): + global power + + hil_instance = HIL() + + hil_instance.load_config("config_charger.json") + hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + # hil_instance.init_can() + + power = hil_instance.dout("RearTester", "RLY1") + + yield hil_instance + + hil_instance.shutdown() +# ---------------------------------------------------------------------------- # + +# ---------------------------------------------------------------------------- # def test_precharge(hil): # Begin the test - hil.start_test(test_precharge.__name__) + # hil.start_test(test_precharge.__name__) # Outputs v_bat = hil.aout("Main_Module", "VBatt") @@ -79,13 +107,17 @@ def test_precharge(hil): # Initial State reset_pchg(v_bat, v_mc) time.sleep(2.5) - hil.check(pchg_cmplt.state == 0, "Precharge not complete on startup") - hil.check(not_pchg_cmplt_delayed.state == 1, "Not precharge complete delayed high on startup") + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on startup") + # hil.check(not_pchg_cmplt_delayed.state == 1, "Not precharge complete delayed high on startup") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on startup") + check.equal(not_pchg_cmplt_delayed.state, 1, "Not precharge complete delayed high on startup") # Check delay v_mc.state = tiff_hv_to_lv(ACCUM_NOM_V) t = utils.measure_trip_time(not_pchg_cmplt_delayed, PCHG_COMPLETE_DELAY_S*3, is_falling=True) - hil.check(not_pchg_cmplt_delayed.state == 0, "Precharge complete delayed") - hil.check_within(t, PCHG_COMPLETE_DELAY_S, 0.25, f"Precharge complete delay of {t:.3}s close to expected {PCHG_COMPLETE_DELAY_S}s") + # hil.check(not_pchg_cmplt_delayed.state == 0, "Precharge complete delayed") + # hil.check_within(t, PCHG_COMPLETE_DELAY_S, 0.25, f"Precharge complete delay of {t:.3}s close to expected {PCHG_COMPLETE_DELAY_S}s") + check.equal(not_pchg_cmplt_delayed.state, 0, "Precharge complete delayed") + check.almost_equal(t, PCHG_COMPLETE_DELAY_S, abs=0.25, rel=0.0, msg=f"Precharge complete delay of {t:.3}s close to expected {PCHG_COMPLETE_DELAY_S}s") # Find threshold at nominal pack voltage for v in [ACCUM_MIN_V, ACCUM_NOM_V, ACCUM_MAX_V]: @@ -95,7 +127,8 @@ def test_precharge(hil): v_mc.state = tiff_hv_to_lv(v*0.8) #time.sleep(0.01) time.sleep(0.5) - hil.check(pchg_cmplt.state == 0, "Precharge Complete Low at Initial State") + # hil.check(pchg_cmplt.state == 0, "Precharge Complete Low at Initial State") + check.equal(pchg_cmplt.state, 0, "Precharge Complete Low at Initial State") start = tiff_hv_to_lv(v*0.8) stop = tiff_hv_to_lv(v) @@ -104,41 +137,52 @@ def test_precharge(hil): pchg_cmplt, is_falling=0) thresh_hv = tiff_lv_to_hv(thresh) print(f"Precharge triggered at {thresh_hv / v * 100:.4}% ({thresh_hv:.5}V) of vbat={v}.") - hil.check_within(thresh_hv / v, R_PCHG_V_BAT_THRESH, 0.03, f"Precharge threshold of {R_PCHG_V_BAT_THRESH*100}% at vbat = {v}V") + # hil.check_within(thresh_hv / v, R_PCHG_V_BAT_THRESH, 0.03, f"Precharge threshold of {R_PCHG_V_BAT_THRESH*100}% at vbat = {v}V") + check.almost_equal(thresh_hv / v, R_PCHG_V_BAT_THRESH, abs=0.03, rel=0.0, msg=f"Precharge threshold of {R_PCHG_V_BAT_THRESH*100}% at vbat = {v}V") v_mc.state = tiff_hv_to_lv(v) #time.sleep(0.25) time.sleep(8) - hil.check(pchg_cmplt.state == 1, f"Precharge completed at vbat = {v}V") + # hil.check(pchg_cmplt.state == 1, f"Precharge completed at vbat = {v}V") + check.equal(pchg_cmplt.state, 1, f"Precharge completed at vbat = {v}V") # Floating conditions (check never precharge complete) reset_pchg(v_bat, v_mc) v_bat.hiZ() v_mc.state = tiff_hv_to_lv(0) - hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc 0V") + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc 0V") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat float, v_mc 0V") v_mc.state = tiff_hv_to_lv(ACCUM_MAX_V) - hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc max V") + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc max V") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat float, v_mc max V") reset_pchg(v_bat, v_mc) v_mc.hiZ() v_bat.state = tiff_hv_to_lv(ACCUM_MIN_V) - hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat min, v_mc float") + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat min, v_mc float") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat min, v_mc float") v_bat.state = tiff_hv_to_lv(ACCUM_MAX_V) - hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat max, v_mc float") + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat max, v_mc float") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat max, v_mc float") reset_pchg(v_bat, v_mc) v_bat.hiZ() v_mc.hiZ() - hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc float") + # hil.check(pchg_cmplt.state == 0, "Precharge not complete on v_bat float, v_mc float") + check.equal(pchg_cmplt.state, 0, "Precharge not complete on v_bat float, v_mc float") # TODO: software precharge validity checks (make precharge take forever) - hil.end_test() + # hil.end_test() +# ---------------------------------------------------------------------------- # + +# ---------------------------------------------------------------------------- # BRK_SWEEP_DELAY = 0.1 BSPD_DASH_ON_TIME = 0 + def test_bspd(hil): # Begin the test - hil.start_test(test_bspd.__name__) + # hil.start_test(test_bspd.__name__) # Outputs brk1 = hil.aout("Dashboard", "BRK1_RAW") @@ -163,23 +207,29 @@ def test_bspd(hil): # Brake threshold check brk1.state = BRK_1_REST_V brk2.state = BRK_2_REST_V - hil.check(brk_stat_tap.state == 0, "Brake stat starts low") + # hil.check(brk_stat_tap.state == 0, "Brake stat starts low") + check.equal(brk_stat_tap.state, 0, "Brake stat starts low") brk1.state = BRK_1_THRESH_V time.sleep(0.1) - hil.check(brk_stat_tap.state == 1, "Brake stat goes high at brk 1 thresh") + # hil.check(brk_stat_tap.state == 1, "Brake stat goes high at brk 1 thresh") + check.equal(brk_stat_tap.state, 1, "Brake stat goes high at brk 1 thresh") brk1.state = BRK_1_REST_V - hil.check(brk_stat_tap.state == 0, "Brake stat starts low") + # hil.check(brk_stat_tap.state == 0, "Brake stat starts low") + check.equal(brk_stat_tap.state, 0, "Brake stat starts low") brk2.state = BRK_2_THRESH_V time.sleep(0.1) - hil.check(brk_stat_tap.state == 1, "Brake stat goes high at brk 2 thresh") + # hil.check(brk_stat_tap.state == 1, "Brake stat goes high at brk 2 thresh") + check.equal(brk_stat_tap.state, 1, "Brake stat goes high at brk 2 thresh") brk1.state = BRK_1_THRESH_V - hil.check(brk_stat_tap.state == 1, "Brake stat stays high for both brakes") + # hil.check(brk_stat_tap.state == 1, "Brake stat stays high for both brakes") + check.equal(brk_stat_tap.state, 1, "Brake stat stays high for both brakes") # Brake threshold scan brk1.state = BRK_MIN_OUT_V brk2.state = BRK_MIN_OUT_V time.sleep(0.1) - hil.check(brk_stat_tap.state == 0, "Brake Stat Starts Low Brk 1") + # hil.check(brk_stat_tap.state == 0, "Brake Stat Starts Low Brk 1") + check.equal(brk_stat_tap.state, 0, "Brake Stat Starts Low Brk 1") start = BRK_MIN_OUT_V stop = BRK_MAX_OUT_V @@ -189,72 +239,108 @@ def test_bspd(hil): BRK_SWEEP_DELAY, brk_stat_tap, is_falling=False) print(f"Brake 1 braking threshold: {thresh}") - hil.check_within(thresh, BRK_1_THRESH_V, 0.2, "Brake 1 trip voltage") - hil.check(brk_stat_tap.state == 1, "Brake Stat Tripped for Brk 1") + # hil.check_within(thresh, BRK_1_THRESH_V, 0.2, "Brake 1 trip voltage") + # hil.check(brk_stat_tap.state == 1, "Brake Stat Tripped for Brk 1") + check.almost_equal(thresh, BRK_1_THRESH_V, abs=0.2, rel=0.0, msg="Brake 1 trip voltage") + check.equal(brk_stat_tap.state, 1, "Brake Stat Tripped for Brk 1") brk1.state = BRK_MIN_OUT_V brk2.state = BRK_MIN_OUT_V - hil.check(brk_stat_tap.state == 0, "Brake Stat Starts Low Brk 2") + # hil.check(brk_stat_tap.state == 0, "Brake Stat Starts Low Brk 2") + check.equal(brk_stat_tap.state, 0, "Brake Stat Starts Low Brk 2") thresh = utils.measure_trip_thresh(brk2, start, stop, step, BRK_SWEEP_DELAY, brk_stat_tap, is_falling=False) print(f"Brake 2 braking threshold: {thresh}") - hil.check_within(thresh, BRK_2_THRESH_V, 0.2, "Brake 2 trip voltage") - hil.check(brk_stat_tap.state == 1, "Brake Stat Tripped for Brk 2") + # hil.check_within(thresh, BRK_2_THRESH_V, 0.2, "Brake 2 trip voltage") + # hil.check(brk_stat_tap.state == 1, "Brake Stat Tripped for Brk 2") + check.almost_equal(thresh, BRK_2_THRESH_V, abs=0.2, rel=0.0, msg="Brake 2 trip voltage") + check.equal(brk_stat_tap.state, 1, "Brake Stat Tripped for Brk 2") # Brake Fail scan brk1.state = BRK_1_REST_V brk2.state = BRK_2_REST_V time.sleep(0.1) - hil.check(brk_fail_tap.state == 0, "Brake Fail Check 1 Starts 0") + # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 1 Starts 0") + check.equal(brk_fail_tap.state, 0, "Brake Fail Check 1 Starts 0") + brk1.state = 0.0 # Force 0 time.sleep(0.1) - hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Short GND") + # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Short GND") + check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 1 Short GND") + brk1.state = BRK_1_REST_V time.sleep(0.1) - hil.check(brk_fail_tap.state == 0, "Brake Fail Check 2 Starts 0") + # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 2 Starts 0") + check.equal(brk_fail_tap.state, 0, "Brake Fail Check 2 Starts 0") + brk2.state = 0.0 # Force 0 time.sleep(0.1) - hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Short GND") + # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Short GND") + check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 2 Short GND") + brk2.state = BRK_2_REST_V time.sleep(0.1) - hil.check(brk_fail_tap.state == 0, "Brake Fail Check 3 Starts 0") + # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 3 Starts 0") + check.equal(brk_fail_tap.state, 0, "Brake Fail Check 3 Starts 0") + brk1.state = 5.0 # Short VCC time.sleep(0.1) - hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Short VCC") + # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Short VCC") + check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 1 Short VCC") + brk1.state = BRK_1_REST_V time.sleep(0.1) - hil.check(brk_fail_tap.state == 0, "Brake Fail Check 4 Starts 0") + # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 4 Starts 0") + check.equal(brk_fail_tap.state, 0, "Brake Fail Check 4 Starts 0") + brk2.state = 5.0 # Short VCC time.sleep(0.1) - hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Short VCC") + # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Short VCC") + check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 2 Short VCC") + brk2.state = BRK_2_REST_V time.sleep(0.1) - hil.check(brk_fail_tap.state == 0, "Brake Fail Check 5 Starts 0") + # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 5 Starts 0") + check.equal(brk_fail_tap.state, 0, "Brake Fail Check 5 Starts 0") + brk1.hiZ() time.sleep(0.1) - hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Hi-Z") + # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Hi-Z") + check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 1 Hi-Z") + brk1.state = BRK_1_REST_V time.sleep(0.1) - hil.check(brk_fail_tap.state == 0, "Brake Fail Check 6 Starts 0") + # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 6 Starts 0") + check.equal(brk_fail_tap.state, 0, "Brake Fail Check 6 Starts 0") + brk2.hiZ() time.sleep(0.1) - hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Hi-Z") + # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Hi-Z") + check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 2 Hi-Z") + brk2.state = BRK_2_REST_V # Brake Fail reset_bspd(brk1, brk2, c_sense) cycle_power() time.sleep(BSPD_DASH_ON_TIME) - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") + brk1.state = 0.0 t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") - hil.check(brk_fail_tap.state == 1, "Brake Fail went high") + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") + # hil.check(brk_fail_tap.state == 1, "Brake Fail went high") + check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Brake Fail") + check.equal(brk_fail_tap.state, 1, "Brake Fail went high") + brk1.state = BRK_1_REST_V time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(brk_fail_tap.state == 0, "Brake Fail returned low") - hil.check(bspd_ctrl.state == 0, "Brake Fail Stays Latched") + # hil.check(brk_fail_tap.state == 0, "Brake Fail returned low") + # hil.check(bspd_ctrl.state == 0, "Brake Fail Stays Latched") + check.equal(brk_fail_tap.state, 0, "Brake Fail returned low") + check.equal(bspd_ctrl.state, 0, "Brake Fail Stays Latched") # Brake Fail on Power On reset_bspd(brk1, brk2, c_sense) @@ -266,7 +352,8 @@ def test_bspd(hil): power.state = 0 time.sleep(R_BSPD_MAX_TRIP_TIME_S) time.sleep(BSPD_DASH_ON_TIME) # NOTE: test can't check for the trip time - hil.check(bspd_ctrl.state == 0, "Power On Brake Fail") + # hil.check(bspd_ctrl.state == 0, "Power On Brake Fail") + check.equal(bspd_ctrl.state, 0, "Power On Brake Fail") # Current no brake reset_bspd(brk1, brk2, c_sense) @@ -280,47 +367,59 @@ def test_bspd(hil): time.sleep(R_BSPD_MAX_TRIP_TIME_S) # time.sleep(100) time.sleep(3) - hil.check(bspd_ctrl.state == 1, "Current no brake") + # hil.check(bspd_ctrl.state == 1, "Current no brake") + check.equal(bspd_ctrl.state, 1, "Current no brake") # Current Sense Short to Ground reset_bspd(brk1, brk2, c_sense) cycle_power() time.sleep(BSPD_DASH_ON_TIME) - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On" + check.equal(bspd_ctrl.state, 1, "Power On") + c_sense.state = 0.0 t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") + check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Current short to ground") set_bspd_current(c_sense, 0.0) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 0, "Current short to ground stays latched") + # hil.check(bspd_ctrl.state == 0, "Current short to ground stays latched") + check.equal(bspd_ctrl.state, 0, "Current short to ground stays latched") # Current Sense Short to 5V reset_bspd(brk1, brk2, c_sense) cycle_power() time.sleep(BSPD_DASH_ON_TIME*1.2) - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") c_sense.state = ABOX_DHAB_CH1_DIV.div(5.0) t = utils.measure_trip_time(bspd_ctrl, 5.0, is_falling=True) - hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") + check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Current short to 5V") set_bspd_current(c_sense, 0.0) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 0, "Current short to 5V stays latched") + # hil.check(bspd_ctrl.state == 0, "Current short to 5V stays latched") + check.equal(bspd_ctrl.state, 0, "Current short to 5V stays latched") # Braking reset_bspd(brk1, brk2, c_sense) cycle_power() time.sleep(BSPD_DASH_ON_TIME) - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") brk1.state = BRK_1_THRESH_V time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 1, "Brake no current") - hil.check(brk_stat_tap.state == 1, "Brake stat went high") + # hil.check(bspd_ctrl.state == 1, "Brake no current") + # hil.check(brk_stat_tap.state == 1, "Brake stat went high") + check.equal(bspd_ctrl.state, 1, "Brake no current") + check.equal(brk_stat_tap.state, 1, "Brake stat went high") # Lowest current required to trip at min_trip_current = R_BSPD_POWER_THRESH_W / ACCUM_MAX_V set_bspd_current(c_sense, min_trip_current) t = utils.measure_trip_time(bspd_ctrl, 10.0, is_falling=True) - hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Braking with current") + # hil.check(t < R_BSPD_MAX_TRIP_TIME_S, "Braking with current") + check.less(t, R_BSPD_MAX_TRIP_TIME_S, "Braking with current") # Measure braking with current threshold reset_bspd(brk1, brk2, c_sense) @@ -328,7 +427,8 @@ def test_bspd(hil): time.sleep(BSPD_DASH_ON_TIME) brk1.state = BRK_1_THRESH_V - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") start = ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(0.0)) stop = ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(DHAB_S124_CH1_MAX_A)) step = 0.1 @@ -337,16 +437,23 @@ def test_bspd(hil): bspd_ctrl, is_falling=True) thresh_amps = dhab_ch1_v_to_a(ABOX_DHAB_CH1_DIV.reverse(thresh)) print(f"Current while braking threshold: {thresh}V = {thresh_amps}A") - hil.check_within(thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), 0.1, "Current while braking threshold") + # hil.check_within(thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), 0.1, "Current while braking threshold") + check.almost_equal( + thresh, ABOX_DHAB_CH1_DIV.div(dhab_ch1_a_to_v(min_trip_current)), + abs=0.1, rel=0.0, + msg="Current while braking threshold" + ) # Determine the current sense short to gnd threshold reset_bspd(brk1, brk2, c_sense) cycle_power() time.sleep(BSPD_DASH_ON_TIME) - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") set_bspd_current(c_sense, DHAB_S124_CH1_MIN_A) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 1, "Min output current okay") + # hil.check(bspd_ctrl.state == 1, "Min output current okay") + check.equal(bspd_ctrl.state, 1, "Min output current okay") start = ABOX_DHAB_CH1_DIV.div(DHAB_S124_MIN_OUT_V) stop = 0.0 step = -0.1 @@ -354,18 +461,21 @@ def test_bspd(hil): R_BSPD_MAX_TRIP_TIME_S, bspd_ctrl, is_falling=True) print(f"Short to ground threshold: {thresh}V") - hil.check(stop < (thresh) < start, "Current short to ground threshold") + # hil.check(stop < (thresh) < start, "Current short to ground threshold") + check.between(thresh, stop, start, "Current short to ground threshold") # Determine the current sense short to 5V threshold reset_bspd(brk1, brk2, c_sense) cycle_power() time.sleep(BSPD_DASH_ON_TIME) - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") time.sleep(2) set_bspd_current(c_sense, DHAB_S124_CH1_MAX_A) time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 1, "Max output current okay") + # hil.check(bspd_ctrl.state == 1, "Max output current okay") + check.equal(bspd_ctrl.state, 1, "Max output current okay") start = ABOX_DHAB_CH1_DIV.div(DHAB_S124_MAX_OUT_V) stop = ABOX_DHAB_CH1_DIV.div(5.0) @@ -373,26 +483,31 @@ def test_bspd(hil): c_sense.state = start time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 1, "Max output voltage okay") + # hil.check(bspd_ctrl.state == 1, "Max output voltage okay") + check.equal(bspd_ctrl.state, 1, "Max output voltage okay") input("enter to continue") thresh = utils.measure_trip_thresh(c_sense, start, stop, step, R_BSPD_MAX_TRIP_TIME_S, bspd_ctrl, is_falling=True) print(f"Short to 5V threshold: {thresh}V") - hil.check(bspd_ctrl.state == 0, "Short to 5V trips") + # hil.check(bspd_ctrl.state == 0, "Short to 5V trips") + check.equal(bspd_ctrl.state, 0, "Short to 5V trips") print(stop) print(start) - hil.check(start < (thresh) <= stop, "Current short to 5V threshold") + # hil.check(start < (thresh) <= stop, "Current short to 5V threshold") + check.between(thresh, start, stop, "Current short to 5V threshold", le=True) # Floating current reset_bspd(brk1, brk2, c_sense) cycle_power() time.sleep(BSPD_DASH_ON_TIME) - hil.check(bspd_ctrl.state == 1, "Power On") + # hil.check(bspd_ctrl.state == 1, "Power On") + check.equal(bspd_ctrl.state, 1, "Power On") c_sense.hiZ() time.sleep(R_BSPD_MAX_TRIP_TIME_S) - hil.check(bspd_ctrl.state == 0, "Floating current") + # hil.check(bspd_ctrl.state == 0, "Floating current") + check.equal(bspd_ctrl.state, 0, "Floating current") # Floating brake_fail # Can't test this at system level! @@ -401,9 +516,11 @@ def test_bspd(hil): # Can't test this at system level! # End the test - hil.end_test() + # hil.end_test() +# ---------------------------------------------------------------------------- # +# ---------------------------------------------------------------------------- # IMD_RC_MIN_TRIP_TIME_S = IMD_STARTUP_TIME_S IMD_RC_MAX_TRIP_TIME_S = R_IMD_MAX_TRIP_TIME_S - IMD_MEASURE_TIME_S IMD_CTRL_OKAY = 1 @@ -411,7 +528,7 @@ def test_bspd(hil): def test_imd(hil): # Begin the test - hil.start_test(test_imd.__name__) + # hil.start_test(test_imd.__name__) # Outputs imd_stat = hil.dout("Main_Module", "IMD_Status") @@ -432,37 +549,47 @@ def test_imd(hil): # IMD Fault reset_imd(imd_stat) cycle_power() - hil.check(imd_ctrl.state == IMD_CTRL_OKAY, "Power On") + # hil.check(imd_ctrl.state == IMD_CTRL_OKAY, "Power On") + check.equal(imd_ctrl.state, IMD_CTRL_OKAY, "Power On") time.sleep(1) imd_stat.state = IMD_STAT_TRIP t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) print(f"Target trip time: [{IMD_RC_MIN_TRIP_TIME_S}, {IMD_RC_MAX_TRIP_TIME_S}]") - hil.check(IMD_RC_MIN_TRIP_TIME_S < t < IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") - hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Trip") + # hil.check(IMD_RC_MIN_TRIP_TIME_S < t < IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Trip") + check.between(t, IMD_RC_MIN_TRIP_TIME_S, IMD_RC_MAX_TRIP_TIME_S, "IMD Trip Time") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Trip") imd_stat.state = IMD_STAT_OKAY time.sleep(IMD_RC_MAX_TRIP_TIME_S * 1.1) - hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Stays Latched") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Stays Latched") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Stays Latched") # IMD Fault on Power On reset_imd(imd_stat) imd_stat.state = IMD_STAT_TRIP cycle_power() time.sleep(IMD_RC_MAX_TRIP_TIME_S) - hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Power On") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Fault Power On") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Fault Power On") # IMD Floating reset_imd(imd_stat) imd_stat.hiZ() cycle_power() t = utils.measure_trip_time(imd_ctrl, R_IMD_MAX_TRIP_TIME_S, is_falling=True) - hil.check(t < R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") - hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Floating Trip") + # hil.check(t < R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") + # hil.check(imd_ctrl.state == IMD_CTRL_TRIP, "IMD Floating Trip") + check.less(t, R_IMD_MAX_TRIP_TIME_S, "IMD Floating Trip Time") + check.equal(imd_ctrl.state, IMD_CTRL_TRIP, "IMD Floating Trip") - hil.end_test() + # hil.end_test() +# ---------------------------------------------------------------------------- # + +# ---------------------------------------------------------------------------- # def test_ams(hil): # Begin the test - hil.start_test(test_ams.__name__) + # hil.start_test(test_ams.__name__) # Outputs ams_stat = hil.dout("Main_Module", "BMS-Status-Main") @@ -483,33 +610,43 @@ def test_ams(hil): # AMS Fault reset_ams(ams_stat) cycle_power() - hil.check(ams_ctrl.state == AMS_CTRL_OKAY, "Power On") + # hil.check(ams_ctrl.state == AMS_CTRL_OKAY, "Power On") + check.equal(ams_ctrl.state, AMS_CTRL_OKAY, "Power On") time.sleep(1) ams_stat.state = AMS_STAT_TRIP t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) - hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") - hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Trip") + # hil.check(0 < t < AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Trip") + check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Trip Time") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Trip") ams_stat.state = AMS_STAT_OKAY time.sleep(AMS_MAX_TRIP_DELAY_S * 1.1) - hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Stays Latched") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Stays Latched") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Stays Latched") # AMS Fault on Power On reset_ams(ams_stat) ams_stat.state = AMS_STAT_TRIP cycle_power() time.sleep(AMS_MAX_TRIP_DELAY_S) - hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Power On") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Fault Power On") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Fault Power On") # AMS Floating reset_ams(ams_stat) ams_stat.hiZ() cycle_power() t = utils.measure_trip_time(ams_ctrl, AMS_MAX_TRIP_DELAY_S * 2, is_falling=True) - hil.check(0 <= t < AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") - hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Floating Trip") + # hil.check(0 <= t < AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") + # hil.check(ams_ctrl.state == AMS_CTRL_TRIP, "AMS Floating Trip") + check.between(t, 0, AMS_MAX_TRIP_DELAY_S, "AMS Floating Trip Time") + check.equal(ams_ctrl.state, AMS_CTRL_TRIP, "AMS Floating Trip") - hil.end_test() + # hil.end_test() +# ---------------------------------------------------------------------------- # + +# ---------------------------------------------------------------------------- # def tsal_is_red(): while 1: i = input("Is TSAL Green (g) or Red (r): ") @@ -536,21 +673,25 @@ def test_tsal(hil): time.sleep(0.2) # No need to power cycle - hil.check(tsal_is_red() == False, "LVAL on at v_mc = 0") + # hil.check(tsal_is_red() == False, "LVAL on at v_mc = 0") + check.equal(tsal_is_red(), False, "LVAL on at v_mc = 0") #hil.check(tsal.state == 0, "TSAL off at v_mc = 0") time.sleep(5) - hil.check(tsal_is_red() == False, "LVAL stays on") + # hil.check(tsal_is_red() == False, "LVAL stays on") + check.equal(tsal_is_red(), False, "LVAL stays on") v_mc.state = tiff_hv_to_lv(ACCUM_MIN_V) time.sleep(0.1) #hil.check(lval.state == 0, f"LVAL off at {ACCUM_MIN_V:.4} V") - hil.check(tsal_is_red() == True, f"TSAL on at {ACCUM_MIN_V:.4} V") + # hil.check(tsal_is_red() == True, f"TSAL on at {ACCUM_MIN_V:.4} V") + check.equal(tsal_is_red(), True, f"TSAL on at {ACCUM_MIN_V:.4} V") reset_tsal(v_mc) time.sleep(0.2) - hil.check(tsal_is_red() == False, f"LVAL turns back on") + # hil.check(tsal_is_red() == False, f"LVAL turns back on") + check.equal(tsal_is_red(), False, f"LVAL turns back on") start = tiff_hv_to_lv(50) stop = tiff_hv_to_lv(R_TSAL_HV_V * 1.5) @@ -574,27 +715,36 @@ def test_tsal(hil): if (not tripped): utils.log_warning(f"TSAL did not trip at stop of {stop}.") thresh = stop - hil.check(tripped, "TSAL tripped") + # hil.check(tripped, "TSAL tripped") + check.is_true(tripped, "TSAL tripped") thresh = tiff_lv_to_hv(thresh) print(f"TSAL on at {thresh:.4} V") hil.check_within(thresh, R_TSAL_HV_V, 4, f"TSAL trips at {R_TSAL_HV_V:.4} +-4") + check.almost_equal(thresh, R_TSAL_HV_V, abs=4, rel=0.0, msg=f"TSAL trips at {R_TSAL_HV_V:.4} +-4") + + # hil.end_test() +# ---------------------------------------------------------------------------- # - hil.end_test() +# ---------------------------------------------------------------------------- # def test_sdc(hil): ''' Check that every node in the sdc trips ''' # Begin the test - hil.start_test(test_sdc.__name__) + # hil.start_test(test_sdc.__name__) # Outputs # Inputs - hil.check(0, "TODO") + # hil.check(False, "TODO") + check.is_true(False, "TODO") - hil.end_test() + # hil.end_test() +# ---------------------------------------------------------------------------- # + +# ---------------------------------------------------------------------------- # def is_buzzer_on(): while 1: i = input("Is Buzzer On (y) or No (n): ") @@ -606,7 +756,7 @@ def is_buzzer_on(): def test_buzzer(hil): # Begin the test - hil.start_test(test_buzzer.__name__) + # hil.start_test(test_buzzer.__name__) # Outputs buzzer_ctrl = hil.daq_var("Main_Module", "daq_buzzer") @@ -616,21 +766,29 @@ def test_buzzer(hil): buzzer_ctrl.state = 0 time.sleep(0.02) - hil.check(buzzer_stat.state == 0, "Buzzer Off") + # hil.check(buzzer_stat.state == 0, "Buzzer Off") + check.equal(buzzer_stat.state, 0, "Buzzer Off") buzzer_ctrl.state = 1 print(buzzer_ctrl.state) time.sleep(0.02) - hil.check(buzzer_stat.state == 1, "Buzzer On") - hil.check(is_buzzer_on() == True, "Buzzer Making Noise") + # hil.check(buzzer_stat.state == 1, "Buzzer On") + # hil.check(is_buzzer_on() == True, "Buzzer Making Noise") + check.equal(buzzer_stat.state, 1, "Buzzer On") + check.is_true(is_buzzer_on(), "Buzzer Making Noise") buzzer_ctrl.state = 0 time.sleep(0.02) - hil.check(buzzer_stat.state == 0, "Buzzer back Off") - hil.check(is_buzzer_on() == False, "Buzzer Not Making Noise") + # hil.check(buzzer_stat.state == 0, "Buzzer back Off") + # hil.check(is_buzzer_on() == False, "Buzzer Not Making Noise") + check.equal(buzzer_stat.state, 0, "Buzzer back Off") + check.is_false(is_buzzer_on(), "Buzzer Not Making Noise") + + # hil.end_test() +# ---------------------------------------------------------------------------- # - hil.end_test() +# ---------------------------------------------------------------------------- # def is_brake_light_on(): while 1: i = input("Is Brake Light On (y) or No (n): ") @@ -642,7 +800,7 @@ def is_brake_light_on(): def test_brake_light(hil): # Begin the test - hil.start_test(test_brake_light.__name__) + # hil.start_test(test_brake_light.__name__) # Outputs brk_ctrl = hil.daq_var("Main_Module", "daq_brake") @@ -652,28 +810,36 @@ def test_brake_light(hil): brk_ctrl.state = 0 time.sleep(0.02) - hil.check(brk_ctrl.state == 0, "Brake Off") + # hil.check(brk_ctrl.state == 0, "Brake Off") + check.equal(brk_ctrl.state, 0, "Brake Off") brk_ctrl.state = 1 print(brk_ctrl.state) time.sleep(0.02) - hil.check(brk_ctrl.state == 1, "Brake Light On") - hil.check(is_brake_light_on() == True, "Brake Light is On") + # hil.check(brk_ctrl.state == 1, "Brake Light On") + # hil.check(is_brake_light_on() == True, "Brake Light is On") + check.equal(brk_ctrl.state, 1, "Brake Light On") + check.is_true(is_brake_light_on(), "Brake Light is On") brk_ctrl.state = 0 time.sleep(0.02) - hil.check(brk_ctrl.state == 0, "Brake Light back Off") - hil.check(is_brake_light_on() == False, "Brake Light is Off") + # hil.check(brk_ctrl.state == 0, "Brake Light back Off") + # hil.check(is_brake_light_on() == False, "Brake Light is Off") + check.equal(brk_ctrl.state, 0, "Brake Light back Off") + check.is_false(is_brake_light_on(), "Brake Light is Off") # Can copy lot from bspd # Read the brake control mcu pin # Finally have user verify light actually turned on - hil.end_test() + # hil.end_test() +# ---------------------------------------------------------------------------- # + +# ---------------------------------------------------------------------------- # def test_light_tsal_buz(hil): - hil.start_test(test_light_tsal_buz.__name__) + # hil.start_test(test_light_tsal_buz.__name__) # Outputs brk_ctrl = hil.daq_var("Main_Module", "daq_brake") @@ -685,30 +851,7 @@ def test_light_tsal_buz(hil): brk_ctrl.state = 0 buzzer_ctrl.state = 0 - hil.end_test() - - -if __name__ == "__main__": - hil = HIL() - - hil.load_config("config_system_hil_attached.json") - hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") - - hil.init_can() - - power = hil.dout("RearTester", "RLY1") - - # Drive Critical Tests - # test_precharge(hil) - test_bspd(hil) - # test_imd(hil) # note: tsal needs to be tripped - # test_ams(hil) - # test_tsal(hil) - # test_sdc(hil) - # test_buzzer(hil) - # test_brake_light(hil) - # test_light_tsal_buz(hil) - - # Peripheral Sensor Tests + check.is_true(True, "TODO") - hil.shutdown() + # hil.end_test() +# ---------------------------------------------------------------------------- # \ No newline at end of file diff --git a/scripts/test_test.py b/scripts/test_test.py index 08af75a..836a1e9 100644 --- a/scripts/test_test.py +++ b/scripts/test_test.py @@ -7,9 +7,30 @@ from rules_constants import * from vehicle_constants import * +import pytest_check as check +import pytest + + +# ---------------------------------------------------------------------------- # +@pytest.fixture(scope="session") +def hil(): + hil_instance = HIL() + + # hil.load_config("config_testing.json") + hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + # hil_instance.init_can() + + yield hil_instance + + hil_instance.shutdown() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # def test_bspd(hil): # Begin the test - hil.start_test(test_bspd.__name__) + # hil.start_test(test_bspd.__name__) # Inputs d2 = hil.din("Test_HIL", "AI2") @@ -53,10 +74,15 @@ def test_bspd(hil): time.sleep(1) time.sleep(2) - hil.end_test() + check.is_true(True, "TODO") + + # hil.end_test() +# ---------------------------------------------------------------------------- # + +# ---------------------------------------------------------------------------- # def test_dac(hil): - hil.start_test(test_dac.__name__) + # hil.start_test(test_dac.__name__) dac1 = hil.aout("Test_HIL", "DAC1") dac2 = hil.aout("Test_HIL", "DAC2") @@ -71,8 +97,13 @@ def test_dac(hil): dac2.state = 0.25 input(".25") - hil.end_test() + check.is_true(True, "TODO") + # hil.end_test() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # def test_pot(hil): pot1 = hil.pot("Test_HIL", "POT1") @@ -107,8 +138,13 @@ def test_pot(hil): pot2.state = 0.5 input("-------") + check.is_true(True, "TODO") +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # def test_mcu_pin(hil): - hil.start_test(test_mcu_pin.__name__) + # hil.start_test(test_mcu_pin.__name__) brk_stat_tap = hil.mcu_pin("Dashboard", "BRK_STAT_TAP") @@ -123,12 +159,16 @@ def test_mcu_pin(hil): delta_cnt = delta_cnt + 1 print(f"Average: {delta_avg/delta_cnt}") + + check.is_true(True, "TODO") - hil.end_test() + # hil.end_test() +# ---------------------------------------------------------------------------- # +# ---------------------------------------------------------------------------- # def test_daq(hil): - hil.start_test(test_daq.__name__) + # hil.start_test(test_daq.__name__) counter = 0 start_time = time.time() @@ -153,20 +193,8 @@ def test_daq(hil): if (delta < 0): delta = 0 time.sleep(delta) + check.is_true(True, "TODO") + print("Done") print(f"Last count sent: {counter - 1}") - - -if __name__ == "__main__": - hil = HIL() - #hil.load_config("config_testing.json") - hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") - - hil.init_can() - #test_bspd(hil) - #test_dac(hil) - # test_pot(hil) - # test_mcu_pin(hil) - test_daq(hil) - - hil.shutdown() +# ---------------------------------------------------------------------------- # \ No newline at end of file From 09e43fb620983686d6f4c11f90b192bfbdf587d0 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 15 Oct 2024 19:21:21 -0400 Subject: [PATCH 026/181] Commenting out old code for in hil.py testing --- hil/hil.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hil/hil.py b/hil/hil.py index 3d33cf5..fc4d2df 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -36,10 +36,10 @@ def __init__(self): self.can_bus = None utils.hilProt = self signal.signal(signal.SIGINT, signal_int_handler) - self.global_failed_checks = [] - self.global_test_names = [] - self.global_check_count = 0 # multiple checks within a test - self.global_test_count = 0 + # self.global_failed_checks = [] + # self.global_test_names = [] + # self.global_check_count = 0 # multiple checks within a test + # self.global_test_count = 0 @utils.log_function_start_end def init_can(self): From 26a68840dc273412b2abe0ad9df3ff2ca0d8d6c3 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 15 Oct 2024 19:28:13 -0400 Subject: [PATCH 027/181] Type hinting return types and instance variables --- hil/hil.py | 83 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 33 deletions(-) diff --git a/hil/hil.py b/hil/hil.py index fc4d2df..1286ad0 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -11,6 +11,7 @@ from communication.can_bus import CanBus from communication.daq_protocol import DaqProtocol from communication.daq_protocol import DAQPin +from communication.daq_protocol import DAQVariable """ HIL TESTER """ @@ -25,24 +26,29 @@ class HIL(): + @utils.log_function_start_end @utils.log_function_start_end def __init__(self): utils.initGlobals() - self.components = {} - self.dut_connections = {} - self.hil_devices = {} - self.serial_manager = SerialManager() - self.hil_params = utils.load_json_config(PARAMS_PATH, None) - self.can_bus = None + self.components: dict[str, Component] = {} + self.dut_connections: dict[str, dict[str, dict[str, tuple[str, str]]]] = {} + self.hil_devices: dict[str, HilDevice] = {} + self.serial_manager: SerialManager = SerialManager() + self.hil_params: dict = utils.load_json_config(PARAMS_PATH, None) + self.can_bus: CanBus = None utils.hilProt = self signal.signal(signal.SIGINT, signal_int_handler) # self.global_failed_checks = [] # self.global_test_names = [] # self.global_check_count = 0 # multiple checks within a test # self.global_test_count = 0 + # self.global_failed_checks = [] + # self.global_test_names = [] + # self.global_check_count = 0 # multiple checks within a test + # self.global_test_count = 0 @utils.log_function_start_end - def init_can(self): + def init_can(self) -> None: config = self.hil_params self.daq_config = utils.load_json_config(os.path.join(config['firmware_path'], config['daq_config_path']), os.path.join(config['firmware_path'], config['daq_schema_path'])) self.can_config = utils.load_json_config(os.path.join(config['firmware_path'], config['can_config_path']), os.path.join(config['firmware_path'], config['can_schema_path'])) @@ -54,7 +60,7 @@ def init_can(self): self.can_bus.start() @utils.log_function_start_end - def load_pin_map(self, net_map, pin_map): + def load_pin_map(self, net_map, pin_map) -> None: net_map_f = os.path.join(NET_MAP_PATH, net_map) pin_map_f = os.path.join(PIN_MAP_PATH, pin_map) @@ -62,19 +68,19 @@ def load_pin_map(self, net_map, pin_map): self.pin_map.load_mcu_pin_map(pin_map_f) @utils.log_function_start_end - def clear_components(self): + def clear_components(self) -> None: """ Reset HIL""" for c in self.components.values(): c.shutdown() self.components = {} @utils.log_function_start_end - def clear_hil_devices(self): + def clear_hil_devices(self) -> None: self.hil_devices = {} self.serial_manager.close_devices() @utils.log_function_start_end - def shutdown(self): + def shutdown(self) -> None: print(f"{utils.bcolors.OKCYAN}HIL shutdown START{utils.bcolors.ENDC}") self.clear_components() self.clear_hil_devices() @@ -82,7 +88,7 @@ def shutdown(self): print(f"{utils.bcolors.OKGREEN}HIL shutdown START{utils.bcolors.OKGREEN}") @utils.log_function_start_end - def stop_can(self): + def stop_can(self) -> None: print(f"{utils.bcolors.OKCYAN}HIL stop_can START{utils.bcolors.ENDC}") if not self.can_bus: return if self.can_bus.connected: @@ -95,7 +101,7 @@ def stop_can(self): print(f"{utils.bcolors.OKGREEN}HIL stop_can END{utils.bcolors.ENDC}") @utils.log_function_start_end - def load_config(self, config_name): + def load_config(self, config_name) -> None: config = utils.load_json_config(os.path.join(CONFIG_PATH, config_name), None) # TODO: validate w/ schema # TODO: support joining configs @@ -107,7 +113,7 @@ def load_config(self, config_name): self.load_connections(config['dut_connections']) @utils.log_function_start_end - def load_connections(self, dut_connections): + def load_connections(self, dut_connections) -> None: self.dut_connections = {} # Dictionary format: # [board][connector][pin] = (hil_device, port) @@ -124,7 +130,7 @@ def load_connections(self, dut_connections): self.dut_connections[board_name][connector][pin] = hil_port @utils.log_function_start_end - def add_component(self, board, net, mode): + def add_component(self, board, net, mode) -> Component: # If board is a HIL device, net is expected to be port name # If board is a DUT device, net is expected to be a net name from the board if board in self.hil_devices: @@ -140,7 +146,7 @@ def add_component(self, board, net, mode): return self.components[comp_name] @utils.log_function_start_end - def load_hil_devices(self, hil_devices): + def load_hil_devices(self, hil_devices) -> None: self.clear_hil_devices() self.serial_manager.discover_devices() for hil_device in hil_devices: @@ -150,14 +156,14 @@ def load_hil_devices(self, hil_devices): self.handle_error(f"Failed to discover HIL device {hil_device['name']} with id {hil_device['id']}") @utils.log_function_start_end - def get_hil_device(self, name): + def get_hil_device(self, name) -> HilDevice: if name in self.hil_devices: return self.hil_devices[name] else: self.handle_error(f"HIL device {name} not recognized") @utils.log_function_start_end - def get_hil_device_connection(self, board, net): + def get_hil_device_connection(self, board, net) -> tuple[str, str]: """ Converts dut net to hil port name """ if not board in self.dut_connections: self.handle_error(f"No connections to {board} found in configuration.") @@ -175,34 +181,42 @@ def get_hil_device_connection(self, board, net): utils.log_warning(net_cons) self.handle_error(f"Connect dut to {net} on {board}.") - def din(self, board, net): + @utils.log_function_start_end + def din(self, board, net) -> Component: return self.add_component(board, net, 'DI') - - def dout(self, board, net): + @utils.log_function_start_end + def dout(self, board, net) -> Component: return self.add_component(board, net, 'DO') - - def ain(self, board, net): + + @utils.log_function_start_end + def ain(self, board, net) -> Component: return self.add_component(board, net, 'AI') - def aout(self, board, net): + @utils.log_function_start_end + def aout(self, board, net) -> Component: return self.add_component(board, net, 'AO') - def pot(self, board, net): + @utils.log_function_start_end + def pot(self, board, net) -> Component: return self.add_component(board, net, 'POT') - def daq_var(self, board, var_name): + @utils.log_function_start_end + def daq_var(self, board, var_name) -> DAQVariable: try: return utils.signals[utils.b_str][board][f"daq_response_{board.upper()}"][var_name] except KeyError as e: self.handle_error(f"Unable to locate DAQ variable {var_name} of {board}") - def can_var(self, board, message_name, signal_name): + @utils.log_function_start_end + def can_var(self, board, message_name, signal_name) -> str: + # TODO: not sure if the return type is correct try: return utils.signals[utils.b_str][board][message_name][signal_name] except KeyError: self.handle_error(f"Unable to locate CAN signal {signal_name} of message {message_name} of board {board}") - def mcu_pin(self, board, net): + @utils.log_function_start_end + def mcu_pin(self, board, net) -> DAQPin: bank, pin = self.pin_map.get_mcu_pin(board, net) if bank == None: self.handle_error(f"Failed to get mcu pin for {board} net {net}") @@ -233,17 +247,20 @@ def mcu_pin(self, board, net): # def end_test(self): # print(f"{utils.bcolors.OKCYAN}{self.curr_test} failed {self.curr_test_fail_count} out of {self.curr_test_count} checks{utils.bcolors.ENDC}") - def handle_error(self, msg): + @utils.log_function_start_end + def handle_error(self, msg) -> None: utils.log_error(msg) self.shutdown() exit(0) -def signal_int_handler(signum, frame): + +@utils.log_function_start_end +def signal_int_handler(signum, frame) -> None: utils.log("Received signal interrupt, shutting down") if (utils.hilProt): utils.hilProt.shutdown() sys.exit(0) -if __name__ == "__main__": - hil = HIL() - hil.load_config("config_test.json") +# if __name__ == "__main__": +# hil = HIL() +# hil.load_config("config_test.json") From 81347b03b49637e2bf3df6e9580808b96ffb4ac6 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 15 Oct 2024 19:39:52 -0400 Subject: [PATCH 028/181] Type hinting hil.py --- hil/hil.py | 34 +++++++++++++++++----------------- hil/utils.py | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/hil/hil.py b/hil/hil.py index 1286ad0..7a9f44c 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -60,7 +60,7 @@ def init_can(self) -> None: self.can_bus.start() @utils.log_function_start_end - def load_pin_map(self, net_map, pin_map) -> None: + def load_pin_map(self, net_map: str, pin_map: str) -> None: net_map_f = os.path.join(NET_MAP_PATH, net_map) pin_map_f = os.path.join(PIN_MAP_PATH, pin_map) @@ -101,7 +101,7 @@ def stop_can(self) -> None: print(f"{utils.bcolors.OKGREEN}HIL stop_can END{utils.bcolors.ENDC}") @utils.log_function_start_end - def load_config(self, config_name) -> None: + def load_config(self, config_name: str) -> None: config = utils.load_json_config(os.path.join(CONFIG_PATH, config_name), None) # TODO: validate w/ schema # TODO: support joining configs @@ -113,7 +113,7 @@ def load_config(self, config_name) -> None: self.load_connections(config['dut_connections']) @utils.log_function_start_end - def load_connections(self, dut_connections) -> None: + def load_connections(self, dut_connections: dict) -> None: self.dut_connections = {} # Dictionary format: # [board][connector][pin] = (hil_device, port) @@ -130,7 +130,7 @@ def load_connections(self, dut_connections) -> None: self.dut_connections[board_name][connector][pin] = hil_port @utils.log_function_start_end - def add_component(self, board, net, mode) -> Component: + def add_component(self, board: str, net: str, mode: str) -> Component: # If board is a HIL device, net is expected to be port name # If board is a DUT device, net is expected to be a net name from the board if board in self.hil_devices: @@ -146,7 +146,7 @@ def add_component(self, board, net, mode) -> Component: return self.components[comp_name] @utils.log_function_start_end - def load_hil_devices(self, hil_devices) -> None: + def load_hil_devices(self, hil_devices: dict) -> None: self.clear_hil_devices() self.serial_manager.discover_devices() for hil_device in hil_devices: @@ -156,14 +156,14 @@ def load_hil_devices(self, hil_devices) -> None: self.handle_error(f"Failed to discover HIL device {hil_device['name']} with id {hil_device['id']}") @utils.log_function_start_end - def get_hil_device(self, name) -> HilDevice: + def get_hil_device(self, name: str) -> HilDevice: if name in self.hil_devices: return self.hil_devices[name] else: self.handle_error(f"HIL device {name} not recognized") @utils.log_function_start_end - def get_hil_device_connection(self, board, net) -> tuple[str, str]: + def get_hil_device_connection(self, board: str, net: str) -> tuple[str, str]: """ Converts dut net to hil port name """ if not board in self.dut_connections: self.handle_error(f"No connections to {board} found in configuration.") @@ -182,41 +182,41 @@ def get_hil_device_connection(self, board, net) -> tuple[str, str]: self.handle_error(f"Connect dut to {net} on {board}.") @utils.log_function_start_end - def din(self, board, net) -> Component: + def din(self, board: str, net: str) -> Component: return self.add_component(board, net, 'DI') @utils.log_function_start_end - def dout(self, board, net) -> Component: + def dout(self, board: str, net: str) -> Component: return self.add_component(board, net, 'DO') @utils.log_function_start_end - def ain(self, board, net) -> Component: + def ain(self, board: str, net: str) -> Component: return self.add_component(board, net, 'AI') @utils.log_function_start_end - def aout(self, board, net) -> Component: + def aout(self, board: str, net: str) -> Component: return self.add_component(board, net, 'AO') @utils.log_function_start_end - def pot(self, board, net) -> Component: + def pot(self, board: str, net: str) -> Component: return self.add_component(board, net, 'POT') @utils.log_function_start_end - def daq_var(self, board, var_name) -> DAQVariable: + def daq_var(self, board: str, var_name: str) -> DAQVariable: try: return utils.signals[utils.b_str][board][f"daq_response_{board.upper()}"][var_name] except KeyError as e: self.handle_error(f"Unable to locate DAQ variable {var_name} of {board}") @utils.log_function_start_end - def can_var(self, board, message_name, signal_name) -> str: - # TODO: not sure if the return type is correct + def can_var(self, board: str, message_name: str, signal_name: str) -> str: + # TODO: not sure if any of the type hints are correct try: return utils.signals[utils.b_str][board][message_name][signal_name] except KeyError: self.handle_error(f"Unable to locate CAN signal {signal_name} of message {message_name} of board {board}") @utils.log_function_start_end - def mcu_pin(self, board, net) -> DAQPin: + def mcu_pin(self, board: str, net: str) -> DAQPin: bank, pin = self.pin_map.get_mcu_pin(board, net) if bank == None: self.handle_error(f"Failed to get mcu pin for {board} net {net}") @@ -248,7 +248,7 @@ def mcu_pin(self, board, net) -> DAQPin: # print(f"{utils.bcolors.OKCYAN}{self.curr_test} failed {self.curr_test_fail_count} out of {self.curr_test_count} checks{utils.bcolors.ENDC}") @utils.log_function_start_end - def handle_error(self, msg) -> None: + def handle_error(self, msg: str) -> None: utils.log_error(msg) self.shutdown() exit(0) diff --git a/hil/utils.py b/hil/utils.py index feaa0ec..43382fa 100644 --- a/hil/utils.py +++ b/hil/utils.py @@ -87,7 +87,7 @@ def log(phrase): global debug_mode if debug_mode: print(phrase) -def load_json_config(config_path, schema_path=None): +def load_json_config(config_path: str, schema_path=None) -> dict: """ loads config from json and validates with schema """ config = json.load(open(config_path)) if (schema_path == None): return config # Bypass schema check From f060d16d9ade73c674df3cab7231ee28044605a1 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 15 Oct 2024 19:49:20 -0400 Subject: [PATCH 029/181] Type hinting pin_mapper.py --- hil/hil.py | 2 +- hil/pin_mapper.py | 26 +++++++++++++++----------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/hil/hil.py b/hil/hil.py index 7a9f44c..1a6e0cc 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -2,7 +2,7 @@ import os import signal import sys -import time +# import time from pin_mapper import PinMapper from hil_devices.hil_device import HilDevice from hil_devices.serial_manager import SerialManager diff --git a/hil/pin_mapper.py b/hil/pin_mapper.py index 8b61edd..8f80a57 100644 --- a/hil/pin_mapper.py +++ b/hil/pin_mapper.py @@ -10,18 +10,22 @@ class PinMapper(): - def __init__(self, net_map): + def __init__(self, net_map: str): #utils.initGlobals() + + # [board name][net name] = [(component, designator, connector name), ...] + self.net_map: dict[str, dict[str, list[tuple[str, str, str]]]] = {} + self.net_map_fname: str = "" + + # [designator] = (bank, pin) + self.mcu_pin_map: dict[int, tuple[int, int]] = {} + self.mcu_pin_name_fname: str = "" + self.load_net_map(net_map) - self.mcu_pin_map = {} - def load_net_map(self, fname): + def load_net_map(self, fname: str) -> None: self.net_map_fname = fname - self.net_map = {} - # CSV format: - # Board,Net,Component,Designator,Connector Name,, - # Create dictionary as follows - # [board name][net name] = [(component, designator, connector name), ...] + # CSV format: Board,Net,Component,Designator,Connector Name,, with open(self.net_map_fname, mode='r') as f: csv_file = csv.DictReader(f) for row in csv_file: @@ -35,7 +39,7 @@ def load_net_map(self, fname): net_map_board[net] = [] self.net_map[board][net].append(items) - def load_mcu_pin_map(self, fname): + def load_mcu_pin_map(self, fname: str) -> None: self.mcu_pin_name_fname = fname self.mcu_pin_map = {} # CSV format: @@ -52,7 +56,7 @@ def load_mcu_pin_map(self, fname): pin = int(row['Pin Name'][2:]) self.mcu_pin_map[designator] = (bank, pin) - def get_mcu_pin(self, board, net): + def get_mcu_pin(self, board: str, net: str) -> tuple[int, int]: """ Returns first MCU pin found that is connected """ connections = self.get_net_connections(board, net) for connection in connections: @@ -65,7 +69,7 @@ def get_mcu_pin(self, board, net): utils.log_error(f"Net {net} on board {board} is not connected to MCU.") return (None, None) - def get_net_connections(self, board, net): + def get_net_connections(self, board: str, net: str) -> list[tuple[str, str, str]]: """ [(component, designator, connector name), ...] """ if not board in self.net_map: utils.log_error(f"Unrecogniazed board {board}.") From e66dbbb203f69c1dcde0bcfd031e19813f333e7c Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 15 Oct 2024 20:00:18 -0400 Subject: [PATCH 030/181] Type hinting utils --- hil/utils.py | 60 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/hil/utils.py b/hil/utils.py index 43382fa..0f55857 100644 --- a/hil/utils.py +++ b/hil/utils.py @@ -1,10 +1,16 @@ -import json -from jsonschema import validate -from jsonschema.exceptions import ValidationError import sys import time import numpy as np +import json +from jsonschema import validate +from jsonschema.exceptions import ValidationError + +from components.component import Component +from hil.hil import HIL +from communication.daq_protocol import DaqProtocol + + def initGlobals(): global signals signals = {} @@ -13,13 +19,13 @@ def initGlobals(): plot_x_range_sec = 10 global events - events = [] + events: list = [] global b_str - b_str = "Main" + b_str: str = "Main" global data_types - data_types = { + data_types: dict[str, np.dtype] = { 'uint8_t': np.dtype(' None: print(f"{bcolors.FAIL}ERROR: {phrase}{bcolors.ENDC}") -def log_warning(phrase): +def log_warning(phrase: str) -> None: log(f"{bcolors.WARNING}WARNING: {phrase}{bcolors.ENDC}") -def log_success(phrase): +def log_success(phrase: str) -> None: log(f"{bcolors.OKGREEN}{phrase}{bcolors.ENDC}") -def log(phrase): +def log(phrase: str) -> None: global debug_mode if debug_mode: print(phrase) @@ -103,20 +109,20 @@ def load_json_config(config_path: str, schema_path=None) -> dict: return config -def clearDictItems(dictionary:dict): +def clearDictItems(dictionary: dict) -> None: """Recursively calls clear on items in multidimensional dict""" - for key, value in dictionary.items(): + for value in dictionary.values(): if type(value) is dict: clearDictItems(value) else: value.clear() -def clear_term_line(): +def clear_term_line() -> None: sys.stdout.write('\033[F\033[K') #sys.stdout.flush() # Credit: https://stackoverflow.com/questions/1133857/how-accurate-is-pythons-time-sleep/76554895#76554895 -def high_precision_sleep(duration): +def high_precision_sleep(duration: float) -> None: start_time = time.perf_counter() while True: elapsed_time = time.perf_counter() - start_time @@ -130,19 +136,19 @@ def high_precision_sleep(duration): class VoltageDivider(): - def __init__(self, r1, r2): + def __init__(self, r1: float, r2: float): self.r1 = float(r1) self.r2 = float(r2) self.ratio = (self.r2 / (self.r1 + self.r2)) - def div(self, input): + def div(self, input: float) -> float: return input * self.ratio - def reverse(self, output): + def reverse(self, output: float) -> float: return output / self.ratio -def measure_trip_time(trip_sig, timeout, is_falling=False): +def measure_trip_time(trip_sig: Component, timeout: float, is_falling: bool = False) -> float: t_start = time.time() while(trip_sig.state == is_falling): time.sleep(0.015) @@ -154,7 +160,15 @@ def measure_trip_time(trip_sig, timeout, is_falling=False): return t_delt -def measure_trip_thresh(thresh_sig, start, stop, step, period_s, trip_sig, is_falling=False): +def measure_trip_thresh( + thresh_sig: Component, + start: float, + stop: float, + step: float, + period_s: float, + trip_sig: Component, + is_falling: bool = False +) -> float: gain = 1000 thresh = start _start = int(start * gain) From ddc141ecaf13a7382baeda15c73606a3eef55afb Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 15 Oct 2024 20:03:11 -0400 Subject: [PATCH 031/181] Trying to improve imports? Makes the errors go away in VSCode, but there was probably a reason it was the way it was :shrug: --- scripts/config_dash.py | 4 ++-- scripts/test_abox.py | 4 ++-- scripts/test_charger.py | 5 ++--- scripts/test_collector.py | 4 ++-- scripts/test_main_base.py | 4 ++-- scripts/test_main_sdc.py | 4 ++-- scripts/test_system.py | 4 ++-- scripts/test_test.py | 4 ++-- scripts/vehicle_constants.py | 2 +- 9 files changed, 17 insertions(+), 18 deletions(-) diff --git a/scripts/config_dash.py b/scripts/config_dash.py index 37448f0..2aeb330 100644 --- a/scripts/config_dash.py +++ b/scripts/config_dash.py @@ -1,7 +1,7 @@ from os import sys, path sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) -from hil import HIL -import utils +from hil.hil import HIL +import hil.utils as utils import time from rules_constants import * from vehicle_constants import * diff --git a/scripts/test_abox.py b/scripts/test_abox.py index 18d5fe9..55b4483 100644 --- a/scripts/test_abox.py +++ b/scripts/test_abox.py @@ -1,7 +1,7 @@ from os import sys, path sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) -from hil import HIL -import utils +from hil.hil import HIL +import hil.utils as utils import time from rules_constants import * from vehicle_constants import * diff --git a/scripts/test_charger.py b/scripts/test_charger.py index 8dea486..651661e 100644 --- a/scripts/test_charger.py +++ b/scripts/test_charger.py @@ -1,9 +1,8 @@ from os import sys, path sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) -from hil import HIL -# import hil.utils as utils -import utils +from hil.hil import HIL +import hil.utils as utils import time from rules_constants import * from vehicle_constants import * diff --git a/scripts/test_collector.py b/scripts/test_collector.py index 382f977..02df12a 100644 --- a/scripts/test_collector.py +++ b/scripts/test_collector.py @@ -1,7 +1,7 @@ from os import sys, path sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) -from hil import HIL -import utils +from hil.hil import HIL +import hil.utils as utils import time import pytest_check as check diff --git a/scripts/test_main_base.py b/scripts/test_main_base.py index c553f4a..cf9f794 100644 --- a/scripts/test_main_base.py +++ b/scripts/test_main_base.py @@ -1,7 +1,7 @@ from os import sys, path sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) -from hil import HIL -import utils +from hil.hil import HIL +import hil.utils as utils import time from rules_constants import * from vehicle_constants import * diff --git a/scripts/test_main_sdc.py b/scripts/test_main_sdc.py index 119d7a1..75d4602 100644 --- a/scripts/test_main_sdc.py +++ b/scripts/test_main_sdc.py @@ -1,7 +1,7 @@ from os import sys, path sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) -from hil import HIL -import utils +from hil.hil import HIL +import hil.utils as utils import time from rules_constants import * from vehicle_constants import * diff --git a/scripts/test_system.py b/scripts/test_system.py index 967f915..8725cf2 100644 --- a/scripts/test_system.py +++ b/scripts/test_system.py @@ -1,7 +1,7 @@ from os import sys, path sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) -from hil import HIL -import utils +from hil.hil import HIL +import hil.utils as utils import time from rules_constants import * from vehicle_constants import * diff --git a/scripts/test_test.py b/scripts/test_test.py index 836a1e9..6429464 100644 --- a/scripts/test_test.py +++ b/scripts/test_test.py @@ -1,7 +1,7 @@ from os import sys, path sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) -from hil import HIL -import utils +from hil.hil import HIL +# import hil.utils as utils import time import can from rules_constants import * diff --git a/scripts/vehicle_constants.py b/scripts/vehicle_constants.py index 35a4050..0340fe9 100644 --- a/scripts/vehicle_constants.py +++ b/scripts/vehicle_constants.py @@ -1,6 +1,6 @@ from os import sys, path sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) -import utils +import hil.utils as utils # NOTE: each value in this file should be a physical or electrical property of the vehicle From 32a235521676aa7cfe0fd479fb8ce9051f0d397d Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 15 Oct 2024 20:22:49 -0400 Subject: [PATCH 032/181] Type hinting component.py --- hil/components/component.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/hil/components/component.py b/hil/components/component.py index b690171..f3b1ffd 100644 --- a/hil/components/component.py +++ b/hil/components/component.py @@ -1,4 +1,6 @@ +from collections.abc import Callable import utils +from hil.hil import HIL class Component(): """ @@ -7,15 +9,15 @@ class Component(): When in measurement or emulation, a source must be specified. """ - def __init__(self, name, hil_con, mode, hil): - self.name = name + def __init__(self, name: str, hil_con: tuple[str, str], mode: str, hil: HIL): + self.name: str = name self._state = 0 - self.inv_meas = False - self.inv_emul = False - self.read_func = None - self.write_func = None - self.hiZ_func = None + self.inv_meas: bool = False + self.inv_emul: bool = False + self.read_func: Callable[[], int] = None + self.write_func: Callable[[int], None] = None + self.hiZ_func: Callable[[], None] = None # TODO: allow both measure and emulation source @@ -89,7 +91,7 @@ def __init__(self, name, hil_con, mode, hil): self.hil = hil @property - def state(self): + def state(self) -> int: if self.read_func: self._state = self.read_func() elif self.write_func == None: @@ -97,7 +99,7 @@ def state(self): return self._state @state.setter - def state(self, s): + def state(self, s: int) -> None: if self.read_func == None: self._state = s if self.write_func: @@ -105,13 +107,13 @@ def state(self, s): else: utils.log_warning(f"Wrote to {self.name}, but no emulation source was found") - def hiZ(self): + def hiZ(self) -> None: if (self.hiZ_func): self.hiZ_func() else: utils.log_warning(f"hiZ is not supported for {self.name}") - def shutdown(self): + def shutdown(self) -> None: if (self.hiZ_func): self.hiZ_func() elif self.write_func: From c462c52f2614daee7d5a53aa46a726498920e320 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 15 Oct 2024 20:30:44 -0400 Subject: [PATCH 033/181] Type hinting hil_device.py --- hil/hil_devices/hil_device.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/hil/hil_devices/hil_device.py b/hil/hil_devices/hil_device.py index 52c91b2..e32348c 100644 --- a/hil/hil_devices/hil_device.py +++ b/hil/hil_devices/hil_device.py @@ -1,7 +1,9 @@ import os -import time -import serial +# import time +# import serial import serial.tools.list_ports +from hil_devices.serial_manager import SerialManager + import utils HIL_CMD_MASK = 0xFF @@ -17,12 +19,11 @@ HIL_DEVICES_PATH = "../hil/hil_devices" class HilDevice(): - - def __init__(self, name, type, id, serial_manager): - self.name = name - self.type = type - self.id = id - self.sm = serial_manager + def __init__(self, name: str, type: str, id: int, serial_manager: SerialManager): + self.name: str = name + self.type: str = type + self.id: int = id + self.sm: SerialManager = serial_manager self.config = utils.load_json_config(os.path.join(HIL_DEVICES_PATH, f"hil_device_{self.type}.json"), None) # TODO: validate w/ schema @@ -61,7 +62,7 @@ def __init__(self, name, type, id, serial_manager): if "pot_config" in self.config: self.pot_max = pow(2, self.config['pot_config']['bit_resolution']) - 1 - def get_port_number(self, port_name, mode): + def get_port_number(self, port_name: str, mode: str) -> int: for p in self.config['ports']: if port_name == p['name']: if mode in p['capabilities']: @@ -75,17 +76,17 @@ def get_port_number(self, port_name, mode): utils.log_error(f"Port {port_name} not found for hil device {self.name}") return -1 - def write_gpio(self, pin, value): + def write_gpio(self, pin: int, value: int) -> None: data = [(HIL_CMD_WRITE_GPIO & HIL_CMD_MASK), (pin & HIL_ID_MASK), value] self.sm.send_data(self.id, data) - def write_dac(self, pin, value): + def write_dac(self, pin: int, value: int) -> None: value = min(self.dac_max, max(0, int(value * self.volts_to_dac))) data = [(HIL_CMD_WRITE_DAC & HIL_CMD_MASK), (pin & HIL_ID_MASK), value] # print(f"write pin {pin} to {value}") self.sm.send_data(self.id, data) - def read_gpio(self, pin): + def read_gpio(self, pin: int) -> int: data = [(HIL_CMD_READ_GPIO & HIL_CMD_MASK), (pin & HIL_ID_MASK), 0] self.sm.send_data(self.id, data) d = self.sm.read_data(self.id, 1) @@ -94,7 +95,7 @@ def read_gpio(self, pin): if (d <= 1): return d utils.log_error(f"Failed to read gpio pin {pin} on {self.name}") - def read_analog(self, pin): + def read_analog(self, pin: int) -> float: data = [(HIL_CMD_READ_ADC & HIL_CMD_MASK), (pin & HIL_ID_MASK), 0] self.sm.send_data(self.id, data) d = self.sm.read_data(self.id, 2) @@ -104,7 +105,7 @@ def read_analog(self, pin): utils.log_error(f"Failed to read adc pin {pin} on {self.name}") return 0 - def write_pot(self, pin, value): + def write_pot(self, pin: int, value: float) -> None: value = min(self.pot_max, max(0, int(value * self.pot_max))) data = [(HIL_CMD_WRITE_POT & HIL_CMD_MASK), (pin & HIL_ID_MASK), value] #print(f"sending {value} to pin {pin}") From 526fca1b261bff2df0a1d0eb598e1404295cc307 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Thu, 17 Oct 2024 13:53:01 -0400 Subject: [PATCH 034/181] Type hinting serial_manager.py --- hil/hil_devices/serial_manager.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hil/hil_devices/serial_manager.py b/hil/hil_devices/serial_manager.py index 0f0dc54..97db15c 100644 --- a/hil/hil_devices/serial_manager.py +++ b/hil/hil_devices/serial_manager.py @@ -6,9 +6,9 @@ class SerialManager(): """ Manages hil device discovery and communication """ def __init__(self): - self.devices = {} + self.devices: dict[int, serial.Serial] = {} - def discover_devices(self): + def discover_devices(self) -> None: #print([a[1] for a in serial.tools.list_ports.comports()]) ports = [a[0] for a in serial.tools.list_ports.comports() if ("Arduino" in a[1] or "USB Serial Device" in a[1])] self.devices = {} @@ -39,15 +39,15 @@ def discover_devices(self): ard.close() print('Tester ids: ' + str(list(self.devices.keys()))) - def port_exists(self, id): + def port_exists(self, id: int) -> bool: return id in self.devices - def send_data(self, id, data): + def send_data(self, id: int, data: list[int]) -> None: self.devices[id].write(data) - def read_data(self, id, length): + def read_data(self, id: int, length: int) -> bytes: return self.devices[id].read(length) - def close_devices(self): + def close_devices(self) -> None: for d in self.devices.values(): d.close() From 446a48ad0b530a8991c32e791174495f69ee2762 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Thu, 17 Oct 2024 13:56:47 -0400 Subject: [PATCH 035/181] Adding list of file which need to be type hinted --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..8afbc6d --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# Branch TODO +## Type hinting +- [x] `./hil/components/component.py` +- [ ] `./hil/communication/can_bus.py` +- [ ] `./hil/communication/client.py` +- [ ] `./hil/communication/daq_protocol.py` +- [x] `./hil/hil_devices/serial_manager.py` +- [x] `./hil/hil_devices/hil_device.py` +- [x] `./hil/hil.py` +- [x] `./hil/utils.py` +- [x] `./hil/pin_mapper.py` From 265f568e127b6bb9a4cb014d50aab35b0218e030 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Thu, 17 Oct 2024 14:12:21 -0400 Subject: [PATCH 036/181] Commenting out unused imports --- hil/communication/can_bus.py | 4 ++-- hil/hil_devices/hil_device.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hil/communication/can_bus.py b/hil/communication/can_bus.py index f16b6fc..30dbedf 100644 --- a/hil/communication/can_bus.py +++ b/hil/communication/can_bus.py @@ -9,8 +9,8 @@ import utils import time import threading -import numpy as np -import math +# import numpy as np +# import math CAN_READ_TIMEOUT_S = 1.0 diff --git a/hil/hil_devices/hil_device.py b/hil/hil_devices/hil_device.py index e32348c..9949a8c 100644 --- a/hil/hil_devices/hil_device.py +++ b/hil/hil_devices/hil_device.py @@ -1,7 +1,7 @@ import os # import time # import serial -import serial.tools.list_ports +# import serial.tools.list_ports from hil_devices.serial_manager import SerialManager import utils From 17d9d50313b8d0cb496685a64e657317864af58c Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 19 Oct 2024 11:21:23 -0400 Subject: [PATCH 037/181] Almost done type hinting client.py missing types on queue items --- hil/communication/client.py | 85 +++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 37 deletions(-) diff --git a/hil/communication/client.py b/hil/communication/client.py index ba643d5..cb64666 100644 --- a/hil/communication/client.py +++ b/hil/communication/client.py @@ -12,6 +12,8 @@ # https://github.com/teebr/socketsocketcan # switched raspi to be the server instead of a client + +# ---------------------------------------------------------------------------- # class TCPBus(can.BusABC): RECV_FRAME_SZ = 29 @@ -19,30 +21,30 @@ class TCPBus(can.BusABC): CAN_RTR_FLAG = 0x40000000 CAN_ERR_FLAG = 0x20000000 - def __init__(self, ip, port,can_filters=None,**kwargs): - super().__init__("whatever",can_filters) - self.port = port - self._is_connected = False - self.recv_buffer = Queue() - self.send_buffer = Queue() - self._shutdown_flag = False#Queue() + def __init__(self, ip: str, port: int, can_filters: can.typechecking.CanFilters | None = None,**kwargs): + super().__init__("whatever", can_filters) + self.port: int = port + self._is_connected: bool = False + self.recv_buffer: Queue = Queue() + self.send_buffer: Queue = Queue() + self._shutdown_flag: bool = False#Queue() print(f"IP: {ip}, port: {port}") #open socket and wait for connection to establish. socket.setdefaulttimeout(3) # seconds utils.log("attempting to connect to tcp") - self._conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) + self._conn: socket.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) utils.log("Connecting...") self._conn.connect((ip, port)) utils.log("connected") - self._is_connected = True + self._is_connected: bool = True self._conn.settimeout(0.5) #blocking makes exiting an infinite loop hard self.start_threads() - def start_threads(self): + def start_threads(self) -> bool: # self._conn.sendall(password.encode()) # data_raw = self._conn.recv(1) # data = int.from_bytes(data_raw,"little") @@ -61,7 +63,7 @@ def start_threads(self): self.send_time_sync() return True - def send_time_sync(self): + def send_time_sync(self) -> None: # Sends the current time to update RTC self.send_buffer.put(4) t = datetime.datetime.now() @@ -69,14 +71,15 @@ def send_time_sync(self): t.day, t.month, (t.year-2000), 0, 0]) self.send_buffer.put(v) - def _recv_internal(self,timeout=None): + def _recv_internal(self,timeout: float | None = None) -> tuple[can.Message | None, bool]: #TODO: filtering try: return (self.recv_buffer.get(timeout=timeout), True) except queue.Empty: return None, True - def send(self,msg): + def send(self, msg): + # TODO: type hint! if msg.is_extended_id: msg.arbitration_id |= self.CAN_EFF_FLAG if msg.is_remote_frame: @@ -86,21 +89,21 @@ def send(self,msg): self.send_buffer.put(0) self.send_buffer.put(msg) - def start_logging(self): + def start_logging(self) -> None: self.send_buffer.put(1) self.send_buffer.put(0xFFFFFFFF) - def stop_logging(self): + def stop_logging(self) -> None: self.send_buffer.put(3) self.send_buffer.put(0xFFFFFFFF) - def _stop_threads(self): + def _stop_threads(self) -> None: #self._shutdown_flag.put(True) self._shutdown_flag = True self._is_connected = False utils.log_warning("Bus Client Shutdown (TCP)") - def shutdown(self, handshake): + def shutdown(self, handshake: int) -> None: """gracefully close TCP connection and exit threads""" #handshake: 0: Currently in handshake mode, 1: In regular send mode if handshake == 0: @@ -116,15 +119,16 @@ def shutdown(self, handshake): sleep(0.005) self._conn.close() #shutdown might be faster but can be ugly and raise an exception - def close(self): + def close(self) -> None: self._conn.close() @property - def is_connected(self): + def is_connected(self) -> bool: """check that a TCP connection is active""" return self._is_connected - def _msg_to_bytes(self,msg): + def _msg_to_bytes(self, msg): + # TODO: type hint! """convert Message object to bytes to be put on TCP socket""" # print(msg) arb_id = msg.arbitration_id.to_bytes(4,"little") #TODO: masks @@ -133,7 +137,7 @@ def _msg_to_bytes(self,msg): # print(arb_id + dlc + data) return arb_id+dlc+data - def _bytes_to_message(self,b): + def _bytes_to_message(self, b: bytes) -> can.Message: """convert raw TCP bytes to can.Message object""" #ts = int.from_bytes(b[:4],"little") + int.from_bytes(b[4:8],"little")/1e6 ts = int.from_bytes(b[:8],"little") + int.from_bytes(b[8:16],"little")/1e6 @@ -160,7 +164,7 @@ def _bytes_to_message(self,b): data=b[21:21+dlc] ) - def _poll_socket(self): + def _poll_socket(self) -> None: """background thread to check for new CAN messages on the TCP socket""" part_formed_message = bytearray() # TCP transfer might off part way through sending a message #with self._conn as conn: @@ -204,7 +208,7 @@ def _poll_socket(self): break # utils.log("Exited poll socket") - def _poll_send(self): + def _poll_send(self) -> None: """background thread to send messages when they are put in the queue""" #with self._conn as s: s = self._conn @@ -234,6 +238,10 @@ def _poll_send(self): except QueueEmpty: pass #NBD, just means nothing to send. # utils.log("Exited poll send") +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # class UDPBus(can.BusABC): #RECV_FRAME_SZ = 29 RECV_FRAME_SZ = 18 @@ -241,28 +249,28 @@ class UDPBus(can.BusABC): CAN_RTR_FLAG = 0x40000000 CAN_ERR_FLAG = 0x20000000 - def __init__(self, ip, port,can_filters=None,**kwargs): + def __init__(self, ip: str, port: int, can_filters: can.typechecking.CanFilters | None = None, **kwargs): super().__init__("whatever",can_filters) - self.port = port - self._is_connected = False - self.recv_buffer = Queue() - self._shutdown_flag = False#Queue() + self.port: int = port + self._is_connected: bool = False + self.recv_buffer: Queue = Queue() + self._shutdown_flag: bool = False#Queue() #open socket and wait for connection to establish. socket.setdefaulttimeout(3) # seconds utils.log("attempting to connect to udp") - self._conn = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + self._conn: socket.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) self._conn.bind(("", 5005)) utils.log("Listening to UDP Port") - self._is_connected = True + self._is_connected: bool = True self._conn.settimeout(0.5) #blocking makes exiting an infinite loop hard #now we're connected, kick off other threads. - self._udp_listener = Thread(target=self._poll_udp_socket) + self._udp_listener: Thread = Thread(target=self._poll_udp_socket) self._udp_listener.start() - def _bytes_to_message(self,b): + def _bytes_to_message(self, b: bytes) -> can.Message: """convert raw TCP bytes to can.Message object""" #ts = int.from_bytes(b[:4],"little") + int.from_bytes(b[4:8],"little")/ e6 # ts = int.from_bytes(b[:8],"little") + int.from_bytes(b[8:16],"little")/1e6 @@ -294,7 +302,9 @@ def _bytes_to_message(self,b): #data=b[21:21+dlc] data=b[10:10+dlc] ) - def send(self,msg): + + def send(self, msg): + # TODO: type hint! if msg.is_extended_id: msg.arbitration_id |= self.CAN_EFF_FLAG if msg.is_remote_frame: @@ -303,14 +313,14 @@ def send(self,msg): msg.arbitration_id |= self.CAN_ERR_FLAG self.send_buffer.put(msg) - def _recv_internal(self,timeout=None): + def _recv_internal(self, timeout: float | None = None) -> tuple[can.Message | None, bool]: #TODO: filtering try: return (self.recv_buffer.get(timeout=timeout), True) except queue.Empty: return None, True - def _poll_udp_socket(self): + def _poll_udp_socket(self) -> None: """background thread to check for new CAN messages on the UDP socket""" part_formed_message = bytearray() # UDP transfer might off part way through sending a message conn = self._conn @@ -352,13 +362,13 @@ def _poll_udp_socket(self): self._stop_threads() break - def _stop_threads(self): + def _stop_threads(self) -> None: #self._shutdown_flag.put(True) self._shutdown_flag = True self._is_connected = False utils.log_warning("Bus Client Shutdown (UDP)") - def shutdown(self): + def shutdown(self) -> None: """gracefully close UDP connection and exit threads""" if self._is_connected: self._stop_threads() @@ -366,3 +376,4 @@ def shutdown(self): while self._udp_listener.is_alive(): sleep(0.005) self._conn.close() #shutdown might be faster but can be ugly and raise an exception +# ---------------------------------------------------------------------------- # \ No newline at end of file From 6b5d37b8ce4d19ffa68263fbec831120026005dd Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 19 Oct 2024 11:24:01 -0400 Subject: [PATCH 038/181] Finishing type hints for client.py Added type hints send/msg types --- hil/communication/client.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/hil/communication/client.py b/hil/communication/client.py index cb64666..8677d19 100644 --- a/hil/communication/client.py +++ b/hil/communication/client.py @@ -25,8 +25,8 @@ def __init__(self, ip: str, port: int, can_filters: can.typechecking.CanFilters super().__init__("whatever", can_filters) self.port: int = port self._is_connected: bool = False - self.recv_buffer: Queue = Queue() - self.send_buffer: Queue = Queue() + self.recv_buffer: Queue = Queue() # Queue[can.Message] + self.send_buffer: Queue = Queue() # Queue[can.Message] self._shutdown_flag: bool = False#Queue() print(f"IP: {ip}, port: {port}") @@ -78,8 +78,7 @@ def _recv_internal(self,timeout: float | None = None) -> tuple[can.Message | Non except queue.Empty: return None, True - def send(self, msg): - # TODO: type hint! + def send(self, msg: can.Message) -> None: if msg.is_extended_id: msg.arbitration_id |= self.CAN_EFF_FLAG if msg.is_remote_frame: @@ -127,8 +126,7 @@ def is_connected(self) -> bool: """check that a TCP connection is active""" return self._is_connected - def _msg_to_bytes(self, msg): - # TODO: type hint! + def _msg_to_bytes(self, msg: can.Message) -> bytes: """convert Message object to bytes to be put on TCP socket""" # print(msg) arb_id = msg.arbitration_id.to_bytes(4,"little") #TODO: masks @@ -303,8 +301,7 @@ def _bytes_to_message(self, b: bytes) -> can.Message: data=b[10:10+dlc] ) - def send(self, msg): - # TODO: type hint! + def send(self, msg: can.Message) -> None: if msg.is_extended_id: msg.arbitration_id |= self.CAN_EFF_FLAG if msg.is_remote_frame: From d5a93b67382810cb6de94f50f228090050f0821b Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 19 Oct 2024 11:24:13 -0400 Subject: [PATCH 039/181] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8afbc6d..fb73214 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## Type hinting - [x] `./hil/components/component.py` - [ ] `./hil/communication/can_bus.py` -- [ ] `./hil/communication/client.py` +- [x] `./hil/communication/client.py` - [ ] `./hil/communication/daq_protocol.py` - [x] `./hil/hil_devices/serial_manager.py` - [x] `./hil/hil_devices/hil_device.py` From ddc7f7ecbdcb14ce907951a4bfb2cc83740f28c0 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 19 Oct 2024 12:08:42 -0400 Subject: [PATCH 040/181] Almost done type hinting can_bus.py --- hil/communication/can_bus.py | 131 +++++++++++++++++++++-------------- 1 file changed, 79 insertions(+), 52 deletions(-) diff --git a/hil/communication/can_bus.py b/hil/communication/can_bus.py index 30dbedf..dd1aa81 100644 --- a/hil/communication/can_bus.py +++ b/hil/communication/can_bus.py @@ -1,3 +1,5 @@ +from collections.abc import Callable +from __future__ import annotations from datetime import datetime import can import can.interfaces.gs_usb @@ -9,53 +11,55 @@ import utils import time import threading -# import numpy as np +import numpy as np # import math CAN_READ_TIMEOUT_S = 1.0 +# ---------------------------------------------------------------------------- # class CanBus(threading.Thread): """ Handles sending and receiving can bus messages, tracks all degined signals (BusSignal) """ - def __init__(self, dbc_path, default_ip, can_config: dict): + def __init__(self, dbc_path: str, default_ip: str, can_config: dict): super(CanBus, self).__init__() - self.db = cantools.db.load_file(dbc_path) + self.db = cantools.db.load_file(dbc_path) # TODO: type hint utils.log(f"CAN version: {can.__version__}") utils.log(f"gs_usb version: {gs_usb.__version__}") - self.connected = False - self.bus = None - self.start_time_bus = -1 - self.start_date_time_str = "" - self.tcp = False - self.tcpbus = None + self.connected: bool = False + self.bus: can.ThreadSafeBus | UDPBus = None + self.start_time_bus: float = -1 + self.start_date_time_str: str = "" + self.tcp: bool = False + self.tcpbus: TCPBus = None - self.handle_daq_msg = None + self.handle_daq_msg: Callable[[can.Message], None] = None # Bus Load Estimation - self.total_bits = 0 - self.last_estimate_time = 0 + self.total_bits: int = 0 + self.last_estimate_time: float = 0 # Load Bus Signals - self.can_config = can_config + self.can_config: dict = can_config self.updateSignals(self.can_config) - self.is_importing = False + self.is_importing: bool = False #self.port = 8080 - self.port = 5005 - self.ip = default_ip #self.ip = "10.42.0.1" - self.password = None - self.is_wireless = False + self.port: int = 5005 + self.ip: str = default_ip + + self.password: str | None = None + self.is_wireless: bool = False - def connect(self): + def connect(self) -> None: """ Connects to the bus """ utils.log("Trying usb") # Attempt usb connection first @@ -117,7 +121,7 @@ def connect(self): # self.connect_sig.emit(self.connected) self.connectError() - def connect_tcp(self): + def connect_tcp(self) -> None: # Usb failed, trying tcp utils.log("Trying tcp") self.connected_disp = 1 @@ -180,7 +184,7 @@ def connect_tcp(self): - def disconnect_bus(self): + def disconnect_bus(self) -> None: self.connected = False # self.connect_sig.emit(self.connected) if self.tcpbus: @@ -191,7 +195,7 @@ def disconnect_bus(self): del(self.bus) self.bus = None - def disconnect_tcp(self): + def disconnect_tcp(self) -> None: self.connected_disp = 0 # self.write_sig.emit(self.connected_disp) if self.tcpbus: @@ -200,7 +204,7 @@ def disconnect_tcp(self): self.tcpbus = None - def reconnect(self): + def reconnect(self) -> None: """ destroy usb connection, attempt to reconnect """ self.connected = False # while(not self.isFinished()): @@ -216,14 +220,15 @@ def reconnect(self): self.start_date_time_str = datetime.now().strftime("%m-%d-%Y %H:%M:%S") self.start() - def sendLogCmd(self, option : bool): + def sendLogCmd(self, option: bool) -> None: """Send the start logging function""" if option == True: self.tcpbus.start_logging() else: self.tcpbus.stop_logging() - def sendFormatMsg(self, msg_name, msg_data: dict): + def sendFormatMsg(self, msg_name, msg_data: dict) -> None: + # TODO: type hint """ Sends a message using a dictionary of its data """ dbc_msg = self.db.get_message_by_name(msg_name) data = dbc_msg.encode(msg_data) @@ -233,7 +238,7 @@ def sendFormatMsg(self, msg_name, msg_data: dict): if self.tcp: self.tcpbus.send(msg) - def sendMsg(self, msg: can.Message): + def sendMsg(self, msg: can.Message) -> None: """ Sends a can message over the bus """ if self.connected: if not self.is_wireless: @@ -247,7 +252,7 @@ def sendMsg(self, msg: can.Message): else: utils.log_error("Tried to send msg without connection") - def onMessageReceived(self, msg: can.Message): + def onMessageReceived(self, msg: can.Message) -> None: """ Emits new message signal and updates the corresponding signals """ if self.start_time_bus == -1: self.start_time_bus = msg.timestamp @@ -286,7 +291,7 @@ def onMessageReceived(self, msg: can.Message): msg_bit_length_max = 64 + msg.dlc * 8 + 18 self.total_bits += msg_bit_length_max - def connectError(self): + def connectError(self) -> None: """ Creates message box prompting to try to reconnect """ # self.ip = ConnectionErrorDialog.connectionError(self.ip) utils.log_error("Ip wrong") @@ -294,7 +299,7 @@ def connectError(self): # self.connect_tcp() - def updateSignals(self, can_config: dict): + def updateSignals(self, can_config: dict) -> None: """ Creates dictionary of BusSignals of all signals in can_config """ utils.signals.clear() for bus in can_config['busses']: @@ -308,7 +313,7 @@ def updateSignals(self, can_config: dict): [msg['msg_name']][signal['sig_name']]\ = BusSignal.fromCANMsg(signal, msg, node, bus) - def run(self): + def run(self) -> None: """ Thread loop to receive can messages """ self.last_estimate_time = time.time() loop_count = 0 @@ -341,8 +346,10 @@ def run(self): skips = 0 #self.connect_sig.emit(self.connected and self.bus.is_connected) # if (self.connected and self.is_wireless): self.connect_sig.emit(self.bus and self.bus.is_connected) +# ---------------------------------------------------------------------------- # +# ---------------------------------------------------------------------------- # class BusSignal(): """ Signal that can be subscribed (connected) to for updates """ @@ -353,61 +360,80 @@ class BusSignal(): # NOTE: don't need lock for now as long as only one writer # However, when timestamp and data are read, it is possible an older timestamp is read for newer data - def __init__(self, bus_name, node_name, msg_name, sig_name, dtype, store_dtype=None, unit="", msg_desc="", sig_desc="", msg_period=0): - self.bus_name = bus_name - self.node_name = node_name - self.message_name = msg_name - self.signal_name = sig_name - self.name = '.'.join([self.bus_name, self.node_name, self.message_name, self.signal_name]) - - self.unit = unit - self.msg_desc = msg_desc - self.sig_desc = sig_desc + def __init__( + self, + bus_name: str, + node_name: str, + msg_name: str, + sig_name: str, + dtype: np.dtype, + store_dtype: np.dtype | None = None, + unit: str = "", + msg_desc: str = "", + sig_desc: str = "", + msg_period = 0 + ): + self.bus_name: str = bus_name + self.node_name: str = node_name + self.message_name: str = msg_name + self.signal_name: str = sig_name + self.name: str = '.'.join([self.bus_name, self.node_name, self.message_name, self.signal_name]) + + self.unit: str = unit + self.msg_desc: str = msg_desc + self.sig_desc: str = sig_desc self.msg_period = msg_period - self.send_dtype = dtype - if not store_dtype: self.store_dtype = self.send_dtype - else: self.store_dtype = store_dtype - self.data = 0 - self.time = 0 - self.stale_timestamp = time.time() - def fromCANMsg(sig, msg, node, bus): + self.send_dtype: np.dtype = dtype + if not store_dtype: + self.store_dtype: np.dtype = self.send_dtype + else: + self.store_dtype: np.dtype = store_dtype + + self.data = 0 # TODO: type hint + self.time: float = 0 + self.stale_timestamp: float = time.time() + + @classmethod + def fromCANMsg(cls, sig: dict, msg: dict, node: dict, bus: dict) -> BusSignal: send_dtype = utils.data_types[sig['type']] # If there is scaling going on, don't store as an integer on accident if ('scale' in sig and sig['scale'] != 1) or ('offset' in sig and sig['offset'] != 0): parse_dtype = utils.data_types['float'] else: parse_dtype = send_dtype - return BusSignal(bus['bus_name'], node['node_name'], msg['msg_name'], sig['sig_name'], + return cls(bus['bus_name'], node['node_name'], msg['msg_name'], sig['sig_name'], send_dtype, store_dtype=parse_dtype, unit=(sig['unit'] if 'unit' in sig else ""), msg_desc=(msg['msg_desc'] if 'msg_desc' in msg else ""), sig_desc=(sig['sig_desc'] if 'sig_desc' in sig else ""), msg_period=msg['msg_period']) - def update(self, val, timestamp): + def update(self, val, timestamp: float) -> None: + # TODO: type hint """ update the value of the signal """ self.data = val self.time = timestamp self.stale_timestamp = time.time() - def clear(self): + def clear(self) -> None: """ clears stored signal values """ self.data = 0 self.time = 0 @property def curr_val(self): + # TODO: type hint """ last value recorded """ return self.data @property - def last_update_time(self): + def last_update_time(self) -> float: """ timestamp of last value recorded """ return self.time @property - def is_stale(self): + def is_stale(self) -> bool: """ based on last receive time """ if self.msg_period == 0: return False else: @@ -415,6 +441,7 @@ def is_stale(self): @property def state(self): + # TODO: type hint start_t = time.time() while (self.is_stale): if (time.time() >= start_t + CAN_READ_TIMEOUT_S): From 2eb6c0cbcdf0fa9341381268345cad293b4b0ffe Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 22 Oct 2024 19:12:18 -0400 Subject: [PATCH 041/181] Finishing type hinting can_bus.py (I think) --- hil/communication/can_bus.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/hil/communication/can_bus.py b/hil/communication/can_bus.py index dd1aa81..3eefad6 100644 --- a/hil/communication/can_bus.py +++ b/hil/communication/can_bus.py @@ -26,7 +26,7 @@ class CanBus(threading.Thread): def __init__(self, dbc_path: str, default_ip: str, can_config: dict): super(CanBus, self).__init__() - self.db = cantools.db.load_file(dbc_path) # TODO: type hint + self.db: cantools.database.can.database.Database = cantools.db.load_file(dbc_path) utils.log(f"CAN version: {can.__version__}") utils.log(f"gs_usb version: {gs_usb.__version__}") @@ -182,8 +182,6 @@ def connect_tcp(self) -> None: self.connected_disp = 0 # self.write_sig.emit(self.connected_disp) - - def disconnect_bus(self) -> None: self.connected = False # self.connect_sig.emit(self.connected) @@ -227,8 +225,8 @@ def sendLogCmd(self, option: bool) -> None: else: self.tcpbus.stop_logging() - def sendFormatMsg(self, msg_name, msg_data: dict) -> None: - # TODO: type hint + def sendFormatMsg(self, msg_name: str, msg_data: dict) -> None: + # TODO: not sure if the type hints are correct """ Sends a message using a dictionary of its data """ dbc_msg = self.db.get_message_by_name(msg_name) data = dbc_msg.encode(msg_data) @@ -390,7 +388,7 @@ def __init__( else: self.store_dtype: np.dtype = store_dtype - self.data = 0 # TODO: type hint + self.data: int = 0 # TODO: n self.time: float = 0 self.stale_timestamp: float = time.time() @@ -409,8 +407,8 @@ def fromCANMsg(cls, sig: dict, msg: dict, node: dict, bus: dict) -> BusSignal: sig_desc=(sig['sig_desc'] if 'sig_desc' in sig else ""), msg_period=msg['msg_period']) - def update(self, val, timestamp: float) -> None: - # TODO: type hint + def update(self, val: int, timestamp: float) -> None: + # TODO: not sure if the type hints are correct """ update the value of the signal """ self.data = val self.time = timestamp @@ -422,8 +420,8 @@ def clear(self) -> None: self.time = 0 @property - def curr_val(self): - # TODO: type hint + def curr_val(self) -> int: + # TODO: not sure if the type hints are correct """ last value recorded """ return self.data @@ -440,8 +438,8 @@ def is_stale(self) -> bool: return ((time.time() - self.stale_timestamp) * 1000) > self.msg_period * 1.5 @property - def state(self): - # TODO: type hint + def state(self) -> int: + # TODO: not sure if the type hints are correct start_t = time.time() while (self.is_stale): if (time.time() >= start_t + CAN_READ_TIMEOUT_S): From f86be0a8e1d0d401e7e570c15e31fd7431727781 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 22 Oct 2024 19:12:51 -0400 Subject: [PATCH 042/181] Updating list of completed files --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fb73214..3593226 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Branch TODO ## Type hinting - [x] `./hil/components/component.py` -- [ ] `./hil/communication/can_bus.py` +- [x] `./hil/communication/can_bus.py` - [x] `./hil/communication/client.py` - [ ] `./hil/communication/daq_protocol.py` - [x] `./hil/hil_devices/serial_manager.py` From 658c0a7562171a006d1dae027ba914a9070a2d4e Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 22 Oct 2024 19:29:13 -0400 Subject: [PATCH 043/181] Type hinting daq_protocal.py -> DAQPin() --- hil/communication/daq_protocol.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/hil/communication/daq_protocol.py b/hil/communication/daq_protocol.py index bfb4fb2..6bdce4d 100644 --- a/hil/communication/daq_protocol.py +++ b/hil/communication/daq_protocol.py @@ -46,6 +46,7 @@ """ +# ---------------------------------------------------------------------------- # class DAQVariable(BusSignal): """ DAQ variable that can be subscribed (connected) to for receiving updates""" @@ -172,8 +173,10 @@ def state(self, s): a = self.state if (abs(s - a) > 0.0001): utils.log_warning(f"Write failed for DAQ var {self.signal_name} of {self.node_name}") +# ---------------------------------------------------------------------------- # +# ---------------------------------------------------------------------------- # class DaqProtocol(): """ Implements CAN daq protocol for modifying and live tracking of variables """ @@ -440,19 +443,20 @@ def updateVarDict(self, daq_config: dict): utils.signals[bus['bus_name']][node['node_name']][f"daq_response_{node['node_name'].upper()}"][var['var_name']] = DAQVariable.fromDAQFileVar( id_counter, var, file['name'], file['eeprom_lbl'], node, bus) id_counter += 1 +# ---------------------------------------------------------------------------- # +# ---------------------------------------------------------------------------- # class DAQPin(): - - def __init__(self, pin_name, board, bank, pin): - self.name = pin_name - self.board = board - self.bank = bank - self.pin = pin - self.t_last = time.time() + def __init__(self, pin_name: str, board: str, bank: int, pin: int): + self.name: str = pin_name + self.board: str = board + self.bank: int = bank + self.pin: int = pin + self.t_last: float = time.time() @property - def state(self): + def state(self) -> int: self.t_last = time.time() t_start = time.time() utils.daqProt.readPin(self.board, self.bank, self.pin) From 5af38367ec9c68fa544fe8d119848e712ab9f2d9 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 22 Oct 2024 19:42:30 -0400 Subject: [PATCH 044/181] (Mostly) type hinting daq_protocol.py -> DaqProtocol --- hil/communication/daq_protocol.py | 47 ++++++++++++++++--------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/hil/communication/daq_protocol.py b/hil/communication/daq_protocol.py index 6bdce4d..4f1310a 100644 --- a/hil/communication/daq_protocol.py +++ b/hil/communication/daq_protocol.py @@ -184,23 +184,24 @@ class DaqProtocol(): def __init__(self, bus: CanBus, daq_config: dict): super(DaqProtocol, self).__init__() - self.can_bus = bus - # self.can_bus.new_msg_sig.connect(self.handleDaqMsg) + self.can_bus: CanBus = bus self.can_bus.handle_daq_msg = self.handleDaqMsg + # self.can_bus.new_msg_sig.connect(self.handleDaqMsg) + self.updateVarDict(daq_config) # eeprom saving (prevent a load while save taking place) - self.last_save_request_id = 0 - self.save_in_progress = False + self.last_save_request_id: int = 0 + self.save_in_progress: bool = False utils.daqProt = self - self.curr_pin = 0 - self.curr_bank = 0 - self.curr_pin_val = 0 - self.pin_read_in_progress = False + self.curr_pin: int = 0 + self.curr_bank: int = 0 + self.curr_pin_val: int = 0 + self.pin_read_in_progress: bool = False - def readPin(self, node, bank, pin): + def readPin(self, node: str, bank: int, pin: int) -> None: """ Requests to read a GPIO pin, expects a reply """ dbc_msg = self.can_bus.db.get_message_by_name(f"daq_command_{node.upper()}") self.curr_bank = bank & DAQ_BANK_MASK @@ -212,7 +213,7 @@ def readPin(self, node, bank, pin): is_extended_id=True, data=data)) - def readVar(self, var: DAQVariable): + def readVar(self, var: DAQVariable) -> None: """ Requests to read a variable, expects a reply """ dbc_msg = self.can_bus.db.get_message_by_name(f"daq_command_{var.node_name.upper()}") data = [((var.id & DAQ_ID_MASK) << DAQ_CMD_LENGTH) | DAQ_CMD_READ] @@ -220,7 +221,8 @@ def readVar(self, var: DAQVariable): is_extended_id=True, data=data)) - def writeVar(self, var: DAQVariable, new_val): + def writeVar(self, var: DAQVariable, new_val) -> None: + # TODO: type hint """ Writes to a variable """ dbc_msg = self.can_bus.db.get_message_by_name(f"daq_command_{var.node_name.upper()}") data = [((var.id & DAQ_ID_MASK) << DAQ_CMD_LENGTH) | DAQ_CMD_WRITE] @@ -234,7 +236,7 @@ def writeVar(self, var: DAQVariable, new_val): is_extended_id=True, data=data)) - def saveFile(self, var: DAQVariable): + def saveFile(self, var: DAQVariable) -> None: """ Saves variable state in eeprom, expects save complete reply """ if var.file_lbl == None: utils.log_error(f"Invalid save var operation for {var.signal_name}") @@ -254,7 +256,7 @@ def saveFile(self, var: DAQVariable): # self.last_save_request_id = var.id # self.save_in_progress_sig.emit(True) - def loadFile(self, var: DAQVariable): + def loadFile(self, var: DAQVariable) -> None: """ Loads a variable from eeprom, cannot be performed during save operation """ if var.file_lbl == None: utils.log_error(f"Invalid load var operation for {var.signal_name}") @@ -274,7 +276,7 @@ def loadFile(self, var: DAQVariable): data=data)) self.setFileClean(var) - def pubVar(self, var: DAQVariable, period_ms): + def pubVar(self, var: DAQVariable, period_ms: int) -> None: """ Requests to start publishing a variable at a specified period """ var.pub_period_ms = period_ms dbc_msg = self.can_bus.db.get_message_by_name(f"daq_command_{var.node_name.upper()}") @@ -284,7 +286,8 @@ def pubVar(self, var: DAQVariable, period_ms): is_extended_id=True, data=data)) - def forceFault(self, id, state): + def forceFault(self, id: int, state) -> None: + # TODO: type hint print(f"Id: {id}, State: {state}") fault_msg = self.can_bus.db.get_message_by_name(f"set_fault") data = fault_msg.encode({"id": id, "value": state}) @@ -292,7 +295,7 @@ def forceFault(self, id, state): is_extended_id=True, data=data)) - def create_ids(self, fault_config): + def create_ids(self, fault_config: dict) -> dict: num = 0 idx = 0 for node in fault_config['modules']: @@ -316,7 +319,7 @@ def create_ids(self, fault_config): print("An error occured configuring a node.") return fault_config - def unforceFault(self, id): + def unforceFault(self, id: int) -> None: print(f"Id: {id}. Returning control!") fault_msg = self.can_bus.db.get_message_by_name(f"return_fault_control") data = fault_msg.encode({"id": id}) @@ -324,7 +327,7 @@ def unforceFault(self, id): is_extended_id=True, data=data)) - def pubVarStop(self, var: DAQVariable): + def pubVarStop(self, var: DAQVariable) -> None: """ Requests to stop publishing a variable """ var.pub_period_ms = 0 dbc_msg = self.can_bus.db.get_message_by_name(f"daq_command_{var.node_name.upper()}") @@ -333,7 +336,7 @@ def pubVarStop(self, var: DAQVariable): is_extended_id=True, data=data)) - def setFileClean(self, var_in_file: DAQVariable): + def setFileClean(self, var_in_file: DAQVariable) -> None: """ Sets all variables in a file to clean (usually after flushing) """ if (var_in_file.file_lbl == None): return node_d = utils.signals[var_in_file.bus_name][var_in_file.node_name] @@ -343,7 +346,7 @@ def setFileClean(self, var_in_file: DAQVariable): vars[file_var].updateDirty(False) - def setFileClean(self, var_in_file: DAQVariable): + def setFileClean(self, var_in_file: DAQVariable) -> None: """ Sets all variables in a file to clean (usually after flushing) """ if (var_in_file.file_lbl == None): return node_d = utils.signals[var_in_file.bus_name][var_in_file.node_name] @@ -353,7 +356,7 @@ def setFileClean(self, var_in_file: DAQVariable): vars[file_var].updateDirty(False) - def handleDaqMsg(self, msg: can.Message): + def handleDaqMsg(self, msg: can.Message) -> None: """ Interprets and runs commands from DAQ message """ # Return if not a DAQ message if (msg.arbitration_id >> 6) & 0xFFFFF != 0xFFFFF: return @@ -415,7 +418,7 @@ def handleDaqMsg(self, msg: can.Message): else: utils.log_warning(f"Got unexpected pin read response {node_name} bank {bank} pin {pin}") - def updateVarDict(self, daq_config: dict): + def updateVarDict(self, daq_config: dict) -> None: """ Creates dictionary of variable objects from daq configuration""" for bus in daq_config['busses']: # create bus keys From b855af7dab0644c4c561dc66a6806191a193faa1 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 22 Oct 2024 20:06:11 -0400 Subject: [PATCH 045/181] (Mostly) type hinting daq_protocol.py -> DAQVariable --- hil/communication/daq_protocol.py | 100 ++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 32 deletions(-) diff --git a/hil/communication/daq_protocol.py b/hil/communication/daq_protocol.py index 4f1310a..7df23c9 100644 --- a/hil/communication/daq_protocol.py +++ b/hil/communication/daq_protocol.py @@ -1,3 +1,4 @@ +from __future__ import annotations from communication.can_bus import BusSignal, CanBus # from PyQt5 import QtCore import utils @@ -49,25 +50,53 @@ # ---------------------------------------------------------------------------- # class DAQVariable(BusSignal): """ DAQ variable that can be subscribed (connected) to for receiving updates""" - - - def __init__(self, bus_name, node_name, msg_name, sig_name, id, read_only, bit_length, - dtype, store_dtype=None, unit="", msg_desc="", sig_desc="", msg_period=0, file_name=None, file_lbl=None, scale=1, offset=0): - super(DAQVariable, self).__init__(bus_name, node_name, msg_name, sig_name, dtype, store_dtype=store_dtype, - unit=unit, msg_desc=msg_desc, sig_desc=sig_desc, msg_period=msg_period) - self.id = id - self.read_only = read_only - self.bit_length = bit_length - self.file = file_name - self.file_lbl = file_lbl - self.pub_period_ms = 0 - - self.scale = scale - self.offset = offset - - self.is_dirty = False - - def fromDAQVar(id, var, node, bus): + def __init__(self, + bus_name: str, + node_name: str, + msg_name: str, + sig_name: str, + id: int, + read_only: bool, + bit_length: int, + dtype: np.dtype, + store_dtype: np.dtype | None = None, + unit: str = "", + msg_desc: str = "", + sig_desc: str = "", + msg_period: int = 0, + file_name: str | None = None, + file_lbl: str | None = None, + scale: int = 1, + offset: int = 0 + ): + super(DAQVariable, self).__init__( + bus_name, + node_name, + msg_name, + sig_name, + dtype, + store_dtype=store_dtype, + unit=unit, + msg_desc=msg_desc, + sig_desc=sig_desc, + msg_period=msg_period + ) + self.id: int = id + self.read_only: bool = read_only + self.bit_length: int = bit_length + self.file: str = file_name + self.file_lbl: str = file_lbl + + self.pub_period_ms: int = 0 + + # TODO: not sure if the type hints are correct + self.scale: int = scale + self.offset: int = offset + + self.is_dirty: bool = False + + @classmethod + def fromDAQVar(cls, id: int, var: dict, node: dict, bus: dict) -> DAQVariable: send_dtype = utils.data_types[var['type']] # If there is scaling going on, don't store as an integer on accident if ('scale' in var and var['scale'] != 1) or ('offset' in var and var['offset'] != 0): @@ -81,7 +110,7 @@ def fromDAQVar(id, var, node, bus): utils.log_error(f"Invalid bit length defined for DAQ variable {var['var_name']}") bit_length = var['length'] - return DAQVariable(bus['bus_name'], node['node_name'], f"daq_response_{node['node_name'].upper()}", var['var_name'], + return cls(bus['bus_name'], node['node_name'], f"daq_response_{node['node_name'].upper()}", var['var_name'], id, var['read_only'], bit_length, send_dtype, store_dtype=parse_dtype, unit=(var['unit'] if 'unit' in var else ""), @@ -90,7 +119,9 @@ def fromDAQVar(id, var, node, bus): scale=(var['scale'] if 'scale' in var else 1), offset=(var['offset'] if 'offset' in var else 0)) - def fromDAQFileVar(id, var, file_name, file_lbl, node, bus): + @classmethod + def fromDAQFileVar(cls, id: int, var: dict, file_name: str, file_lbl: str, node: dict, bus: dict) -> DAQVariable: + # TODO: not sure if the type hints are correct send_dtype = utils.data_types[var['type']] # If there is scaling going on, don't store as an integer on accident if ('scale' in var and var['scale'] != 1) or ('offset' in var and var['offset'] != 0): @@ -100,7 +131,7 @@ def fromDAQFileVar(id, var, file_name, file_lbl, node, bus): # Calculate bit length bit_length = utils.data_type_length[var['type']] - return DAQVariable(bus['bus_name'], node['node_name'], f"daq_response_{node['node_name'].upper()}", var['var_name'], + return cls(bus['bus_name'], node['node_name'], f"daq_response_{node['node_name'].upper()}", var['var_name'], id, False, bit_length, send_dtype, store_dtype=parse_dtype, unit=(var['unit'] if 'unit' in var else ""), @@ -109,15 +140,17 @@ def fromDAQFileVar(id, var, file_name, file_lbl, node, bus): scale=(var['scale'] if 'scale' in var else 1), offset=(var['offset'] if 'offset' in var else 0)) - def update(self, bytes, timestamp): + def update(self, bytes: int, timestamp: float) -> None: val = np.frombuffer(bytes.to_bytes((self.bit_length + 7)//8, 'little'), dtype=self.send_dtype, count=1) val = val * self.scale + self.offset - return super().update(val, timestamp) + super().update(val, timestamp) - def reverseScale(self, val): + def reverseScale(self, val: float) -> float: + # TODO: not sure if the type hint is correct return (val - self.offset) / self.scale - def valueSendable(self, val): + def valueSendable(self, val: float) -> bool: + # TODO: not sure if the type hint is correct # TODO: check max and min from json config val = self.reverseScale(val) if 'uint' in str(self.send_dtype): @@ -130,27 +163,29 @@ def valueSendable(self, val): return False return True - def reverseToBytes(self, val): + def reverseToBytes(self, val: float) -> bytes | bool: if not self.valueSendable(val): return False # Value will not fit in the given dtype return (np.array([self.reverseScale(val)], dtype=self.send_dtype).tobytes()) - def getSendValue(self, val): + def getSendValue(self, val: float) -> float | bool: + # TODO: not sure if the type hint is correct if not self.valueSendable(val): return False # Value will not fit in the given dtype # Convert to send a = np.array([self.reverseScale(val)], dtype=self.send_dtype)[0] # Convert back return a * self.scale + self.offset - def isDirty(self): + def isDirty(self) -> bool: if self.file_lbl == None: return False return self.is_dirty - def updateDirty(self, dirty): + def updateDirty(self, dirty: bool) -> None: if self.file_lbl == None: return self.is_dirty = dirty @property - def state(self): + def state(self) -> int: + # TODO: not sure if the type hints are correct """ Read the value in blocking manner """ old_t = self.last_update_time utils.daqProt.readVar(self) @@ -163,7 +198,8 @@ def state(self): return self.curr_val @state.setter - def state(self, s): + def state(self, s: int) -> None: + # TODO: not sure if the type hint is correct """ Writes the value in blocking manner """ if (self.read_only): utils.log_error(f"Can't write to read-only DAQ variable {self.signal_name} of {self.node_name}") From 4695144bcd0e88b76983947dbb7d207e930415b1 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 22 Oct 2024 20:10:35 -0400 Subject: [PATCH 046/181] Finishing type hinting daq_protocol.py --- hil/communication/daq_protocol.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hil/communication/daq_protocol.py b/hil/communication/daq_protocol.py index 7df23c9..c35f570 100644 --- a/hil/communication/daq_protocol.py +++ b/hil/communication/daq_protocol.py @@ -257,8 +257,8 @@ def readVar(self, var: DAQVariable) -> None: is_extended_id=True, data=data)) - def writeVar(self, var: DAQVariable, new_val) -> None: - # TODO: type hint + def writeVar(self, var: DAQVariable, new_val: float) -> None: + # TODO: not sure if the type hint is correct """ Writes to a variable """ dbc_msg = self.can_bus.db.get_message_by_name(f"daq_command_{var.node_name.upper()}") data = [((var.id & DAQ_ID_MASK) << DAQ_CMD_LENGTH) | DAQ_CMD_WRITE] @@ -322,8 +322,8 @@ def pubVar(self, var: DAQVariable, period_ms: int) -> None: is_extended_id=True, data=data)) - def forceFault(self, id: int, state) -> None: - # TODO: type hint + def forceFault(self, id: int, state: int) -> None: + # TODO: not sure if the type hint is correct print(f"Id: {id}, State: {state}") fault_msg = self.can_bus.db.get_message_by_name(f"set_fault") data = fault_msg.encode({"id": id, "value": state}) From 2d03591fde78a85d54dea16015f1133f9d53631f Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 22 Oct 2024 20:10:47 -0400 Subject: [PATCH 047/181] Done with all files --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3593226..d566681 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ - [x] `./hil/components/component.py` - [x] `./hil/communication/can_bus.py` - [x] `./hil/communication/client.py` -- [ ] `./hil/communication/daq_protocol.py` +- [x] `./hil/communication/daq_protocol.py` - [x] `./hil/hil_devices/serial_manager.py` - [x] `./hil/hil_devices/hil_device.py` - [x] `./hil/hil.py` From 46eaac416bdc9f4a58c6f3362f5a88f99011ccdc Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 22 Oct 2024 20:10:59 -0400 Subject: [PATCH 048/181] No longer need the TODO --- README.md | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 README.md diff --git a/README.md b/README.md deleted file mode 100644 index d566681..0000000 --- a/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Branch TODO -## Type hinting -- [x] `./hil/components/component.py` -- [x] `./hil/communication/can_bus.py` -- [x] `./hil/communication/client.py` -- [x] `./hil/communication/daq_protocol.py` -- [x] `./hil/hil_devices/serial_manager.py` -- [x] `./hil/hil_devices/hil_device.py` -- [x] `./hil/hil.py` -- [x] `./hil/utils.py` -- [x] `./hil/pin_mapper.py` From e1e390881ece809a39fb0444d8619ac978413d24 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 26 Oct 2024 11:00:48 -0400 Subject: [PATCH 049/181] Trying to understand the structure of utils.signals Thanks ChatGPT! --- hil/utils.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/hil/utils.py b/hil/utils.py index 0f55857..0ea0f88 100644 --- a/hil/utils.py +++ b/hil/utils.py @@ -14,6 +14,30 @@ def initGlobals(): global signals signals = {} + # signals = { + # "bus_name": { # Top level, keyed by bus name (e.g., "Main", "Test") + # "node_name": { # Second level, keyed by node name (e.g., "Main_Module", "TEST_NODE") + # "daq_response_NODE_NAME": { # DAQ-specific dictionary; exists if DAQ variables are defined + # "var_name": DAQVariable # Each variable from `daq_config`, stored as DAQVariable instances + # # e.g., "cal_steer_angle": DAQVariable instance + # }, + # "files": { # Optional DAQ-specific dictionary; exists if file data is present in DAQ config + # "file_name": { # Keyed by file name (e.g., "config") + # "contents": [ # List of variable names in the file + # "var_name" # e.g., "blue_on" + # ] + # } + # }, + # "messages": { # CAN-specific dictionary; exists if CAN messages are defined + # "msg_name": { # Keyed by message name from `can_config` (e.g., "main_hb", "gearbox") + # "sig_name": BusSignal # Each signal from CAN message, stored as BusSignal instances + # # e.g., "car_state": BusSignal instance + # } + # } + # } + # } + # } + global plot_x_range_sec plot_x_range_sec = 10 From f587275e82f8853b17c197c7ce1b80def614d1e9 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 26 Oct 2024 11:41:20 -0400 Subject: [PATCH 050/181] Fixing utils.signals outline/structure ChatGPT was wrong --- hil/utils.py | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/hil/utils.py b/hil/utils.py index 0ea0f88..ccf5075 100644 --- a/hil/utils.py +++ b/hil/utils.py @@ -14,28 +14,25 @@ def initGlobals(): global signals signals = {} + # Structure of signals based on daq_config and can_config # signals = { - # "bus_name": { # Top level, keyed by bus name (e.g., "Main", "Test") - # "node_name": { # Second level, keyed by node name (e.g., "Main_Module", "TEST_NODE") - # "daq_response_NODE_NAME": { # DAQ-specific dictionary; exists if DAQ variables are defined - # "var_name": DAQVariable # Each variable from `daq_config`, stored as DAQVariable instances - # # e.g., "cal_steer_angle": DAQVariable instance - # }, - # "files": { # Optional DAQ-specific dictionary; exists if file data is present in DAQ config - # "file_name": { # Keyed by file name (e.g., "config") - # "contents": [ # List of variable names in the file - # "var_name" # e.g., "blue_on" - # ] - # } - # }, - # "messages": { # CAN-specific dictionary; exists if CAN messages are defined - # "msg_name": { # Keyed by message name from `can_config` (e.g., "main_hb", "gearbox") - # "sig_name": BusSignal # Each signal from CAN message, stored as BusSignal instances - # # e.g., "car_state": BusSignal instance - # } - # } + # 'bus_name': { # busses; ex: "Main", "Test" + # 'node_name': { # busses->nodes; ex: "Main_Module", "Dashboard" + # 'msg_name': { # busses->nodes->tx; ex: "main_hb", "coolant_temps" + # 'sig_name': BusSignal # # busses->nodes->tx->signals; ex: "car_state", "battery_in_temp" + # }, + # "daq_response_{node['node_name'].upper()}": { # busses->nodes; ex: "daq_response_MAIN_MODULE", "daq_response_DASHBOARD" + # 'var_name': DAQVariable # busses->nodes->variables | busses->nodes->files->contents; ex: "cal_steer_angle", "sdc_main_status", "blue_on", "odometer" + # }, + # "files": { + # 'name': { # busses->nodes->files; ex: "config" + # "contents": [ + # 'var_name' # busses->nodes->files->contents; ex: "blue_on", "odometer" + # ] # } + # } # } + # } # } From 77c37b9d05a706d117f4ca155a551a5e4877464b Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 26 Oct 2024 11:42:11 -0400 Subject: [PATCH 051/181] Type hinting/commenting out globals --- hil/utils.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hil/utils.py b/hil/utils.py index ccf5075..0409e62 100644 --- a/hil/utils.py +++ b/hil/utils.py @@ -36,11 +36,11 @@ def initGlobals(): # } - global plot_x_range_sec - plot_x_range_sec = 10 + # global plot_x_range_sec + # plot_x_range_sec: int = 10 - global events - events: list = [] + # global events + # events: list = [] global b_str b_str: str = "Main" From e3753dfee0a29f230cfe92c4f2a80af00a8080eb Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 26 Oct 2024 11:42:49 -0400 Subject: [PATCH 052/181] Fixing type hint (BusSignal from util.signals not str) --- hil/hil.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hil/hil.py b/hil/hil.py index 1a6e0cc..aa6cbb5 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -8,7 +8,7 @@ from hil_devices.serial_manager import SerialManager from components.component import Component -from communication.can_bus import CanBus +from communication.can_bus import CanBus, BusSignal from communication.daq_protocol import DaqProtocol from communication.daq_protocol import DAQPin from communication.daq_protocol import DAQVariable @@ -208,7 +208,7 @@ def daq_var(self, board: str, var_name: str) -> DAQVariable: self.handle_error(f"Unable to locate DAQ variable {var_name} of {board}") @utils.log_function_start_end - def can_var(self, board: str, message_name: str, signal_name: str) -> str: + def can_var(self, board: str, message_name: str, signal_name: str) -> BusSignal: # TODO: not sure if any of the type hints are correct try: return utils.signals[utils.b_str][board][message_name][signal_name] From 3a0e1b1886b3eef1461b74decc2df71889785b07 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 29 Oct 2024 19:14:58 -0400 Subject: [PATCH 053/181] Fixing typo --- hil/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hil/utils.py b/hil/utils.py index 0409e62..c8d4758 100644 --- a/hil/utils.py +++ b/hil/utils.py @@ -19,7 +19,7 @@ def initGlobals(): # 'bus_name': { # busses; ex: "Main", "Test" # 'node_name': { # busses->nodes; ex: "Main_Module", "Dashboard" # 'msg_name': { # busses->nodes->tx; ex: "main_hb", "coolant_temps" - # 'sig_name': BusSignal # # busses->nodes->tx->signals; ex: "car_state", "battery_in_temp" + # 'sig_name': BusSignal # busses->nodes->tx->signals; ex: "car_state", "battery_in_temp" # }, # "daq_response_{node['node_name'].upper()}": { # busses->nodes; ex: "daq_response_MAIN_MODULE", "daq_response_DASHBOARD" # 'var_name': DAQVariable # busses->nodes->variables | busses->nodes->files->contents; ex: "cal_steer_angle", "sdc_main_status", "blue_on", "odometer" From 2a1c3ba6d677f66ecc9926e8fbf755d4a3b5a0f0 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 29 Oct 2024 21:48:21 -0400 Subject: [PATCH 054/181] Removing duplicate line --- hil/hil.py | 1 - 1 file changed, 1 deletion(-) diff --git a/hil/hil.py b/hil/hil.py index aa6cbb5..6b9c0a8 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -26,7 +26,6 @@ class HIL(): - @utils.log_function_start_end @utils.log_function_start_end def __init__(self): utils.initGlobals() From 1c2e96774d3944d89c336a0e21845f70192b36f3 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 5 Nov 2024 20:01:07 -0500 Subject: [PATCH 055/181] Folder name must match ino name (case sensitive) testbench -> TestBench.ino --- {testbench => TestBench}/MCP4021.cpp | 0 {testbench => TestBench}/MCP4021.h | 0 {testbench => TestBench}/TestBench.ino | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename {testbench => TestBench}/MCP4021.cpp (100%) rename {testbench => TestBench}/MCP4021.h (100%) rename {testbench => TestBench}/TestBench.ino (100%) diff --git a/testbench/MCP4021.cpp b/TestBench/MCP4021.cpp similarity index 100% rename from testbench/MCP4021.cpp rename to TestBench/MCP4021.cpp diff --git a/testbench/MCP4021.h b/TestBench/MCP4021.h similarity index 100% rename from testbench/MCP4021.h rename to TestBench/MCP4021.h diff --git a/testbench/TestBench.ino b/TestBench/TestBench.ino similarity index 100% rename from testbench/TestBench.ino rename to TestBench/TestBench.ino From f383c6f2614c7f6da67f7a823b7bfbbb4697c498 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 5 Nov 2024 20:11:28 -0500 Subject: [PATCH 056/181] Trying to add DFRobot_MCP4725 driver Source: https://github.com/DFRobot/DFRobot_MCP4725 --- TestBench/DFRobot_MCP4725.cpp | 394 ++++++++++++++++++++++++++++++++++ TestBench/DFRobot_MCP4725.h | 101 +++++++++ 2 files changed, 495 insertions(+) create mode 100644 TestBench/DFRobot_MCP4725.cpp create mode 100644 TestBench/DFRobot_MCP4725.h diff --git a/TestBench/DFRobot_MCP4725.cpp b/TestBench/DFRobot_MCP4725.cpp new file mode 100644 index 0000000..ae212f5 --- /dev/null +++ b/TestBench/DFRobot_MCP4725.cpp @@ -0,0 +1,394 @@ +/*! + * @file DFRobot_MCP4725.cpp + * @brief Implementation of the MCP4725 function library class definition + * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + * @license The MIT License (MIT) + * @author [TangJie]](jie.tang@dfrobot.com) + * @version V1.0.0 + * @date 2018-01-15 + * @url https://github.com/DFRobot/DFRobot_MCP4725 + */ +#include "DFRobot_MCP4725.h" + +const PROGMEM uint16_t DACLookup_FullSine_5Bit[32] = +{ + 2048, 2447, 2831, 3185, 3495, 3750, 3939, 4056, + 4095, 4056, 3939, 3750, 3495, 3185, 2831, 2447, + 2048, 1648, 1264, 910, 600, 345, 156, 39, + 0, 39, 156, 345, 600, 910, 1264, 1648 +}; + +const PROGMEM uint16_t DACLookup_FullSine_6Bit[64] = +{ + 2048, 2248, 2447, 2642, 2831, 3013, 3185, 3346, + 3495, 3630, 3750, 3853, 3939, 4007, 4056, 4085, + 4095, 4085, 4056, 4007, 3939, 3853, 3750, 3630, + 3495, 3346, 3185, 3013, 2831, 2642, 2447, 2248, + 2048, 1847, 1648, 1453, 1264, 1082, 910, 749, + 600, 465, 345, 242, 156, 88, 39, 10, + 0, 10, 39, 88, 156, 242, 345, 465, + 600, 749, 910, 1082, 1264, 1453, 1648, 1847 +}; + +const PROGMEM uint16_t DACLookup_FullSine_7Bit[128] = +{ + 2048, 2148, 2248, 2348, 2447, 2545, 2642, 2737, + 2831, 2923, 3013, 3100, 3185, 3267, 3346, 3423, + 3495, 3565, 3630, 3692, 3750, 3804, 3853, 3898, + 3939, 3975, 4007, 4034, 4056, 4073, 4085, 4093, + 4095, 4093, 4085, 4073, 4056, 4034, 4007, 3975, + 3939, 3898, 3853, 3804, 3750, 3692, 3630, 3565, + 3495, 3423, 3346, 3267, 3185, 3100, 3013, 2923, + 2831, 2737, 2642, 2545, 2447, 2348, 2248, 2148, + 2048, 1947, 1847, 1747, 1648, 1550, 1453, 1358, + 1264, 1172, 1082, 995, 910, 828, 749, 672, + 600, 530, 465, 403, 345, 291, 242, 197, + 156, 120, 88, 61, 39, 22, 10, 2, + 0, 2, 10, 22, 39, 61, 88, 120, + 156, 197, 242, 291, 345, 403, 465, 530, + 600, 672, 749, 828, 910, 995, 1082, 1172, + 1264, 1358, 1453, 1550, 1648, 1747, 1847, 1947 +}; + +const PROGMEM uint16_t DACLookup_FullSine_8Bit[256] = +{ + 2048, 2098, 2148, 2198, 2248, 2298, 2348, 2398, + 2447, 2496, 2545, 2594, 2642, 2690, 2737, 2784, + 2831, 2877, 2923, 2968, 3013, 3057, 3100, 3143, + 3185, 3226, 3267, 3307, 3346, 3385, 3423, 3459, + 3495, 3530, 3565, 3598, 3630, 3662, 3692, 3722, + 3750, 3777, 3804, 3829, 3853, 3876, 3898, 3919, + 3939, 3958, 3975, 3992, 4007, 4021, 4034, 4045, + 4056, 4065, 4073, 4080, 4085, 4089, 4093, 4094, + 4095, 4094, 4093, 4089, 4085, 4080, 4073, 4065, + 4056, 4045, 4034, 4021, 4007, 3992, 3975, 3958, + 3939, 3919, 3898, 3876, 3853, 3829, 3804, 3777, + 3750, 3722, 3692, 3662, 3630, 3598, 3565, 3530, + 3495, 3459, 3423, 3385, 3346, 3307, 3267, 3226, + 3185, 3143, 3100, 3057, 3013, 2968, 2923, 2877, + 2831, 2784, 2737, 2690, 2642, 2594, 2545, 2496, + 2447, 2398, 2348, 2298, 2248, 2198, 2148, 2098, + 2048, 1997, 1947, 1897, 1847, 1797, 1747, 1697, + 1648, 1599, 1550, 1501, 1453, 1405, 1358, 1311, + 1264, 1218, 1172, 1127, 1082, 1038, 995, 952, + 910, 869, 828, 788, 749, 710, 672, 636, + 600, 565, 530, 497, 465, 433, 403, 373, + 345, 318, 291, 266, 242, 219, 197, 176, + 156, 137, 120, 103, 88, 74, 61, 50, + 39, 30, 22, 15, 10, 6, 2, 1, + 0, 1, 2, 6, 10, 15, 22, 30, + 39, 50, 61, 74, 88, 103, 120, 137, + 156, 176, 197, 219, 242, 266, 291, 318, + 345, 373, 403, 433, 465, 497, 530, 565, + 600, 636, 672, 710, 749, 788, 828, 869, + 910, 952, 995, 1038, 1082, 1127, 1172, 1218, + 1264, 1311, 1358, 1405, 1453, 1501, 1550, 1599, + 1648, 1697, 1747, 1797, 1847, 1897, 1947, 1997 +}; + +const PROGMEM uint16_t DACLookup_FullSine_9Bit[512] = +{ + 2048, 2073, 2098, 2123, 2148, 2174, 2199, 2224, + 2249, 2274, 2299, 2324, 2349, 2373, 2398, 2423, + 2448, 2472, 2497, 2521, 2546, 2570, 2594, 2618, + 2643, 2667, 2690, 2714, 2738, 2762, 2785, 2808, + 2832, 2855, 2878, 2901, 2924, 2946, 2969, 2991, + 3013, 3036, 3057, 3079, 3101, 3122, 3144, 3165, + 3186, 3207, 3227, 3248, 3268, 3288, 3308, 3328, + 3347, 3367, 3386, 3405, 3423, 3442, 3460, 3478, + 3496, 3514, 3531, 3548, 3565, 3582, 3599, 3615, + 3631, 3647, 3663, 3678, 3693, 3708, 3722, 3737, + 3751, 3765, 3778, 3792, 3805, 3817, 3830, 3842, + 3854, 3866, 3877, 3888, 3899, 3910, 3920, 3930, + 3940, 3950, 3959, 3968, 3976, 3985, 3993, 4000, + 4008, 4015, 4022, 4028, 4035, 4041, 4046, 4052, + 4057, 4061, 4066, 4070, 4074, 4077, 4081, 4084, + 4086, 4088, 4090, 4092, 4094, 4095, 4095, 4095, + 4095, 4095, 4095, 4095, 4094, 4092, 4090, 4088, + 4086, 4084, 4081, 4077, 4074, 4070, 4066, 4061, + 4057, 4052, 4046, 4041, 4035, 4028, 4022, 4015, + 4008, 4000, 3993, 3985, 3976, 3968, 3959, 3950, + 3940, 3930, 3920, 3910, 3899, 3888, 3877, 3866, + 3854, 3842, 3830, 3817, 3805, 3792, 3778, 3765, + 3751, 3737, 3722, 3708, 3693, 3678, 3663, 3647, + 3631, 3615, 3599, 3582, 3565, 3548, 3531, 3514, + 3496, 3478, 3460, 3442, 3423, 3405, 3386, 3367, + 3347, 3328, 3308, 3288, 3268, 3248, 3227, 3207, + 3186, 3165, 3144, 3122, 3101, 3079, 3057, 3036, + 3013, 2991, 2969, 2946, 2924, 2901, 2878, 2855, + 2832, 2808, 2785, 2762, 2738, 2714, 2690, 2667, + 2643, 2618, 2594, 2570, 2546, 2521, 2497, 2472, + 2448, 2423, 2398, 2373, 2349, 2324, 2299, 2274, + 2249, 2224, 2199, 2174, 2148, 2123, 2098, 2073, + 2048, 2023, 1998, 1973, 1948, 1922, 1897, 1872, + 1847, 1822, 1797, 1772, 1747, 1723, 1698, 1673, + 1648, 1624, 1599, 1575, 1550, 1526, 1502, 1478, + 1453, 1429, 1406, 1382, 1358, 1334, 1311, 1288, + 1264, 1241, 1218, 1195, 1172, 1150, 1127, 1105, + 1083, 1060, 1039, 1017, 995, 974, 952, 931, + 910, 889, 869, 848, 828, 808, 788, 768, + 749, 729, 710, 691, 673, 654, 636, 618, + 600, 582, 565, 548, 531, 514, 497, 481, + 465, 449, 433, 418, 403, 388, 374, 359, + 345, 331, 318, 304, 291, 279, 266, 254, + 242, 230, 219, 208, 197, 186, 176, 166, + 156, 146, 137, 128, 120, 111, 103, 96, + 88, 81, 74, 68, 61, 55, 50, 44, + 39, 35, 30, 26, 22, 19, 15, 12, + 10, 8, 6, 4, 2, 1, 1, 0, + 0, 0, 1, 1, 2, 4, 6, 8, + 10, 12, 15, 19, 22, 26, 30, 35, + 39, 44, 50, 55, 61, 68, 74, 81, + 88, 96, 103, 111, 120, 128, 137, 146, + 156, 166, 176, 186, 197, 208, 219, 230, + 242, 254, 266, 279, 291, 304, 318, 331, + 345, 359, 374, 388, 403, 418, 433, 449, + 465, 481, 497, 514, 531, 548, 565, 582, + 600, 618, 636, 654, 673, 691, 710, 729, + 749, 768, 788, 808, 828, 848, 869, 889, + 910, 931, 952, 974, 995, 1017, 1039, 1060, + 1083, 1105, 1127, 1150, 1172, 1195, 1218, 1241, + 1264, 1288, 1311, 1334, 1358, 1382, 1406, 1429, + 1453, 1478, 1502, 1526, 1550, 1575, 1599, 1624, + 1648, 1673, 1698, 1723, 1747, 1772, 1797, 1822, + 1847, 1872, 1897, 1922, 1948, 1973, 1998, 2023 +}; + +bool DFRobot_MCP4725::check_mcp4725() +{ + uint8_t error; + Wire.beginTransmission(_IIC_addr); + error = Wire.endTransmission(); + if(error == 0){ + return true; + }else{ + return false; + } +} +void DFRobot_MCP4725::init(uint8_t addr, uint16_t vRef) +{ + byte error; + _IIC_addr = addr; + _refVoltage = vRef; + _PowerMode = MCP4725_NORMAL_MODE; + Wire.begin(); + Wire.beginTransmission(_IIC_addr); + + Wire.endTransmission(); + /* + while(error) + { + Wire.beginTransmission(_IIC_addr); + + error = Wire.endTransmission(); + Serial.println("ERROR! Not found I2C device address "); + delay(500); + } + */ +} + +void DFRobot_MCP4725::setMode(uint8_t powerMode) +{ + _PowerMode = powerMode; + outputVoltage(_voltage); +} + +void DFRobot_MCP4725::outputVoltage( uint16_t voltage) +{ + uint16_t data = 0; + _voltage = voltage; + if(_voltage > _refVoltage) + { + Serial.print("ERROR! The input voltage is greater than the maximum voltage!"); + return ; + } + else + { + data = (uint16_t)(((float)_voltage / _refVoltage) * 4095); + + Wire.beginTransmission(_IIC_addr); + + Wire.write(MCP4725_Write_CMD | (_PowerMode << 1)); + + Wire.write(data / 16); + Wire.write((data % 16) << 4); + Wire.endTransmission(); + } +} + +void DFRobot_MCP4725::outputVoltageEEPROM( uint16_t voltage) +{ + uint16_t data = 0; + _voltage = voltage; + if(_voltage > _refVoltage) + { + Serial.print("ERROR! The input voltage is greater than the maximum voltage!"); + return ; + } + else + { + data = (uint16_t)(((float)_voltage / _refVoltage) * 4095); + + Wire.beginTransmission(_IIC_addr); + Wire.write(MCP4725_WriteEEPROM_CMD | (_PowerMode << 1)); + Wire.write(data / 16); + Wire.write((data % 16) << 4); + Wire.endTransmission(); + } +} + +void DFRobot_MCP4725::outputTriangle(uint16_t amp, uint16_t freq, uint16_t offset, uint8_t dutyCycle) +{ + uint64_t starttime; + uint64_t stoptime; + uint64_t looptime; + uint64_t frame; + uint16_t num = 64; + uint16_t up_num; + uint16_t down_num; + uint16_t maxV; + maxV=amp*(4096/(float)_refVoltage); + if(freq > 100){ + num = 16; + }else if(50 <= freq && freq <= 100){ + num = 32; + }else{ + num = 64; + } + frame = 1000000/(freq*num*2); + if(dutyCycle>100){ + dutyCycle = 100; + } + if(dutyCycle<0){ + dutyCycle=0; + } + up_num = (2*num)*((float)dutyCycle/100); + down_num = ((2*num) - up_num); +#ifdef TWBR + uint8_t twbrback = TWBR; + TWBR = ((F_CPU / 400000L) - 16) / 2; // Set I2C frequency to 400kHz +#endif + uint32_t counter; + uint32_t enterV; + + for (counter = 0; counter < (maxV-(maxV/up_num)-1); counter+=(maxV/up_num)) + { + starttime = micros(); + enterV=counter+(offset*(4096/(float)_refVoltage)); + if(enterV > 4095){ + enterV = 4095; + }else if(enterV < 0){ + enterV = 0; + } + Wire.beginTransmission(_IIC_addr); + Wire.write(MCP4725_Write_CMD | (_PowerMode << 1)); + Wire.write(enterV / 16); + Wire.write((enterV % 16) << 4); + Wire.endTransmission(); + stoptime = micros(); + looptime = stoptime-starttime; + while(looptime <= frame){ + stoptime = micros(); + looptime = stoptime-starttime; + } + } + for (counter = maxV-1; counter > (maxV/down_num); counter-=(maxV/down_num)) + { + starttime = micros(); + enterV=counter+(offset*(4096/(float)_refVoltage)); + if(enterV > 4095){ + enterV = 4095; + }else if(enterV < 0){ + enterV = 0; + } + Wire.beginTransmission(_IIC_addr); + Wire.write(MCP4725_Write_CMD | (_PowerMode << 1)); + Wire.write(enterV / 16); + Wire.write((enterV % 16) << 4); + Wire.endTransmission(); + stoptime = micros(); + looptime = stoptime-starttime; + while(looptime <= frame){ + stoptime = micros(); + looptime = stoptime-starttime; + } + } +#ifdef TWBR + TWBR = twbrback; +#endif +} + +void DFRobot_MCP4725::outputSin(uint16_t amp, uint16_t freq, uint16_t offset) +{ + uint64_t starttime; + uint64_t stoptime; + uint64_t looptime; + uint64_t frame; + uint16_t num=512; +#ifdef TWBR + uint8_t twbrback = TWBR; + TWBR = ((F_CPU / 400000L) - 16) / 2; // Set I2C frequency to 400kHz +#endif + int16_t data = 0; + + if(freq < 8){ + num = 512; + }else if( 8 <= freq && freq <= 16){ + num = 256; + }else if(16 < freq && freq < 33){ + num = 128; + }else if(33 <= freq && freq <= 68 ){ + num = 64; + }else{ + num = 32; + } + if(freq > 100){ + freq = 100; + } + frame = 1000000/(freq*num); + for(int i=0;i= 4095){ + data=4095; + } + Wire.beginTransmission(_IIC_addr); + Wire.write(MCP4725_Write_CMD); + Wire.write(data / 16); + Wire.write((data % 16) << 4); + Wire.endTransmission(); + stoptime = micros(); + looptime = stoptime-starttime; + while(looptime <= frame){ + stoptime = micros(); + looptime = stoptime-starttime; + } + } +#ifdef TWBR + TWBR = twbrback; +#endif +} diff --git a/TestBench/DFRobot_MCP4725.h b/TestBench/DFRobot_MCP4725.h new file mode 100644 index 0000000..a468074 --- /dev/null +++ b/TestBench/DFRobot_MCP4725.h @@ -0,0 +1,101 @@ +/*! + * @file DFRobot_MCP4725.h + * @brief Definition and explanation of the MCP4725 function library class + * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + * @license The MIT License (MIT) + * @author [TangJie]](jie.tang@dfrobot.com) + * @version V1.0.0 + * @date 2018-01-15 + * @url https://github.com/DFRobot/DFRobot_MCP4725 + */ + +#if ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + +#include + +#define MCP4725_Write_CMD 0x40 ///< Write data to the DAC address. +#define MCP4725_WriteEEPROM_CMD 0x60 ///< Write data to the DAC EEPROM address. + +///< The IIC address of MCP4725A0 may be 0x60 or 0x61, depending on the location of the dial code switch on the sensor. +#define MCP4725A0_IIC_Address0 0x60 +#define MCP4725A0_IIC_Address1 0x61 + +#define MCP4725_NORMAL_MODE 0 +#define MCP4725_POWER_DOWN_1KRES 1 +#define MCP4725_POWER_DOWN_100KRES 2 +#define MCP4725_POWER_DOWN_500KRES 3 + +class DFRobot_MCP4725{ +public: + /** + * @fn init + * @brief init MCP4725 device + * @param addr Init the IIC address. + * @param vRefSetting the base voltage of DAC must equal the power supply voltage, and the unit is millivolt. + * @return None + */ + void init(uint8_t addr, uint16_t vRef); + + /** + * @fn setMode + * @brief set power mode + * @param powerMode Set power mode,three are normal mode and power down mode. + * @n The following are three modes of power down. + * @n MCP4725_POWER_DOWN_1KRES 1 kΩ resistor to ground + * @n MCP4725_POWER_DOWN_100KRES 100 kΩ resistor to ground + * @n MCP4725_POWER_DOWN_500KRES 500 kΩ resistor to ground + * @return None + */ + void setMode(uint8_t powerMode); + + /** + * @fn outputVoltage + * @brief Output voltage value range 0-5000mv. + * @param voltage Voltage value, range 0-5000, unit millivolt. + * @return None + */ + void outputVoltage(uint16_t voltage); + + /** + * @fn outputVoltageEEPROM + * @brief Output voltage value range 0-5000mv and write to the EEPROM, + * @n meaning that the DAC will retain the current voltage output + * @n after power-down or reset. + * @param voltage Voltage value, range 0-5000, unit millivolt. + * @return None + */ + void outputVoltageEEPROM(uint16_t voltage); + + /** + * @fn outputSin + * @brief Output a sine wave. + * @param amp amp value, output sine wave amplitude range 0-5000mv + * @param freq freq value, output sine wave frequency + * @param offset offset value, output sine wave DC offset + * @return None + */ + void outputSin(uint16_t amp, uint16_t freq, uint16_t offset); + + /** + * @fn outputTriangle + * @brief Output a sine wave. + * @param amp amp value, output triangular wave amplitude range 0-5000mv + * @param freq freq value, output the triangle wave frequency + * @param offset offset value, output the DC offset of the triangle wave + * @param dutyCycle dutyCycle value, set the rising percentage of the triangle wave as a percentage of the entire cycle. + * @n Value range 0-100 (0 for only the decline of 100, only the rise of paragraph) + * @return None + */ + void outputTriangle(uint16_t amp, uint16_t freq, uint16_t offset, uint8_t dutyCycle); + + private: + bool check_mcp4725(); + uint8_t _IIC_addr; + uint8_t _PowerMode; + uint16_t _refVoltage; + uint16_t _voltage; +}; From fd31bf0a61674f9c638b9017c4e06bc299557499 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 5 Nov 2024 20:17:13 -0500 Subject: [PATCH 057/181] DFRobot_MCP4725: local #include instead of library global #include --- TestBench/TestBench.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestBench/TestBench.ino b/TestBench/TestBench.ino index 8618ef4..80b7202 100644 --- a/TestBench/TestBench.ino +++ b/TestBench/TestBench.ino @@ -21,7 +21,7 @@ const int TESTER_ID = 2; #endif #ifdef DAC -#include +#include "DFRobot_MCP4725.h" #define NUM_DACS 2 DFRobot_MCP4725 dacs[NUM_DACS]; uint8_t dac_power_down[NUM_DACS]; From feae448453e3537f4db3dd9bf5e3db9dd100296a Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 5 Nov 2024 20:29:04 -0500 Subject: [PATCH 058/181] Indentation: 2 spaces -> tabs With tabs, each person can choose the display size --- TestBench/TestBench.ino | 312 ++++++++++++++++++++-------------------- 1 file changed, 158 insertions(+), 154 deletions(-) diff --git a/TestBench/TestBench.ino b/TestBench/TestBench.ino index 80b7202..a113a5f 100644 --- a/TestBench/TestBench.ino +++ b/TestBench/TestBench.ino @@ -2,12 +2,12 @@ #include #include "MCP4021.h" -//#define STM32 +// #define STM32 #ifdef STM32 -#define SERIAL SerialUSB -#define HAL_DAC_MODULE_ENABLED 1 + #define SERIAL SerialUSB + #define HAL_DAC_MODULE_ENABLED 1 #else -#define SERIAL Serial + #define SERIAL Serial #endif const int TESTER_ID = 2; @@ -15,26 +15,28 @@ const int TESTER_ID = 2; #define DAC #ifdef STM32 -#ifdef DAC -#warning "Can't have both DAC and STM32 enabled" -#endif + #ifdef DAC + #warning "Can't have both DAC and STM32 enabled" + #endif #endif #ifdef DAC -#include "DFRobot_MCP4725.h" -#define NUM_DACS 2 -DFRobot_MCP4725 dacs[NUM_DACS]; -uint8_t dac_power_down[NUM_DACS]; -const uint16_t dac_vref = 255; + #include "DFRobot_MCP4725.h + #define NUM_DACS 2 + + DFRobot_MCP4725 dacs[NUM_DACS]; + uint8_t dac_power_down[NUM_DACS]; + const uint16_t dac_vref = 255; #endif #define DIGIPOT_EN #ifdef DIGIPOT_EN -const uint8_t DIGIPOT_UD_PIN = 7; -const uint8_t DIGIPOT_CS1_PIN = 22; // A4 -const uint8_t DIGIPOT_CS2_PIN = 23; // A5 -MCP4021 digipot1(DIGIPOT_CS1_PIN, DIGIPOT_UD_PIN, false); // initialize Digipot 1 -MCP4021 digipot2(DIGIPOT_CS2_PIN, DIGIPOT_UD_PIN, false); // initialize Digipot 2 + const uint8_t DIGIPOT_UD_PIN = 7; + const uint8_t DIGIPOT_CS1_PIN = 22; // A4 + const uint8_t DIGIPOT_CS2_PIN = 23; // A5 + + MCP4021 digipot1(DIGIPOT_CS1_PIN, DIGIPOT_UD_PIN, false); // initialize Digipot 1 + MCP4021 digipot2(DIGIPOT_CS2_PIN, DIGIPOT_UD_PIN, false); // initialize Digipot 2 #endif int count = 0; @@ -42,173 +44,175 @@ char data[3]; struct Command { - Command(uint8_t command=0, uint8_t pin=0, uint8_t value=0) - { - data[0] = command; - data[1] = pin; - data[2] = value; - }; - - void reinit(char data[]) - { - this->data[0] = data[0]; - this->data[1] = data[1]; - this->data[2] = data[2]; - }; - - uint8_t command() { return data[0];}; - uint8_t pin() { return data[1]; }; - uint16_t value() { - return data[2]; - }; - int size() { return 3 * sizeof(char); }; - char data[3]; + Command(uint8_t command=0, uint8_t pin=0, uint8_t value=0) + { + data[0] = command; + data[1] = pin; + data[2] = value; + }; + + void reinit(char data[]) + { + this->data[0] = data[0]; + this->data[1] = data[1]; + this->data[2] = data[2]; + }; + + uint8_t command() { return data[0]; }; + uint8_t pin() { return data[1]; }; + uint16_t value() { return data[2]; }; + int size() { return 3 * sizeof(char); }; + + char data[3]; }; enum GpioCommands { - READ_ADC = 0, - READ_GPIO = 1, - WRITE_DAC = 2, - WRITE_GPIO = 3, - READ_ID = 4, - WRITE_POT = 5, + READ_ADC = 0, + READ_GPIO = 1, + WRITE_DAC = 2, + WRITE_GPIO = 3, + READ_ID = 4, + WRITE_POT = 5, }; void setup() { - SERIAL.begin(115200); + SERIAL.begin(115200); #ifdef DIGIPOT_EN - // Setting up Digipot 1 - digipot1.setup(); - digipot1.begin(); + // Setting up Digipot 1 + digipot1.setup(); + digipot1.begin(); - // Setting up Digipot 2 - digipot2.setup(); - digipot2.begin(); + // Setting up Digipot 2 + digipot2.setup(); + digipot2.begin(); #endif #ifdef DAC - dacs[0].init(0x63, dac_vref); - dacs[1].init(0x62, dac_vref); - dacs[0].setMode(MCP4725_POWER_DOWN_500KRES); - dacs[1].setMode(MCP4725_POWER_DOWN_500KRES); - dac_power_down[0] = 1; - dac_power_down[1] = 1; + dacs[0].init(0x63, dac_vref); + dacs[1].init(0x62, dac_vref); + dacs[0].setMode(MCP4725_POWER_DOWN_500KRES); + dacs[1].setMode(MCP4725_POWER_DOWN_500KRES); + dac_power_down[0] = 1; + dac_power_down[1] = 1; #endif } void error(String error_string) { - SERIAL.write(0xFF); - SERIAL.write(0xFF); - SERIAL.println(error_string); + SERIAL.write(0xFF); + SERIAL.write(0xFF); + SERIAL.println(error_string); } void loop() { - if (SERIAL.available() >= 3) - { - data[0] = SERIAL.read(); - data[1] = SERIAL.read(); - data[2] = SERIAL.read(); - Command c; - c.reinit(data); - count++; - uint8_t command = c.command(); - uint8_t pin = c.pin(); - uint16_t value = c.value(); - - switch (command) - { - case (WRITE_GPIO): - { - //if (pin < DIGITAL_PIN_COUNT) - if (1) - { - pinMode(pin, OUTPUT); - digitalWrite(pin, value); - } - else - { - error("GPIO PIN COUNT EXCEEDED"); - } - break; - } - case (READ_GPIO): - { + if (SERIAL.available() >= 3) + { + data[0] = SERIAL.read(); + data[1] = SERIAL.read(); + data[2] = SERIAL.read(); + + Command c; + c.reinit(data); + + count++; + + uint8_t command = c.command(); + uint8_t pin = c.pin(); + uint16_t value = c.value(); + + switch (command) + { + case (WRITE_GPIO): + { + //if (pin < DIGITAL_PIN_COUNT) + if (1) + { + pinMode(pin, OUTPUT); + digitalWrite(pin, value); + } + else + { + error("GPIO PIN COUNT EXCEEDED"); + } + break; + } + case (READ_GPIO): + { #ifdef DAC - if (pin >= 200 && pin < 200 + NUM_DACS) - { - dacs[pin - 200].setMode(MCP4725_POWER_DOWN_500KRES); - dac_power_down[pin - 200] = 1; - SERIAL.write(0x01); - } - else + if (pin >= 200 && pin < 200 + NUM_DACS) + { + dacs[pin - 200].setMode(MCP4725_POWER_DOWN_500KRES); + dac_power_down[pin - 200] = 1; + SERIAL.write(0x01); + } + else #endif - { - pinMode(pin, INPUT); - int val = digitalRead(pin); - SERIAL.write(val & 0xFF); - } - break; - } - case (WRITE_DAC): - { + { + pinMode(pin, INPUT); + int val = digitalRead(pin); + SERIAL.write(val & 0xFF); + } + break; + } + case (WRITE_DAC): + { #ifdef DAC - if (pin >= 200 && pin < 200 + NUM_DACS) - { - if (dac_power_down[pin-200]) - { - dacs[pin-200].setMode(MCP4725_NORMAL_MODE); - dac_power_down[pin - 200] = 0; - } - dacs[pin - 200].outputVoltage(value & 0xFF); - } + if (pin >= 200 && pin < 200 + NUM_DACS) + { + if (dac_power_down[pin-200]) + { + dacs[pin-200].setMode(MCP4725_NORMAL_MODE); + dac_power_down[pin - 200] = 0; + } + dacs[pin - 200].outputVoltage(value & 0xFF); + } #endif #ifdef STM32 - // 4 and 5 have DAC on f407 - pinMode(pin, OUTPUT); - analogWrite(pin, value & 0xFF); // max val 255 + // 4 and 5 have DAC on f407 + pinMode(pin, OUTPUT); + analogWrite(pin, value & 0xFF); // max val 255 #endif - break; - } - case (READ_ADC): - { - //if (pin <= ANALOG_PIN_COUNT) - if (1) - { - int val = analogRead(pin); - SERIAL.write((val >> 8) & 0xFF); - SERIAL.write(val & 0xFF); - } - else - { - error("ADC PIN COUNT EXCEEDED"); - } - break; - } - case (READ_ID): - { - SERIAL.write(TESTER_ID); - break; - } - case (WRITE_POT): - { + break; + } + case (READ_ADC): + { + //if (pin <= ANALOG_PIN_COUNT) + if (1) + { + int val = analogRead(pin); + SERIAL.write((val >> 8) & 0xFF); + SERIAL.write(val & 0xFF); + } + else + { + error("ADC PIN COUNT EXCEEDED"); + } + break; + } + case (READ_ID): + { + SERIAL.write(TESTER_ID); + break; + } + case (WRITE_POT): + { #ifdef DIGIPOT_EN - if (pin == 1) - digipot1.setTap((uint8_t) value); - else if (pin == 2) - digipot2.setTap((uint8_t) value); - else + if (pin == 1) + digipot1.setTap((uint8_t) value); + else if (pin == 2) + digipot2.setTap((uint8_t) value); + else #endif - { - error("POT PIN COUNT EXCEEDED"); - } - break; - } - } - } + { + error("POT PIN COUNT EXCEEDED"); + } + break; + } + } + } } From 187548b6fa377d8ed0bacae94e153be6d43a41c2 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 5 Nov 2024 20:47:28 -0500 Subject: [PATCH 059/181] Adding README to the repo for how I think it could be run --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..d839eae --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# HIL Tester for PER + +## Running + +- Code in `./TestBench` runs on the Arduino + - Basically it just reads commands over the serial port and either executs them or writes messages back over the serial port + - To flash it, use the Arduino IDE +- Code in `./Scripts` runs on your laptop + - It uses all the Python files + - Each file in `./Scripts` can run a Pytest script to test some board on the car + - Do `./run.sh [filename]` to run the script, or no filename to run all of them. \ No newline at end of file From c28cbff0ed25cdd539217cbee4d18bd5c3bf450b Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 5 Nov 2024 20:55:00 -0500 Subject: [PATCH 060/181] typo fix (missing end quote) --- TestBench/TestBench.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestBench/TestBench.ino b/TestBench/TestBench.ino index a113a5f..5b8517d 100644 --- a/TestBench/TestBench.ino +++ b/TestBench/TestBench.ino @@ -21,7 +21,7 @@ const int TESTER_ID = 2; #endif #ifdef DAC - #include "DFRobot_MCP4725.h + #include "DFRobot_MCP4725.h" #define NUM_DACS 2 DFRobot_MCP4725 dacs[NUM_DACS]; From ffc8ecaa8d412220509b622bdda2cb1ebc753ccd Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 5 Nov 2024 20:56:35 -0500 Subject: [PATCH 061/181] Fixing misnamed test script --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d839eae..c6297dc 100644 --- a/README.md +++ b/README.md @@ -8,4 +8,4 @@ - Code in `./Scripts` runs on your laptop - It uses all the Python files - Each file in `./Scripts` can run a Pytest script to test some board on the car - - Do `./run.sh [filename]` to run the script, or no filename to run all of them. \ No newline at end of file + - Do `./test.sh [filename]` to run the script, or no filename to run all of them. \ No newline at end of file From 40780dccc767591771b278d865c7111ec3eb5969 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 5 Nov 2024 21:00:44 -0500 Subject: [PATCH 062/181] type hints fix: global + type hint = bad Now: - Declared in global scope with type hint - Simply assigned in utils.initGlobals() --- hil/utils.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/hil/utils.py b/hil/utils.py index c8d4758..1f184cd 100644 --- a/hil/utils.py +++ b/hil/utils.py @@ -11,6 +11,15 @@ from communication.daq_protocol import DaqProtocol +signals: dict = {} +b_str: str = "" +data_types: dict[str, np.dtype] = {} +data_type_length: dict[str, int] = {} +debug_mode: bool = True +daqProt: DaqProtocol = None +hilProt: HIL = None + + def initGlobals(): global signals signals = {} @@ -37,16 +46,16 @@ def initGlobals(): # global plot_x_range_sec - # plot_x_range_sec: int = 10 + # plot_x_range_sec = 10 # global events - # events: list = [] + # events = [] global b_str - b_str: str = "Main" + b_str = "Main" global data_types - data_types: dict[str, np.dtype] = { + data_types = { 'uint8_t': np.dtype(' Date: Tue, 5 Nov 2024 21:24:24 -0500 Subject: [PATCH 063/181] Fixing imports. Everything relative to ./ instead of ./hil now - Only fixed for test_abox - Broke 2 type hints in the process to solve the circular dependency --- hil/communication/can_bus.py | 7 ++++--- hil/communication/client.py | 2 +- hil/communication/daq_protocol.py | 4 ++-- hil/components/component.py | 7 ++++--- hil/hil.py | 20 ++++++++++---------- hil/hil_devices/hil_device.py | 4 ++-- hil/pin_mapper.py | 2 +- hil/utils.py | 9 +++++---- scripts/test_abox.py | 3 ++- 9 files changed, 31 insertions(+), 27 deletions(-) diff --git a/hil/communication/can_bus.py b/hil/communication/can_bus.py index 3eefad6..2408d5a 100644 --- a/hil/communication/can_bus.py +++ b/hil/communication/can_bus.py @@ -1,5 +1,6 @@ -from collections.abc import Callable from __future__ import annotations +from collections.abc import Callable + from datetime import datetime import can import can.interfaces.gs_usb @@ -7,8 +8,8 @@ import socket import usb import cantools -from communication.client import TCPBus, UDPBus -import utils +from hil.communication.client import TCPBus, UDPBus +import hil.utils as utils import time import threading import numpy as np diff --git a/hil/communication/client.py b/hil/communication/client.py index 8677d19..b317f80 100644 --- a/hil/communication/client.py +++ b/hil/communication/client.py @@ -5,7 +5,7 @@ from threading import Thread import can from time import sleep -import utils +import hil.utils as utils import datetime # modification of: diff --git a/hil/communication/daq_protocol.py b/hil/communication/daq_protocol.py index c35f570..290f3ed 100644 --- a/hil/communication/daq_protocol.py +++ b/hil/communication/daq_protocol.py @@ -1,7 +1,7 @@ from __future__ import annotations -from communication.can_bus import BusSignal, CanBus +from hil.communication.can_bus import BusSignal, CanBus # from PyQt5 import QtCore -import utils +import hil.utils as utils import can import math import numpy as np diff --git a/hil/components/component.py b/hil/components/component.py index f3b1ffd..0eeba74 100644 --- a/hil/components/component.py +++ b/hil/components/component.py @@ -1,6 +1,6 @@ from collections.abc import Callable -import utils -from hil.hil import HIL +import hil.utils as utils +# from hil.hil import HIL class Component(): """ @@ -9,7 +9,8 @@ class Component(): When in measurement or emulation, a source must be specified. """ - def __init__(self, name: str, hil_con: tuple[str, str], mode: str, hil: HIL): + def __init__(self, name: str, hil_con: tuple[str, str], mode: str, hil): + # def __init__(self, name: str, hil_con: tuple[str, str], mode: str, hil: HIL): self.name: str = name self._state = 0 diff --git a/hil/hil.py b/hil/hil.py index 6b9c0a8..8a68e21 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -1,17 +1,17 @@ -import utils +import hil.utils as utils import os import signal import sys # import time -from pin_mapper import PinMapper -from hil_devices.hil_device import HilDevice -from hil_devices.serial_manager import SerialManager -from components.component import Component - -from communication.can_bus import CanBus, BusSignal -from communication.daq_protocol import DaqProtocol -from communication.daq_protocol import DAQPin -from communication.daq_protocol import DAQVariable +from hil.pin_mapper import PinMapper +from hil.hil_devices.hil_device import HilDevice +from hil.hil_devices.serial_manager import SerialManager +from hil.components.component import Component + +from hil.communication.can_bus import CanBus, BusSignal +from hil.communication.daq_protocol import DaqProtocol +from hil.communication.daq_protocol import DAQPin +from hil.communication.daq_protocol import DAQVariable """ HIL TESTER """ diff --git a/hil/hil_devices/hil_device.py b/hil/hil_devices/hil_device.py index 9949a8c..0b4fd3d 100644 --- a/hil/hil_devices/hil_device.py +++ b/hil/hil_devices/hil_device.py @@ -2,9 +2,9 @@ # import time # import serial # import serial.tools.list_ports -from hil_devices.serial_manager import SerialManager +from hil.hil_devices.serial_manager import SerialManager -import utils +import hil.utils as utils HIL_CMD_MASK = 0xFF HIL_CMD_READ_ADC = 0 diff --git a/hil/pin_mapper.py b/hil/pin_mapper.py index 8f80a57..218bf5d 100644 --- a/hil/pin_mapper.py +++ b/hil/pin_mapper.py @@ -2,7 +2,7 @@ import os #from hil_devices.hil_device import HilDevice import csv -import utils +import hil.utils as utils """ PIN MAPPER """ diff --git a/hil/utils.py b/hil/utils.py index 1f184cd..2eccc7f 100644 --- a/hil/utils.py +++ b/hil/utils.py @@ -6,9 +6,9 @@ from jsonschema import validate from jsonschema.exceptions import ValidationError -from components.component import Component -from hil.hil import HIL -from communication.daq_protocol import DaqProtocol +from hil.components.component import Component +# from hil.hil import HIL +from hil.communication.daq_protocol import DaqProtocol signals: dict = {} @@ -17,7 +17,8 @@ data_type_length: dict[str, int] = {} debug_mode: bool = True daqProt: DaqProtocol = None -hilProt: HIL = None +# hilProt: HIL = None +hilProt = None def initGlobals(): diff --git a/scripts/test_abox.py b/scripts/test_abox.py index 55b4483..1663875 100644 --- a/scripts/test_abox.py +++ b/scripts/test_abox.py @@ -1,5 +1,6 @@ from os import sys, path -sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) +sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) + from hil.hil import HIL import hil.utils as utils import time From 2c568c9b37237a5657cbaffe2b5cc10ebe342d51 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 5 Nov 2024 21:26:43 -0500 Subject: [PATCH 064/181] Fixing path for all pytest scripts --- scripts/config_dash.py | 6 ++++-- scripts/test_abox.py | 3 ++- scripts/test_charger.py | 5 +++-- scripts/test_collector.py | 6 ++++-- scripts/test_main_base.py | 6 ++++-- scripts/test_main_sdc.py | 6 ++++-- scripts/test_system.py | 6 ++++-- scripts/test_test.py | 6 ++++-- scripts/vehicle_constants.py | 6 ++++-- 9 files changed, 33 insertions(+), 17 deletions(-) diff --git a/scripts/config_dash.py b/scripts/config_dash.py index 2aeb330..2266bbb 100644 --- a/scripts/config_dash.py +++ b/scripts/config_dash.py @@ -1,5 +1,7 @@ -from os import sys, path -sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) +from os import sys, path +# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher +sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) + from hil.hil import HIL import hil.utils as utils import time diff --git a/scripts/test_abox.py b/scripts/test_abox.py index 1663875..99e9269 100644 --- a/scripts/test_abox.py +++ b/scripts/test_abox.py @@ -1,4 +1,5 @@ -from os import sys, path +from os import sys, path +# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) from hil.hil import HIL diff --git a/scripts/test_charger.py b/scripts/test_charger.py index 651661e..4b7138c 100644 --- a/scripts/test_charger.py +++ b/scripts/test_charger.py @@ -1,5 +1,6 @@ -from os import sys, path -sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) +from os import sys, path +# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher +sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) from hil.hil import HIL import hil.utils as utils diff --git a/scripts/test_collector.py b/scripts/test_collector.py index 02df12a..bc27ee3 100644 --- a/scripts/test_collector.py +++ b/scripts/test_collector.py @@ -1,5 +1,7 @@ -from os import sys, path -sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) +from os import sys, path +# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher +sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) + from hil.hil import HIL import hil.utils as utils import time diff --git a/scripts/test_main_base.py b/scripts/test_main_base.py index cf9f794..3a50363 100644 --- a/scripts/test_main_base.py +++ b/scripts/test_main_base.py @@ -1,5 +1,7 @@ -from os import sys, path -sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) +from os import sys, path +# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher +sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) + from hil.hil import HIL import hil.utils as utils import time diff --git a/scripts/test_main_sdc.py b/scripts/test_main_sdc.py index 75d4602..c084436 100644 --- a/scripts/test_main_sdc.py +++ b/scripts/test_main_sdc.py @@ -1,5 +1,7 @@ -from os import sys, path -sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) +from os import sys, path +# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher +sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) + from hil.hil import HIL import hil.utils as utils import time diff --git a/scripts/test_system.py b/scripts/test_system.py index 8725cf2..62202b2 100644 --- a/scripts/test_system.py +++ b/scripts/test_system.py @@ -1,5 +1,7 @@ -from os import sys, path -sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) +from os import sys, path +# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher +sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) + from hil.hil import HIL import hil.utils as utils import time diff --git a/scripts/test_test.py b/scripts/test_test.py index 6429464..c170ccb 100644 --- a/scripts/test_test.py +++ b/scripts/test_test.py @@ -1,5 +1,7 @@ -from os import sys, path -sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) +from os import sys, path +# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher +sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) + from hil.hil import HIL # import hil.utils as utils import time diff --git a/scripts/vehicle_constants.py b/scripts/vehicle_constants.py index 0340fe9..4db3f2a 100644 --- a/scripts/vehicle_constants.py +++ b/scripts/vehicle_constants.py @@ -1,5 +1,7 @@ -from os import sys, path -sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'hil')) +from os import sys, path +# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher +sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) + import hil.utils as utils # NOTE: each value in this file should be a physical or electrical property of the vehicle From 083f4d65d8fd8e1a41fc26798f70240587179481 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 5 Nov 2024 21:31:19 -0500 Subject: [PATCH 065/181] using typing.TYPE_CHECKING to avoid circular dependencies --- hil/components/component.py | 8 +++++--- hil/utils.py | 9 ++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/hil/components/component.py b/hil/components/component.py index 0eeba74..b38d8fa 100644 --- a/hil/components/component.py +++ b/hil/components/component.py @@ -1,6 +1,9 @@ from collections.abc import Callable +from typing import TYPE_CHECKING + import hil.utils as utils -# from hil.hil import HIL +if TYPE_CHECKING: + from hil.hil import HIL class Component(): """ @@ -9,8 +12,7 @@ class Component(): When in measurement or emulation, a source must be specified. """ - def __init__(self, name: str, hil_con: tuple[str, str], mode: str, hil): - # def __init__(self, name: str, hil_con: tuple[str, str], mode: str, hil: HIL): + def __init__(self, name: str, hil_con: tuple[str, str], mode: str, hil: 'HIL'): self.name: str = name self._state = 0 diff --git a/hil/utils.py b/hil/utils.py index 2eccc7f..0bfd8c8 100644 --- a/hil/utils.py +++ b/hil/utils.py @@ -1,3 +1,5 @@ +from typing import TYPE_CHECKING + import sys import time import numpy as np @@ -7,9 +9,11 @@ from jsonschema.exceptions import ValidationError from hil.components.component import Component -# from hil.hil import HIL from hil.communication.daq_protocol import DaqProtocol +if TYPE_CHECKING: + from hil.hil import HIL + signals: dict = {} b_str: str = "" @@ -17,8 +21,7 @@ data_type_length: dict[str, int] = {} debug_mode: bool = True daqProt: DaqProtocol = None -# hilProt: HIL = None -hilProt = None +hilProt: 'HIL' = None def initGlobals(): From 26fcd2f0bd6b91562344011ed2605a6ebc58f0d7 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 5 Nov 2024 21:38:02 -0500 Subject: [PATCH 066/181] Removing unneeded logging --- hil/hil.py | 25 +------------------------ hil/utils.py | 8 -------- pytest-example/fake_test.py | 10 ---------- 3 files changed, 1 insertion(+), 42 deletions(-) diff --git a/hil/hil.py b/hil/hil.py index 8a68e21..efc4d2f 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -25,8 +25,6 @@ class HIL(): - - @utils.log_function_start_end def __init__(self): utils.initGlobals() self.components: dict[str, Component] = {} @@ -46,7 +44,6 @@ def __init__(self): # self.global_check_count = 0 # multiple checks within a test # self.global_test_count = 0 - @utils.log_function_start_end def init_can(self) -> None: config = self.hil_params self.daq_config = utils.load_json_config(os.path.join(config['firmware_path'], config['daq_config_path']), os.path.join(config['firmware_path'], config['daq_schema_path'])) @@ -58,7 +55,6 @@ def init_can(self) -> None: self.can_bus.connect() self.can_bus.start() - @utils.log_function_start_end def load_pin_map(self, net_map: str, pin_map: str) -> None: net_map_f = os.path.join(NET_MAP_PATH, net_map) pin_map_f = os.path.join(PIN_MAP_PATH, pin_map) @@ -66,19 +62,16 @@ def load_pin_map(self, net_map: str, pin_map: str) -> None: self.pin_map = PinMapper(net_map_f) self.pin_map.load_mcu_pin_map(pin_map_f) - @utils.log_function_start_end def clear_components(self) -> None: """ Reset HIL""" for c in self.components.values(): c.shutdown() self.components = {} - @utils.log_function_start_end def clear_hil_devices(self) -> None: self.hil_devices = {} self.serial_manager.close_devices() - @utils.log_function_start_end def shutdown(self) -> None: print(f"{utils.bcolors.OKCYAN}HIL shutdown START{utils.bcolors.ENDC}") self.clear_components() @@ -86,7 +79,6 @@ def shutdown(self) -> None: self.stop_can() print(f"{utils.bcolors.OKGREEN}HIL shutdown START{utils.bcolors.OKGREEN}") - @utils.log_function_start_end def stop_can(self) -> None: print(f"{utils.bcolors.OKCYAN}HIL stop_can START{utils.bcolors.ENDC}") if not self.can_bus: return @@ -99,7 +91,6 @@ def stop_can(self) -> None: self.can_bus.disconnect_bus() print(f"{utils.bcolors.OKGREEN}HIL stop_can END{utils.bcolors.ENDC}") - @utils.log_function_start_end def load_config(self, config_name: str) -> None: config = utils.load_json_config(os.path.join(CONFIG_PATH, config_name), None) # TODO: validate w/ schema @@ -111,7 +102,6 @@ def load_config(self, config_name: str) -> None: # Setup corresponding components self.load_connections(config['dut_connections']) - @utils.log_function_start_end def load_connections(self, dut_connections: dict) -> None: self.dut_connections = {} # Dictionary format: @@ -128,7 +118,6 @@ def load_connections(self, dut_connections: dict) -> None: self.dut_connections[board_name][connector] = {} self.dut_connections[board_name][connector][pin] = hil_port - @utils.log_function_start_end def add_component(self, board: str, net: str, mode: str) -> Component: # If board is a HIL device, net is expected to be port name # If board is a DUT device, net is expected to be a net name from the board @@ -144,7 +133,6 @@ def add_component(self, board: str, net: str, mode: str) -> Component: utils.log_warning(f"Component {comp_name} already exists") return self.components[comp_name] - @utils.log_function_start_end def load_hil_devices(self, hil_devices: dict) -> None: self.clear_hil_devices() self.serial_manager.discover_devices() @@ -154,14 +142,12 @@ def load_hil_devices(self, hil_devices: dict) -> None: else: self.handle_error(f"Failed to discover HIL device {hil_device['name']} with id {hil_device['id']}") - @utils.log_function_start_end def get_hil_device(self, name: str) -> HilDevice: if name in self.hil_devices: return self.hil_devices[name] else: self.handle_error(f"HIL device {name} not recognized") - @utils.log_function_start_end def get_hil_device_connection(self, board: str, net: str) -> tuple[str, str]: """ Converts dut net to hil port name """ if not board in self.dut_connections: @@ -180,33 +166,27 @@ def get_hil_device_connection(self, board: str, net: str) -> tuple[str, str]: utils.log_warning(net_cons) self.handle_error(f"Connect dut to {net} on {board}.") - @utils.log_function_start_end def din(self, board: str, net: str) -> Component: return self.add_component(board, net, 'DI') - @utils.log_function_start_end + def dout(self, board: str, net: str) -> Component: return self.add_component(board, net, 'DO') - @utils.log_function_start_end def ain(self, board: str, net: str) -> Component: return self.add_component(board, net, 'AI') - @utils.log_function_start_end def aout(self, board: str, net: str) -> Component: return self.add_component(board, net, 'AO') - @utils.log_function_start_end def pot(self, board: str, net: str) -> Component: return self.add_component(board, net, 'POT') - @utils.log_function_start_end def daq_var(self, board: str, var_name: str) -> DAQVariable: try: return utils.signals[utils.b_str][board][f"daq_response_{board.upper()}"][var_name] except KeyError as e: self.handle_error(f"Unable to locate DAQ variable {var_name} of {board}") - @utils.log_function_start_end def can_var(self, board: str, message_name: str, signal_name: str) -> BusSignal: # TODO: not sure if any of the type hints are correct try: @@ -214,7 +194,6 @@ def can_var(self, board: str, message_name: str, signal_name: str) -> BusSignal: except KeyError: self.handle_error(f"Unable to locate CAN signal {signal_name} of message {message_name} of board {board}") - @utils.log_function_start_end def mcu_pin(self, board: str, net: str) -> DAQPin: bank, pin = self.pin_map.get_mcu_pin(board, net) if bank == None: @@ -246,14 +225,12 @@ def mcu_pin(self, board: str, net: str) -> DAQPin: # def end_test(self): # print(f"{utils.bcolors.OKCYAN}{self.curr_test} failed {self.curr_test_fail_count} out of {self.curr_test_count} checks{utils.bcolors.ENDC}") - @utils.log_function_start_end def handle_error(self, msg: str) -> None: utils.log_error(msg) self.shutdown() exit(0) -@utils.log_function_start_end def signal_int_handler(signum, frame) -> None: utils.log("Received signal interrupt, shutting down") if (utils.hilProt): diff --git a/hil/utils.py b/hil/utils.py index 0bfd8c8..351e71b 100644 --- a/hil/utils.py +++ b/hil/utils.py @@ -93,14 +93,6 @@ def initGlobals(): global hilProt hilProt = None -# display current function start/end -def log_function_start_end(func): - def wrapper_function(*args, **kwargs): - global debug_mode - if debug_mode: print(f"{bcolors.OKCYAN}START: {func.__name__}{bcolors.ENDC}") - func(*args, **kwargs) - if debug_mode: print(f"{bcolors.OKCYAN}END: {func.__name__}{bcolors.ENDC}") - return wrapper_function # Logging helper functions class bcolors: diff --git a/pytest-example/fake_test.py b/pytest-example/fake_test.py index a85317e..beed2b8 100644 --- a/pytest-example/fake_test.py +++ b/pytest-example/fake_test.py @@ -30,19 +30,9 @@ def param(): yield param_instance -def log_function_start_end(func): - def wrapper_function(*args, **kwargs): - print(f"START: {func.__name__}") - func(*args, **kwargs) - print(f"END: {func.__name__}") - return wrapper_function - - -@log_function_start_end def do_something(): print("Doing something") -@log_function_start_end def do_something_with_args(arg1, arg2): print(f"Arg1: {arg1}, Arg2: {arg2}") From 561adb7031a456da00ad59dd43743f35dec61cfe Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 5 Nov 2024 21:43:47 -0500 Subject: [PATCH 067/181] Firmware path for Millan Kumar --- hil_params.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hil_params.json b/hil_params.json index b9562e7..142f056 100644 --- a/hil_params.json +++ b/hil_params.json @@ -1,5 +1,5 @@ { - "firmware_path": "C:/users/lukeo/Documents/firmware", + "firmware_path": "/home/millankumar/Documents/PER/firmware", "daq_config_path": "common/daq/daq_config.json", "daq_schema_path": "common/daq/daq_schema.json", "dbc_path": "common/daq/per_dbc.dbc", From cfc04a5ba41e2df586887828426685763b0eb59d Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 5 Nov 2024 21:49:23 -0500 Subject: [PATCH 068/181] Correctly initializing can for test_test.py --- scripts/test_test.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/test_test.py b/scripts/test_test.py index c170ccb..b2536bb 100644 --- a/scripts/test_test.py +++ b/scripts/test_test.py @@ -20,8 +20,7 @@ def hil(): # hil.load_config("config_testing.json") hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") - - # hil_instance.init_can() + hil_instance.init_can() yield hil_instance From b986258964bc5da8225f5b0d41a4011ff6540967 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 5 Nov 2024 22:06:02 -0500 Subject: [PATCH 069/181] Debug print for while CanBus init fails --- hil/hil.py | 1 + 1 file changed, 1 insertion(+) diff --git a/hil/hil.py b/hil/hil.py index efc4d2f..d9a4ae7 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -49,6 +49,7 @@ def init_can(self) -> None: self.daq_config = utils.load_json_config(os.path.join(config['firmware_path'], config['daq_config_path']), os.path.join(config['firmware_path'], config['daq_schema_path'])) self.can_config = utils.load_json_config(os.path.join(config['firmware_path'], config['can_config_path']), os.path.join(config['firmware_path'], config['can_schema_path'])) + print(f"PATH: {os.path.join(config['firmware_path'], config['dbc_path'])}") self.can_bus = CanBus(os.path.join(config['firmware_path'], config['dbc_path']), config['default_ip'], self.can_config) self.daq_protocol = DaqProtocol(self.can_bus, self.daq_config) From 4f635fc1a92f174acdc74a692afbe830781f2e68 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Wed, 6 Nov 2024 08:45:50 -0500 Subject: [PATCH 070/181] Pytest for config_dash.py --- scripts/config_dash.py | 131 +++++++++++++++++++++++++++++------------ 1 file changed, 93 insertions(+), 38 deletions(-) diff --git a/scripts/config_dash.py b/scripts/config_dash.py index 2266bbb..57501f2 100644 --- a/scripts/config_dash.py +++ b/scripts/config_dash.py @@ -8,11 +8,32 @@ from rules_constants import * from vehicle_constants import * +import pytest_check as check +import pytest + +# ---------------------------------------------------------------------------- # +@pytest.fixture(scope="session") +def hil(): + hil_instance = HIL() + + hil_instance.load_config("config_system_hil_attached.json") + hil_instance.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + hil_instance.init_can() + + yield hil_instance + + hil_instance.shutdown() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # BRK_SWEEP_DELAY = 0.1 + def test_bspd(hil): # Begin the test - hil.start_test(test_bspd.__name__) + # hil.start_test(test_bspd.__name__) # Outputs brk1 = hil.aout("Dashboard", "BRK1_RAW") @@ -25,23 +46,34 @@ def test_bspd(hil): # Brake threshold check brk1.state = BRK_1_REST_V brk2.state = BRK_2_REST_V - hil.check(brk_stat_tap.state == 0, "Brake stat starts low") + # hil.check(brk_stat_tap.state == 0, "Brake stat starts low") + check.equal(brk_stat_tap.state, 0, "Brake stat starts low") + brk1.state = BRK_1_THRESH_V time.sleep(0.1) - hil.check(brk_stat_tap.state == 1, "Brake stat goes high at brk 1 thresh") + # hil.check(brk_stat_tap.state == 1, "Brake stat goes high at brk 1 thresh") + check.equal(brk_stat_tap.state, 1, "Brake stat goes high at brk 1 thresh") + brk1.state = BRK_1_REST_V - hil.check(brk_stat_tap.state == 0, "Brake stat starts low") + # hil.check(brk_stat_tap.state == 0, "Brake stat starts low") + check.equal(brk_stat_tap.state, 0, "Brake stat starts low") + brk2.state = BRK_2_THRESH_V time.sleep(0.1) - hil.check(brk_stat_tap.state == 1, "Brake stat goes high at brk 2 thresh") + # hil.check(brk_stat_tap.state == 1, "Brake stat goes high at brk 2 thresh") + check.equal(brk_stat_tap.state, 1, "Brake stat goes high at brk 2 thresh") + brk1.state = BRK_1_THRESH_V - hil.check(brk_stat_tap.state == 1, "Brake stat stays high for both brakes") + # hil.check(brk_stat_tap.state == 1, "Brake stat stays high for both brakes") + check.equal(brk_stat_tap.state, 1, "Brake stat stays high for both brakes") + # Brake threshold scan brk1.state = BRK_MIN_OUT_V brk2.state = BRK_MIN_OUT_V time.sleep(0.1) - hil.check(brk_stat_tap.state == 0, "Brake Stat Starts Low Brk 1") + # hil.check(brk_stat_tap.state == 0, "Brake Stat Starts Low Brk 1") + check.equal(brk_stat_tap.state, 0, "Brake Stat Starts Low Brk 1") start = BRK_MIN_OUT_V stop = BRK_MAX_OUT_V @@ -51,8 +83,14 @@ def test_bspd(hil): BRK_SWEEP_DELAY, brk_stat_tap, is_falling=False) print(f"Brake 1 braking threshold: {thresh}") - hil.check_within(thresh, BRK_1_THRESH_V, 0.2, "Brake 1 trip voltage") - hil.check(brk_stat_tap.state == 1, "Brake Stat Tripped for Brk 1") + # hil.check_within(thresh, BRK_1_THRESH_V, 0.2, "Brake 1 trip voltage") + # hil.check(brk_stat_tap.state == 1, "Brake Stat Tripped for Brk 1") + check.almost_equal( + thresh, BRK_1_THRESH_V, + abs=0.2, rel=0.0, + msg="Brake 1 trip voltage" + ) + check.equal(brk_stat_tap.state, 1, "Brake Stat Tripped for Brk 1") brk1.state = BRK_MIN_OUT_V brk2.state = BRK_MIN_OUT_V @@ -61,66 +99,83 @@ def test_bspd(hil): BRK_SWEEP_DELAY, brk_stat_tap, is_falling=False) print(f"Brake 2 braking threshold: {thresh}") - hil.check_within(thresh, BRK_2_THRESH_V, 0.2, "Brake 2 trip voltage") - hil.check(brk_stat_tap.state == 1, "Brake Stat Tripped for Brk 2") + # hil.check_within(thresh, BRK_2_THRESH_V, 0.2, "Brake 2 trip voltage") + # hil.check(brk_stat_tap.state == 1, "Brake Stat Tripped for Brk 2") + check.almost_equal( + thresh, BRK_2_THRESH_V, + abs=0.2, rel=0.0, + msg="Brake 2 trip voltage" + ) + check.equal(brk_stat_tap.state, 1, "Brake Stat Tripped for Brk 2") # Brake Fail scan brk1.state = BRK_1_REST_V brk2.state = BRK_2_REST_V time.sleep(0.1) - hil.check(brk_fail_tap.state == 0, "Brake Fail Check 1 Starts 0") + # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 1 Starts 0") + check.equal(brk_fail_tap.state, 0, "Brake Fail Check 1 Starts 0") + brk1.state = 0.0 # Force 0 time.sleep(0.1) - hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Short GND") + # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Short GND") + check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 1 Short GND") + brk1.state = BRK_1_REST_V time.sleep(0.1) - hil.check(brk_fail_tap.state == 0, "Brake Fail Check 2 Starts 0") + # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 2 Starts 0") + check.equal(brk_fail_tap.state, 0, "Brake Fail Check 2 Starts 0") + brk2.state = 0.0 # Force 0 time.sleep(0.1) hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Short GND") + check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 2 Short GND") + brk2.state = BRK_2_REST_V time.sleep(0.1) - hil.check(brk_fail_tap.state == 0, "Brake Fail Check 3 Starts 0") + # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 3 Starts 0") + check.equal(brk_fail_tap.state, 0, "Brake Fail Check 3 Starts 0") + brk1.state = 5.0 # Short VCC time.sleep(0.1) - hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Short VCC") + # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Short VCC") + check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 1 Short VCC") + brk1.state = BRK_1_REST_V time.sleep(0.1) - hil.check(brk_fail_tap.state == 0, "Brake Fail Check 4 Starts 0") + # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 4 Starts 0") + check.equal(brk_fail_tap.state, 0, "Brake Fail Check 4 Starts 0") + brk2.state = 5.0 # Short VCC time.sleep(0.1) - hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Short VCC") + # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Short VCC") + check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 2 Short VCC") + brk2.state = BRK_2_REST_V time.sleep(0.1) - hil.check(brk_fail_tap.state == 0, "Brake Fail Check 5 Starts 0") + # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 5 Starts 0") + check.equal(brk_fail_tap.state, 0, "Brake Fail Check 5 Starts 0") + brk1.hiZ() time.sleep(0.1) - hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Hi-Z") + # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 1 Hi-Z") + check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 1 Hi-Z") + brk1.state = BRK_1_REST_V time.sleep(0.1) - hil.check(brk_fail_tap.state == 0, "Brake Fail Check 6 Starts 0") + # hil.check(brk_fail_tap.state == 0, "Brake Fail Check 6 Starts 0") + check.equal(brk_fail_tap.state, 0, "Brake Fail Check 6 Starts 0") + brk2.hiZ() time.sleep(0.1) - hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Hi-Z") + # hil.check(brk_fail_tap.state == 1, "Brake Fail Brk 2 Hi-Z") + check.equal(brk_fail_tap.state, 1, "Brake Fail Brk 2 Hi-Z") + brk2.state = BRK_2_REST_V # End the test - hil.end_test() + # hil.end_test() +# ---------------------------------------------------------------------------- # -# TODO: add throttle checks - - -if __name__ == "__main__": - hil = HIL() - - hil.load_config("config_system_hil_attached.json") - hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") - hil.init_can() - - # Drive Critical Tests - test_bspd(hil) - - # Peripheral Sensor Tests +# TODO: add throttle checks - hil.shutdown() From 66c90a81f59418995a4631e47780c8f609154fe7 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Wed, 6 Nov 2024 08:46:11 -0500 Subject: [PATCH 071/181] "config_dash" -> "test_dash" for naming consistency --- scripts/{config_dash.py => test_dash.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/{config_dash.py => test_dash.py} (100%) diff --git a/scripts/config_dash.py b/scripts/test_dash.py similarity index 100% rename from scripts/config_dash.py rename to scripts/test_dash.py From 5b692b95220ee973cc380b2c156f317a6e47b3f4 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Wed, 6 Nov 2024 08:50:29 -0500 Subject: [PATCH 072/181] Correctly lower casing scripts folder --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c6297dc..d6c0b14 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,8 @@ - Code in `./TestBench` runs on the Arduino - Basically it just reads commands over the serial port and either executs them or writes messages back over the serial port - To flash it, use the Arduino IDE -- Code in `./Scripts` runs on your laptop +- Code in `./scripts` runs on your laptop - It uses all the Python files - - Each file in `./Scripts` can run a Pytest script to test some board on the car - - Do `./test.sh [filename]` to run the script, or no filename to run all of them. \ No newline at end of file + - Each file in `./scripts` can run a Pytest script to test some board on the car + - Do `./test.sh [filename]` to run the script, or no filename to run all of them + - (Note: have to run from the `./scripts` directory) \ No newline at end of file From fd77a01754b9c31bf67662f542996f091b00d79a Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Wed, 6 Nov 2024 09:09:03 -0500 Subject: [PATCH 073/181] Adding note about firmware path --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d6c0b14..6650720 100644 --- a/README.md +++ b/README.md @@ -9,4 +9,5 @@ - It uses all the Python files - Each file in `./scripts` can run a Pytest script to test some board on the car - Do `./test.sh [filename]` to run the script, or no filename to run all of them - - (Note: have to run from the `./scripts` directory) \ No newline at end of file + - (Note: have to run from the `./scripts` directory) +- Make sure you correctly set `firmware_path` in `./hil_params.json` to the path of the primary PER firmware repo! \ No newline at end of file From 0c783f0d69dbad4b644c99cfeb8d49791867439e Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Fri, 8 Nov 2024 08:52:54 -0500 Subject: [PATCH 074/181] Format fix --- hil/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hil/utils.py b/hil/utils.py index 351e71b..607c74a 100644 --- a/hil/utils.py +++ b/hil/utils.py @@ -119,7 +119,7 @@ def log(phrase: str) -> None: global debug_mode if debug_mode: print(phrase) -def load_json_config(config_path: str, schema_path=None) -> dict: +def load_json_config(config_path: str, schema_path: str = None) -> dict: """ loads config from json and validates with schema """ config = json.load(open(config_path)) if (schema_path == None): return config # Bypass schema check From 2e8c2223d05641d7380ac46edfadd61f93117841 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Fri, 8 Nov 2024 22:02:10 -0500 Subject: [PATCH 075/181] A note about inputs vs output naming Likely obvious if you are competent, but I am not :shrug: --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6650720..6c9d1cb 100644 --- a/README.md +++ b/README.md @@ -10,4 +10,11 @@ - Each file in `./scripts` can run a Pytest script to test some board on the car - Do `./test.sh [filename]` to run the script, or no filename to run all of them - (Note: have to run from the `./scripts` directory) -- Make sure you correctly set `firmware_path` in `./hil_params.json` to the path of the primary PER firmware repo! \ No newline at end of file +- Make sure you correctly set `firmware_path` in `./hil_params.json` to the path of the primary PER firmware repo! + +## Notes + +### Input vs Output + +- `AI`/`DI` = inputs to hil (reads from the car/other board -> Arduino -> laptop/Python) +- `AO`/`DO` = outputs from hil (writes from laptop/Python -> Arduino -> car/other board) \ No newline at end of file From 9478ffebed52176b5ccb091272dd3af948ce963e Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Fri, 8 Nov 2024 22:03:11 -0500 Subject: [PATCH 076/181] Slightly cleaning code and adding prints --- scripts/test_collector.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/scripts/test_collector.py b/scripts/test_collector.py index bc27ee3..7b67d54 100644 --- a/scripts/test_collector.py +++ b/scripts/test_collector.py @@ -62,13 +62,22 @@ def test_collector(hil): m4.state = i & 0x8 time.sleep(0.01) - if (i == thermistor): - # hil.check_within(to.state, test_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") - check.almost_equal(to.state, test_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") + to_state = to.state + if i == thermistor: + expected_voltage = test_voltage else: - # hil.check_within(to.state, pullup_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") - check.almost_equal(to.state, pullup_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") - print(to.state) + expected_voltage = pullup_voltage + within = abs(to_state - expected_voltage) < tolerance_v + + print(f"({thermistor=}, {i=}) {to_state=} ?= {expected_voltage=} -> {within=}") + check.almost_equal(to_state, expected_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") + + # if i == thermistor: + # # hil.check_within(to.state, test_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") + # # check.almost_equal(to.state, test_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") + # else: + # # hil.check_within(to.state, pullup_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") + # # check.almost_equal(to.state, pullup_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") # End the test # hil.end_test() From c8c1563d3c6b54c219df367c0aee4fd0c35a73e7 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Fri, 8 Nov 2024 22:06:12 -0500 Subject: [PATCH 077/181] Adding a comment explaining the bit and-ing --- scripts/test_collector.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/test_collector.py b/scripts/test_collector.py index 7b67d54..511b518 100644 --- a/scripts/test_collector.py +++ b/scripts/test_collector.py @@ -56,6 +56,9 @@ def test_collector(hil): input("") for i in range(num_therm): + # MUX (multiplexer) = choose which output to return from the thermistor based on the input + # Like a giant switch statement (0 -> return thermistor 0, 1 -> return thermistor 1, etc.) + # Encode the current thermistor into binary where each bit corresponds to each pin being high or low m1.state = i & 0x1 m2.state = i & 0x2 m3.state = i & 0x4 From 857ea0e0698e15d60f37e06635bdbcdfdaa217e5 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 10:32:29 -0500 Subject: [PATCH 078/181] Only one arduino so id = 1?? --- configurations/config_collector_bench.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configurations/config_collector_bench.json b/configurations/config_collector_bench.json index 9a67bf7..cfc76d4 100644 --- a/configurations/config_collector_bench.json +++ b/configurations/config_collector_bench.json @@ -10,6 +10,6 @@ ]} ], "hil_devices":[ - {"name":"CollTester", "type":"arduino_uno", "id":5} + {"name":"CollTester", "type":"arduino_uno", "id":1} ] } From b15a9c3738c00372b27168c2fc7cea80a8bf90a2 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 10:33:09 -0500 Subject: [PATCH 079/181] Deleting old script code --- scripts/test_collector.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/scripts/test_collector.py b/scripts/test_collector.py index 511b518..b1ce8a5 100644 --- a/scripts/test_collector.py +++ b/scripts/test_collector.py @@ -85,13 +85,3 @@ def test_collector(hil): # End the test # hil.end_test() # ---------------------------------------------------------------------------- # - -# ---------------------------------------------------------------------------- # -# if __name__ == "__main__": - hil = HIL() - hil.load_config("config_collector_bench.json") - hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") - - test_collector(hil) - - hil.shutdown() From b3ed7ce2db8ca6e1a99d3ebad78b2e8365a95ec5 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 10:33:14 -0500 Subject: [PATCH 080/181] Cleaning prints --- hil/hil_devices/serial_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hil/hil_devices/serial_manager.py b/hil/hil_devices/serial_manager.py index 97db15c..5edea6d 100644 --- a/hil/hil_devices/serial_manager.py +++ b/hil/hil_devices/serial_manager.py @@ -9,7 +9,7 @@ def __init__(self): self.devices: dict[int, serial.Serial] = {} def discover_devices(self) -> None: - #print([a[1] for a in serial.tools.list_ports.comports()]) + # print([a[0] for a in serial.tools.list_ports.comports()]) ports = [a[0] for a in serial.tools.list_ports.comports() if ("Arduino" in a[1] or "USB Serial Device" in a[1])] self.devices = {} print('Arduinos found on ports ' + str(ports)) From e7652f669daf34207b78157c3c921a34feb333da Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 10:38:56 -0500 Subject: [PATCH 081/181] Can't use "input" with Pytest --- scripts/test_collector.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/test_collector.py b/scripts/test_collector.py index b1ce8a5..a7a1d7d 100644 --- a/scripts/test_collector.py +++ b/scripts/test_collector.py @@ -53,7 +53,9 @@ def test_collector(hil): for thermistor in range(num_therm): print(f"Place test input on thermistor {thermistor}. Press Enter when ready") - input("") + + # TODO: find some way to wait for user input + # input("") for i in range(num_therm): # MUX (multiplexer) = choose which output to return from the thermistor based on the input From 939b60aeae8f5fa812b663f118952cc02de44d30 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 10:39:08 -0500 Subject: [PATCH 082/181] Improving teardown print statements --- hil/hil.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hil/hil.py b/hil/hil.py index d9a4ae7..a2b25cf 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -78,11 +78,12 @@ def shutdown(self) -> None: self.clear_components() self.clear_hil_devices() self.stop_can() - print(f"{utils.bcolors.OKGREEN}HIL shutdown START{utils.bcolors.OKGREEN}") + print(f"{utils.bcolors.OKGREEN}HIL shutdown END{utils.bcolors.OKGREEN}") def stop_can(self) -> None: - print(f"{utils.bcolors.OKCYAN}HIL stop_can START{utils.bcolors.ENDC}") if not self.can_bus: return + print(f"{utils.bcolors.OKCYAN}HIL stop_can START{utils.bcolors.ENDC}") + if self.can_bus.connected: self.can_bus.connected = False self.can_bus.join() From 6c011e2b63b0f57504476dc7b2b53b4cf048c3a5 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 10:42:47 -0500 Subject: [PATCH 083/181] Improving prints --- scripts/test_collector.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/test_collector.py b/scripts/test_collector.py index a7a1d7d..3065b1c 100644 --- a/scripts/test_collector.py +++ b/scripts/test_collector.py @@ -52,10 +52,10 @@ def test_collector(hil): utils.log_warning(test_voltage) for thermistor in range(num_therm): - print(f"Place test input on thermistor {thermistor}. Press Enter when ready") + print(f"\nPlace test input on thermistor {thermistor}.") # TODO: find some way to wait for user input - # input("") + # input("Press Enter when ready...") for i in range(num_therm): # MUX (multiplexer) = choose which output to return from the thermistor based on the input From eac16716f80dd3dfd14ff9a634eccdcd27fa0b80 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 10:49:07 -0500 Subject: [PATCH 084/181] test_collector but no pytest so can wait using input() Also has some improved print formatting --- scripts/no_pytest_collector.py | 80 ++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 scripts/no_pytest_collector.py diff --git a/scripts/no_pytest_collector.py b/scripts/no_pytest_collector.py new file mode 100644 index 0000000..98b93dc --- /dev/null +++ b/scripts/no_pytest_collector.py @@ -0,0 +1,80 @@ +from os import sys, path +# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher +sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) + +from hil.hil import HIL +import hil.utils as utils +import time + + +# ---------------------------------------------------------------------------- # +def test_collector(hil): + # Begin the test + # hil.start_test(test_collector.__name__) + + # Outputs + mux_a = hil.dout("Collector", "MUX_A") + mux_b = hil.dout("Collector", "MUX_B") + mux_c = hil.dout("Collector", "MUX_C") + mux_d = hil.dout("Collector", "MUX_D") + + # Inputs + temp_out = hil.ain("Collector", "TEMP_OUT") + + tolerance_v = 0.1 # volts + current_res = 9100.0 # ohms + pullup_res = 4700.0 # ohms + test_voltage = 3.3 # volts + pullup_voltage = 5 # volts + num_therm = 10 + + test_voltage = (pullup_voltage / (current_res + pullup_res)) * current_res + + utils.log_warning(f"Test voltage: {test_voltage}") + + for thermistor in range(num_therm): + print(f"\nPlace test input on thermistor {thermistor}.") + input("Press Enter when ready...") + + for i in range(num_therm): + # MUX (multiplexer) = choose which output to return from the thermistor based on the input + # Like a giant switch statement (0 -> return thermistor 0, 1 -> return thermistor 1, etc.) + # Encode the current thermistor into binary where each bit corresponds to each pin being high or low + mux_a.state = i & 0x1 + mux_b.state = i & 0x2 + mux_c.state = i & 0x4 + mux_d.state = i & 0x8 + time.sleep(0.01) + + temp_out_state = temp_out.state + if i == thermistor: + expected_voltage = test_voltage + else: + expected_voltage = pullup_voltage + within = abs(temp_out_state - expected_voltage) < tolerance_v + + print(f"({thermistor=}, {i=}) temp_out_state={temp_out_state:.1f} ?= expected_voltage={expected_voltage:.1f} -> {within=}") + # check.almost_equal(to_state, expected_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") + + # if i == thermistor: + # # hil.check_within(to.state, test_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") + # # check.almost_equal(to.state, test_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") + # else: + # # hil.check_within(to.state, pullup_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") + # # check.almost_equal(to.state, pullup_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") + + # End the test + # hil.end_test() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +if __name__ == "__main__": + hil = HIL() + + hil.load_config("config_collector_bench.json") + hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + test_collector(hil) + + hil.shutdown() \ No newline at end of file From fb9363417b05ad38b369284e32076876377d05ff Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 10:52:44 -0500 Subject: [PATCH 085/181] Type hinting new test --- scripts/no_pytest_collector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/no_pytest_collector.py b/scripts/no_pytest_collector.py index 98b93dc..8cabe33 100644 --- a/scripts/no_pytest_collector.py +++ b/scripts/no_pytest_collector.py @@ -8,7 +8,7 @@ # ---------------------------------------------------------------------------- # -def test_collector(hil): +def test_collector(hil: HIL): # Begin the test # hil.start_test(test_collector.__name__) From 3a782ac5c8995731850864d0b8f9eff52c6411cb Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 11:03:14 -0500 Subject: [PATCH 086/181] Improving test output + tabs --- scripts/no_pytest_collector.py | 113 +++++++++++++++++---------------- 1 file changed, 57 insertions(+), 56 deletions(-) diff --git a/scripts/no_pytest_collector.py b/scripts/no_pytest_collector.py index 8cabe33..e7e215d 100644 --- a/scripts/no_pytest_collector.py +++ b/scripts/no_pytest_collector.py @@ -9,62 +9,63 @@ # ---------------------------------------------------------------------------- # def test_collector(hil: HIL): - # Begin the test - # hil.start_test(test_collector.__name__) - - # Outputs - mux_a = hil.dout("Collector", "MUX_A") - mux_b = hil.dout("Collector", "MUX_B") - mux_c = hil.dout("Collector", "MUX_C") - mux_d = hil.dout("Collector", "MUX_D") - - # Inputs - temp_out = hil.ain("Collector", "TEMP_OUT") - - tolerance_v = 0.1 # volts - current_res = 9100.0 # ohms - pullup_res = 4700.0 # ohms - test_voltage = 3.3 # volts - pullup_voltage = 5 # volts - num_therm = 10 - - test_voltage = (pullup_voltage / (current_res + pullup_res)) * current_res - - utils.log_warning(f"Test voltage: {test_voltage}") - - for thermistor in range(num_therm): - print(f"\nPlace test input on thermistor {thermistor}.") - input("Press Enter when ready...") - - for i in range(num_therm): - # MUX (multiplexer) = choose which output to return from the thermistor based on the input - # Like a giant switch statement (0 -> return thermistor 0, 1 -> return thermistor 1, etc.) - # Encode the current thermistor into binary where each bit corresponds to each pin being high or low - mux_a.state = i & 0x1 - mux_b.state = i & 0x2 - mux_c.state = i & 0x4 - mux_d.state = i & 0x8 - time.sleep(0.01) - - temp_out_state = temp_out.state - if i == thermistor: - expected_voltage = test_voltage - else: - expected_voltage = pullup_voltage - within = abs(temp_out_state - expected_voltage) < tolerance_v - - print(f"({thermistor=}, {i=}) temp_out_state={temp_out_state:.1f} ?= expected_voltage={expected_voltage:.1f} -> {within=}") - # check.almost_equal(to_state, expected_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") - - # if i == thermistor: - # # hil.check_within(to.state, test_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") - # # check.almost_equal(to.state, test_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") - # else: - # # hil.check_within(to.state, pullup_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") - # # check.almost_equal(to.state, pullup_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") - - # End the test - # hil.end_test() + # Begin the test + # hil.start_test(test_collector.__name__) + + # Outputs + mux_a = hil.dout("Collector", "MUX_A") + mux_b = hil.dout("Collector", "MUX_B") + mux_c = hil.dout("Collector", "MUX_C") + mux_d = hil.dout("Collector", "MUX_D") + + # Inputs + temp_out = hil.ain("Collector", "TEMP_OUT") + + tolerance_v = 0.1 # volts + current_res = 9100.0 # ohms + pullup_res = 4700.0 # ohms + test_voltage = 3.3 # volts + pullup_voltage = 5 # volts + num_therm = 10 + + test_voltage = (pullup_voltage / (current_res + pullup_res)) * current_res + + utils.log_warning(f"Test voltage: {test_voltage}") + + for thermistor in range(num_therm): + print(f"\nPlace test input on thermistor {thermistor}.") + input("Press Enter when ready...") + + for i in range(num_therm): + # MUX (multiplexer) = choose which output to return from the thermistor based on the input + # Like a giant switch statement (0 -> return thermistor 0, 1 -> return thermistor 1, etc.) + # Encode the current thermistor into binary where each bit corresponds to each pin being high or low + mux_a.state = i & 0x1 + mux_b.state = i & 0x2 + mux_c.state = i & 0x4 + mux_d.state = i & 0x8 + time.sleep(0.01) + + temp_out_state = temp_out.state + if i == thermistor: expected_voltage = test_voltage + else: expected_voltage = pullup_voltage + within = abs(temp_out_state - expected_voltage) < tolerance_v + + if within: within_text = utils.bcolors.OKGREEN + "PASS" + utils.bcolors.ENDC + else: within_text = utils.bcolors.FAIL + "FAIL" + utils.bcolors.ENDC + + print(f"({thermistor=}, {i=}) temp_out_state={temp_out_state:.1f} ?= expected_voltage={expected_voltage:.1f} -> {within_text}") + # check.almost_equal(to_state, expected_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") + + # if i == thermistor: + # # hil.check_within(to.state, test_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") + # # check.almost_equal(to.state, test_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") + # else: + # # hil.check_within(to.state, pullup_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") + # # check.almost_equal(to.state, pullup_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") + + # End the test + # hil.end_test() # ---------------------------------------------------------------------------- # From 7eb2cd8ec4bb9e4a8bbe3dacc643eadfad843e80 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 11:03:29 -0500 Subject: [PATCH 087/181] Test to toggle a DO to make sure things work --- scripts/do_on_off.py | 63 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 scripts/do_on_off.py diff --git a/scripts/do_on_off.py b/scripts/do_on_off.py new file mode 100644 index 0000000..557fa7b --- /dev/null +++ b/scripts/do_on_off.py @@ -0,0 +1,63 @@ +from os import sys, path +# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher +sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) + +from hil.hil import HIL +import hil.utils as utils +import time + + +# ---------------------------------------------------------------------------- # +def do_on_off(hil: HIL): + # Outputs + mux_a = hil.dout("Collector", "MUX_A") + + input("Turning on MUX_A. Press Enter when ready...") + mux_a.state = 1 + input("MUX_A is on. Press Enter when ready...") + + input("Turning off MUX_A. Press Enter when ready...") + mux_a.state = 0 + input("MUX_A is off. Press Enter when ready...") + + print("Test complete.") + + # # Inputs + # temp_out = hil.ain("Collector", "TEMP_OUT") + + # for thermistor in range(num_therm): + # print(f"\nPlace test input on thermistor {thermistor}.") + # input("Press Enter when ready...") + + # for i in range(num_therm): + # # MUX (multiplexer) = choose which output to return from the thermistor based on the input + # # Like a giant switch statement (0 -> return thermistor 0, 1 -> return thermistor 1, etc.) + # # Encode the current thermistor into binary where each bit corresponds to each pin being high or low + # mux_a.state = i & 0x1 + # mux_b.state = i & 0x2 + # mux_c.state = i & 0x4 + # mux_d.state = i & 0x8 + # time.sleep(0.01) + + # temp_out_state = temp_out.state + # if i == thermistor: expected_voltage = test_voltage + # else: expected_voltage = pullup_voltage + # within = abs(temp_out_state - expected_voltage) < tolerance_v + + # if within: within_text = utils.bcolors.OKGREEN + "PASS" + utils.bcolors.ENDC + # else: within_text = utils.bcolors.FAIL + "FAIL" + utils.bcolors.ENDC + + # print(f"({thermistor=}, {i=}) temp_out_state={temp_out_state:.1f} ?= expected_voltage={expected_voltage:.1f} -> {within_text}") +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +if __name__ == "__main__": + hil = HIL() + + hil.load_config("config_collector_bench.json") + hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") + + do_on_off(hil) + + hil.shutdown() \ No newline at end of file From 03ddb3ffc51958c967d129eb264ec2aafe52beff Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 12:02:35 -0500 Subject: [PATCH 088/181] idk why the id is 2 now --- configurations/config_collector_bench.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configurations/config_collector_bench.json b/configurations/config_collector_bench.json index cfc76d4..fb4c4b7 100644 --- a/configurations/config_collector_bench.json +++ b/configurations/config_collector_bench.json @@ -10,6 +10,6 @@ ]} ], "hil_devices":[ - {"name":"CollTester", "type":"arduino_uno", "id":1} + {"name":"CollTester", "type":"arduino_uno", "id":2} ] } From c4efb4d280a3b7c22f4ffcec6e48308f1df316e9 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 12:03:06 -0500 Subject: [PATCH 089/181] Simple Arduino program that toggles DO for pin 4 --- Hello/Hello.ino | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 Hello/Hello.ino diff --git a/Hello/Hello.ino b/Hello/Hello.ino new file mode 100644 index 0000000..71418f9 --- /dev/null +++ b/Hello/Hello.ino @@ -0,0 +1,18 @@ +#include + +int value = 0; + +void setup() { + Serial.begin(115200); +} + +void loop() { + value = !value; + + Serial.println("Value: " + String(value)); + + pinMode(4, OUTPUT); + digitalWrite(4, value); + + delay(3000); +} From 71ae4a0b9193825d0d38d16b8dc3d4cfcfb05e69 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 12:03:12 -0500 Subject: [PATCH 090/181] Debug print --- hil/hil_devices/hil_device.py | 1 + 1 file changed, 1 insertion(+) diff --git a/hil/hil_devices/hil_device.py b/hil/hil_devices/hil_device.py index 0b4fd3d..bfe2151 100644 --- a/hil/hil_devices/hil_device.py +++ b/hil/hil_devices/hil_device.py @@ -78,6 +78,7 @@ def get_port_number(self, port_name: str, mode: str) -> int: def write_gpio(self, pin: int, value: int) -> None: data = [(HIL_CMD_WRITE_GPIO & HIL_CMD_MASK), (pin & HIL_ID_MASK), value] + print(f"write pin {pin} to {value}") self.sm.send_data(self.id, data) def write_dac(self, pin: int, value: int) -> None: From 1fbeb49f522448d0f7aa7e3f05eb40c661fb9a37 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 18:29:23 -0500 Subject: [PATCH 091/181] Making the arduino LED reflect the pin high/low --- Hello/Hello.ino | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Hello/Hello.ino b/Hello/Hello.ino index 71418f9..376f27b 100644 --- a/Hello/Hello.ino +++ b/Hello/Hello.ino @@ -1,6 +1,7 @@ #include int value = 0; +int PIN = 3; void setup() { Serial.begin(115200); @@ -9,10 +10,12 @@ void setup() { void loop() { value = !value; + digitalWrite(LED_BUILTIN, value); + Serial.println("Value: " + String(value)); - pinMode(4, OUTPUT); - digitalWrite(4, value); + pinMode(PIN, OUTPUT); + digitalWrite(PIN, value); delay(3000); } From 4125a78fd51982bb1b45e33d4d7b7f7d0761d3cd Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 18:30:09 -0500 Subject: [PATCH 092/181] Python HIL can set Arduino pins high/low --- scripts/do_on_off.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/scripts/do_on_off.py b/scripts/do_on_off.py index 557fa7b..abe4a81 100644 --- a/scripts/do_on_off.py +++ b/scripts/do_on_off.py @@ -12,15 +12,14 @@ def do_on_off(hil: HIL): # Outputs mux_a = hil.dout("Collector", "MUX_A") - input("Turning on MUX_A. Press Enter when ready...") - mux_a.state = 1 - input("MUX_A is on. Press Enter when ready...") - - input("Turning off MUX_A. Press Enter when ready...") - mux_a.state = 0 - input("MUX_A is off. Press Enter when ready...") - - print("Test complete.") + while True: + mux_a.state = 1 + print("ON") + time.sleep(5) + + mux_a.state = 0 + print("OFF") + time.sleep(5) # # Inputs # temp_out = hil.ain("Collector", "TEMP_OUT") From 62aed183cf513950f001421ca5fb82d2f69fc3d9 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 18:41:50 -0500 Subject: [PATCH 093/181] HIL Micro led matches last GPIO write --- TestBench/TestBench.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/TestBench/TestBench.ino b/TestBench/TestBench.ino index 5b8517d..bf11c29 100644 --- a/TestBench/TestBench.ino +++ b/TestBench/TestBench.ino @@ -134,6 +134,7 @@ void loop() { pinMode(pin, OUTPUT); digitalWrite(pin, value); + digitalWrite(LED_BUILTIN, value); } else { From 04b349230689e5c7f9d4e35e1b4bf23ef72c968d Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 18:49:29 -0500 Subject: [PATCH 094/181] Currently using an Arduino micro --- configurations/config_collector_bench.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configurations/config_collector_bench.json b/configurations/config_collector_bench.json index fb4c4b7..dbf67a2 100644 --- a/configurations/config_collector_bench.json +++ b/configurations/config_collector_bench.json @@ -10,6 +10,6 @@ ]} ], "hil_devices":[ - {"name":"CollTester", "type":"arduino_uno", "id":2} + {"name":"CollTester", "type":"arduino_micro", "id":2} ] } From 5f4038f63860c542a8840f8d4a65b0fcb723933b Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 19:33:11 -0500 Subject: [PATCH 095/181] We don't need DAC features rn (I think) --- TestBench/TestBench.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestBench/TestBench.ino b/TestBench/TestBench.ino index bf11c29..0dd5518 100644 --- a/TestBench/TestBench.ino +++ b/TestBench/TestBench.ino @@ -12,7 +12,7 @@ const int TESTER_ID = 2; -#define DAC +// #define DAC #ifdef STM32 #ifdef DAC From 171572338b642a26b4de40604c0cfe1d87e71a05 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 19:33:22 -0500 Subject: [PATCH 096/181] renaming to millan.py --- scripts/{do_on_off.py => millan.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/{do_on_off.py => millan.py} (100%) diff --git a/scripts/do_on_off.py b/scripts/millan.py similarity index 100% rename from scripts/do_on_off.py rename to scripts/millan.py From 03d5c98956c6fff2d72ba41659e787771c2017f9 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 19:48:38 -0500 Subject: [PATCH 097/181] Working!: Fully custom DO and DI HIL test (without the board) --- configurations/config_millan.json | 12 ++++++ net_maps/millan_net_map.csv | 3 ++ scripts/millan.py | 62 ------------------------------- scripts/test_millan.py | 45 ++++++++++++++++++++++ 4 files changed, 60 insertions(+), 62 deletions(-) create mode 100644 configurations/config_millan.json create mode 100644 net_maps/millan_net_map.csv delete mode 100644 scripts/millan.py create mode 100644 scripts/test_millan.py diff --git a/configurations/config_millan.json b/configurations/config_millan.json new file mode 100644 index 0000000..446459d --- /dev/null +++ b/configurations/config_millan.json @@ -0,0 +1,12 @@ +{ + "$schema": "./config_schema.json", + "dut_connections":[ + {"board":"Millan", "harness_connections":[ + {"dut":{"connector":"breadboard","pin":1}, "hil":{"device":"MillanTester", "port":"D3"}}, + {"dut":{"connector":"breadboard","pin":2}, "hil":{"device":"MillanTester", "port":"D5"}} + ]} + ], + "hil_devices":[ + {"name":"MillanTester", "type":"arduino_micro", "id":2} + ] +} diff --git a/net_maps/millan_net_map.csv b/net_maps/millan_net_map.csv new file mode 100644 index 0000000..1604333 --- /dev/null +++ b/net_maps/millan_net_map.csv @@ -0,0 +1,3 @@ +Board,Net,Component,Designator,Connector Name,, +Millan,HIL_OUT,breadboard,1,FRED,, +Millan,HIL_IN,breadboard,2,FRED,, \ No newline at end of file diff --git a/scripts/millan.py b/scripts/millan.py deleted file mode 100644 index abe4a81..0000000 --- a/scripts/millan.py +++ /dev/null @@ -1,62 +0,0 @@ -from os import sys, path -# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher -sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) - -from hil.hil import HIL -import hil.utils as utils -import time - - -# ---------------------------------------------------------------------------- # -def do_on_off(hil: HIL): - # Outputs - mux_a = hil.dout("Collector", "MUX_A") - - while True: - mux_a.state = 1 - print("ON") - time.sleep(5) - - mux_a.state = 0 - print("OFF") - time.sleep(5) - - # # Inputs - # temp_out = hil.ain("Collector", "TEMP_OUT") - - # for thermistor in range(num_therm): - # print(f"\nPlace test input on thermistor {thermistor}.") - # input("Press Enter when ready...") - - # for i in range(num_therm): - # # MUX (multiplexer) = choose which output to return from the thermistor based on the input - # # Like a giant switch statement (0 -> return thermistor 0, 1 -> return thermistor 1, etc.) - # # Encode the current thermistor into binary where each bit corresponds to each pin being high or low - # mux_a.state = i & 0x1 - # mux_b.state = i & 0x2 - # mux_c.state = i & 0x4 - # mux_d.state = i & 0x8 - # time.sleep(0.01) - - # temp_out_state = temp_out.state - # if i == thermistor: expected_voltage = test_voltage - # else: expected_voltage = pullup_voltage - # within = abs(temp_out_state - expected_voltage) < tolerance_v - - # if within: within_text = utils.bcolors.OKGREEN + "PASS" + utils.bcolors.ENDC - # else: within_text = utils.bcolors.FAIL + "FAIL" + utils.bcolors.ENDC - - # print(f"({thermistor=}, {i=}) temp_out_state={temp_out_state:.1f} ?= expected_voltage={expected_voltage:.1f} -> {within_text}") -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # -if __name__ == "__main__": - hil = HIL() - - hil.load_config("config_collector_bench.json") - hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") - - do_on_off(hil) - - hil.shutdown() \ No newline at end of file diff --git a/scripts/test_millan.py b/scripts/test_millan.py new file mode 100644 index 0000000..98e49d8 --- /dev/null +++ b/scripts/test_millan.py @@ -0,0 +1,45 @@ +from os import sys, path +# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher +sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) + +from hil.hil import HIL +import hil.utils as utils +import time + + +# ---------------------------------------------------------------------------- # +def test_do_di(hil: HIL): + hil_out = hil.dout("Millan", "HIL_OUT") + hil_in = hil.din("Millan", "HIL_IN") + + for _i in range(3): + print("\nHIL_OUT: 0") + hil_out.state = 0 + hil_in_state = hil_in.state + same = hil_in_state == 0 + print(f"HIL_IN: {hil_in_state} == 0: {same}") + + time.sleep(3) + + print("\nHIL_OUT: 1") + hil_out.state = 1 + hil_in_state = hil_in.state + same = hil_in_state == 1 + print(f"HIL_IN: {hil_in_state} == 1: {same}") + + time.sleep(3) + + print() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +if __name__ == "__main__": + hil = HIL() + + hil.load_config("config_millan.json") + hil.load_pin_map("millan_net_map.csv", "stm32f407_pin_map.csv") + + test_do_di(hil) + + hil.shutdown() \ No newline at end of file From 6c8d0690bc198ff4800d71567ea581c21708a131 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 19:52:57 -0500 Subject: [PATCH 098/181] Pytest version of custom test --- scripts/pytest_millan.py | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 scripts/pytest_millan.py diff --git a/scripts/pytest_millan.py b/scripts/pytest_millan.py new file mode 100644 index 0000000..45ea912 --- /dev/null +++ b/scripts/pytest_millan.py @@ -0,0 +1,39 @@ +from os import sys, path +# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher +sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) + +from hil.hil import HIL +import hil.utils as utils +import time + +import pytest_check as check +import pytest + + +# ---------------------------------------------------------------------------- # +@pytest.fixture(scope="session") +def hil(): + hil_instance = HIL() + + hil_instance.load_config("config_millan.json") + hil_instance.load_pin_map("millan_net_map.csv", "stm32f407_pin_map.csv") + + yield hil_instance + + hil_instance.shutdown() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +def test_do_di(hil: HIL): + hil_out = hil.dout("Millan", "HIL_OUT") + hil_in = hil.din("Millan", "HIL_IN") + + for _i in range(3): + for state in range(2): # 0, 1 + hil_out.state = state + hil_in_state = hil_in.state + check.equal(hil_in_state, state , f"Expected HIL_IN to be {state}, got {hil_in_state}") + + time.sleep(1) +# ---------------------------------------------------------------------------- # \ No newline at end of file From 1aad878a0f8e55913dba530c63083b38583a624a Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 20:11:44 -0500 Subject: [PATCH 099/181] Trying to test "AI" mode (unsuccessful?) --- configurations/config_millan.json | 2 +- scripts/test_millan.py | 41 +++++++++++++++++++++---------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/configurations/config_millan.json b/configurations/config_millan.json index 446459d..34258f4 100644 --- a/configurations/config_millan.json +++ b/configurations/config_millan.json @@ -3,7 +3,7 @@ "dut_connections":[ {"board":"Millan", "harness_connections":[ {"dut":{"connector":"breadboard","pin":1}, "hil":{"device":"MillanTester", "port":"D3"}}, - {"dut":{"connector":"breadboard","pin":2}, "hil":{"device":"MillanTester", "port":"D5"}} + {"dut":{"connector":"breadboard","pin":2}, "hil":{"device":"MillanTester", "port":"D4"}} ]} ], "hil_devices":[ diff --git a/scripts/test_millan.py b/scripts/test_millan.py index 98e49d8..2a2150d 100644 --- a/scripts/test_millan.py +++ b/scripts/test_millan.py @@ -13,21 +13,35 @@ def test_do_di(hil: HIL): hil_in = hil.din("Millan", "HIL_IN") for _i in range(3): - print("\nHIL_OUT: 0") - hil_out.state = 0 - hil_in_state = hil_in.state - same = hil_in_state == 0 - print(f"HIL_IN: {hil_in_state} == 0: {same}") + for state in range(2): # 0, 1 + print("\nHIL_OUT: 0") + hil_out.state = state + hil_in_state = hil_in.state + same = hil_in_state == state + print(f"HIL_IN: {state} == {hil_in_state}: {same}") - time.sleep(3) + time.sleep(1) - print("\nHIL_OUT: 1") - hil_out.state = 1 - hil_in_state = hil_in.state - same = hil_in_state == 1 - print(f"HIL_IN: {hil_in_state} == 1: {same}") + print() +# ---------------------------------------------------------------------------- # + +# ---------------------------------------------------------------------------- # +def test_do_ai(hil: HIL): + hil_out = hil.dout("Millan", "HIL_OUT") + hil_in = hil.ain("Millan", "HIL_IN") + + for _i in range(3): + for state in range(2): # 0, 1 + print("\nHIL_OUT: 0") + hil_out.state = state + time.sleep(1) + hil_in_state = hil_in.state + + target = state * 5.0 + same = abs(hil_in_state - target) < 0.1 + print(f"HIL_IN: {target} == {hil_in_state}: {same}") - time.sleep(3) + time.sleep(2) print() # ---------------------------------------------------------------------------- # @@ -40,6 +54,7 @@ def test_do_di(hil: HIL): hil.load_config("config_millan.json") hil.load_pin_map("millan_net_map.csv", "stm32f407_pin_map.csv") - test_do_di(hil) + # test_do_di(hil) + test_do_ai(hil) hil.shutdown() \ No newline at end of file From 78768e2f6f4f9d8570b21404a11aeb8ac40b0233 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 20:23:52 -0500 Subject: [PATCH 100/181] Testing DI and AI at the same time --- configurations/config_millan.json | 3 +- net_maps/millan_net_map.csv | 3 +- scripts/test_millan.py | 49 +++++++++++++------------------ 3 files changed, 25 insertions(+), 30 deletions(-) diff --git a/configurations/config_millan.json b/configurations/config_millan.json index 34258f4..5692e01 100644 --- a/configurations/config_millan.json +++ b/configurations/config_millan.json @@ -3,7 +3,8 @@ "dut_connections":[ {"board":"Millan", "harness_connections":[ {"dut":{"connector":"breadboard","pin":1}, "hil":{"device":"MillanTester", "port":"D3"}}, - {"dut":{"connector":"breadboard","pin":2}, "hil":{"device":"MillanTester", "port":"D4"}} + {"dut":{"connector":"breadboard","pin":2}, "hil":{"device":"MillanTester", "port":"D4"}}, + {"dut":{"connector":"breadboard","pin":3}, "hil":{"device":"MillanTester", "port":"D5"}} ]} ], "hil_devices":[ diff --git a/net_maps/millan_net_map.csv b/net_maps/millan_net_map.csv index 1604333..286f15d 100644 --- a/net_maps/millan_net_map.csv +++ b/net_maps/millan_net_map.csv @@ -1,3 +1,4 @@ Board,Net,Component,Designator,Connector Name,, Millan,HIL_OUT,breadboard,1,FRED,, -Millan,HIL_IN,breadboard,2,FRED,, \ No newline at end of file +Millan,HIL_AIN,breadboard,2,FRED,, +Millan,HIL_DIN,breadboard,3,FRED,, \ No newline at end of file diff --git a/scripts/test_millan.py b/scripts/test_millan.py index 2a2150d..6afccc9 100644 --- a/scripts/test_millan.py +++ b/scripts/test_millan.py @@ -8,40 +8,34 @@ # ---------------------------------------------------------------------------- # -def test_do_di(hil: HIL): - hil_out = hil.dout("Millan", "HIL_OUT") - hil_in = hil.din("Millan", "HIL_IN") - - for _i in range(3): - for state in range(2): # 0, 1 - print("\nHIL_OUT: 0") - hil_out.state = state - hil_in_state = hil_in.state - same = hil_in_state == state - print(f"HIL_IN: {state} == {hil_in_state}: {same}") - - time.sleep(1) +def same_to_color_str(same: bool) -> str: + if same: + return utils.bcolors.OKGREEN + "SUCCESS" + utils.bcolors.ENDC + else: + return utils.bcolors.FAIL + "FAILURE" + utils.bcolors.ENDC - print() -# ---------------------------------------------------------------------------- # -# ---------------------------------------------------------------------------- # -def test_do_ai(hil: HIL): +def test(hil: HIL): hil_out = hil.dout("Millan", "HIL_OUT") - hil_in = hil.ain("Millan", "HIL_IN") + hil_ain = hil.ain("Millan", "HIL_AIN") + hil_din = hil.din("Millan", "HIL_DIN") for _i in range(3): - for state in range(2): # 0, 1 - print("\nHIL_OUT: 0") + for state in [0, 1]: + print(f"\nHIL_OUT: {state}") hil_out.state = state - time.sleep(1) - hil_in_state = hil_in.state + time.sleep(0.5) + + hil_din_state = hil_din.state + din_same = hil_din_state == state + print(f"HIL_DIN: {hil_din_state} == {state} -> {same_to_color_str(din_same)}") - target = state * 5.0 - same = abs(hil_in_state - target) < 0.1 - print(f"HIL_IN: {target} == {hil_in_state}: {same}") + hil_ain_state = hil_ain.state + ain_target = state * 5.0 + ain_same = abs(hil_ain_state - ain_target) < 0.1 + print(f"HIL_AIN: {hil_ain_state} == {ain_target} -> {same_to_color_str(ain_same)}") - time.sleep(2) + time.sleep(1) print() # ---------------------------------------------------------------------------- # @@ -54,7 +48,6 @@ def test_do_ai(hil: HIL): hil.load_config("config_millan.json") hil.load_pin_map("millan_net_map.csv", "stm32f407_pin_map.csv") - # test_do_di(hil) - test_do_ai(hil) + test(hil) hil.shutdown() \ No newline at end of file From 39a02380f8f3a2da13d936fc47d18a47a49bf3d9 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 20:33:04 -0500 Subject: [PATCH 101/181] Better comment for Arduino discovery --- hil/hil_devices/serial_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hil/hil_devices/serial_manager.py b/hil/hil_devices/serial_manager.py index 5edea6d..2cb362d 100644 --- a/hil/hil_devices/serial_manager.py +++ b/hil/hil_devices/serial_manager.py @@ -26,7 +26,7 @@ def discover_devices(self) -> None: ard.setDTR(True) # Uno takes a while startup, have to treat it nicely for _ in range(5): - # Get Tester id + # Get Tester id - [command, pin, value], but we only care about the pin ard.write(b'\x04\x00\x00') i = ard.read(1) if (len(i) == 1): From e0fc9f17f3ce796a2243be219cb1cdc292fbc88f Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 9 Nov 2024 20:33:17 -0500 Subject: [PATCH 102/181] Tester id = 1 (from 2) --- TestBench/TestBench.ino | 2 +- configurations/config_millan.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/TestBench/TestBench.ino b/TestBench/TestBench.ino index 0dd5518..2050af9 100644 --- a/TestBench/TestBench.ino +++ b/TestBench/TestBench.ino @@ -10,7 +10,7 @@ #define SERIAL Serial #endif -const int TESTER_ID = 2; +const int TESTER_ID = 1; // #define DAC diff --git a/configurations/config_millan.json b/configurations/config_millan.json index 5692e01..3d8f76c 100644 --- a/configurations/config_millan.json +++ b/configurations/config_millan.json @@ -8,6 +8,6 @@ ]} ], "hil_devices":[ - {"name":"MillanTester", "type":"arduino_micro", "id":2} + {"name":"MillanTester", "type":"arduino_micro", "id":1} ] } From de39b88a4a0447a4c8c4d84f634061ec17d17d88 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Mon, 11 Nov 2024 11:29:56 -0500 Subject: [PATCH 103/181] Creating files to setup a breadboard Collector test --- configurations/config_mil_col.json | 13 ++++++++ net_maps/mil_col_net_map.csv | 4 +++ scripts/test_mil_col.py | 53 ++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 configurations/config_mil_col.json create mode 100644 net_maps/mil_col_net_map.csv create mode 100644 scripts/test_mil_col.py diff --git a/configurations/config_mil_col.json b/configurations/config_mil_col.json new file mode 100644 index 0000000..3d8f76c --- /dev/null +++ b/configurations/config_mil_col.json @@ -0,0 +1,13 @@ +{ + "$schema": "./config_schema.json", + "dut_connections":[ + {"board":"Millan", "harness_connections":[ + {"dut":{"connector":"breadboard","pin":1}, "hil":{"device":"MillanTester", "port":"D3"}}, + {"dut":{"connector":"breadboard","pin":2}, "hil":{"device":"MillanTester", "port":"D4"}}, + {"dut":{"connector":"breadboard","pin":3}, "hil":{"device":"MillanTester", "port":"D5"}} + ]} + ], + "hil_devices":[ + {"name":"MillanTester", "type":"arduino_micro", "id":1} + ] +} diff --git a/net_maps/mil_col_net_map.csv b/net_maps/mil_col_net_map.csv new file mode 100644 index 0000000..286f15d --- /dev/null +++ b/net_maps/mil_col_net_map.csv @@ -0,0 +1,4 @@ +Board,Net,Component,Designator,Connector Name,, +Millan,HIL_OUT,breadboard,1,FRED,, +Millan,HIL_AIN,breadboard,2,FRED,, +Millan,HIL_DIN,breadboard,3,FRED,, \ No newline at end of file diff --git a/scripts/test_mil_col.py b/scripts/test_mil_col.py new file mode 100644 index 0000000..6afccc9 --- /dev/null +++ b/scripts/test_mil_col.py @@ -0,0 +1,53 @@ +from os import sys, path +# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher +sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) + +from hil.hil import HIL +import hil.utils as utils +import time + + +# ---------------------------------------------------------------------------- # +def same_to_color_str(same: bool) -> str: + if same: + return utils.bcolors.OKGREEN + "SUCCESS" + utils.bcolors.ENDC + else: + return utils.bcolors.FAIL + "FAILURE" + utils.bcolors.ENDC + + +def test(hil: HIL): + hil_out = hil.dout("Millan", "HIL_OUT") + hil_ain = hil.ain("Millan", "HIL_AIN") + hil_din = hil.din("Millan", "HIL_DIN") + + for _i in range(3): + for state in [0, 1]: + print(f"\nHIL_OUT: {state}") + hil_out.state = state + time.sleep(0.5) + + hil_din_state = hil_din.state + din_same = hil_din_state == state + print(f"HIL_DIN: {hil_din_state} == {state} -> {same_to_color_str(din_same)}") + + hil_ain_state = hil_ain.state + ain_target = state * 5.0 + ain_same = abs(hil_ain_state - ain_target) < 0.1 + print(f"HIL_AIN: {hil_ain_state} == {ain_target} -> {same_to_color_str(ain_same)}") + + time.sleep(1) + + print() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +if __name__ == "__main__": + hil = HIL() + + hil.load_config("config_millan.json") + hil.load_pin_map("millan_net_map.csv", "stm32f407_pin_map.csv") + + test(hil) + + hil.shutdown() \ No newline at end of file From 163f8975950e51469593fa2c25c8d15835404937 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Mon, 11 Nov 2024 17:00:16 -0500 Subject: [PATCH 104/181] Trying to setup a breadboard test for Collector Plate --- configurations/config_mil_col.json | 10 ++-- net_maps/mil_col_net_map.csv | 36 +++++++++++-- scripts/no_pytest_collector.py | 81 ------------------------------ scripts/test_mil_col.py | 66 ++++++++++++++---------- 4 files changed, 79 insertions(+), 114 deletions(-) delete mode 100644 scripts/no_pytest_collector.py diff --git a/configurations/config_mil_col.json b/configurations/config_mil_col.json index 3d8f76c..36c77bd 100644 --- a/configurations/config_mil_col.json +++ b/configurations/config_mil_col.json @@ -2,12 +2,14 @@ "$schema": "./config_schema.json", "dut_connections":[ {"board":"Millan", "harness_connections":[ - {"dut":{"connector":"breadboard","pin":1}, "hil":{"device":"MillanTester", "port":"D3"}}, - {"dut":{"connector":"breadboard","pin":2}, "hil":{"device":"MillanTester", "port":"D4"}}, - {"dut":{"connector":"breadboard","pin":3}, "hil":{"device":"MillanTester", "port":"D5"}} + {"dut":{"connector":"J4","pin":2,"_":"MUX_A"}, "hil":{"device":"MilColTester", "port":"D0", "_":"DO"}}, + {"dut":{"connector":"J4","pin":1,"_":"MUX_B"}, "hil":{"device":"MilColTester", "port":"D1", "_":"DO"}}, + {"dut":{"connector":"J4","pin":4,"_":"MUX_C"}, "hil":{"device":"MilColTester", "port":"D2", "_":"DO"}}, + {"dut":{"connector":"J4","pin":7,"_":"MUX_D"}, "hil":{"device":"MilColTester", "port":"D3", "_":"DO"}}, + {"dut":{"connector":"J4","pin":5,"_":"TEMP_OUT"}, "hil":{"device":"MilColTester", "port":"D8", "_":"AI"}} ]} ], "hil_devices":[ - {"name":"MillanTester", "type":"arduino_micro", "id":1} + {"name":"MilColTester", "type":"arduino_micro", "id":1} ] } diff --git a/net_maps/mil_col_net_map.csv b/net_maps/mil_col_net_map.csv index 286f15d..7420532 100644 --- a/net_maps/mil_col_net_map.csv +++ b/net_maps/mil_col_net_map.csv @@ -1,4 +1,34 @@ Board,Net,Component,Designator,Connector Name,, -Millan,HIL_OUT,breadboard,1,FRED,, -Millan,HIL_AIN,breadboard,2,FRED,, -Millan,HIL_DIN,breadboard,3,FRED,, \ No newline at end of file +Collector,MUX_A,J4,2,ABOX,, +Collector,MUX_B,J4,1,ABOX,, +Collector,MUX_C,J4,4,ABOX,, +Collector,MUX_D,J4,7,ABOX,, +Collector,TEMP_OUT,J4,5,ABOX,, + +Collector,GND_I,J4,3,ABOX,, + +Collector,3V3,J4,8,ABOX,, +Collector,CELL_0,J3,1,ORION,, +Collector,CELL_2,J3,2,ORION,, +Collector,CELL_4,J3,3,ORION,, +Collector,CELL_6,J3,4,ORION,, +Collector,CELL_8,J3,5,ORION,, +Collector,CELL_10,J3,6,ORION,, +Collector,CELL_12,J3,7,ORION,, +Collector,CELL_13,J3,8,ORION,, +Collector,CELL_15,J3,9,ORION,, +Collector,CELL_17,J3,10,ORION,, +Collector,CELL_19,J3,11,ORION,, +Collector,CELL_19,J3,12,ORION,, +Collector,CELL_1,J3,13,ORION,, +Collector,CELL_3,J3,14,ORION,, +Collector,CELL_5,J3,15,ORION,, +Collector,CELL_7,J3,16,ORION,, +Collector,CELL_9,J3,17,ORION,, +Collector,CELL_11,J3,18,ORION,, +Collector,CELL_12,J3,19,ORION,, +Collector,CELL_14,J3,20,ORION,, +Collector,CELL_16,J3,21,ORION,, +Collector,CELL_18,J3,22,ORION,, +Collector,CELL_19,J3,23,ORION,, +Collector,CELL_19,J3,24,ORION,, diff --git a/scripts/no_pytest_collector.py b/scripts/no_pytest_collector.py deleted file mode 100644 index e7e215d..0000000 --- a/scripts/no_pytest_collector.py +++ /dev/null @@ -1,81 +0,0 @@ -from os import sys, path -# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher -sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) - -from hil.hil import HIL -import hil.utils as utils -import time - - -# ---------------------------------------------------------------------------- # -def test_collector(hil: HIL): - # Begin the test - # hil.start_test(test_collector.__name__) - - # Outputs - mux_a = hil.dout("Collector", "MUX_A") - mux_b = hil.dout("Collector", "MUX_B") - mux_c = hil.dout("Collector", "MUX_C") - mux_d = hil.dout("Collector", "MUX_D") - - # Inputs - temp_out = hil.ain("Collector", "TEMP_OUT") - - tolerance_v = 0.1 # volts - current_res = 9100.0 # ohms - pullup_res = 4700.0 # ohms - test_voltage = 3.3 # volts - pullup_voltage = 5 # volts - num_therm = 10 - - test_voltage = (pullup_voltage / (current_res + pullup_res)) * current_res - - utils.log_warning(f"Test voltage: {test_voltage}") - - for thermistor in range(num_therm): - print(f"\nPlace test input on thermistor {thermistor}.") - input("Press Enter when ready...") - - for i in range(num_therm): - # MUX (multiplexer) = choose which output to return from the thermistor based on the input - # Like a giant switch statement (0 -> return thermistor 0, 1 -> return thermistor 1, etc.) - # Encode the current thermistor into binary where each bit corresponds to each pin being high or low - mux_a.state = i & 0x1 - mux_b.state = i & 0x2 - mux_c.state = i & 0x4 - mux_d.state = i & 0x8 - time.sleep(0.01) - - temp_out_state = temp_out.state - if i == thermistor: expected_voltage = test_voltage - else: expected_voltage = pullup_voltage - within = abs(temp_out_state - expected_voltage) < tolerance_v - - if within: within_text = utils.bcolors.OKGREEN + "PASS" + utils.bcolors.ENDC - else: within_text = utils.bcolors.FAIL + "FAIL" + utils.bcolors.ENDC - - print(f"({thermistor=}, {i=}) temp_out_state={temp_out_state:.1f} ?= expected_voltage={expected_voltage:.1f} -> {within_text}") - # check.almost_equal(to_state, expected_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") - - # if i == thermistor: - # # hil.check_within(to.state, test_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") - # # check.almost_equal(to.state, test_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") - # else: - # # hil.check_within(to.state, pullup_voltage, tolerance_v, f"Input on therm {thermistor}, selecting {i}") - # # check.almost_equal(to.state, pullup_voltage, abs=tolerance_v, rel=0.0, msg=f"Input on therm {thermistor}, selecting {i}") - - # End the test - # hil.end_test() -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # -if __name__ == "__main__": - hil = HIL() - - hil.load_config("config_collector_bench.json") - hil.load_pin_map("per_24_net_map.csv", "stm32f407_pin_map.csv") - - test_collector(hil) - - hil.shutdown() \ No newline at end of file diff --git a/scripts/test_mil_col.py b/scripts/test_mil_col.py index 6afccc9..3eaf153 100644 --- a/scripts/test_mil_col.py +++ b/scripts/test_mil_col.py @@ -8,36 +8,50 @@ # ---------------------------------------------------------------------------- # -def same_to_color_str(same: bool) -> str: - if same: - return utils.bcolors.OKGREEN + "SUCCESS" + utils.bcolors.ENDC - else: - return utils.bcolors.FAIL + "FAILURE" + utils.bcolors.ENDC +def test_collector(hil: HIL): + # HIL ouputs -> Collector inputs + mux_a = hil.dout("Collector", "MUX_A") + mux_b = hil.dout("Collector", "MUX_B") + mux_c = hil.dout("Collector", "MUX_C") + mux_d = hil.dout("Collector", "MUX_D") + # HIL inputs -> Collector outputs + temp_out = hil.ain("Collector", "TEMP_OUT") -def test(hil: HIL): - hil_out = hil.dout("Millan", "HIL_OUT") - hil_ain = hil.ain("Millan", "HIL_AIN") - hil_din = hil.din("Millan", "HIL_DIN") + tolerance_v = 0.1 # volts + current_res = 9100.0 # ohms + pullup_res = 4700.0 # ohms + test_voltage = 3.3 # volts + pullup_voltage = 5 # volts + num_therm = 10 - for _i in range(3): - for state in [0, 1]: - print(f"\nHIL_OUT: {state}") - hil_out.state = state - time.sleep(0.5) + test_voltage = (pullup_voltage / (current_res + pullup_res)) * current_res + utils.log_warning(f"Test voltage: {test_voltage}") + - hil_din_state = hil_din.state - din_same = hil_din_state == state - print(f"HIL_DIN: {hil_din_state} == {state} -> {same_to_color_str(din_same)}") + for thermistor in range(num_therm): + print(f"\nPlace test input on thermistor {thermistor}.") + input("Press Enter when ready...") - hil_ain_state = hil_ain.state - ain_target = state * 5.0 - ain_same = abs(hil_ain_state - ain_target) < 0.1 - print(f"HIL_AIN: {hil_ain_state} == {ain_target} -> {same_to_color_str(ain_same)}") + for i in range(num_therm): + # MUX (multiplexer) = choose which output to return from the thermistor based on the input + # Like a giant switch statement (0 -> return thermistor 0, 1 -> return thermistor 1, etc.) + # Encode the current thermistor into binary where each bit corresponds to each pin being high or low + mux_a.state = i & 0x1 + mux_b.state = i & 0x2 + mux_c.state = i & 0x4 + mux_d.state = i & 0x8 + time.sleep(0.01) - time.sleep(1) + temp_out_state = temp_out.state + if i == thermistor: expected_voltage = test_voltage + else: expected_voltage = pullup_voltage + within = abs(temp_out_state - expected_voltage) < tolerance_v + + if within: within_text = utils.bcolors.OKGREEN + "PASS" + utils.bcolors.ENDC + else: within_text = utils.bcolors.FAIL + "FAIL" + utils.bcolors.ENDC - print() + print(f"({thermistor=}, {i=}) temp_out_state={temp_out_state:.1f} ?= expected_voltage={expected_voltage:.1f} -> {within_text}") # ---------------------------------------------------------------------------- # @@ -45,9 +59,9 @@ def test(hil: HIL): if __name__ == "__main__": hil = HIL() - hil.load_config("config_millan.json") - hil.load_pin_map("millan_net_map.csv", "stm32f407_pin_map.csv") + hil.load_config("config_mil_col.json") + hil.load_pin_map("mil_col_net_map.csv", "stm32f407_pin_map.csv") - test(hil) + test_collector(hil) hil.shutdown() \ No newline at end of file From 8783a56c719605fb5a6ad9fa1e84fbfc7f10d4aa Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Mon, 11 Nov 2024 18:37:52 -0500 Subject: [PATCH 105/181] Indentation changes --- scripts/test_mil_col.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/test_mil_col.py b/scripts/test_mil_col.py index 3eaf153..846ed14 100644 --- a/scripts/test_mil_col.py +++ b/scripts/test_mil_col.py @@ -27,7 +27,7 @@ def test_collector(hil: HIL): test_voltage = (pullup_voltage / (current_res + pullup_res)) * current_res utils.log_warning(f"Test voltage: {test_voltage}") - + for thermistor in range(num_therm): print(f"\nPlace test input on thermistor {thermistor}.") @@ -49,7 +49,7 @@ def test_collector(hil: HIL): within = abs(temp_out_state - expected_voltage) < tolerance_v if within: within_text = utils.bcolors.OKGREEN + "PASS" + utils.bcolors.ENDC - else: within_text = utils.bcolors.FAIL + "FAIL" + utils.bcolors.ENDC + else: within_text = utils.bcolors.FAIL + "FAIL" + utils.bcolors.ENDC print(f"({thermistor=}, {i=}) temp_out_state={temp_out_state:.1f} ?= expected_voltage={expected_voltage:.1f} -> {within_text}") # ---------------------------------------------------------------------------- # From c2fcccb52702e33c8ebb357ab65b0439acd251a9 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Mon, 11 Nov 2024 20:35:18 -0500 Subject: [PATCH 106/181] Commenting out unneeded variable declaration --- scripts/test_mil_col.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test_mil_col.py b/scripts/test_mil_col.py index 846ed14..8904876 100644 --- a/scripts/test_mil_col.py +++ b/scripts/test_mil_col.py @@ -21,7 +21,7 @@ def test_collector(hil: HIL): tolerance_v = 0.1 # volts current_res = 9100.0 # ohms pullup_res = 4700.0 # ohms - test_voltage = 3.3 # volts + # test_voltage = 3.3 # volts pullup_voltage = 5 # volts num_therm = 10 From df4ee5af33d7761f76054b483769ddc6ad5719f6 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 12 Nov 2024 13:53:29 -0500 Subject: [PATCH 107/181] Fixing board name for simple collector test --- configurations/config_mil_col.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configurations/config_mil_col.json b/configurations/config_mil_col.json index 36c77bd..6f1f811 100644 --- a/configurations/config_mil_col.json +++ b/configurations/config_mil_col.json @@ -1,7 +1,7 @@ { "$schema": "./config_schema.json", "dut_connections":[ - {"board":"Millan", "harness_connections":[ + {"board":"Collector", "harness_connections":[ {"dut":{"connector":"J4","pin":2,"_":"MUX_A"}, "hil":{"device":"MilColTester", "port":"D0", "_":"DO"}}, {"dut":{"connector":"J4","pin":1,"_":"MUX_B"}, "hil":{"device":"MilColTester", "port":"D1", "_":"DO"}}, {"dut":{"connector":"J4","pin":4,"_":"MUX_C"}, "hil":{"device":"MilColTester", "port":"D2", "_":"DO"}}, From e6329b19eded968db00cad9696c42a1c2a5ce719 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 12 Nov 2024 13:53:38 -0500 Subject: [PATCH 108/181] Changing print statements slightly --- hil/hil_devices/hil_device.py | 2 +- scripts/test_mil_col.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/hil/hil_devices/hil_device.py b/hil/hil_devices/hil_device.py index bfe2151..7a8675c 100644 --- a/hil/hil_devices/hil_device.py +++ b/hil/hil_devices/hil_device.py @@ -78,7 +78,7 @@ def get_port_number(self, port_name: str, mode: str) -> int: def write_gpio(self, pin: int, value: int) -> None: data = [(HIL_CMD_WRITE_GPIO & HIL_CMD_MASK), (pin & HIL_ID_MASK), value] - print(f"write pin {pin} to {value}") + # print(f"write pin {pin} to {value}") self.sm.send_data(self.id, data) def write_dac(self, pin: int, value: int) -> None: diff --git a/scripts/test_mil_col.py b/scripts/test_mil_col.py index 8904876..f5f3c5d 100644 --- a/scripts/test_mil_col.py +++ b/scripts/test_mil_col.py @@ -51,6 +51,8 @@ def test_collector(hil: HIL): if within: within_text = utils.bcolors.OKGREEN + "PASS" + utils.bcolors.ENDC else: within_text = utils.bcolors.FAIL + "FAIL" + utils.bcolors.ENDC + if i == thermistor: print("- ", end="") + print(f"({thermistor=}, {i=}) temp_out_state={temp_out_state:.1f} ?= expected_voltage={expected_voltage:.1f} -> {within_text}") # ---------------------------------------------------------------------------- # From 57b917435891a564923deaaa3b837c34a1bfa1ed Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 12 Nov 2024 20:47:04 -0500 Subject: [PATCH 109/181] New config for breadboard + 12 bit dac --- TestBench/TestBench.ino | 2 +- .../hil_device_arduino_micro_breadboard.json | 31 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 hil/hil_devices/hil_device_arduino_micro_breadboard.json diff --git a/TestBench/TestBench.ino b/TestBench/TestBench.ino index 2050af9..81c8237 100644 --- a/TestBench/TestBench.ino +++ b/TestBench/TestBench.ino @@ -12,7 +12,7 @@ const int TESTER_ID = 1; -// #define DAC +#define DAC #ifdef STM32 #ifdef DAC diff --git a/hil/hil_devices/hil_device_arduino_micro_breadboard.json b/hil/hil_devices/hil_device_arduino_micro_breadboard.json new file mode 100644 index 0000000..c5af465 --- /dev/null +++ b/hil/hil_devices/hil_device_arduino_micro_breadboard.json @@ -0,0 +1,31 @@ +{ + "$schema": "./emulator_schema.json", + "communication_mode":"serial", + "ports":[ + {"port":0, "name":"0", "capabilities":["DI", "DO"], "notes":"5V dig (RX)"}, + {"port":1, "name":"1", "capabilities":["DI", "DO"], "notes":"5V dig (TX)"}, + {"port":2, "name":"2", "capabilities":[], "notes":"SDA (5V dig)"}, + {"port":3, "name":"3", "capabilities":[], "notes":"SCL (5V dig)"}, + {"port":4, "name":"4", "capabilities":["DI", "DO", "AI"], "notes":"5V dig / analog in"}, + {"port":5, "name":"5", "capabilities":["DI", "DO"], "notes":"5V dig"}, + {"port":6, "name":"6", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, + {"port":7, "name":"7", "capabilities":["DI", "DO"], "notes":"5V dig"}, + {"port":8, "name":"8", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, + {"port":9, "name":"9", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, + {"port":10, "name":"10", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, + {"port":11, "name":"11", "capabilities":["DI", "DO"], "notes":"5V digital"}, + {"port":12, "name":"12", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, + {"port":13, "name":"13", "capabilities":["DI", "DO"], "notes":"5V dig"}, + {"port":14, "name":"14", "capabilities":["DI", "AI", "DO"], "notes":"5V dig"}, + {"port":15, "name":"15", "capabilities":["DI", "AI", "DO"], "notes":"5V dig"}, + {"port":16, "name":"16", "capabilities":["DI", "AI", "DO"], "notes":"5V dig"}, + {"port":17, "name":"17", "capabilities":["DI", "AI", "DO"], "notes":"5V dig"}, + {"port":18, "name":"18", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, + {"port":19, "name":"19", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, + {"port":200, "name":"DAC1", "capabilities":["AO"], "notes":"5V 12-bit DAC"}, + {"port":201, "name":"DAC2", "capabilities":["AO"], "notes":"5V 12-bit DAC"} + ], + "adc_config":{"bit_resolution":10, "reference_v":5.0}, + "dac_config":{"bit_resolution":12, "reference_v":5.0}, + "calibrate_rail":false +} \ No newline at end of file From d16cff81056440f5b3ddd33c7f4d1a5f860c5481 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 12 Nov 2024 21:10:48 -0500 Subject: [PATCH 110/181] Renaming folder --- {Hello => ArduinoFlashTest}/Hello.ino | 0 ArduinoFlashTest/deleteWhenEverythingWorks.txt | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {Hello => ArduinoFlashTest}/Hello.ino (100%) create mode 100644 ArduinoFlashTest/deleteWhenEverythingWorks.txt diff --git a/Hello/Hello.ino b/ArduinoFlashTest/Hello.ino similarity index 100% rename from Hello/Hello.ino rename to ArduinoFlashTest/Hello.ino diff --git a/ArduinoFlashTest/deleteWhenEverythingWorks.txt b/ArduinoFlashTest/deleteWhenEverythingWorks.txt new file mode 100644 index 0000000..e69de29 From 5690b02bc85345715276ac9b8c6f7790eb4af3b9 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 12 Nov 2024 21:11:08 -0500 Subject: [PATCH 111/181] Deleting old test I made while learning --- scripts/pytest_millan.py | 39 --------------------------------------- 1 file changed, 39 deletions(-) delete mode 100644 scripts/pytest_millan.py diff --git a/scripts/pytest_millan.py b/scripts/pytest_millan.py deleted file mode 100644 index 45ea912..0000000 --- a/scripts/pytest_millan.py +++ /dev/null @@ -1,39 +0,0 @@ -from os import sys, path -# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher -sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) - -from hil.hil import HIL -import hil.utils as utils -import time - -import pytest_check as check -import pytest - - -# ---------------------------------------------------------------------------- # -@pytest.fixture(scope="session") -def hil(): - hil_instance = HIL() - - hil_instance.load_config("config_millan.json") - hil_instance.load_pin_map("millan_net_map.csv", "stm32f407_pin_map.csv") - - yield hil_instance - - hil_instance.shutdown() -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # -def test_do_di(hil: HIL): - hil_out = hil.dout("Millan", "HIL_OUT") - hil_in = hil.din("Millan", "HIL_IN") - - for _i in range(3): - for state in range(2): # 0, 1 - hil_out.state = state - hil_in_state = hil_in.state - check.equal(hil_in_state, state , f"Expected HIL_IN to be {state}, got {hil_in_state}") - - time.sleep(1) -# ---------------------------------------------------------------------------- # \ No newline at end of file From 98fef5dfddfd41081df8b2ecfa400033885c5528 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 12 Nov 2024 21:19:25 -0500 Subject: [PATCH 112/181] Writing the python test (and it should dictate how the net map is made) --- scripts/test_mil_dac.py | 50 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 scripts/test_mil_dac.py diff --git a/scripts/test_mil_dac.py b/scripts/test_mil_dac.py new file mode 100644 index 0000000..8acf59e --- /dev/null +++ b/scripts/test_mil_dac.py @@ -0,0 +1,50 @@ +from os import sys, path +# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher +sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) + +from hil.hil import HIL +import hil.utils as utils +import time + + +# ---------------------------------------------------------------------------- # +def same_to_color_str(same: bool) -> str: + if same: + return utils.bcolors.OKGREEN + "SUCCESS" + utils.bcolors.ENDC + else: + return utils.bcolors.FAIL + "FAILURE" + utils.bcolors.ENDC + + +def test(hil: HIL): + hil_ao = hil.ao("Millan", "HIL_AO") + hil_ai = hil.ai("Millan", "HIL_AI") + + for _i in range(3): + for voltage in [0.0, 1.0, 2.5, 3.3, 5.0]: + print(f"\nHIL_AO: {voltage}") + hil_ao.voltage = voltage + + time.sleep(0.5) + + hil_ai_voltage = hil_ai.voltage + ai_same = abs(hil_ai_voltage - voltage) < 0.1 + + print(f"HIL_AI: {hil_ai_voltage} == {voltage} -> {same_to_color_str(ai_same)}") + + + time.sleep(1) + + print() +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +if __name__ == "__main__": + hil = HIL() + + hil.load_config("config_mil_dac.json") + hil.load_pin_map("mil_dac_net_map.csv", "stm32f407_pin_map.csv") + + test(hil) + + hil.shutdown() \ No newline at end of file From 804f7cb3aacaf97159880777756129cc693012d5 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 12 Nov 2024 21:29:07 -0500 Subject: [PATCH 113/181] mil_dac: maybe net map and config (untested) --- configurations/config_mil_dac.json | 12 ++++++++++++ net_maps/mil_dac_net_map.csv | 3 +++ scripts/test_mil_dac.py | 4 ++-- 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 configurations/config_mil_dac.json create mode 100644 net_maps/mil_dac_net_map.csv diff --git a/configurations/config_mil_dac.json b/configurations/config_mil_dac.json new file mode 100644 index 0000000..c22b756 --- /dev/null +++ b/configurations/config_mil_dac.json @@ -0,0 +1,12 @@ +{ + "$schema": "./config_schema.json", + "dut_connections":[ + {"board":"Millan", "harness_connections":[ + {"dut":{"connector":"breadboard","pin":1, "_":"HIL_AO"}, "hil":{"device":"MilDacTester", "port":"DAC1", "_":"AO"}}, + {"dut":{"connector":"breadboard","pin":2, "_":"HIL_AI"}, "hil":{"device":"MilDacTester", "port":"4", "_":"AI"}} + ]} + ], + "hil_devices":[ + {"name":"MilDacTester", "type":"arduino_micro_breadboard", "id":1} + ] +} diff --git a/net_maps/mil_dac_net_map.csv b/net_maps/mil_dac_net_map.csv new file mode 100644 index 0000000..ff5c21d --- /dev/null +++ b/net_maps/mil_dac_net_map.csv @@ -0,0 +1,3 @@ +Board,Net,Component,Designator,Connector Name,, +Millan,HIL_AO,breadboard,1,FRED,, +Millan,HIL_AI,breadboard,2,FRED,, \ No newline at end of file diff --git a/scripts/test_mil_dac.py b/scripts/test_mil_dac.py index 8acf59e..4ade636 100644 --- a/scripts/test_mil_dac.py +++ b/scripts/test_mil_dac.py @@ -16,8 +16,8 @@ def same_to_color_str(same: bool) -> str: def test(hil: HIL): - hil_ao = hil.ao("Millan", "HIL_AO") - hil_ai = hil.ai("Millan", "HIL_AI") + hil_ao = hil.ao("Millan", "HIL_AO") # HIL writes + hil_ai = hil.ai("Millan", "HIL_AI") # HIL reads for _i in range(3): for voltage in [0.0, 1.0, 2.5, 3.3, 5.0]: From 3212cff8468a710a4c52958bd928e144d9451aa1 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Wed, 13 Nov 2024 16:11:03 -0500 Subject: [PATCH 114/181] Slightly improving breadboard 12-bit DAC test --- scripts/test_mil_dac.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/scripts/test_mil_dac.py b/scripts/test_mil_dac.py index 4ade636..7e4b9c8 100644 --- a/scripts/test_mil_dac.py +++ b/scripts/test_mil_dac.py @@ -5,10 +5,11 @@ from hil.hil import HIL import hil.utils as utils import time +import random # ---------------------------------------------------------------------------- # -def same_to_color_str(same: bool) -> str: +def within_to_color_str(same: bool) -> str: if same: return utils.bcolors.OKGREEN + "SUCCESS" + utils.bcolors.ENDC else: @@ -20,19 +21,19 @@ def test(hil: HIL): hil_ai = hil.ai("Millan", "HIL_AI") # HIL reads for _i in range(3): - for voltage in [0.0, 1.0, 2.5, 3.3, 5.0]: - print(f"\nHIL_AO: {voltage}") + random_voltage = random.uniform(0.0, 5.0) + for voltage in [0.0, 1.0, 2.5, 3.3, 5.0, random_voltage]: hil_ao.voltage = voltage - time.sleep(0.5) + time.sleep(0.2) hil_ai_voltage = hil_ai.voltage - ai_same = abs(hil_ai_voltage - voltage) < 0.1 + ai_within = abs(hil_ai_voltage - voltage) < 0.1 - print(f"HIL_AI: {hil_ai_voltage} == {voltage} -> {same_to_color_str(ai_same)}") + print(f"HIL_AI: {hil_ai_voltage:1.2f} == {voltage:1.2f} -> {within_to_color_str(ai_within)}") - time.sleep(1) + time.sleep(0.5) print() # ---------------------------------------------------------------------------- # From e818d23a888e3050cdce6682fa436f1aa3b247b0 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Thu, 14 Nov 2024 19:54:53 -0500 Subject: [PATCH 115/181] I think I figured out how to use the DAC and maybe a valid pin mapping for the board --- configurations/config_mil_pcb.json | 14 +++++ hil/hil_devices/hil_device_mil_pcb.json | 36 ++++++++++++ net_maps/mil_pcb_net_map.csv | 7 +++ scripts/test_mil_pcb.py | 73 +++++++++++++++++++++++++ 4 files changed, 130 insertions(+) create mode 100644 configurations/config_mil_pcb.json create mode 100644 hil/hil_devices/hil_device_mil_pcb.json create mode 100644 net_maps/mil_pcb_net_map.csv create mode 100644 scripts/test_mil_pcb.py diff --git a/configurations/config_mil_pcb.json b/configurations/config_mil_pcb.json new file mode 100644 index 0000000..0e81861 --- /dev/null +++ b/configurations/config_mil_pcb.json @@ -0,0 +1,14 @@ +{ + "$schema": "./config_schema.json", + "dut_connections":[ + {"board":"Millan", "harness_connections":[ + {"dut":{"connector":"breadboard","pin":1, "_":"HIL_DO"}, "hil":{"device":"MilPcbTester", "port":"A1", "_":"DO"}}, + {"dut":{"connector":"breadboard","pin":2, "_":"HIL_DI"}, "hil":{"device":"MilPcbTester", "port":"D2", "_":"DI"}}, + {"dut":{"connector":"breadboard","pin":3, "_":"HIL_AO"}, "hil":{"device":"MilPcbTester", "port":"DAC1", "_":"AO"}}, + {"dut":{"connector":"breadboard","pin":4, "_":"HIL_AI"}, "hil":{"device":"MilPcbTester", "port":"A2", "_":"AI"}} + ]} + ], + "hil_devices":[ + {"name":"MilPcbTester", "type":"arduino_micro_mil_pcb", "id":1} + ] +} diff --git a/hil/hil_devices/hil_device_mil_pcb.json b/hil/hil_devices/hil_device_mil_pcb.json new file mode 100644 index 0000000..de3977e --- /dev/null +++ b/hil/hil_devices/hil_device_mil_pcb.json @@ -0,0 +1,36 @@ +{ + "$schema": "./emulator_schema.json", + "communication_mode":"serial", + "ports":[ + {"port":18, "name":"A1", "capabilities":["DI", "DO", "AI"], "notes":"5V dig / analog in"}, + {"port":19, "name":"A2", "capabilities":["DI", "DO", "AI"], "notes":"5V dig / analog in"}, + {"port":20, "name":"A3", "capabilities":["DI", "DO", "AI"], "notes":"5V dig / analog in"}, + {"port":21, "name":"A4", "capabilities":["DI", "DO", "AI"], "notes":"5V dig / analog in"}, + + {"port":2, "name":"D1", "capabilities":[], "notes":"SDA (5V dig in)"}, + {"port":4, "name":"D2", "capabilities":["DI"], "notes":"5V dig in"}, + {"port":8, "name":"D3", "capabilities":["DI"], "notes":"5V dig in"}, + {"port":15, "name":"D4", "capabilities":["DI"], "notes":"5V dig in (SCK)"}, + {"port":14, "name":"D5", "capabilities":["DI"], "notes":"5V dig in (COPI/MISO)"}, + {"port":16, "name":"D6", "capabilities":["DI"], "notes":"5V dig in (COPI/MOSI)"}, + {"port":1, "name":"D7", "capabilities":["DI"], "notes":"5V dig in (TX)"}, + {"port":0, "name":"D8", "capabilities":["DI"], "notes":"5V dig in (RX)"}, + + {"port":10, "name":"RLY1", "capabilities":["DO"], "notes":"relay"}, + {"port":11, "name":"RLY2", "capabilities":["DO"], "notes":"relay"}, + {"port":12, "name":"RLY3", "capabilities":["DO"], "notes":"relay"}, + {"port":13, "name":"RLY4", "capabilities":["DO"], "notes":"relay"}, + + {"port":1, "name":"POT1", "capabilities":["POT"], "notes":"6-bit Digipot"}, + {"port":2, "name":"POT2", "capabilities":["POT"], "notes":"6-bit Digipot"}, + + {"port":9, "name":"3v3ref", "capabilities":["AI"], "notes":"3V3 input reference"}, + + {"port":200, "name":"DAC1", "capabilities":["AO"], "notes":"5V 12-bit DAC"}, + {"port":201, "name":"DAC2", "capabilities":["AO"], "notes":"5V 12-bit DAC"} + ], + "adc_config":{"bit_resolution":10, "reference_v":5.0}, + "dac_config":{"bit_resolution":12, "reference_v":5.0}, + "pot_config":{"bit_resolution":6}, + "calibrate_rail":true +} \ No newline at end of file diff --git a/net_maps/mil_pcb_net_map.csv b/net_maps/mil_pcb_net_map.csv new file mode 100644 index 0000000..1fd6849 --- /dev/null +++ b/net_maps/mil_pcb_net_map.csv @@ -0,0 +1,7 @@ +Board,Net,Component,Designator,Connector Name,, + +Millan,HIL_DO,breadboard,1,FRED,, +Millan,HIL_DI,breadboard,2,FRED,, + +Millan,HIL_AO,breadboard,3,FRED,, +Millan,HIL_AI,breadboard,4,FRED,, \ No newline at end of file diff --git a/scripts/test_mil_pcb.py b/scripts/test_mil_pcb.py new file mode 100644 index 0000000..c54e463 --- /dev/null +++ b/scripts/test_mil_pcb.py @@ -0,0 +1,73 @@ +from os import sys, path +# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher +sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) + +from hil.hil import HIL +import hil.utils as utils +import time +import random + + +# ---------------------------------------------------------------------------- # +def bool_to_color_str(same: bool) -> str: + if same: + return utils.bcolors.OKGREEN + "SUCCESS" + utils.bcolors.ENDC + else: + return utils.bcolors.FAIL + "FAILURE" + utils.bcolors.ENDC + + +def test_do_di(hil: HIL): + hil_do = hil.ao("Millan", "HIL_DO") # HIL writes + hil_di = hil.ai("Millan", "HIL_DI") # HIL reads + + for _i in range(3): + for state in [True, False]: + hil_do.state = state + + time.sleep(0.2) + + hil_di_state = hil_di.state + same = hil_di_state == state + + print(f"HIL_DI: {hil_di_state} == {state} -> {bool_to_color_str(same)}") + + time.sleep(0.5) + + print() + +def test_ao_ai(hil: HIL): + hil_ao = hil.ao("Millan", "HIL_AO") # HIL writes + hil_ai = hil.ai("Millan", "HIL_AI") # HIL reads + + for _i in range(3): + random_voltage = random.uniform(0.0, 5.0) + for voltage in [0.0, 1.0, 2.5, 3.3, 5.0, random_voltage]: + hil_ao.voltage = voltage + time.sleep(0.2) + + hil_ai_voltage = hil_ai.voltage + within = abs(hil_ai_voltage - voltage) < 0.1 + + print(f"HIL_AI: {hil_ai_voltage:1.2f} == {voltage:1.2f} -> {bool_to_color_str(within)}") + + time.sleep(0.5) + + print() + +# TODO: test RLY +# TODO: test POT +# TODO: test PWM? +# ---------------------------------------------------------------------------- # + + +# ---------------------------------------------------------------------------- # +if __name__ == "__main__": + hil = HIL() + + hil.load_config("config_mil_pcb.json") + hil.load_pin_map("mil_pcb_net_map.csv", "stm32f407_pin_map.csv") + + test_do_di(hil) + test_ao_ai(hil) + + hil.shutdown() \ No newline at end of file From 0113f8a30f9d02f3fdc30567c973df38c4123b3e Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Thu, 14 Nov 2024 20:47:24 -0500 Subject: [PATCH 116/181] Renaming for Arduino IDE --- ArduinoFlashTest/{Hello.ino => ArduinoFlashTest.ino} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename ArduinoFlashTest/{Hello.ino => ArduinoFlashTest.ino} (89%) diff --git a/ArduinoFlashTest/Hello.ino b/ArduinoFlashTest/ArduinoFlashTest.ino similarity index 89% rename from ArduinoFlashTest/Hello.ino rename to ArduinoFlashTest/ArduinoFlashTest.ino index 376f27b..53b6bc1 100644 --- a/ArduinoFlashTest/Hello.ino +++ b/ArduinoFlashTest/ArduinoFlashTest.ino @@ -1,7 +1,7 @@ #include int value = 0; -int PIN = 3; +int PIN = 4; void setup() { Serial.begin(115200); @@ -17,5 +17,5 @@ void loop() { pinMode(PIN, OUTPUT); digitalWrite(PIN, value); - delay(3000); + delay(10000); } From 164e611e62c0d488244717fa239232f934bee0d2 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Thu, 14 Nov 2024 20:48:28 -0500 Subject: [PATCH 117/181] Fixing file name --- configurations/config_mil_pcb.json | 2 +- ...{hil_device_mil_pcb.json => hil_device_arduino_mil_pcb.json} | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) rename hil/hil_devices/{hil_device_mil_pcb.json => hil_device_arduino_mil_pcb.json} (98%) diff --git a/configurations/config_mil_pcb.json b/configurations/config_mil_pcb.json index 0e81861..5cc9a1a 100644 --- a/configurations/config_mil_pcb.json +++ b/configurations/config_mil_pcb.json @@ -9,6 +9,6 @@ ]} ], "hil_devices":[ - {"name":"MilPcbTester", "type":"arduino_micro_mil_pcb", "id":1} + {"name":"MilPcbTester", "type":"arduino_mil_pcb", "id":1} ] } diff --git a/hil/hil_devices/hil_device_mil_pcb.json b/hil/hil_devices/hil_device_arduino_mil_pcb.json similarity index 98% rename from hil/hil_devices/hil_device_mil_pcb.json rename to hil/hil_devices/hil_device_arduino_mil_pcb.json index de3977e..f6167b1 100644 --- a/hil/hil_devices/hil_device_mil_pcb.json +++ b/hil/hil_devices/hil_device_arduino_mil_pcb.json @@ -1,5 +1,4 @@ { - "$schema": "./emulator_schema.json", "communication_mode":"serial", "ports":[ {"port":18, "name":"A1", "capabilities":["DI", "DO", "AI"], "notes":"5V dig / analog in"}, From cf2399e22a909320670eac80fca671050c9844bb Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Thu, 14 Nov 2024 20:48:45 -0500 Subject: [PATCH 118/181] DX pins don't work, AX pins work fine for DI/DO at least --- configurations/config_mil_pcb.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configurations/config_mil_pcb.json b/configurations/config_mil_pcb.json index 5cc9a1a..45833a4 100644 --- a/configurations/config_mil_pcb.json +++ b/configurations/config_mil_pcb.json @@ -3,7 +3,7 @@ "dut_connections":[ {"board":"Millan", "harness_connections":[ {"dut":{"connector":"breadboard","pin":1, "_":"HIL_DO"}, "hil":{"device":"MilPcbTester", "port":"A1", "_":"DO"}}, - {"dut":{"connector":"breadboard","pin":2, "_":"HIL_DI"}, "hil":{"device":"MilPcbTester", "port":"D2", "_":"DI"}}, + {"dut":{"connector":"breadboard","pin":2, "_":"HIL_DI"}, "hil":{"device":"MilPcbTester", "port":"A4", "_":"DI"}}, {"dut":{"connector":"breadboard","pin":3, "_":"HIL_AO"}, "hil":{"device":"MilPcbTester", "port":"DAC1", "_":"AO"}}, {"dut":{"connector":"breadboard","pin":4, "_":"HIL_AI"}, "hil":{"device":"MilPcbTester", "port":"A2", "_":"AI"}} ]} From 86bc5908659b7a699680a8a1fe3bb900baa5db48 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Thu, 14 Nov 2024 20:49:21 -0500 Subject: [PATCH 119/181] Successfully running DI/DO on AI pins --- scripts/test_mil_pcb.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/scripts/test_mil_pcb.py b/scripts/test_mil_pcb.py index c54e463..d107372 100644 --- a/scripts/test_mil_pcb.py +++ b/scripts/test_mil_pcb.py @@ -17,11 +17,11 @@ def bool_to_color_str(same: bool) -> str: def test_do_di(hil: HIL): - hil_do = hil.ao("Millan", "HIL_DO") # HIL writes - hil_di = hil.ai("Millan", "HIL_DI") # HIL reads + hil_do = hil.dout("Millan", "HIL_DO") # HIL writes + hil_di = hil.din("Millan", "HIL_DI") # HIL reads for _i in range(3): - for state in [True, False]: + for state in [0, 1]: hil_do.state = state time.sleep(0.2) @@ -29,15 +29,17 @@ def test_do_di(hil: HIL): hil_di_state = hil_di.state same = hil_di_state == state - print(f"HIL_DI: {hil_di_state} == {state} -> {bool_to_color_str(same)}") + print(f"{hil_di_state} == {state} -> {bool_to_color_str(same)}") + + input("Press Enter to continue...") time.sleep(0.5) print() def test_ao_ai(hil: HIL): - hil_ao = hil.ao("Millan", "HIL_AO") # HIL writes - hil_ai = hil.ai("Millan", "HIL_AI") # HIL reads + hil_ao = hil.aout("Millan", "HIL_AO") # HIL writes + hil_ai = hil.ain("Millan", "HIL_AI") # HIL reads for _i in range(3): random_voltage = random.uniform(0.0, 5.0) @@ -68,6 +70,6 @@ def test_ao_ai(hil: HIL): hil.load_pin_map("mil_pcb_net_map.csv", "stm32f407_pin_map.csv") test_do_di(hil) - test_ao_ai(hil) + # test_ao_ai(hil) hil.shutdown() \ No newline at end of file From 6e6d8a65862e4493abe1737c91647a61bbe3aebf Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Thu, 14 Nov 2024 20:59:41 -0500 Subject: [PATCH 120/181] Fixing typo --- scripts/test_mil_pcb.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/test_mil_pcb.py b/scripts/test_mil_pcb.py index d107372..7ad514d 100644 --- a/scripts/test_mil_pcb.py +++ b/scripts/test_mil_pcb.py @@ -44,10 +44,10 @@ def test_ao_ai(hil: HIL): for _i in range(3): random_voltage = random.uniform(0.0, 5.0) for voltage in [0.0, 1.0, 2.5, 3.3, 5.0, random_voltage]: - hil_ao.voltage = voltage + hil_ao.state = voltage time.sleep(0.2) - hil_ai_voltage = hil_ai.voltage + hil_ai_voltage = hil_ai.state within = abs(hil_ai_voltage - voltage) < 0.1 print(f"HIL_AI: {hil_ai_voltage:1.2f} == {voltage:1.2f} -> {bool_to_color_str(within)}") @@ -69,7 +69,7 @@ def test_ao_ai(hil: HIL): hil.load_config("config_mil_pcb.json") hil.load_pin_map("mil_pcb_net_map.csv", "stm32f407_pin_map.csv") - test_do_di(hil) - # test_ao_ai(hil) + # test_do_di(hil) + test_ao_ai(hil) hil.shutdown() \ No newline at end of file From 51b17eef137158a12820393bb055818568dcfa38 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Thu, 14 Nov 2024 21:13:31 -0500 Subject: [PATCH 121/181] Can write 0 voltage :shrug: --- configurations/config_mil_pcb.json | 4 ++-- hil/hil_devices/hil_device_arduino_mil_pcb.json | 2 +- scripts/test_mil_pcb.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configurations/config_mil_pcb.json b/configurations/config_mil_pcb.json index 45833a4..2118740 100644 --- a/configurations/config_mil_pcb.json +++ b/configurations/config_mil_pcb.json @@ -3,9 +3,9 @@ "dut_connections":[ {"board":"Millan", "harness_connections":[ {"dut":{"connector":"breadboard","pin":1, "_":"HIL_DO"}, "hil":{"device":"MilPcbTester", "port":"A1", "_":"DO"}}, - {"dut":{"connector":"breadboard","pin":2, "_":"HIL_DI"}, "hil":{"device":"MilPcbTester", "port":"A4", "_":"DI"}}, + {"dut":{"connector":"breadboard","pin":2, "_":"HIL_DI"}, "hil":{"device":"MilPcbTester", "port":"A2", "_":"DI"}}, {"dut":{"connector":"breadboard","pin":3, "_":"HIL_AO"}, "hil":{"device":"MilPcbTester", "port":"DAC1", "_":"AO"}}, - {"dut":{"connector":"breadboard","pin":4, "_":"HIL_AI"}, "hil":{"device":"MilPcbTester", "port":"A2", "_":"AI"}} + {"dut":{"connector":"breadboard","pin":4, "_":"HIL_AI"}, "hil":{"device":"MilPcbTester", "port":"A4", "_":"AI"}} ]} ], "hil_devices":[ diff --git a/hil/hil_devices/hil_device_arduino_mil_pcb.json b/hil/hil_devices/hil_device_arduino_mil_pcb.json index f6167b1..5b5185f 100644 --- a/hil/hil_devices/hil_device_arduino_mil_pcb.json +++ b/hil/hil_devices/hil_device_arduino_mil_pcb.json @@ -31,5 +31,5 @@ "adc_config":{"bit_resolution":10, "reference_v":5.0}, "dac_config":{"bit_resolution":12, "reference_v":5.0}, "pot_config":{"bit_resolution":6}, - "calibrate_rail":true + "calibrate_rail":false } \ No newline at end of file diff --git a/scripts/test_mil_pcb.py b/scripts/test_mil_pcb.py index 7ad514d..0328185 100644 --- a/scripts/test_mil_pcb.py +++ b/scripts/test_mil_pcb.py @@ -50,7 +50,7 @@ def test_ao_ai(hil: HIL): hil_ai_voltage = hil_ai.state within = abs(hil_ai_voltage - voltage) < 0.1 - print(f"HIL_AI: {hil_ai_voltage:1.2f} == {voltage:1.2f} -> {bool_to_color_str(within)}") + print(f"{hil_ai_voltage:1.2f} == {voltage:1.2f} -> {bool_to_color_str(within)}") time.sleep(0.5) From 6a22fb45c351c211f412a268f406778cdaf1c77d Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Thu, 14 Nov 2024 21:46:26 -0500 Subject: [PATCH 122/181] DAC works! The math for voltage to DAC is wrong Also: you can only write: 0-255 because it is a char over serial, but then it defeats the purpose of a 12-bit dac --- configurations/config_mil_pcb.json | 2 +- hil/hil_devices/hil_device.py | 2 +- scripts/test_mil_pcb.py | 8 +++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/configurations/config_mil_pcb.json b/configurations/config_mil_pcb.json index 2118740..2866652 100644 --- a/configurations/config_mil_pcb.json +++ b/configurations/config_mil_pcb.json @@ -4,7 +4,7 @@ {"board":"Millan", "harness_connections":[ {"dut":{"connector":"breadboard","pin":1, "_":"HIL_DO"}, "hil":{"device":"MilPcbTester", "port":"A1", "_":"DO"}}, {"dut":{"connector":"breadboard","pin":2, "_":"HIL_DI"}, "hil":{"device":"MilPcbTester", "port":"A2", "_":"DI"}}, - {"dut":{"connector":"breadboard","pin":3, "_":"HIL_AO"}, "hil":{"device":"MilPcbTester", "port":"DAC1", "_":"AO"}}, + {"dut":{"connector":"breadboard","pin":3, "_":"HIL_AO"}, "hil":{"device":"MilPcbTester", "port":"DAC2", "_":"AO"}}, {"dut":{"connector":"breadboard","pin":4, "_":"HIL_AI"}, "hil":{"device":"MilPcbTester", "port":"A4", "_":"AI"}} ]} ], diff --git a/hil/hil_devices/hil_device.py b/hil/hil_devices/hil_device.py index 7a8675c..44ab2c7 100644 --- a/hil/hil_devices/hil_device.py +++ b/hil/hil_devices/hil_device.py @@ -84,7 +84,7 @@ def write_gpio(self, pin: int, value: int) -> None: def write_dac(self, pin: int, value: int) -> None: value = min(self.dac_max, max(0, int(value * self.volts_to_dac))) data = [(HIL_CMD_WRITE_DAC & HIL_CMD_MASK), (pin & HIL_ID_MASK), value] - # print(f"write pin {pin} to {value}") + print(f"write pin {pin} to {value}") self.sm.send_data(self.id, data) def read_gpio(self, pin: int) -> int: diff --git a/scripts/test_mil_pcb.py b/scripts/test_mil_pcb.py index 0328185..42f5185 100644 --- a/scripts/test_mil_pcb.py +++ b/scripts/test_mil_pcb.py @@ -5,7 +5,7 @@ from hil.hil import HIL import hil.utils as utils import time -import random +# import random # ---------------------------------------------------------------------------- # @@ -42,8 +42,10 @@ def test_ao_ai(hil: HIL): hil_ai = hil.ain("Millan", "HIL_AI") # HIL reads for _i in range(3): - random_voltage = random.uniform(0.0, 5.0) - for voltage in [0.0, 1.0, 2.5, 3.3, 5.0, random_voltage]: + # random_voltage = random.uniform(0.0, 5.0) + for voltage in [0.34]: + # 5 * 255 / (2^12 - 1) = 0.31135531135 + # 5 * 0.1 / 0.31135531135 = 1.60588235297 hil_ao.state = voltage time.sleep(0.2) From f117d2b191bdfd6d4564fd2c2dfcf70a91fd2ac6 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Fri, 15 Nov 2024 09:09:44 -0500 Subject: [PATCH 123/181] DAC is effectively 8-bit when sent over serial --- hil/hil_devices/hil_device_arduino_mil_pcb.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hil/hil_devices/hil_device_arduino_mil_pcb.json b/hil/hil_devices/hil_device_arduino_mil_pcb.json index 5b5185f..c668263 100644 --- a/hil/hil_devices/hil_device_arduino_mil_pcb.json +++ b/hil/hil_devices/hil_device_arduino_mil_pcb.json @@ -25,11 +25,11 @@ {"port":9, "name":"3v3ref", "capabilities":["AI"], "notes":"3V3 input reference"}, - {"port":200, "name":"DAC1", "capabilities":["AO"], "notes":"5V 12-bit DAC"}, - {"port":201, "name":"DAC2", "capabilities":["AO"], "notes":"5V 12-bit DAC"} + {"port":200, "name":"DAC1", "capabilities":["AO"], "notes":"5V ~8-bit DAC"}, + {"port":201, "name":"DAC2", "capabilities":["AO"], "notes":"5V ~8-bit DAC"} ], "adc_config":{"bit_resolution":10, "reference_v":5.0}, - "dac_config":{"bit_resolution":12, "reference_v":5.0}, + "dac_config":{"bit_resolution":8, "reference_v":5.0}, "pot_config":{"bit_resolution":6}, "calibrate_rail":false } \ No newline at end of file From cb0a6b4a9b5a78e7e4a1ec6cc52f83f341af2690 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Fri, 15 Nov 2024 09:43:19 -0500 Subject: [PATCH 124/181] Flipping addresses for DACs More intuitive. The first DAC is the one with the "normal"/not modified address --- TestBench/TestBench.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TestBench/TestBench.ino b/TestBench/TestBench.ino index 81c8237..fb2fd9f 100644 --- a/TestBench/TestBench.ino +++ b/TestBench/TestBench.ino @@ -92,8 +92,8 @@ void setup() digipot2.begin(); #endif #ifdef DAC - dacs[0].init(0x63, dac_vref); - dacs[1].init(0x62, dac_vref); + dacs[0].init(0x62, dac_vref); + dacs[1].init(0x63, dac_vref); dacs[0].setMode(MCP4725_POWER_DOWN_500KRES); dacs[1].setMode(MCP4725_POWER_DOWN_500KRES); dac_power_down[0] = 1; From 888a566ba0a17920196b622fccd920e040ebd623 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Fri, 15 Nov 2024 11:39:33 -0500 Subject: [PATCH 125/181] Writing a test for the RLY --- configurations/config_mil_pcb.json | 11 +++++++---- scripts/test_mil_pcb.py | 31 +++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/configurations/config_mil_pcb.json b/configurations/config_mil_pcb.json index 2866652..e9408ad 100644 --- a/configurations/config_mil_pcb.json +++ b/configurations/config_mil_pcb.json @@ -2,10 +2,13 @@ "$schema": "./config_schema.json", "dut_connections":[ {"board":"Millan", "harness_connections":[ - {"dut":{"connector":"breadboard","pin":1, "_":"HIL_DO"}, "hil":{"device":"MilPcbTester", "port":"A1", "_":"DO"}}, - {"dut":{"connector":"breadboard","pin":2, "_":"HIL_DI"}, "hil":{"device":"MilPcbTester", "port":"A2", "_":"DI"}}, - {"dut":{"connector":"breadboard","pin":3, "_":"HIL_AO"}, "hil":{"device":"MilPcbTester", "port":"DAC2", "_":"AO"}}, - {"dut":{"connector":"breadboard","pin":4, "_":"HIL_AI"}, "hil":{"device":"MilPcbTester", "port":"A4", "_":"AI"}} + {"dut":{"connector":"breadboard","pin":1, "_":"HIL_DO"}, "hil":{"device":"MilPcbTester", "port":"A1", "_":"DO"}}, + {"dut":{"connector":"breadboard","pin":2, "_":"HIL_DI"}, "hil":{"device":"MilPcbTester", "port":"A2", "_":"DI"}}, + + {"dut":{"connector":"breadboard","pin":3, "_":"HIL_AO"}, "hil":{"device":"MilPcbTester", "port":"DAC1", "_":"AO"}}, + {"dut":{"connector":"breadboard","pin":4, "_":"HIL_AI"}, "hil":{"device":"MilPcbTester", "port":"A4", "_":"AI"}}, + + {"dut":{"connector":"breadboard","pin":5, "_":"HIL_RLY"}, "hil":{"device":"MilPcbTester", "port":"RLY1", "_":"DO"}} ]} ], "hil_devices":[ diff --git a/scripts/test_mil_pcb.py b/scripts/test_mil_pcb.py index 42f5185..35723d9 100644 --- a/scripts/test_mil_pcb.py +++ b/scripts/test_mil_pcb.py @@ -17,8 +17,8 @@ def bool_to_color_str(same: bool) -> str: def test_do_di(hil: HIL): - hil_do = hil.dout("Millan", "HIL_DO") # HIL writes - hil_di = hil.din("Millan", "HIL_DI") # HIL reads + hil_do = hil.dout("Millan", "HIL_DO") # A1 + hil_di = hil.din("Millan", "HIL_DI") # A2 for _i in range(3): for state in [0, 1]: @@ -38,8 +38,8 @@ def test_do_di(hil: HIL): print() def test_ao_ai(hil: HIL): - hil_ao = hil.aout("Millan", "HIL_AO") # HIL writes - hil_ai = hil.ain("Millan", "HIL_AI") # HIL reads + hil_ao = hil.aout("Millan", "HIL_AO") # DAC1 + hil_ai = hil.ain("Millan", "HIL_AI") # A4 for _i in range(3): # random_voltage = random.uniform(0.0, 5.0) @@ -58,7 +58,28 @@ def test_ao_ai(hil: HIL): print() -# TODO: test RLY +def test_rly(hil: HIL): + hil_rly = hil.dout("Millan", "HIL_RLY") # RLY1 + hil_di = hil.din("Millan", "HIL_DI") # A2 + + # 5V -> RLY1+ + # RLY1- -> A2 + + for _i in range(3): + for state in [0, 1]: + hil_rly.state = state + + time.sleep(0.2) + + hil_di_state = hil_di.state + same = hil_di_state == state + + print(f"{hil_di_state} == {state} -> {bool_to_color_str(same)}") + + time.sleep(0.5) + + print() + # TODO: test POT # TODO: test PWM? # ---------------------------------------------------------------------------- # From 7cf4ba307f81051aa0e154c91020156e7e2dded5 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 16 Nov 2024 17:17:29 -0500 Subject: [PATCH 126/181] Adding last year's "pcb" device config for DI pins for comparison --- hil/hil_devices/hil_device_arduino_mil_pcb.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hil/hil_devices/hil_device_arduino_mil_pcb.json b/hil/hil_devices/hil_device_arduino_mil_pcb.json index c668263..f323a0d 100644 --- a/hil/hil_devices/hil_device_arduino_mil_pcb.json +++ b/hil/hil_devices/hil_device_arduino_mil_pcb.json @@ -15,6 +15,12 @@ {"port":1, "name":"D7", "capabilities":["DI"], "notes":"5V dig in (TX)"}, {"port":0, "name":"D8", "capabilities":["DI"], "notes":"5V dig in (RX)"}, + {"port":16, "name":"DI3", "capabilities":["DI"], "notes":"digital input 5V-30V"}, + {"port":14, "name":"DI4", "capabilities":["DI"], "notes":"digital input 5V-30V"}, + {"port":15, "name":"DI5", "capabilities":["DI"], "notes":"digital input 5V-30V"}, + {"port":8, "name":"DI6", "capabilities":["DI"], "notes":"digital input 5V-30V"}, + {"port":4, "name":"DI7", "capabilities":["DI"], "notes":"digital input 5V-30V"}, + {"port":10, "name":"RLY1", "capabilities":["DO"], "notes":"relay"}, {"port":11, "name":"RLY2", "capabilities":["DO"], "notes":"relay"}, {"port":12, "name":"RLY3", "capabilities":["DO"], "notes":"relay"}, From c3d598389fc14016397f7908bbcb9e9bed6004b1 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 16 Nov 2024 17:25:07 -0500 Subject: [PATCH 127/181] Improving RLY test to take DO input --- scripts/test_mil_pcb.py | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/scripts/test_mil_pcb.py b/scripts/test_mil_pcb.py index 35723d9..5ef4566 100644 --- a/scripts/test_mil_pcb.py +++ b/scripts/test_mil_pcb.py @@ -59,26 +59,31 @@ def test_ao_ai(hil: HIL): print() def test_rly(hil: HIL): + hil_do = hil.dout("Millan", "HIL_DO") # A1 hil_rly = hil.dout("Millan", "HIL_RLY") # RLY1 hil_di = hil.din("Millan", "HIL_DI") # A2 - # 5V -> RLY1+ + # A1 -> RLY1+ # RLY1- -> A2 for _i in range(3): - for state in [0, 1]: - hil_rly.state = state + for do_state in [0, 1]: + for rly_state in [0, 1]: + hil_do.state = do_state + hil_rly.state = rly_state - time.sleep(0.2) + expected_state = do_state and rly_state - hil_di_state = hil_di.state - same = hil_di_state == state + time.sleep(0.2) - print(f"{hil_di_state} == {state} -> {bool_to_color_str(same)}") + hil_di_state = hil_di.state + same = hil_di_state == expected_state - time.sleep(0.5) + print(f"{hil_di_state} == {expected_state} -> {bool_to_color_str(same)}") - print() + # input("Press Enter to continue...") + + time.sleep(0.5) # TODO: test POT # TODO: test PWM? @@ -86,6 +91,7 @@ def test_rly(hil: HIL): # ---------------------------------------------------------------------------- # +# ONLY RUN ONE TEST AT A TIME AS THEY REFERENCE OVERLAPPING PINS if __name__ == "__main__": hil = HIL() @@ -93,6 +99,7 @@ def test_rly(hil: HIL): hil.load_pin_map("mil_pcb_net_map.csv", "stm32f407_pin_map.csv") # test_do_di(hil) - test_ao_ai(hil) + # test_ao_ai(hil) + test_rly(hil) hil.shutdown() \ No newline at end of file From 6fca615217a4d1414016483095304cbf7ab0cee1 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 16 Nov 2024 17:29:36 -0500 Subject: [PATCH 128/181] Renaming test --- scripts/test_mil_pcb.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/test_mil_pcb.py b/scripts/test_mil_pcb.py index 5ef4566..64b811d 100644 --- a/scripts/test_mil_pcb.py +++ b/scripts/test_mil_pcb.py @@ -37,7 +37,7 @@ def test_do_di(hil: HIL): print() -def test_ao_ai(hil: HIL): +def test_dac_ai(hil: HIL): hil_ao = hil.aout("Millan", "HIL_AO") # DAC1 hil_ai = hil.ain("Millan", "HIL_AI") # A4 @@ -99,7 +99,7 @@ def test_rly(hil: HIL): hil.load_pin_map("mil_pcb_net_map.csv", "stm32f407_pin_map.csv") # test_do_di(hil) - # test_ao_ai(hil) + # test_dac_ai(hil) test_rly(hil) hil.shutdown() \ No newline at end of file From ad2aa9cf7db42f02eca2944024b6f1f71963c75d Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 16 Nov 2024 18:09:59 -0500 Subject: [PATCH 129/181] WRITE_PWM command/device type --- TestBench/TestBench.ino | 7 +++++++ hil/components/component.py | 2 ++ hil/hil.py | 3 +++ hil/hil_devices/hil_device.py | 6 ++++++ 4 files changed, 18 insertions(+) diff --git a/TestBench/TestBench.ino b/TestBench/TestBench.ino index fb2fd9f..e2820b0 100644 --- a/TestBench/TestBench.ino +++ b/TestBench/TestBench.ino @@ -75,6 +75,7 @@ enum GpioCommands WRITE_GPIO = 3, READ_ID = 4, WRITE_POT = 5, + WRITE_PWM = 6, }; @@ -214,6 +215,12 @@ void loop() } break; } + case (WRITE_PWM): + { + pinMode(pin, OUTPUT); + analogWrite(pin, value & 0xFF); + break; + } } } } diff --git a/hil/components/component.py b/hil/components/component.py index b38d8fa..ba03705 100644 --- a/hil/components/component.py +++ b/hil/components/component.py @@ -86,6 +86,8 @@ def __init__(self, name: str, hil_con: tuple[str, str], mode: str, hil: 'HIL'): self.hiZ_func = lambda : dev.read_gpio(hil_port_num) elif(mode == "POT"): self.write_func = lambda s: dev.write_pot(hil_port_num, s) + elif mode == "PWM": + self.write_func = lambda s: dev.write_pwm(hil_port_num, s) else: utils.log_error(f"Unrecognized emulation/measurement mode {mode} for component {self.name}") else: diff --git a/hil/hil.py b/hil/hil.py index a2b25cf..eeecdc8 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -182,6 +182,9 @@ def aout(self, board: str, net: str) -> Component: def pot(self, board: str, net: str) -> Component: return self.add_component(board, net, 'POT') + + def pwm(self, board: str, net: str) -> Component: + return self.add_component(board, net, 'PWM') def daq_var(self, board: str, var_name: str) -> DAQVariable: try: diff --git a/hil/hil_devices/hil_device.py b/hil/hil_devices/hil_device.py index 44ab2c7..58bb0b5 100644 --- a/hil/hil_devices/hil_device.py +++ b/hil/hil_devices/hil_device.py @@ -13,6 +13,7 @@ HIL_CMD_WRITE_GPIO = 3 HIL_CMD_READ_ID = 4 HIL_CMD_WRITE_POT = 5 +HIL_CMD_WRITE_PWM = 6 HIL_ID_MASK = 0xFF @@ -111,3 +112,8 @@ def write_pot(self, pin: int, value: float) -> None: data = [(HIL_CMD_WRITE_POT & HIL_CMD_MASK), (pin & HIL_ID_MASK), value] #print(f"sending {value} to pin {pin}") self.sm.send_data(self.id, data) + + def write_pwm(self, pin: int, value: int) -> None: + data = [(HIL_CMD_WRITE_PWM & HIL_CMD_MASK), (pin & HIL_ID_MASK), value] + print(f"writing {value} to pin {pin}") + self.sm.send_data(self.id, data) From 2146ddd1abab1d08407c3593942238061a510883 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 16 Nov 2024 19:47:38 -0500 Subject: [PATCH 130/181] Adding PWM pins to the device config --- hil/hil_devices/hil_device_arduino_mil_pcb.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hil/hil_devices/hil_device_arduino_mil_pcb.json b/hil/hil_devices/hil_device_arduino_mil_pcb.json index f323a0d..01d3f43 100644 --- a/hil/hil_devices/hil_device_arduino_mil_pcb.json +++ b/hil/hil_devices/hil_device_arduino_mil_pcb.json @@ -15,6 +15,11 @@ {"port":1, "name":"D7", "capabilities":["DI"], "notes":"5V dig in (TX)"}, {"port":0, "name":"D8", "capabilities":["DI"], "notes":"5V dig in (RX)"}, + {"port":3, "name":"PWM1", "capabilities":["PWM"], "notes":"5V 8-bit PWM -> RC"}, + {"port":5, "name":"PWM2", "capabilities":["PWM"], "notes":"5V 8-bit PWM -> RC"}, + {"port":6, "name":"PWM3", "capabilities":["PWM"], "notes":"5V 8-bit PWM -> RC"}, + {"port":9, "name":"PWM4", "capabilities":["PWM"], "notes":"5V 8-bit PWM -> RC"}, + {"port":16, "name":"DI3", "capabilities":["DI"], "notes":"digital input 5V-30V"}, {"port":14, "name":"DI4", "capabilities":["DI"], "notes":"digital input 5V-30V"}, {"port":15, "name":"DI5", "capabilities":["DI"], "notes":"digital input 5V-30V"}, From 78931f057cbf8406a7b2446b82a1ef98279b86fa Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 16 Nov 2024 19:48:43 -0500 Subject: [PATCH 131/181] Reorganizing files --- hil/hil_devices/hil_device_arduino_mil_pcb.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hil/hil_devices/hil_device_arduino_mil_pcb.json b/hil/hil_devices/hil_device_arduino_mil_pcb.json index 01d3f43..cc362bd 100644 --- a/hil/hil_devices/hil_device_arduino_mil_pcb.json +++ b/hil/hil_devices/hil_device_arduino_mil_pcb.json @@ -15,17 +15,17 @@ {"port":1, "name":"D7", "capabilities":["DI"], "notes":"5V dig in (TX)"}, {"port":0, "name":"D8", "capabilities":["DI"], "notes":"5V dig in (RX)"}, + {"port":16, "name":"DI3", "capabilities":["DI"], "notes":"digital input 5V-30V"}, + {"port":14, "name":"DI4", "capabilities":["DI"], "notes":"digital input 5V-30V"}, + {"port":15, "name":"DI5", "capabilities":["DI"], "notes":"digital input 5V-30V"}, + {"port":8, "name":"DI6", "capabilities":["DI"], "notes":"digital input 5V-30V"}, + {"port":4, "name":"DI7", "capabilities":["DI"], "notes":"digital input 5V-30V"}, + {"port":3, "name":"PWM1", "capabilities":["PWM"], "notes":"5V 8-bit PWM -> RC"}, {"port":5, "name":"PWM2", "capabilities":["PWM"], "notes":"5V 8-bit PWM -> RC"}, {"port":6, "name":"PWM3", "capabilities":["PWM"], "notes":"5V 8-bit PWM -> RC"}, {"port":9, "name":"PWM4", "capabilities":["PWM"], "notes":"5V 8-bit PWM -> RC"}, - {"port":16, "name":"DI3", "capabilities":["DI"], "notes":"digital input 5V-30V"}, - {"port":14, "name":"DI4", "capabilities":["DI"], "notes":"digital input 5V-30V"}, - {"port":15, "name":"DI5", "capabilities":["DI"], "notes":"digital input 5V-30V"}, - {"port":8, "name":"DI6", "capabilities":["DI"], "notes":"digital input 5V-30V"}, - {"port":4, "name":"DI7", "capabilities":["DI"], "notes":"digital input 5V-30V"}, - {"port":10, "name":"RLY1", "capabilities":["DO"], "notes":"relay"}, {"port":11, "name":"RLY2", "capabilities":["DO"], "notes":"relay"}, {"port":12, "name":"RLY3", "capabilities":["DO"], "notes":"relay"}, From 46fb8304d99817c2fdc6850ae505c910da35cf3e Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 16 Nov 2024 20:16:35 -0500 Subject: [PATCH 132/181] net_map and config for all the possible pins; need to update test --- configurations/config_mil_pcb.json | 30 ++++++++++++++++++++++++------ net_maps/mil_pcb_net_map.csv | 28 ++++++++++++++++++++++++---- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/configurations/config_mil_pcb.json b/configurations/config_mil_pcb.json index e9408ad..d0e2b1a 100644 --- a/configurations/config_mil_pcb.json +++ b/configurations/config_mil_pcb.json @@ -2,13 +2,31 @@ "$schema": "./config_schema.json", "dut_connections":[ {"board":"Millan", "harness_connections":[ - {"dut":{"connector":"breadboard","pin":1, "_":"HIL_DO"}, "hil":{"device":"MilPcbTester", "port":"A1", "_":"DO"}}, - {"dut":{"connector":"breadboard","pin":2, "_":"HIL_DI"}, "hil":{"device":"MilPcbTester", "port":"A2", "_":"DI"}}, - - {"dut":{"connector":"breadboard","pin":3, "_":"HIL_AO"}, "hil":{"device":"MilPcbTester", "port":"DAC1", "_":"AO"}}, - {"dut":{"connector":"breadboard","pin":4, "_":"HIL_AI"}, "hil":{"device":"MilPcbTester", "port":"A4", "_":"AI"}}, + {"dut":{"connector":"breadboard","pin":5, "_":"HIL_PWM1"}, "hil":{"device":"MilPcbTester", "port":"PWM1", "_":"PWM"}}, + {"dut":{"connector":"breadboard","pin":6, "_":"HIL_PWM2"}, "hil":{"device":"MilPcbTester", "port":"PWM2", "_":"PWM"}}, + {"dut":{"connector":"breadboard","pin":7, "_":"HIL_PWM3"}, "hil":{"device":"MilPcbTester", "port":"PWM3", "_":"PWM"}}, + {"dut":{"connector":"breadboard","pin":8, "_":"HIL_PWM4"}, "hil":{"device":"MilPcbTester", "port":"PWM4", "_":"PWM"}}, - {"dut":{"connector":"breadboard","pin":5, "_":"HIL_RLY"}, "hil":{"device":"MilPcbTester", "port":"RLY1", "_":"DO"}} + {"dut":{"connector":"breadboard","pin":9, "_":"HIL_A1"}, "hil":{"device":"MilPcbTester", "port":"A1", "_":"DI/DO/AI"}}, + {"dut":{"connector":"breadboard","pin":10, "_":"HIL_A2"}, "hil":{"device":"MilPcbTester", "port":"A2", "_":"DI/DO/AI"}}, + {"dut":{"connector":"breadboard","pin":11, "_":"HIL_A3"}, "hil":{"device":"MilPcbTester", "port":"A3", "_":"DI/DO/AI"}}, + {"dut":{"connector":"breadboard","pin":12, "_":"HIL_A4"}, "hil":{"device":"MilPcbTester", "port":"A4", "_":"DI/DO/AI"}}, + + {"dut":{"connector":"breadboard","pin":13, "_":"HIL_RLY1"}, "hil":{"device":"MilPcbTester", "port":"RLY1", "_":"DO"}}, + {"dut":{"connector":"breadboard","pin":14, "_":"HIL_RLY2"}, "hil":{"device":"MilPcbTester", "port":"RLY2", "_":"DO"}}, + {"dut":{"connector":"breadboard","pin":15, "_":"HIL_RLY3"}, "hil":{"device":"MilPcbTester", "port":"RLY3", "_":"DO"}}, + {"dut":{"connector":"breadboard","pin":16, "_":"HIL_RLY4"}, "hil":{"device":"MilPcbTester", "port":"RLY4", "_":"DO"}}, + + {"dut":{"connector":"breadboard","pin":17, "_":"HIL_D2"}, "hil":{"device":"MilPcbTester", "port":"D2", "_":"DI"}}, + {"dut":{"connector":"breadboard","pin":18, "_":"HIL_D3"}, "hil":{"device":"MilPcbTester", "port":"D3", "_":"DI"}}, + {"dut":{"connector":"breadboard","pin":19, "_":"HIL_D4"}, "hil":{"device":"MilPcbTester", "port":"D4", "_":"DI"}}, + {"dut":{"connector":"breadboard","pin":20, "_":"HIL_D5"}, "hil":{"device":"MilPcbTester", "port":"D5", "_":"DI"}}, + {"dut":{"connector":"breadboard","pin":21, "_":"HIL_D6"}, "hil":{"device":"MilPcbTester", "port":"D6", "_":"DI"}}, + {"dut":{"connector":"breadboard","pin":22, "_":"HIL_D7"}, "hil":{"device":"MilPcbTester", "port":"D7", "_":"DI"}}, + {"dut":{"connector":"breadboard","pin":23, "_":"HIL_D8"}, "hil":{"device":"MilPcbTester", "port":"D8", "_":"DI"}}, + + {"dut":{"connector":"breadboard","pin":24, "_":"HIL_DAC1"}, "hil":{"device":"MilPcbTester", "port":"DAC1", "_":"AO"}}, + {"dut":{"connector":"breadboard","pin":25, "_":"HIL_DAC2"}, "hil":{"device":"MilPcbTester", "port":"DAC2", "_":"AO"}} ]} ], "hil_devices":[ diff --git a/net_maps/mil_pcb_net_map.csv b/net_maps/mil_pcb_net_map.csv index 1fd6849..48ff349 100644 --- a/net_maps/mil_pcb_net_map.csv +++ b/net_maps/mil_pcb_net_map.csv @@ -1,7 +1,27 @@ Board,Net,Component,Designator,Connector Name,, -Millan,HIL_DO,breadboard,1,FRED,, -Millan,HIL_DI,breadboard,2,FRED,, +Millan,HIL_PWM1,breadboard,5,FRED,, +Millan,HIL_PWM2,breadboard,6,FRED,, +Millan,HIL_PWM3,breadboard,7,FRED,, +Millan,HIL_PWM4,breadboard,8,FRED,, -Millan,HIL_AO,breadboard,3,FRED,, -Millan,HIL_AI,breadboard,4,FRED,, \ No newline at end of file +Millan,HIL_A1,breadboard,9,FRED,, +Millan,HIL_A2,breadboard,10,FRED,, +Millan,HIL_A3,breadboard,11,FRED,, +Millan,HIL_A4,breadboard,12,FRED,, + +Millan,HIL_RLY1,breadboard,13,FRED,, +Millan,HIL_RLY2,breadboard,14,FRED,, +Millan,HIL_RLY3,breadboard,15,FRED,, +Millan,HIL_RLY4,breadboard,16,FRED,, + +Millan,HIL_D2,breadboard,17,FRED,, +Millan,HIL_D3,breadboard,18,FRED,, +Millan,HIL_D4,breadboard,19,FRED,, +Millan,HIL_D5,breadboard,20,FRED,, +Millan,HIL_D6,breadboard,21,FRED,, +Millan,HIL_D7,breadboard,22,FRED,, +Millan,HIL_D8,breadboard,23,FRED,, + +Millan,HIL_DAC1,breadboard,24,FRED,, +Millan,HIL_DAC2,breadboard,25,FRED,, \ No newline at end of file From 53604cdd570e05e643b5dabca2233b94d00f14cd Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 16 Nov 2024 20:23:32 -0500 Subject: [PATCH 133/181] Updating test to match net_map and config changes --- scripts/test_mil_pcb.py | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/scripts/test_mil_pcb.py b/scripts/test_mil_pcb.py index 64b811d..16aa675 100644 --- a/scripts/test_mil_pcb.py +++ b/scripts/test_mil_pcb.py @@ -5,7 +5,7 @@ from hil.hil import HIL import hil.utils as utils import time -# import random +import random # ---------------------------------------------------------------------------- # @@ -17,16 +17,16 @@ def bool_to_color_str(same: bool) -> str: def test_do_di(hil: HIL): - hil_do = hil.dout("Millan", "HIL_DO") # A1 - hil_di = hil.din("Millan", "HIL_DI") # A2 + hil_a1 = hil.dout("Millan", "HIL_A1") # DO -> HIL writes + hil_a2 = hil.din ("Millan", "HIL_A2") # DI -> HIL reads for _i in range(3): for state in [0, 1]: - hil_do.state = state + hil_a1.state = state time.sleep(0.2) - hil_di_state = hil_di.state + hil_di_state = hil_a2.state same = hil_di_state == state print(f"{hil_di_state} == {state} -> {bool_to_color_str(same)}") @@ -38,18 +38,17 @@ def test_do_di(hil: HIL): print() def test_dac_ai(hil: HIL): - hil_ao = hil.aout("Millan", "HIL_AO") # DAC1 - hil_ai = hil.ain("Millan", "HIL_AI") # A4 + hil_dac1 = hil.aout("Millan", "HIL_DAC1") # AO -> HIL writes + hil_a4 = hil.ain ("Millan", "HIL_A3") # AI -> HIL reads for _i in range(3): - # random_voltage = random.uniform(0.0, 5.0) - for voltage in [0.34]: - # 5 * 255 / (2^12 - 1) = 0.31135531135 - # 5 * 0.1 / 0.31135531135 = 1.60588235297 - hil_ao.state = voltage + random_voltage = random.uniform(0.0, 5.0) + voltages = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, random_voltage] + for voltage in voltages: + hil_dac1.state = voltage time.sleep(0.2) - hil_ai_voltage = hil_ai.state + hil_ai_voltage = hil_a4.state within = abs(hil_ai_voltage - voltage) < 0.1 print(f"{hil_ai_voltage:1.2f} == {voltage:1.2f} -> {bool_to_color_str(within)}") @@ -59,9 +58,9 @@ def test_dac_ai(hil: HIL): print() def test_rly(hil: HIL): - hil_do = hil.dout("Millan", "HIL_DO") # A1 - hil_rly = hil.dout("Millan", "HIL_RLY") # RLY1 - hil_di = hil.din("Millan", "HIL_DI") # A2 + hil_a1 = hil.dout("Millan", "HIL_A1") # DO -> HIL writes + hil_rly1 = hil.dout("Millan", "HIL_RLY1") # DO -> HIL writes + hil_a2 = hil.din ("Millan", "HIL_A2") # DI -> HIL reads # A1 -> RLY1+ # RLY1- -> A2 @@ -69,14 +68,14 @@ def test_rly(hil: HIL): for _i in range(3): for do_state in [0, 1]: for rly_state in [0, 1]: - hil_do.state = do_state - hil_rly.state = rly_state + hil_a1.state = do_state + hil_rly1.state = rly_state expected_state = do_state and rly_state time.sleep(0.2) - hil_di_state = hil_di.state + hil_di_state = hil_a2.state same = hil_di_state == expected_state print(f"{hil_di_state} == {expected_state} -> {bool_to_color_str(same)}") From 3381d99b3921e935942b8ca7b743a2466e6ed45b Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 16 Nov 2024 20:31:41 -0500 Subject: [PATCH 134/181] Test for pwm. Runs all 4 PWMs --- scripts/test_mil_pcb.py | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/scripts/test_mil_pcb.py b/scripts/test_mil_pcb.py index 16aa675..0bfd178 100644 --- a/scripts/test_mil_pcb.py +++ b/scripts/test_mil_pcb.py @@ -84,8 +84,29 @@ def test_rly(hil: HIL): time.sleep(0.5) +def test_pwm(hil: HIL): + hil_pwms = [hil.pwm("Millan", f"HIL_PWM{i}") for i in range(1, 5)] # PWM -> HIL writes + hil_as = [hil.ain("Millan", f"HIL_A{i}") for i in range(1, 5)] # AI -> HIL writes + + for _i in range(3): + for i in range(4): + random_voltage = random.uniform(0.0, 5.0) + voltages = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, random_voltage] + for voltage in voltages: + # voltage: [0.0, 5.0] -> pwm_value: [0, 255] + pwm_value = int(voltage / 5.0 * 255) + + hil_pwms[i].state = pwm_value + time.sleep(0.2) + + hil_ai_voltage = hil_as[i].state + within = abs(hil_ai_voltage - voltage) < 0.1 + + print(f"{hil_ai_voltage:1.2f} == {voltage:1.2f} -> {bool_to_color_str(within)}") + + time.sleep(0.5) + # TODO: test POT -# TODO: test PWM? # ---------------------------------------------------------------------------- # @@ -99,6 +120,7 @@ def test_rly(hil: HIL): # test_do_di(hil) # test_dac_ai(hil) - test_rly(hil) + # test_rly(hil) + # test_pwm(hil) hil.shutdown() \ No newline at end of file From d84c98352c0f1d92e5ec12867a284199b60c21f4 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 16 Nov 2024 20:34:41 -0500 Subject: [PATCH 135/181] Testing both DACs --- scripts/test_mil_pcb.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/scripts/test_mil_pcb.py b/scripts/test_mil_pcb.py index 0bfd178..436b647 100644 --- a/scripts/test_mil_pcb.py +++ b/scripts/test_mil_pcb.py @@ -37,26 +37,29 @@ def test_do_di(hil: HIL): print() + def test_dac_ai(hil: HIL): - hil_dac1 = hil.aout("Millan", "HIL_DAC1") # AO -> HIL writes - hil_a4 = hil.ain ("Millan", "HIL_A3") # AI -> HIL reads + hil_dacs = [hil.aout("Millan", f"HIL_DAC{i}") for i in range(1, 5)] # AO -> HIL writes + hil_ais = [hil.ain ("Millan", f"HIL_A{i}") for i in range(1, 5)] # AI -> HIL reads for _i in range(3): - random_voltage = random.uniform(0.0, 5.0) - voltages = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, random_voltage] - for voltage in voltages: - hil_dac1.state = voltage - time.sleep(0.2) - - hil_ai_voltage = hil_a4.state - within = abs(hil_ai_voltage - voltage) < 0.1 + for i in range(4): + random_voltage = random.uniform(0.0, 5.0) + voltages = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, random_voltage] + for voltage in voltages: + hil_dacs[i].state = voltage + time.sleep(0.2) - print(f"{hil_ai_voltage:1.2f} == {voltage:1.2f} -> {bool_to_color_str(within)}") + hil_ai_voltage = hil_ais[i].state + within = abs(hil_ai_voltage - voltage) < 0.1 - time.sleep(0.5) + print(f"{i}: {hil_ai_voltage:1.2f} == {voltage:1.2f} -> {bool_to_color_str(within)}") + time.sleep(0.5) + print() print() + def test_rly(hil: HIL): hil_a1 = hil.dout("Millan", "HIL_A1") # DO -> HIL writes hil_rly1 = hil.dout("Millan", "HIL_RLY1") # DO -> HIL writes @@ -84,6 +87,7 @@ def test_rly(hil: HIL): time.sleep(0.5) + def test_pwm(hil: HIL): hil_pwms = [hil.pwm("Millan", f"HIL_PWM{i}") for i in range(1, 5)] # PWM -> HIL writes hil_as = [hil.ain("Millan", f"HIL_A{i}") for i in range(1, 5)] # AI -> HIL writes From 34bd87c280537577ee2a7bb9fd2ca7d822426e62 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 16 Nov 2024 20:35:54 -0500 Subject: [PATCH 136/181] Improving print formating --- scripts/test_mil_pcb.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/test_mil_pcb.py b/scripts/test_mil_pcb.py index 436b647..6d2af69 100644 --- a/scripts/test_mil_pcb.py +++ b/scripts/test_mil_pcb.py @@ -81,11 +81,10 @@ def test_rly(hil: HIL): hil_di_state = hil_a2.state same = hil_di_state == expected_state - print(f"{hil_di_state} == {expected_state} -> {bool_to_color_str(same)}") - - # input("Press Enter to continue...") + print(f"({do_state}, {rly_state}): {hil_di_state} == {expected_state} -> {bool_to_color_str(same)}") time.sleep(0.5) + print() def test_pwm(hil: HIL): @@ -106,9 +105,11 @@ def test_pwm(hil: HIL): hil_ai_voltage = hil_as[i].state within = abs(hil_ai_voltage - voltage) < 0.1 - print(f"{hil_ai_voltage:1.2f} == {voltage:1.2f} -> {bool_to_color_str(within)}") + print(f"{i}: {hil_ai_voltage:1.2f} == {voltage:1.2f} -> {bool_to_color_str(within)}") time.sleep(0.5) + print() + print() # TODO: test POT # ---------------------------------------------------------------------------- # From 95c40442a5f607b0468ffc2bf22be3671dfa54bc Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 16 Nov 2024 20:40:39 -0500 Subject: [PATCH 137/181] Formatting changes --- scripts/test_mil_pcb.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/test_mil_pcb.py b/scripts/test_mil_pcb.py index 6d2af69..fe3709e 100644 --- a/scripts/test_mil_pcb.py +++ b/scripts/test_mil_pcb.py @@ -40,7 +40,7 @@ def test_do_di(hil: HIL): def test_dac_ai(hil: HIL): hil_dacs = [hil.aout("Millan", f"HIL_DAC{i}") for i in range(1, 5)] # AO -> HIL writes - hil_ais = [hil.ain ("Millan", f"HIL_A{i}") for i in range(1, 5)] # AI -> HIL reads + hil_ais = [hil.ain ("Millan", f"HIL_A{i}") for i in range(1, 5)] # AI -> HIL reads for _i in range(3): for i in range(4): @@ -89,7 +89,7 @@ def test_rly(hil: HIL): def test_pwm(hil: HIL): hil_pwms = [hil.pwm("Millan", f"HIL_PWM{i}") for i in range(1, 5)] # PWM -> HIL writes - hil_as = [hil.ain("Millan", f"HIL_A{i}") for i in range(1, 5)] # AI -> HIL writes + hil_as = [hil.ain("Millan", f"HIL_A{i}") for i in range(1, 5)] # AI -> HIL writes for _i in range(3): for i in range(4): From 07d5e76cd31b3d64b1aa9aa026405677390305f8 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sun, 17 Nov 2024 12:00:31 -0500 Subject: [PATCH 138/181] Untested: HIL python can now send data of arbitrary data sizes Instead of being locked to [command, pin, value], it is now [command, ...] where the amount of things is specified by an array that is parallel to GpioCommand. 100% untested --- TestBench/TestBench.ino | 232 ++++++++++++++---------------- hil/hil_devices/hil_device.py | 28 ++-- hil/hil_devices/serial_manager.py | 4 +- 3 files changed, 122 insertions(+), 142 deletions(-) diff --git a/TestBench/TestBench.ino b/TestBench/TestBench.ino index e2820b0..4a675ed 100644 --- a/TestBench/TestBench.ino +++ b/TestBench/TestBench.ino @@ -26,7 +26,7 @@ const int TESTER_ID = 1; DFRobot_MCP4725 dacs[NUM_DACS]; uint8_t dac_power_down[NUM_DACS]; - const uint16_t dac_vref = 255; + const uint16_t dac_vref = 4095; #endif #define DIGIPOT_EN @@ -39,36 +39,7 @@ const int TESTER_ID = 1; MCP4021 digipot2(DIGIPOT_CS2_PIN, DIGIPOT_UD_PIN, false); // initialize Digipot 2 #endif -int count = 0; -char data[3]; - -struct Command -{ - Command(uint8_t command=0, uint8_t pin=0, uint8_t value=0) - { - data[0] = command; - data[1] = pin; - data[2] = value; - }; - - void reinit(char data[]) - { - this->data[0] = data[0]; - this->data[1] = data[1]; - this->data[2] = data[2]; - }; - - uint8_t command() { return data[0]; }; - uint8_t pin() { return data[1]; }; - uint16_t value() { return data[2]; }; - int size() { return 3 * sizeof(char); }; - - char data[3]; -}; - - -enum GpioCommands -{ +enum GpioCommand { READ_ADC = 0, READ_GPIO = 1, WRITE_DAC = 2, @@ -78,9 +49,23 @@ enum GpioCommands WRITE_PWM = 6, }; +int CHARS_TO_READ[] = { + 2, // READ_ADC - command, pin + 2, // READ_GPIO - command, pin + 4, // WRITE_DAC - command, pin, value (2 bytes) + 3, // WRITE_GPIO - command, pin, value + 1, // READ_ID - command + 3, // WRITE_POT - command, pin, value + 3, // WRITE_PWM - command, pin, value +}; + +// 4: max CHARS_TO_READ +char data[4] = {-1, -1, -1, -1}; +int data_index = 0; +bool data_ready = false; + -void setup() -{ +void setup() { SERIAL.begin(115200); #ifdef DIGIPOT_EN @@ -102,124 +87,117 @@ void setup() #endif } -void error(String error_string) -{ +void error(String error_string) { SERIAL.write(0xFF); SERIAL.write(0xFF); SERIAL.println(error_string); } -void loop() -{ - if (SERIAL.available() >= 3) - { - data[0] = SERIAL.read(); - data[1] = SERIAL.read(); - data[2] = SERIAL.read(); - - Command c; - c.reinit(data); - - count++; - - uint8_t command = c.command(); - uint8_t pin = c.pin(); - uint16_t value = c.value(); - - switch (command) - { - case (WRITE_GPIO): - { - //if (pin < DIGITAL_PIN_COUNT) - if (1) - { - pinMode(pin, OUTPUT); - digitalWrite(pin, value); - digitalWrite(LED_BUILTIN, value); - } - else - { - error("GPIO PIN COUNT EXCEEDED"); - } - break; + +void loop() { + if (data_ready) { + data_ready = false; + data_index = 0; + + GpioCommand command = (GpioCommand) data[0]; + + switch (expression) { + case GpioCommand::READ_ADC: { + int pin = data[1]; + // if (pin <= ANALOG_PIN_COUNT) + if (1) { + int val = analogRead(pin); + SERIAL.write((val >> 8) & 0xFF); + SERIAL.write(val & 0xFF); + } else { + error("ADC PIN COUNT EXCEEDED"); } - case (READ_GPIO): - { -#ifdef DAC - if (pin >= 200 && pin < 200 + NUM_DACS) - { + break; + } + case GpioCommand::READ_GPIO: { + int pin = data[1]; + #ifdef DAC + if (pin >= 200 && pin < 200 + NUM_DACS) { dacs[pin - 200].setMode(MCP4725_POWER_DOWN_500KRES); dac_power_down[pin - 200] = 1; SERIAL.write(0x01); - } - else -#endif + } else + #endif { pinMode(pin, INPUT); int val = digitalRead(pin); SERIAL.write(val & 0xFF); } - break; - } - case (WRITE_DAC): - { -#ifdef DAC - if (pin >= 200 && pin < 200 + NUM_DACS) - { - if (dac_power_down[pin-200]) - { + break; + } + case GpioCommand::WRITE_DAC: { + int pin = data[1]; + int value = (data[2] << 8) | data[3]; + #ifdef DAC + if (pin >= 200 && pin < 200 + NUM_DACS) { + if (dac_power_down[pin-200]) { dacs[pin-200].setMode(MCP4725_NORMAL_MODE); dac_power_down[pin - 200] = 0; } - dacs[pin - 200].outputVoltage(value & 0xFF); + dacs[pin - 200].outputVoltage(value); } -#endif -#ifdef STM32 - // 4 and 5 have DAC on f407 - pinMode(pin, OUTPUT); - analogWrite(pin, value & 0xFF); // max val 255 -#endif - break; - } - case (READ_ADC): - { - //if (pin <= ANALOG_PIN_COUNT) - if (1) - { - int val = analogRead(pin); - SERIAL.write((val >> 8) & 0xFF); - SERIAL.write(val & 0xFF); - } - else - { - error("ADC PIN COUNT EXCEEDED"); - } - break; - } - case (READ_ID): - { - SERIAL.write(TESTER_ID); - break; + #endif + #ifdef STM32 + // 4 and 5 have DAC on f407 + pinMode(pin, OUTPUT); + analogWrite(pin, value & 0xFF); // max val 255 + #endif + + break; + } + case GpioCommand::WRITE_GPIO: { + int pin = data[1]; + int value = data[2]; + // if (pin < DIGITAL_PIN_COUNT) + if (1) { + pinMode(pin, OUTPUT); + digitalWrite(pin, value); + digitalWrite(LED_BUILTIN, value); + } else { + error("GPIO PIN COUNT EXCEEDED"); } - case (WRITE_POT): - { -#ifdef DIGIPOT_EN - if (pin == 1) + break; + } + case GpioCommand::READ_ID: { + SERIAL.write(TESTER_ID); + break; + } + case GpioCommand::WRITE_POT: { + int pin = data[1]; + int value = data[2]; + #ifdef DIGIPOT_EN + if (pin == 1) { digipot1.setTap((uint8_t) value); - else if (pin == 2) + } else if (pin == 2) { digipot2.setTap((uint8_t) value); - else -#endif + } else + #endif { error("POT PIN COUNT EXCEEDED"); } - break; - } - case (WRITE_PWM): - { - pinMode(pin, OUTPUT); - analogWrite(pin, value & 0xFF); - break; + break; + } + case GpioCommand::WRITE_PWM: { + int pin = data[1]; + int value = data[2]; + pinMode(pin, OUTPUT); + analogWrite(pin, value & 0xFF); + break; + } + } + } else { + if (SERIAL.available() > 0) { + data[data_index] = SERIAL.read(); + data_index++; + + char command = data[0]; + if (data_index == CHARS_TO_READ[command]) { + data_ready = true; } } } diff --git a/hil/hil_devices/hil_device.py b/hil/hil_devices/hil_device.py index 58bb0b5..a6743c0 100644 --- a/hil/hil_devices/hil_device.py +++ b/hil/hil_devices/hil_device.py @@ -7,13 +7,13 @@ import hil.utils as utils HIL_CMD_MASK = 0xFF -HIL_CMD_READ_ADC = 0 -HIL_CMD_READ_GPIO = 1 -HIL_CMD_WRITE_DAC = 2 -HIL_CMD_WRITE_GPIO = 3 -HIL_CMD_READ_ID = 4 -HIL_CMD_WRITE_POT = 5 -HIL_CMD_WRITE_PWM = 6 +HIL_CMD_READ_ADC = 0 # command, pin +HIL_CMD_READ_GPIO = 1 # command, pin +HIL_CMD_WRITE_DAC = 2 # command, pin, value (2 bytes) +HIL_CMD_WRITE_GPIO = 3 # command, pin, value +HIL_CMD_READ_ID = 4 # command +HIL_CMD_WRITE_POT = 5 # command, pin, value +HIL_CMD_WRITE_PWM = 6 # command, pin, value HIL_ID_MASK = 0xFF @@ -82,14 +82,16 @@ def write_gpio(self, pin: int, value: int) -> None: # print(f"write pin {pin} to {value}") self.sm.send_data(self.id, data) - def write_dac(self, pin: int, value: int) -> None: - value = min(self.dac_max, max(0, int(value * self.volts_to_dac))) - data = [(HIL_CMD_WRITE_DAC & HIL_CMD_MASK), (pin & HIL_ID_MASK), value] - print(f"write pin {pin} to {value}") + def write_dac(self, pin: int, voltage: float) -> None: + value = int(voltage * self.volts_to_dac) + char_1 = (value >> 8) & 0xFF + char_2 = value & 0xFF + data = [(HIL_CMD_WRITE_DAC & HIL_CMD_MASK), (pin & HIL_ID_MASK), char_1, char_2] + print(f"write pin {pin} to {voltage}V = {value} ({char_1}, {char_2})") self.sm.send_data(self.id, data) def read_gpio(self, pin: int) -> int: - data = [(HIL_CMD_READ_GPIO & HIL_CMD_MASK), (pin & HIL_ID_MASK), 0] + data = [(HIL_CMD_READ_GPIO & HIL_CMD_MASK), (pin & HIL_ID_MASK)] self.sm.send_data(self.id, data) d = self.sm.read_data(self.id, 1) if len(d) == 1: @@ -98,7 +100,7 @@ def read_gpio(self, pin: int) -> int: utils.log_error(f"Failed to read gpio pin {pin} on {self.name}") def read_analog(self, pin: int) -> float: - data = [(HIL_CMD_READ_ADC & HIL_CMD_MASK), (pin & HIL_ID_MASK), 0] + data = [(HIL_CMD_READ_ADC & HIL_CMD_MASK), (pin & HIL_ID_MASK)] self.sm.send_data(self.id, data) d = self.sm.read_data(self.id, 2) if len(d) == 2: diff --git a/hil/hil_devices/serial_manager.py b/hil/hil_devices/serial_manager.py index 2cb362d..4d47005 100644 --- a/hil/hil_devices/serial_manager.py +++ b/hil/hil_devices/serial_manager.py @@ -26,8 +26,8 @@ def discover_devices(self) -> None: ard.setDTR(True) # Uno takes a while startup, have to treat it nicely for _ in range(5): - # Get Tester id - [command, pin, value], but we only care about the pin - ard.write(b'\x04\x00\x00') + # 4 = HIL_CMD_READ_ID + ard.write(b'\x04') i = ard.read(1) if (len(i) == 1): break From a0bd0fe9df2a341143990bab7df019050868bbec Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sun, 17 Nov 2024 12:05:04 -0500 Subject: [PATCH 139/181] Theoretically: DACS can now function as 12-bit --- hil/hil_devices/hil_device_arduino_mil_pcb.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hil/hil_devices/hil_device_arduino_mil_pcb.json b/hil/hil_devices/hil_device_arduino_mil_pcb.json index cc362bd..8fd2a21 100644 --- a/hil/hil_devices/hil_device_arduino_mil_pcb.json +++ b/hil/hil_devices/hil_device_arduino_mil_pcb.json @@ -36,11 +36,11 @@ {"port":9, "name":"3v3ref", "capabilities":["AI"], "notes":"3V3 input reference"}, - {"port":200, "name":"DAC1", "capabilities":["AO"], "notes":"5V ~8-bit DAC"}, - {"port":201, "name":"DAC2", "capabilities":["AO"], "notes":"5V ~8-bit DAC"} + {"port":200, "name":"DAC1", "capabilities":["AO"], "notes":"5V 12-bit DAC"}, + {"port":201, "name":"DAC2", "capabilities":["AO"], "notes":"5V 12-bit DAC"} ], "adc_config":{"bit_resolution":10, "reference_v":5.0}, - "dac_config":{"bit_resolution":8, "reference_v":5.0}, + "dac_config":{"bit_resolution":12, "reference_v":5.0}, "pot_config":{"bit_resolution":6}, "calibrate_rail":false } \ No newline at end of file From 25da538786bd0a13c598a0badb04d74b865835a9 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sun, 17 Nov 2024 12:07:20 -0500 Subject: [PATCH 140/181] Fixing typo (code compiles) --- TestBench/TestBench.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestBench/TestBench.ino b/TestBench/TestBench.ino index 4a675ed..7365eae 100644 --- a/TestBench/TestBench.ino +++ b/TestBench/TestBench.ino @@ -101,7 +101,7 @@ void loop() { GpioCommand command = (GpioCommand) data[0]; - switch (expression) { + switch (command) { case GpioCommand::READ_ADC: { int pin = data[1]; // if (pin <= ANALOG_PIN_COUNT) From 71f03d97e34346eda07a6f9a4a7e6811c119c966 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sun, 17 Nov 2024 12:31:12 -0500 Subject: [PATCH 141/181] Built in LED switches state whenever a command finishes --- TestBench/TestBench.ino | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/TestBench/TestBench.ino b/TestBench/TestBench.ino index 7365eae..90ea891 100644 --- a/TestBench/TestBench.ino +++ b/TestBench/TestBench.ino @@ -64,10 +64,14 @@ char data[4] = {-1, -1, -1, -1}; int data_index = 0; bool data_ready = false; +bool led_builtin_state = false; + void setup() { SERIAL.begin(115200); + digitalWrite(LED_BUILTIN, led_builtin_state); + #ifdef DIGIPOT_EN // Setting up Digipot 1 digipot1.setup(); @@ -99,6 +103,9 @@ void loop() { data_ready = false; data_index = 0; + led_builtin_state = !led_builtin_state; + digitalWrite(LED_BUILTIN, led_builtin_state); + GpioCommand command = (GpioCommand) data[0]; switch (command) { @@ -157,7 +164,6 @@ void loop() { if (1) { pinMode(pin, OUTPUT); digitalWrite(pin, value); - digitalWrite(LED_BUILTIN, value); } else { error("GPIO PIN COUNT EXCEEDED"); } From a6a463ef31861dbe50d69545dfa74ce851960a32 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sun, 17 Nov 2024 12:42:41 -0500 Subject: [PATCH 142/181] There are only 2 DACS to test (typo from 4) --- scripts/test_mil_pcb.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/test_mil_pcb.py b/scripts/test_mil_pcb.py index fe3709e..625ba36 100644 --- a/scripts/test_mil_pcb.py +++ b/scripts/test_mil_pcb.py @@ -39,11 +39,11 @@ def test_do_di(hil: HIL): def test_dac_ai(hil: HIL): - hil_dacs = [hil.aout("Millan", f"HIL_DAC{i}") for i in range(1, 5)] # AO -> HIL writes - hil_ais = [hil.ain ("Millan", f"HIL_A{i}") for i in range(1, 5)] # AI -> HIL reads + hil_dacs = [hil.aout("Millan", f"HIL_DAC{i}") for i in range(1, 3)] # AO -> HIL writes + hil_ais = [hil.ain ("Millan", f"HIL_A{i}") for i in range(1, 3)] # AI -> HIL reads for _i in range(3): - for i in range(4): + for i in range(2): random_voltage = random.uniform(0.0, 5.0) voltages = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, random_voltage] for voltage in voltages: From 105bd69cc4986a84575bc3fdc04e43767c32a9d3 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 19 Nov 2024 20:01:18 -0500 Subject: [PATCH 143/181] Rewriting collector plate to use RLY1 as a DO Need 4 DO and 1 AI, but only AX headers can do either, so one DO is mimicked from a RLY --- configurations/config_mil_col.json | 12 ++++++------ scripts/test_mil_col.py | 17 ++++++++--------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/configurations/config_mil_col.json b/configurations/config_mil_col.json index 6f1f811..42815b7 100644 --- a/configurations/config_mil_col.json +++ b/configurations/config_mil_col.json @@ -2,14 +2,14 @@ "$schema": "./config_schema.json", "dut_connections":[ {"board":"Collector", "harness_connections":[ - {"dut":{"connector":"J4","pin":2,"_":"MUX_A"}, "hil":{"device":"MilColTester", "port":"D0", "_":"DO"}}, - {"dut":{"connector":"J4","pin":1,"_":"MUX_B"}, "hil":{"device":"MilColTester", "port":"D1", "_":"DO"}}, - {"dut":{"connector":"J4","pin":4,"_":"MUX_C"}, "hil":{"device":"MilColTester", "port":"D2", "_":"DO"}}, - {"dut":{"connector":"J4","pin":7,"_":"MUX_D"}, "hil":{"device":"MilColTester", "port":"D3", "_":"DO"}}, - {"dut":{"connector":"J4","pin":5,"_":"TEMP_OUT"}, "hil":{"device":"MilColTester", "port":"D8", "_":"AI"}} + {"dut":{"connector":"J4","pin":2,"_":"MUX_A"}, "hil":{"device":"MilColTester", "port":"A1", "_":"DO"}}, + {"dut":{"connector":"J4","pin":1,"_":"MUX_B"}, "hil":{"device":"MilColTester", "port":"A2", "_":"DO"}}, + {"dut":{"connector":"J4","pin":4,"_":"MUX_C"}, "hil":{"device":"MilColTester", "port":"A3", "_":"DO"}}, + {"dut":{"connector":"J4","pin":7,"_":"MUX_D"}, "hil":{"device":"MilColTester", "port":"RLY1", "_":"DO"}}, + {"dut":{"connector":"J4","pin":5,"_":"TEMP_OUT"}, "hil":{"device":"MilColTester", "port":"A4", "_":"AI"}} ]} ], "hil_devices":[ - {"name":"MilColTester", "type":"arduino_micro", "id":1} + {"name":"MilColTester", "type":"arduino_mil_pcb", "id":1} ] } diff --git a/scripts/test_mil_col.py b/scripts/test_mil_col.py index f5f3c5d..3079cb0 100644 --- a/scripts/test_mil_col.py +++ b/scripts/test_mil_col.py @@ -9,14 +9,11 @@ # ---------------------------------------------------------------------------- # def test_collector(hil: HIL): - # HIL ouputs -> Collector inputs - mux_a = hil.dout("Collector", "MUX_A") - mux_b = hil.dout("Collector", "MUX_B") - mux_c = hil.dout("Collector", "MUX_C") - mux_d = hil.dout("Collector", "MUX_D") - - # HIL inputs -> Collector outputs - temp_out = hil.ain("Collector", "TEMP_OUT") + mux_a = hil.dout("Collector", "MUX_A") # A1 + mux_b = hil.dout("Collector", "MUX_B") # A2 + mux_d = hil.dout("Collector", "MUX_C") # A3 + mux_c = hil.dout("Collector", "MUX_D") # RLY1: have to wire: 5V -> RLY1 -> MUX_D + temp_out = hil.ain("Collector", "TEMP_OUT") # A4 tolerance_v = 0.1 # volts current_res = 9100.0 # ohms @@ -41,7 +38,9 @@ def test_collector(hil: HIL): mux_b.state = i & 0x2 mux_c.state = i & 0x4 mux_d.state = i & 0x8 - time.sleep(0.01) + + # Wait for relay + time.sleep(0.1) temp_out_state = temp_out.state if i == thermistor: expected_voltage = test_voltage From 7b9aa2d06c30e1dfbb47edb2b2588f5226cb1791 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Fri, 13 Dec 2024 12:22:04 -0500 Subject: [PATCH 144/181] Finally testing DX pins (3-7 work, 8 not usable, 1 & 2 don't work) --- .../hil_device_arduino_mil_pcb.json | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/hil/hil_devices/hil_device_arduino_mil_pcb.json b/hil/hil_devices/hil_device_arduino_mil_pcb.json index 8fd2a21..1ae3d28 100644 --- a/hil/hil_devices/hil_device_arduino_mil_pcb.json +++ b/hil/hil_devices/hil_device_arduino_mil_pcb.json @@ -6,20 +6,14 @@ {"port":20, "name":"A3", "capabilities":["DI", "DO", "AI"], "notes":"5V dig / analog in"}, {"port":21, "name":"A4", "capabilities":["DI", "DO", "AI"], "notes":"5V dig / analog in"}, - {"port":2, "name":"D1", "capabilities":[], "notes":"SDA (5V dig in)"}, - {"port":4, "name":"D2", "capabilities":["DI"], "notes":"5V dig in"}, - {"port":8, "name":"D3", "capabilities":["DI"], "notes":"5V dig in"}, - {"port":15, "name":"D4", "capabilities":["DI"], "notes":"5V dig in (SCK)"}, - {"port":14, "name":"D5", "capabilities":["DI"], "notes":"5V dig in (COPI/MISO)"}, - {"port":16, "name":"D6", "capabilities":["DI"], "notes":"5V dig in (COPI/MOSI)"}, - {"port":1, "name":"D7", "capabilities":["DI"], "notes":"5V dig in (TX)"}, - {"port":0, "name":"D8", "capabilities":["DI"], "notes":"5V dig in (RX)"}, - - {"port":16, "name":"DI3", "capabilities":["DI"], "notes":"digital input 5V-30V"}, - {"port":14, "name":"DI4", "capabilities":["DI"], "notes":"digital input 5V-30V"}, - {"port":15, "name":"DI5", "capabilities":["DI"], "notes":"digital input 5V-30V"}, - {"port":8, "name":"DI6", "capabilities":["DI"], "notes":"digital input 5V-30V"}, - {"port":4, "name":"DI7", "capabilities":["DI"], "notes":"digital input 5V-30V"}, + {"port":2, "name":"D1", "capabilities":[], "notes":"SDA (5V dig in)"}, + {"port":4, "name":"D2", "capabilities":[], "notes":"(5V dig in)"}, + {"port":16, "name":"D3", "capabilities":["DI"], "notes":"5V dig in (COPI/MISO)"}, + {"port":14, "name":"D4", "capabilities":["DI"], "notes":"5V dig in (COPI/MOSI)"}, + {"port":15, "name":"D5", "capabilities":["DI"], "notes":"5V dig in (SCK)"}, + {"port":8, "name":"D6", "capabilities":["DI"], "notes":"5V dig in"}, + {"port":4, "name":"D7", "capabilities":["DI"], "notes":"5V dig in"}, + {"port":0, "name":"D8", "capabilities":[], "notes":"RX"}, {"port":3, "name":"PWM1", "capabilities":["PWM"], "notes":"5V 8-bit PWM -> RC"}, {"port":5, "name":"PWM2", "capabilities":["PWM"], "notes":"5V 8-bit PWM -> RC"}, From 1d7134abcf487cc5edb3bb7fcc6e24a92839876a Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Fri, 13 Dec 2024 14:12:14 -0500 Subject: [PATCH 145/181] Can't use LED_BUILTIN because it is tied to 13 --- TestBench/TestBench.ino | 7 ------- 1 file changed, 7 deletions(-) diff --git a/TestBench/TestBench.ino b/TestBench/TestBench.ino index 90ea891..c22909c 100644 --- a/TestBench/TestBench.ino +++ b/TestBench/TestBench.ino @@ -64,14 +64,10 @@ char data[4] = {-1, -1, -1, -1}; int data_index = 0; bool data_ready = false; -bool led_builtin_state = false; - void setup() { SERIAL.begin(115200); - digitalWrite(LED_BUILTIN, led_builtin_state); - #ifdef DIGIPOT_EN // Setting up Digipot 1 digipot1.setup(); @@ -103,9 +99,6 @@ void loop() { data_ready = false; data_index = 0; - led_builtin_state = !led_builtin_state; - digitalWrite(LED_BUILTIN, led_builtin_state); - GpioCommand command = (GpioCommand) data[0]; switch (command) { From 16dc679525b64f150796e6e5153174c95cb4dc67 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Fri, 13 Dec 2024 14:12:26 -0500 Subject: [PATCH 146/181] RLY3 and RLY4 are flipped --- hil/hil_devices/hil_device_arduino_mil_pcb.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hil/hil_devices/hil_device_arduino_mil_pcb.json b/hil/hil_devices/hil_device_arduino_mil_pcb.json index 1ae3d28..dc00df6 100644 --- a/hil/hil_devices/hil_device_arduino_mil_pcb.json +++ b/hil/hil_devices/hil_device_arduino_mil_pcb.json @@ -22,8 +22,8 @@ {"port":10, "name":"RLY1", "capabilities":["DO"], "notes":"relay"}, {"port":11, "name":"RLY2", "capabilities":["DO"], "notes":"relay"}, - {"port":12, "name":"RLY3", "capabilities":["DO"], "notes":"relay"}, - {"port":13, "name":"RLY4", "capabilities":["DO"], "notes":"relay"}, + {"port":13, "name":"RLY3", "capabilities":["DO"], "notes":"relay"}, + {"port":12, "name":"RLY4", "capabilities":["DO"], "notes":"relay"}, {"port":1, "name":"POT1", "capabilities":["POT"], "notes":"6-bit Digipot"}, {"port":2, "name":"POT2", "capabilities":["POT"], "notes":"6-bit Digipot"}, From 5765844cb037fe202632ba91e81e71b3310dc992 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Fri, 13 Dec 2024 16:14:55 -0500 Subject: [PATCH 147/181] AX pins shouldn't be used for DO because they are not pulled down --- hil/hil_devices/hil_device_arduino_mil_pcb.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hil/hil_devices/hil_device_arduino_mil_pcb.json b/hil/hil_devices/hil_device_arduino_mil_pcb.json index dc00df6..5c586d3 100644 --- a/hil/hil_devices/hil_device_arduino_mil_pcb.json +++ b/hil/hil_devices/hil_device_arduino_mil_pcb.json @@ -1,10 +1,10 @@ { "communication_mode":"serial", "ports":[ - {"port":18, "name":"A1", "capabilities":["DI", "DO", "AI"], "notes":"5V dig / analog in"}, - {"port":19, "name":"A2", "capabilities":["DI", "DO", "AI"], "notes":"5V dig / analog in"}, - {"port":20, "name":"A3", "capabilities":["DI", "DO", "AI"], "notes":"5V dig / analog in"}, - {"port":21, "name":"A4", "capabilities":["DI", "DO", "AI"], "notes":"5V dig / analog in"}, + {"port":18, "name":"A1", "capabilities":["DO", "AI"], "notes":"5V dig / analog in"}, + {"port":19, "name":"A2", "capabilities":["DO", "AI"], "notes":"5V dig / analog in"}, + {"port":20, "name":"A3", "capabilities":["DO", "AI"], "notes":"5V dig / analog in"}, + {"port":21, "name":"A4", "capabilities":["DO", "AI"], "notes":"5V dig / analog in"}, {"port":2, "name":"D1", "capabilities":[], "notes":"SDA (5V dig in)"}, {"port":4, "name":"D2", "capabilities":[], "notes":"(5V dig in)"}, From 044f7f5dae1aa38347c6a9a7b47f3734bc3d24f3 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Fri, 13 Dec 2024 16:31:21 -0500 Subject: [PATCH 148/181] The relays now work --- scripts/test_mil_pcb.py | 85 +++++++++++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 24 deletions(-) diff --git a/scripts/test_mil_pcb.py b/scripts/test_mil_pcb.py index 625ba36..478acf9 100644 --- a/scripts/test_mil_pcb.py +++ b/scripts/test_mil_pcb.py @@ -62,11 +62,11 @@ def test_dac_ai(hil: HIL): def test_rly(hil: HIL): hil_a1 = hil.dout("Millan", "HIL_A1") # DO -> HIL writes - hil_rly1 = hil.dout("Millan", "HIL_RLY1") # DO -> HIL writes - hil_a2 = hil.din ("Millan", "HIL_A2") # DI -> HIL reads + hil_rly1 = hil.dout("Millan", "HIL_RLY2") # DO -> HIL writes + hil_d3 = hil.din ("Millan", "HIL_D3") # DI -> HIL reads # A1 -> RLY1+ - # RLY1- -> A2 + # RLY1- -> D3 for _i in range(3): for do_state in [0, 1]: @@ -74,11 +74,11 @@ def test_rly(hil: HIL): hil_a1.state = do_state hil_rly1.state = rly_state - expected_state = do_state and rly_state + expected_state = do_state and not rly_state - time.sleep(0.2) + time.sleep(0.5) - hil_di_state = hil_a2.state + hil_di_state = hil_d3.state same = hil_di_state == expected_state print(f"({do_state}, {rly_state}): {hil_di_state} == {expected_state} -> {bool_to_color_str(same)}") @@ -88,28 +88,63 @@ def test_rly(hil: HIL): def test_pwm(hil: HIL): - hil_pwms = [hil.pwm("Millan", f"HIL_PWM{i}") for i in range(1, 5)] # PWM -> HIL writes - hil_as = [hil.ain("Millan", f"HIL_A{i}") for i in range(1, 5)] # AI -> HIL writes + # hil_pwms = [hil.pwm("Millan", f"HIL_PWM{i}") for i in range(1, 5)] # PWM -> HIL writes + # hil_as = [hil.ain("Millan", f"HIL_A{i}") for i in range(1, 5)] # AI -> HIL reads - for _i in range(3): - for i in range(4): - random_voltage = random.uniform(0.0, 5.0) - voltages = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, random_voltage] - for voltage in voltages: - # voltage: [0.0, 5.0] -> pwm_value: [0, 255] - pwm_value = int(voltage / 5.0 * 255) + # for _i in range(3): + # for i in range(4): + # random_voltage = random.uniform(0.0, 5.0) + # voltages = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, random_voltage] + # for voltage in voltages: + # # voltage: [0.0, 5.0] -> pwm_value: [0, 255] + # pwm_value = int(voltage / 5.0 * 255) - hil_pwms[i].state = pwm_value - time.sleep(0.2) + # hil_pwms[i].state = pwm_value + # time.sleep(0.2) - hil_ai_voltage = hil_as[i].state - within = abs(hil_ai_voltage - voltage) < 0.1 + # hil_ai_voltage = hil_as[i].state + # within = abs(hil_ai_voltage - voltage) < 0.1 - print(f"{i}: {hil_ai_voltage:1.2f} == {voltage:1.2f} -> {bool_to_color_str(within)}") + # print(f"{i}: {hil_ai_voltage:1.2f} == {voltage:1.2f} -> {bool_to_color_str(within)}") - time.sleep(0.5) - print() - print() + # time.sleep(0.5) + # print() + # print() + + hil_pwm = hil.pwm("Millan", "HIL_PWM3") # PWM -> HIL writes + hil_a = hil.ain("Millan", "HIL_A2") # AI -> HIL reads + + voltage = 3 + pwm_value = int(voltage / 5.0 * 255) + hil_pwm.state = pwm_value + + for i in range(1000): + time.sleep(0.1) + + hil_ai_voltage = hil_a.state + print(f"{hil_ai_voltage:1.2f}") + # within = abs(hil_ai_voltage - voltage) < 0.1 + + # print(f"{hil_ai_voltage:1.2f} == {voltage:1.2f} -> {bool_to_color_str(within)}") + + # time.sleep(0.5) + + # for _i in range(3): + # random_voltage = random.uniform(0.0, 5.0) + # voltages = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, random_voltage] + # for voltage in voltages: + # # voltage: [0.0, 5.0] -> pwm_value: [0, 255] + # pwm_value = int(voltage / 5.0 * 255) + + # hil_pwm.state = pwm_value + # time.sleep(0.2) + + # hil_ai_voltage = hil_a.state + # within = abs(hil_ai_voltage - voltage) < 0.1 + + # print(f"{hil_ai_voltage:1.2f} == {voltage:1.2f} -> {bool_to_color_str(within)}") + + # time.sleep(0.5) # TODO: test POT # ---------------------------------------------------------------------------- # @@ -122,10 +157,12 @@ def test_pwm(hil: HIL): hil.load_config("config_mil_pcb.json") hil.load_pin_map("mil_pcb_net_map.csv", "stm32f407_pin_map.csv") + + # time.sleep(5) # test_do_di(hil) # test_dac_ai(hil) - # test_rly(hil) + test_rly(hil) # test_pwm(hil) hil.shutdown() \ No newline at end of file From 94770240e53c40a6fc908b494e7c701a881472e8 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 14 Jan 2025 19:44:15 -0500 Subject: [PATCH 149/181] Reorganzing --- {ArduinoFlashTest => _old/ArduinoFlashTest}/ArduinoFlashTest.ino | 0 .../ArduinoFlashTest}/deleteWhenEverythingWorks.txt | 0 {pytest-example => _old/SimplePyTestExample}/fake_test.py | 0 {old_scripts => _old/SimplePyTestExample}/test.sh | 0 {old_scripts => _old/old_scripts}/config_dash.py | 0 {old_scripts => _old/old_scripts}/rules_constants.py | 0 {pytest-example => _old/old_scripts}/test.sh | 0 {old_scripts => _old/old_scripts}/test_abox.py | 0 {old_scripts => _old/old_scripts}/test_charger.py | 0 {old_scripts => _old/old_scripts}/test_collector.py | 0 {old_scripts => _old/old_scripts}/test_main_base.py | 0 {old_scripts => _old/old_scripts}/test_main_sdc.py | 0 {old_scripts => _old/old_scripts}/test_system.py | 0 {old_scripts => _old/old_scripts}/test_test.py | 0 {old_scripts => _old/old_scripts}/vehicle_constants.py | 0 15 files changed, 0 insertions(+), 0 deletions(-) rename {ArduinoFlashTest => _old/ArduinoFlashTest}/ArduinoFlashTest.ino (100%) rename {ArduinoFlashTest => _old/ArduinoFlashTest}/deleteWhenEverythingWorks.txt (100%) rename {pytest-example => _old/SimplePyTestExample}/fake_test.py (100%) rename {old_scripts => _old/SimplePyTestExample}/test.sh (100%) rename {old_scripts => _old/old_scripts}/config_dash.py (100%) rename {old_scripts => _old/old_scripts}/rules_constants.py (100%) rename {pytest-example => _old/old_scripts}/test.sh (100%) rename {old_scripts => _old/old_scripts}/test_abox.py (100%) rename {old_scripts => _old/old_scripts}/test_charger.py (100%) rename {old_scripts => _old/old_scripts}/test_collector.py (100%) rename {old_scripts => _old/old_scripts}/test_main_base.py (100%) rename {old_scripts => _old/old_scripts}/test_main_sdc.py (100%) rename {old_scripts => _old/old_scripts}/test_system.py (100%) rename {old_scripts => _old/old_scripts}/test_test.py (100%) rename {old_scripts => _old/old_scripts}/vehicle_constants.py (100%) diff --git a/ArduinoFlashTest/ArduinoFlashTest.ino b/_old/ArduinoFlashTest/ArduinoFlashTest.ino similarity index 100% rename from ArduinoFlashTest/ArduinoFlashTest.ino rename to _old/ArduinoFlashTest/ArduinoFlashTest.ino diff --git a/ArduinoFlashTest/deleteWhenEverythingWorks.txt b/_old/ArduinoFlashTest/deleteWhenEverythingWorks.txt similarity index 100% rename from ArduinoFlashTest/deleteWhenEverythingWorks.txt rename to _old/ArduinoFlashTest/deleteWhenEverythingWorks.txt diff --git a/pytest-example/fake_test.py b/_old/SimplePyTestExample/fake_test.py similarity index 100% rename from pytest-example/fake_test.py rename to _old/SimplePyTestExample/fake_test.py diff --git a/old_scripts/test.sh b/_old/SimplePyTestExample/test.sh similarity index 100% rename from old_scripts/test.sh rename to _old/SimplePyTestExample/test.sh diff --git a/old_scripts/config_dash.py b/_old/old_scripts/config_dash.py similarity index 100% rename from old_scripts/config_dash.py rename to _old/old_scripts/config_dash.py diff --git a/old_scripts/rules_constants.py b/_old/old_scripts/rules_constants.py similarity index 100% rename from old_scripts/rules_constants.py rename to _old/old_scripts/rules_constants.py diff --git a/pytest-example/test.sh b/_old/old_scripts/test.sh similarity index 100% rename from pytest-example/test.sh rename to _old/old_scripts/test.sh diff --git a/old_scripts/test_abox.py b/_old/old_scripts/test_abox.py similarity index 100% rename from old_scripts/test_abox.py rename to _old/old_scripts/test_abox.py diff --git a/old_scripts/test_charger.py b/_old/old_scripts/test_charger.py similarity index 100% rename from old_scripts/test_charger.py rename to _old/old_scripts/test_charger.py diff --git a/old_scripts/test_collector.py b/_old/old_scripts/test_collector.py similarity index 100% rename from old_scripts/test_collector.py rename to _old/old_scripts/test_collector.py diff --git a/old_scripts/test_main_base.py b/_old/old_scripts/test_main_base.py similarity index 100% rename from old_scripts/test_main_base.py rename to _old/old_scripts/test_main_base.py diff --git a/old_scripts/test_main_sdc.py b/_old/old_scripts/test_main_sdc.py similarity index 100% rename from old_scripts/test_main_sdc.py rename to _old/old_scripts/test_main_sdc.py diff --git a/old_scripts/test_system.py b/_old/old_scripts/test_system.py similarity index 100% rename from old_scripts/test_system.py rename to _old/old_scripts/test_system.py diff --git a/old_scripts/test_test.py b/_old/old_scripts/test_test.py similarity index 100% rename from old_scripts/test_test.py rename to _old/old_scripts/test_test.py diff --git a/old_scripts/vehicle_constants.py b/_old/old_scripts/vehicle_constants.py similarity index 100% rename from old_scripts/vehicle_constants.py rename to _old/old_scripts/vehicle_constants.py From c644a6bd7a3db45e915e2df71ea5e8ff09494fda Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 14 Jan 2025 20:00:51 -0500 Subject: [PATCH 150/181] Removing old test files --- configurations/config_mil_dac.json | 12 --- net_maps/mil_dac_net_map.csv | 3 - scripts/test_mil_dac.py | 51 --------- scripts/test_mil_pcb.py | 168 ----------------------------- scripts/test_millan.py | 53 --------- 5 files changed, 287 deletions(-) delete mode 100644 configurations/config_mil_dac.json delete mode 100644 net_maps/mil_dac_net_map.csv delete mode 100644 scripts/test_mil_dac.py delete mode 100644 scripts/test_mil_pcb.py delete mode 100644 scripts/test_millan.py diff --git a/configurations/config_mil_dac.json b/configurations/config_mil_dac.json deleted file mode 100644 index c22b756..0000000 --- a/configurations/config_mil_dac.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "./config_schema.json", - "dut_connections":[ - {"board":"Millan", "harness_connections":[ - {"dut":{"connector":"breadboard","pin":1, "_":"HIL_AO"}, "hil":{"device":"MilDacTester", "port":"DAC1", "_":"AO"}}, - {"dut":{"connector":"breadboard","pin":2, "_":"HIL_AI"}, "hil":{"device":"MilDacTester", "port":"4", "_":"AI"}} - ]} - ], - "hil_devices":[ - {"name":"MilDacTester", "type":"arduino_micro_breadboard", "id":1} - ] -} diff --git a/net_maps/mil_dac_net_map.csv b/net_maps/mil_dac_net_map.csv deleted file mode 100644 index ff5c21d..0000000 --- a/net_maps/mil_dac_net_map.csv +++ /dev/null @@ -1,3 +0,0 @@ -Board,Net,Component,Designator,Connector Name,, -Millan,HIL_AO,breadboard,1,FRED,, -Millan,HIL_AI,breadboard,2,FRED,, \ No newline at end of file diff --git a/scripts/test_mil_dac.py b/scripts/test_mil_dac.py deleted file mode 100644 index 7e4b9c8..0000000 --- a/scripts/test_mil_dac.py +++ /dev/null @@ -1,51 +0,0 @@ -from os import sys, path -# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher -sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) - -from hil.hil import HIL -import hil.utils as utils -import time -import random - - -# ---------------------------------------------------------------------------- # -def within_to_color_str(same: bool) -> str: - if same: - return utils.bcolors.OKGREEN + "SUCCESS" + utils.bcolors.ENDC - else: - return utils.bcolors.FAIL + "FAILURE" + utils.bcolors.ENDC - - -def test(hil: HIL): - hil_ao = hil.ao("Millan", "HIL_AO") # HIL writes - hil_ai = hil.ai("Millan", "HIL_AI") # HIL reads - - for _i in range(3): - random_voltage = random.uniform(0.0, 5.0) - for voltage in [0.0, 1.0, 2.5, 3.3, 5.0, random_voltage]: - hil_ao.voltage = voltage - - time.sleep(0.2) - - hil_ai_voltage = hil_ai.voltage - ai_within = abs(hil_ai_voltage - voltage) < 0.1 - - print(f"HIL_AI: {hil_ai_voltage:1.2f} == {voltage:1.2f} -> {within_to_color_str(ai_within)}") - - - time.sleep(0.5) - - print() -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # -if __name__ == "__main__": - hil = HIL() - - hil.load_config("config_mil_dac.json") - hil.load_pin_map("mil_dac_net_map.csv", "stm32f407_pin_map.csv") - - test(hil) - - hil.shutdown() \ No newline at end of file diff --git a/scripts/test_mil_pcb.py b/scripts/test_mil_pcb.py deleted file mode 100644 index 478acf9..0000000 --- a/scripts/test_mil_pcb.py +++ /dev/null @@ -1,168 +0,0 @@ -from os import sys, path -# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher -sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) - -from hil.hil import HIL -import hil.utils as utils -import time -import random - - -# ---------------------------------------------------------------------------- # -def bool_to_color_str(same: bool) -> str: - if same: - return utils.bcolors.OKGREEN + "SUCCESS" + utils.bcolors.ENDC - else: - return utils.bcolors.FAIL + "FAILURE" + utils.bcolors.ENDC - - -def test_do_di(hil: HIL): - hil_a1 = hil.dout("Millan", "HIL_A1") # DO -> HIL writes - hil_a2 = hil.din ("Millan", "HIL_A2") # DI -> HIL reads - - for _i in range(3): - for state in [0, 1]: - hil_a1.state = state - - time.sleep(0.2) - - hil_di_state = hil_a2.state - same = hil_di_state == state - - print(f"{hil_di_state} == {state} -> {bool_to_color_str(same)}") - - input("Press Enter to continue...") - - time.sleep(0.5) - - print() - - -def test_dac_ai(hil: HIL): - hil_dacs = [hil.aout("Millan", f"HIL_DAC{i}") for i in range(1, 3)] # AO -> HIL writes - hil_ais = [hil.ain ("Millan", f"HIL_A{i}") for i in range(1, 3)] # AI -> HIL reads - - for _i in range(3): - for i in range(2): - random_voltage = random.uniform(0.0, 5.0) - voltages = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, random_voltage] - for voltage in voltages: - hil_dacs[i].state = voltage - time.sleep(0.2) - - hil_ai_voltage = hil_ais[i].state - within = abs(hil_ai_voltage - voltage) < 0.1 - - print(f"{i}: {hil_ai_voltage:1.2f} == {voltage:1.2f} -> {bool_to_color_str(within)}") - - time.sleep(0.5) - print() - print() - - -def test_rly(hil: HIL): - hil_a1 = hil.dout("Millan", "HIL_A1") # DO -> HIL writes - hil_rly1 = hil.dout("Millan", "HIL_RLY2") # DO -> HIL writes - hil_d3 = hil.din ("Millan", "HIL_D3") # DI -> HIL reads - - # A1 -> RLY1+ - # RLY1- -> D3 - - for _i in range(3): - for do_state in [0, 1]: - for rly_state in [0, 1]: - hil_a1.state = do_state - hil_rly1.state = rly_state - - expected_state = do_state and not rly_state - - time.sleep(0.5) - - hil_di_state = hil_d3.state - same = hil_di_state == expected_state - - print(f"({do_state}, {rly_state}): {hil_di_state} == {expected_state} -> {bool_to_color_str(same)}") - - time.sleep(0.5) - print() - - -def test_pwm(hil: HIL): - # hil_pwms = [hil.pwm("Millan", f"HIL_PWM{i}") for i in range(1, 5)] # PWM -> HIL writes - # hil_as = [hil.ain("Millan", f"HIL_A{i}") for i in range(1, 5)] # AI -> HIL reads - - # for _i in range(3): - # for i in range(4): - # random_voltage = random.uniform(0.0, 5.0) - # voltages = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, random_voltage] - # for voltage in voltages: - # # voltage: [0.0, 5.0] -> pwm_value: [0, 255] - # pwm_value = int(voltage / 5.0 * 255) - - # hil_pwms[i].state = pwm_value - # time.sleep(0.2) - - # hil_ai_voltage = hil_as[i].state - # within = abs(hil_ai_voltage - voltage) < 0.1 - - # print(f"{i}: {hil_ai_voltage:1.2f} == {voltage:1.2f} -> {bool_to_color_str(within)}") - - # time.sleep(0.5) - # print() - # print() - - hil_pwm = hil.pwm("Millan", "HIL_PWM3") # PWM -> HIL writes - hil_a = hil.ain("Millan", "HIL_A2") # AI -> HIL reads - - voltage = 3 - pwm_value = int(voltage / 5.0 * 255) - hil_pwm.state = pwm_value - - for i in range(1000): - time.sleep(0.1) - - hil_ai_voltage = hil_a.state - print(f"{hil_ai_voltage:1.2f}") - # within = abs(hil_ai_voltage - voltage) < 0.1 - - # print(f"{hil_ai_voltage:1.2f} == {voltage:1.2f} -> {bool_to_color_str(within)}") - - # time.sleep(0.5) - - # for _i in range(3): - # random_voltage = random.uniform(0.0, 5.0) - # voltages = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, random_voltage] - # for voltage in voltages: - # # voltage: [0.0, 5.0] -> pwm_value: [0, 255] - # pwm_value = int(voltage / 5.0 * 255) - - # hil_pwm.state = pwm_value - # time.sleep(0.2) - - # hil_ai_voltage = hil_a.state - # within = abs(hil_ai_voltage - voltage) < 0.1 - - # print(f"{hil_ai_voltage:1.2f} == {voltage:1.2f} -> {bool_to_color_str(within)}") - - # time.sleep(0.5) - -# TODO: test POT -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # -# ONLY RUN ONE TEST AT A TIME AS THEY REFERENCE OVERLAPPING PINS -if __name__ == "__main__": - hil = HIL() - - hil.load_config("config_mil_pcb.json") - hil.load_pin_map("mil_pcb_net_map.csv", "stm32f407_pin_map.csv") - - # time.sleep(5) - - # test_do_di(hil) - # test_dac_ai(hil) - test_rly(hil) - # test_pwm(hil) - - hil.shutdown() \ No newline at end of file diff --git a/scripts/test_millan.py b/scripts/test_millan.py deleted file mode 100644 index 6afccc9..0000000 --- a/scripts/test_millan.py +++ /dev/null @@ -1,53 +0,0 @@ -from os import sys, path -# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher -sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) - -from hil.hil import HIL -import hil.utils as utils -import time - - -# ---------------------------------------------------------------------------- # -def same_to_color_str(same: bool) -> str: - if same: - return utils.bcolors.OKGREEN + "SUCCESS" + utils.bcolors.ENDC - else: - return utils.bcolors.FAIL + "FAILURE" + utils.bcolors.ENDC - - -def test(hil: HIL): - hil_out = hil.dout("Millan", "HIL_OUT") - hil_ain = hil.ain("Millan", "HIL_AIN") - hil_din = hil.din("Millan", "HIL_DIN") - - for _i in range(3): - for state in [0, 1]: - print(f"\nHIL_OUT: {state}") - hil_out.state = state - time.sleep(0.5) - - hil_din_state = hil_din.state - din_same = hil_din_state == state - print(f"HIL_DIN: {hil_din_state} == {state} -> {same_to_color_str(din_same)}") - - hil_ain_state = hil_ain.state - ain_target = state * 5.0 - ain_same = abs(hil_ain_state - ain_target) < 0.1 - print(f"HIL_AIN: {hil_ain_state} == {ain_target} -> {same_to_color_str(ain_same)}") - - time.sleep(1) - - print() -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # -if __name__ == "__main__": - hil = HIL() - - hil.load_config("config_millan.json") - hil.load_pin_map("millan_net_map.csv", "stm32f407_pin_map.csv") - - test(hil) - - hil.shutdown() \ No newline at end of file From 136affe83aba56328a925d015ccdf7d4fc763b94 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 14 Jan 2025 20:22:25 -0500 Subject: [PATCH 151/181] Delete config_millan.json --- configurations/config_millan.json | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 configurations/config_millan.json diff --git a/configurations/config_millan.json b/configurations/config_millan.json deleted file mode 100644 index 3d8f76c..0000000 --- a/configurations/config_millan.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "./config_schema.json", - "dut_connections":[ - {"board":"Millan", "harness_connections":[ - {"dut":{"connector":"breadboard","pin":1}, "hil":{"device":"MillanTester", "port":"D3"}}, - {"dut":{"connector":"breadboard","pin":2}, "hil":{"device":"MillanTester", "port":"D4"}}, - {"dut":{"connector":"breadboard","pin":3}, "hil":{"device":"MillanTester", "port":"D5"}} - ]} - ], - "hil_devices":[ - {"name":"MillanTester", "type":"arduino_micro", "id":1} - ] -} From a12a2f5ba542be6a4c93c5b4e8e820ce9e1f7ff4 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 14 Jan 2025 20:22:47 -0500 Subject: [PATCH 152/181] Delete millan_net_map.csv --- net_maps/millan_net_map.csv | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 net_maps/millan_net_map.csv diff --git a/net_maps/millan_net_map.csv b/net_maps/millan_net_map.csv deleted file mode 100644 index 286f15d..0000000 --- a/net_maps/millan_net_map.csv +++ /dev/null @@ -1,4 +0,0 @@ -Board,Net,Component,Designator,Connector Name,, -Millan,HIL_OUT,breadboard,1,FRED,, -Millan,HIL_AIN,breadboard,2,FRED,, -Millan,HIL_DIN,breadboard,3,FRED,, \ No newline at end of file From b359811a7960b229ae1e1e82e5932a6d3d007962 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 14 Jan 2025 20:31:21 -0500 Subject: [PATCH 153/181] Deleting old files --- hil/hil_devices/hil_device_arduino_micro.json | 50 +++++++++---------- .../hil_device_arduino_micro_breadboard.json | 31 ------------ 2 files changed, 25 insertions(+), 56 deletions(-) delete mode 100644 hil/hil_devices/hil_device_arduino_micro_breadboard.json diff --git a/hil/hil_devices/hil_device_arduino_micro.json b/hil/hil_devices/hil_device_arduino_micro.json index 5e85d1d..c5af465 100644 --- a/hil/hil_devices/hil_device_arduino_micro.json +++ b/hil/hil_devices/hil_device_arduino_micro.json @@ -2,30 +2,30 @@ "$schema": "./emulator_schema.json", "communication_mode":"serial", "ports":[ - {"port":0, "name":"D0", "capabilities":["DI", "DO"], "notes":"5V digital"}, - {"port":1, "name":"D1", "capabilities":["DI", "DO"], "notes":"5V digital"}, - {"port":2, "name":"D2", "capabilities":["DI", "DO"], "notes":"5V digital"}, - {"port":3, "name":"D3", "capabilities":["DI", "DO"], "notes":"5V digital"}, - {"port":4, "name":"D4", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, - {"port":5, "name":"D5", "capabilities":["DI", "DO"], "notes":"5V digital"}, - {"port":6, "name":"D6", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, - {"port":7, "name":"D7", "capabilities":["DI", "DO"], "notes":"5V digital"}, - {"port":8, "name":"D8", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, - {"port":9, "name":"D9", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, - {"port":10, "name":"D10", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, - {"port":11, "name":"D11", "capabilities":["DI", "DO"], "notes":"5V digital"}, - {"port":12, "name":"D12", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, - {"port":13, "name":"D13", "capabilities":["DI", "DO"], "notes":"5V digital"}, - {"port":14, "name":"D14", "capabilities":["DI", "DO"], "notes":"5V digital"}, - {"port":15, "name":"D15", "capabilities":["DI", "DO"], "notes":"5V digital"}, - {"port":16, "name":"D16", "capabilities":["DI", "DO"], "notes":"5V digital"}, - {"port":17, "name":"D17", "capabilities":["DI", "DO"], "notes":"5V digital"}, - {"port":18, "name":"A0", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, - {"port":19, "name":"A1", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, - {"port":20, "name":"A2", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, - {"port":21, "name":"A3", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, - {"port":22, "name":"A4", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, - {"port":23, "name":"A5", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"} + {"port":0, "name":"0", "capabilities":["DI", "DO"], "notes":"5V dig (RX)"}, + {"port":1, "name":"1", "capabilities":["DI", "DO"], "notes":"5V dig (TX)"}, + {"port":2, "name":"2", "capabilities":[], "notes":"SDA (5V dig)"}, + {"port":3, "name":"3", "capabilities":[], "notes":"SCL (5V dig)"}, + {"port":4, "name":"4", "capabilities":["DI", "DO", "AI"], "notes":"5V dig / analog in"}, + {"port":5, "name":"5", "capabilities":["DI", "DO"], "notes":"5V dig"}, + {"port":6, "name":"6", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, + {"port":7, "name":"7", "capabilities":["DI", "DO"], "notes":"5V dig"}, + {"port":8, "name":"8", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, + {"port":9, "name":"9", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, + {"port":10, "name":"10", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, + {"port":11, "name":"11", "capabilities":["DI", "DO"], "notes":"5V digital"}, + {"port":12, "name":"12", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, + {"port":13, "name":"13", "capabilities":["DI", "DO"], "notes":"5V dig"}, + {"port":14, "name":"14", "capabilities":["DI", "AI", "DO"], "notes":"5V dig"}, + {"port":15, "name":"15", "capabilities":["DI", "AI", "DO"], "notes":"5V dig"}, + {"port":16, "name":"16", "capabilities":["DI", "AI", "DO"], "notes":"5V dig"}, + {"port":17, "name":"17", "capabilities":["DI", "AI", "DO"], "notes":"5V dig"}, + {"port":18, "name":"18", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, + {"port":19, "name":"19", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, + {"port":200, "name":"DAC1", "capabilities":["AO"], "notes":"5V 12-bit DAC"}, + {"port":201, "name":"DAC2", "capabilities":["AO"], "notes":"5V 12-bit DAC"} ], - "adc_config":{"bit_resolution":10, "reference_v":5.0} + "adc_config":{"bit_resolution":10, "reference_v":5.0}, + "dac_config":{"bit_resolution":12, "reference_v":5.0}, + "calibrate_rail":false } \ No newline at end of file diff --git a/hil/hil_devices/hil_device_arduino_micro_breadboard.json b/hil/hil_devices/hil_device_arduino_micro_breadboard.json deleted file mode 100644 index c5af465..0000000 --- a/hil/hil_devices/hil_device_arduino_micro_breadboard.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "./emulator_schema.json", - "communication_mode":"serial", - "ports":[ - {"port":0, "name":"0", "capabilities":["DI", "DO"], "notes":"5V dig (RX)"}, - {"port":1, "name":"1", "capabilities":["DI", "DO"], "notes":"5V dig (TX)"}, - {"port":2, "name":"2", "capabilities":[], "notes":"SDA (5V dig)"}, - {"port":3, "name":"3", "capabilities":[], "notes":"SCL (5V dig)"}, - {"port":4, "name":"4", "capabilities":["DI", "DO", "AI"], "notes":"5V dig / analog in"}, - {"port":5, "name":"5", "capabilities":["DI", "DO"], "notes":"5V dig"}, - {"port":6, "name":"6", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, - {"port":7, "name":"7", "capabilities":["DI", "DO"], "notes":"5V dig"}, - {"port":8, "name":"8", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, - {"port":9, "name":"9", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, - {"port":10, "name":"10", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, - {"port":11, "name":"11", "capabilities":["DI", "DO"], "notes":"5V digital"}, - {"port":12, "name":"12", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, - {"port":13, "name":"13", "capabilities":["DI", "DO"], "notes":"5V dig"}, - {"port":14, "name":"14", "capabilities":["DI", "AI", "DO"], "notes":"5V dig"}, - {"port":15, "name":"15", "capabilities":["DI", "AI", "DO"], "notes":"5V dig"}, - {"port":16, "name":"16", "capabilities":["DI", "AI", "DO"], "notes":"5V dig"}, - {"port":17, "name":"17", "capabilities":["DI", "AI", "DO"], "notes":"5V dig"}, - {"port":18, "name":"18", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, - {"port":19, "name":"19", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, - {"port":200, "name":"DAC1", "capabilities":["AO"], "notes":"5V 12-bit DAC"}, - {"port":201, "name":"DAC2", "capabilities":["AO"], "notes":"5V 12-bit DAC"} - ], - "adc_config":{"bit_resolution":10, "reference_v":5.0}, - "dac_config":{"bit_resolution":12, "reference_v":5.0}, - "calibrate_rail":false -} \ No newline at end of file From 9bf79e857c18a7bb32475dcfaa86f3e45d913d0e Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 14 Jan 2025 20:36:43 -0500 Subject: [PATCH 154/181] Adjusting the simple col test for the inverted relay --- scripts/test_mil_col.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/test_mil_col.py b/scripts/test_mil_col.py index 3079cb0..c2f9473 100644 --- a/scripts/test_mil_col.py +++ b/scripts/test_mil_col.py @@ -12,7 +12,10 @@ def test_collector(hil: HIL): mux_a = hil.dout("Collector", "MUX_A") # A1 mux_b = hil.dout("Collector", "MUX_B") # A2 mux_d = hil.dout("Collector", "MUX_C") # A3 + mux_c = hil.dout("Collector", "MUX_D") # RLY1: have to wire: 5V -> RLY1 -> MUX_D + mux_c.state = 1 # turn on relay (it is inverted) + temp_out = hil.ain("Collector", "TEMP_OUT") # A4 tolerance_v = 0.1 # volts @@ -36,7 +39,7 @@ def test_collector(hil: HIL): # Encode the current thermistor into binary where each bit corresponds to each pin being high or low mux_a.state = i & 0x1 mux_b.state = i & 0x2 - mux_c.state = i & 0x4 + mux_c.state = not (i & 0x4) # relay is inverted mux_d.state = i & 0x8 # Wait for relay From 15d1e53255e389c7fc76f2f5138178aab6f36bd0 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 21 Jan 2025 20:23:16 -0500 Subject: [PATCH 155/181] Deleting old test files --- _old/ArduinoFlashTest/ArduinoFlashTest.ino | 21 ------ .../deleteWhenEverythingWorks.txt | 0 _old/SimplePyTestExample/fake_test.py | 69 ------------------- _old/SimplePyTestExample/test.sh | 10 --- 4 files changed, 100 deletions(-) delete mode 100644 _old/ArduinoFlashTest/ArduinoFlashTest.ino delete mode 100644 _old/ArduinoFlashTest/deleteWhenEverythingWorks.txt delete mode 100644 _old/SimplePyTestExample/fake_test.py delete mode 100755 _old/SimplePyTestExample/test.sh diff --git a/_old/ArduinoFlashTest/ArduinoFlashTest.ino b/_old/ArduinoFlashTest/ArduinoFlashTest.ino deleted file mode 100644 index 53b6bc1..0000000 --- a/_old/ArduinoFlashTest/ArduinoFlashTest.ino +++ /dev/null @@ -1,21 +0,0 @@ -#include - -int value = 0; -int PIN = 4; - -void setup() { - Serial.begin(115200); -} - -void loop() { - value = !value; - - digitalWrite(LED_BUILTIN, value); - - Serial.println("Value: " + String(value)); - - pinMode(PIN, OUTPUT); - digitalWrite(PIN, value); - - delay(10000); -} diff --git a/_old/ArduinoFlashTest/deleteWhenEverythingWorks.txt b/_old/ArduinoFlashTest/deleteWhenEverythingWorks.txt deleted file mode 100644 index e69de29..0000000 diff --git a/_old/SimplePyTestExample/fake_test.py b/_old/SimplePyTestExample/fake_test.py deleted file mode 100644 index beed2b8..0000000 --- a/_old/SimplePyTestExample/fake_test.py +++ /dev/null @@ -1,69 +0,0 @@ -# import pytest - -# def test_fake(): -# assert 1 == 1, "Power" -# assert 2 == 3, "Fire" -# assert 3 == 3, "Cooling" -# assert 4 == 5, "Brakes" -# assert 5 == 5, "Steering" -# assert 6 == 6, "Suspension" - -# def test_fake2(): -# assert False -# assert True -# assert False -# assert True - -# def test_fake3(): -# assert True -# assert True -# assert True -# assert True - - -import pytest -import pytest_check as check - -@pytest.fixture(scope="session") -def param(): - param_instance = None - yield param_instance - - -def do_something(): - print("Doing something") - -def do_something_with_args(arg1, arg2): - print(f"Arg1: {arg1}, Arg2: {arg2}") - -def test_fake(param): - check.equal(1, 1, "Power") - do_something() - check.equal(2, 3, "Fire") - check.equal(3, 3, "Cooling") - do_something_with_args(1, 2) - check.equal(4, 5, "Brakes") - do_something() - check.equal(5, 5, "Steering") - check.equal(6, 6, "Suspension") - do_something_with_args(3, 4) - check.between_equal(5, 1, 10, "Speed") - check.between_equal(11, 1, 10, "Speed 2") - -def test_fake2(param): - check.is_true(False, "A") - check.is_true(True, "B") - check.is_true(False, "C") - do_something_with_args(5, 6) - check.is_true(True, "D") - -def test_fake3(param): - check.is_true(True, "True 1") - check.is_true(True, "True 2") - check.is_true(True, "True 3") - do_something_with_args(7, 8) - check.is_true(True, "True 4") - -def test_fake4(param): - check.almost_equal(0.2, 0.23, abs=0.1, rel=0.0, msg="Almost 1") - diff --git a/_old/SimplePyTestExample/test.sh b/_old/SimplePyTestExample/test.sh deleted file mode 100755 index 9a919dd..0000000 --- a/_old/SimplePyTestExample/test.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -# If no file passed, run on all files -if [ "$#" -ne 1 ]; then - echo "Running tests on all files..." - pytest --cache-clear --no-header -v -else - echo "Running tests on $1..." - pytest --cache-clear --no-header -v "$1" -fi \ No newline at end of file From a85395bf0dc8a4f5440098dc80cf20da8dcf8a75 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 21 Jan 2025 20:25:01 -0500 Subject: [PATCH 156/181] Removing old hil checks/testing suite + copying old file --- _old/hil.py | 247 ++++++++++++++++++++++++++++++++++++++++++++++++++++ hil/hil.py | 33 ------- 2 files changed, 247 insertions(+), 33 deletions(-) create mode 100644 _old/hil.py diff --git a/_old/hil.py b/_old/hil.py new file mode 100644 index 0000000..eeecdc8 --- /dev/null +++ b/_old/hil.py @@ -0,0 +1,247 @@ +import hil.utils as utils +import os +import signal +import sys +# import time +from hil.pin_mapper import PinMapper +from hil.hil_devices.hil_device import HilDevice +from hil.hil_devices.serial_manager import SerialManager +from hil.components.component import Component + +from hil.communication.can_bus import CanBus, BusSignal +from hil.communication.daq_protocol import DaqProtocol +from hil.communication.daq_protocol import DAQPin +from hil.communication.daq_protocol import DAQVariable + +""" HIL TESTER """ + +JSON_CONFIG_SCHEMA_PATH = "" +CONFIG_PATH = "../configurations" + +NET_MAP_PATH = "../net_maps" +PIN_MAP_PATH = "../pin_maps" + +PARAMS_PATH = "../hil_params.json" + + +class HIL(): + def __init__(self): + utils.initGlobals() + self.components: dict[str, Component] = {} + self.dut_connections: dict[str, dict[str, dict[str, tuple[str, str]]]] = {} + self.hil_devices: dict[str, HilDevice] = {} + self.serial_manager: SerialManager = SerialManager() + self.hil_params: dict = utils.load_json_config(PARAMS_PATH, None) + self.can_bus: CanBus = None + utils.hilProt = self + signal.signal(signal.SIGINT, signal_int_handler) + # self.global_failed_checks = [] + # self.global_test_names = [] + # self.global_check_count = 0 # multiple checks within a test + # self.global_test_count = 0 + # self.global_failed_checks = [] + # self.global_test_names = [] + # self.global_check_count = 0 # multiple checks within a test + # self.global_test_count = 0 + + def init_can(self) -> None: + config = self.hil_params + self.daq_config = utils.load_json_config(os.path.join(config['firmware_path'], config['daq_config_path']), os.path.join(config['firmware_path'], config['daq_schema_path'])) + self.can_config = utils.load_json_config(os.path.join(config['firmware_path'], config['can_config_path']), os.path.join(config['firmware_path'], config['can_schema_path'])) + + print(f"PATH: {os.path.join(config['firmware_path'], config['dbc_path'])}") + self.can_bus = CanBus(os.path.join(config['firmware_path'], config['dbc_path']), config['default_ip'], self.can_config) + self.daq_protocol = DaqProtocol(self.can_bus, self.daq_config) + + self.can_bus.connect() + self.can_bus.start() + + def load_pin_map(self, net_map: str, pin_map: str) -> None: + net_map_f = os.path.join(NET_MAP_PATH, net_map) + pin_map_f = os.path.join(PIN_MAP_PATH, pin_map) + + self.pin_map = PinMapper(net_map_f) + self.pin_map.load_mcu_pin_map(pin_map_f) + + def clear_components(self) -> None: + """ Reset HIL""" + for c in self.components.values(): + c.shutdown() + self.components = {} + + def clear_hil_devices(self) -> None: + self.hil_devices = {} + self.serial_manager.close_devices() + + def shutdown(self) -> None: + print(f"{utils.bcolors.OKCYAN}HIL shutdown START{utils.bcolors.ENDC}") + self.clear_components() + self.clear_hil_devices() + self.stop_can() + print(f"{utils.bcolors.OKGREEN}HIL shutdown END{utils.bcolors.OKGREEN}") + + def stop_can(self) -> None: + if not self.can_bus: return + print(f"{utils.bcolors.OKCYAN}HIL stop_can START{utils.bcolors.ENDC}") + + if self.can_bus.connected: + self.can_bus.connected = False + self.can_bus.join() + # while(not self.can_bus.isFinished()): + # # wait for bus receive to finish + # pass + self.can_bus.disconnect_bus() + print(f"{utils.bcolors.OKGREEN}HIL stop_can END{utils.bcolors.ENDC}") + + def load_config(self, config_name: str) -> None: + config = utils.load_json_config(os.path.join(CONFIG_PATH, config_name), None) # TODO: validate w/ schema + + # TODO: support joining configs + + # Load hil_devices + self.load_hil_devices(config['hil_devices']) + + # Setup corresponding components + self.load_connections(config['dut_connections']) + + def load_connections(self, dut_connections: dict) -> None: + self.dut_connections = {} + # Dictionary format: + # [board][connector][pin] = (hil_device, port) + for board_connections in dut_connections: + board_name = board_connections['board'] + if not board_name in self.dut_connections: + self.dut_connections[board_name] = {} + for c in board_connections['harness_connections']: + connector = c['dut']['connector'] + pin = str(c['dut']['pin']) + hil_port = (c['hil']['device'], c['hil']['port']) + if not connector in self.dut_connections[board_name]: + self.dut_connections[board_name][connector] = {} + self.dut_connections[board_name][connector][pin] = hil_port + + def add_component(self, board: str, net: str, mode: str) -> Component: + # If board is a HIL device, net is expected to be port name + # If board is a DUT device, net is expected to be a net name from the board + if board in self.hil_devices: + hil_con = (board, net) + else: + hil_con = self.get_hil_device_connection(board, net) + comp_name = '.'.join([board, net]) + if not comp_name in self.components: + comp = Component(comp_name, hil_con, mode, self) + self.components[comp_name] = comp + else: + utils.log_warning(f"Component {comp_name} already exists") + return self.components[comp_name] + + def load_hil_devices(self, hil_devices: dict) -> None: + self.clear_hil_devices() + self.serial_manager.discover_devices() + for hil_device in hil_devices: + if self.serial_manager.port_exists(hil_device["id"]): + self.hil_devices[hil_device['name']] = HilDevice(hil_device['name'], hil_device['type'], hil_device['id'], self.serial_manager) + else: + self.handle_error(f"Failed to discover HIL device {hil_device['name']} with id {hil_device['id']}") + + def get_hil_device(self, name: str) -> HilDevice: + if name in self.hil_devices: + return self.hil_devices[name] + else: + self.handle_error(f"HIL device {name} not recognized") + + def get_hil_device_connection(self, board: str, net: str) -> tuple[str, str]: + """ Converts dut net to hil port name """ + if not board in self.dut_connections: + self.handle_error(f"No connections to {board} found in configuration.") + board_cons = self.dut_connections[board] + + net_cons = self.pin_map.get_net_connections(board, net) + for c in net_cons: + connector = c[0] + pin = c[1] + if connector in board_cons: + if pin in board_cons[connector]: + return board_cons[connector][pin] + utils.log_warning(f"Unable to find dut connection to net {net} on board {board}") + utils.log_warning(f"The net {net} is available on {board} via ...") + utils.log_warning(net_cons) + self.handle_error(f"Connect dut to {net} on {board}.") + + def din(self, board: str, net: str) -> Component: + return self.add_component(board, net, 'DI') + + def dout(self, board: str, net: str) -> Component: + return self.add_component(board, net, 'DO') + + def ain(self, board: str, net: str) -> Component: + return self.add_component(board, net, 'AI') + + def aout(self, board: str, net: str) -> Component: + return self.add_component(board, net, 'AO') + + def pot(self, board: str, net: str) -> Component: + return self.add_component(board, net, 'POT') + + def pwm(self, board: str, net: str) -> Component: + return self.add_component(board, net, 'PWM') + + def daq_var(self, board: str, var_name: str) -> DAQVariable: + try: + return utils.signals[utils.b_str][board][f"daq_response_{board.upper()}"][var_name] + except KeyError as e: + self.handle_error(f"Unable to locate DAQ variable {var_name} of {board}") + + def can_var(self, board: str, message_name: str, signal_name: str) -> BusSignal: + # TODO: not sure if any of the type hints are correct + try: + return utils.signals[utils.b_str][board][message_name][signal_name] + except KeyError: + self.handle_error(f"Unable to locate CAN signal {signal_name} of message {message_name} of board {board}") + + def mcu_pin(self, board: str, net: str) -> DAQPin: + bank, pin = self.pin_map.get_mcu_pin(board, net) + if bank == None: + self.handle_error(f"Failed to get mcu pin for {board} net {net}") + return DAQPin(net, board, bank, pin) + + # def start_test(self, name): + # print(f"{utils.bcolors.OKCYAN}Starting {name}{utils.bcolors.ENDC}") + # self.curr_test = name + # self.curr_test_fail_count = 0 + # self.curr_test_count = 0 + # self.global_test_count = self.global_test_count + 1 + # self.global_test_names.append(name) + + # def check(self, stat, check_name): + # stat_str = "PASS" if stat else "FAIL" + # stat_clr = utils.bcolors.OKGREEN if stat else utils.bcolors.FAIL + # print(f"{self.curr_test + ' - ' + check_name:<50}: {stat_clr+'['+stat_str+']'+utils.bcolors.ENDC:>10}") + # if (not stat): + # self.curr_test_fail_count = self.curr_test_fail_count + 1 + # self.global_failed_checks.append((self.curr_test,check_name)) + # self.curr_test_count = self.curr_test_count + 1 + # self.global_check_count = self.global_check_count + 1 + # return stat + + # def check_within(self, val1, val2, thresh, check_name): + # self.check(abs(val1 - val2) <= thresh, check_name) + + # def end_test(self): + # print(f"{utils.bcolors.OKCYAN}{self.curr_test} failed {self.curr_test_fail_count} out of {self.curr_test_count} checks{utils.bcolors.ENDC}") + + def handle_error(self, msg: str) -> None: + utils.log_error(msg) + self.shutdown() + exit(0) + + +def signal_int_handler(signum, frame) -> None: + utils.log("Received signal interrupt, shutting down") + if (utils.hilProt): + utils.hilProt.shutdown() + sys.exit(0) + +# if __name__ == "__main__": +# hil = HIL() +# hil.load_config("config_test.json") diff --git a/hil/hil.py b/hil/hil.py index eeecdc8..490788e 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -35,14 +35,6 @@ def __init__(self): self.can_bus: CanBus = None utils.hilProt = self signal.signal(signal.SIGINT, signal_int_handler) - # self.global_failed_checks = [] - # self.global_test_names = [] - # self.global_check_count = 0 # multiple checks within a test - # self.global_test_count = 0 - # self.global_failed_checks = [] - # self.global_test_names = [] - # self.global_check_count = 0 # multiple checks within a test - # self.global_test_count = 0 def init_can(self) -> None: config = self.hil_params @@ -205,31 +197,6 @@ def mcu_pin(self, board: str, net: str) -> DAQPin: self.handle_error(f"Failed to get mcu pin for {board} net {net}") return DAQPin(net, board, bank, pin) - # def start_test(self, name): - # print(f"{utils.bcolors.OKCYAN}Starting {name}{utils.bcolors.ENDC}") - # self.curr_test = name - # self.curr_test_fail_count = 0 - # self.curr_test_count = 0 - # self.global_test_count = self.global_test_count + 1 - # self.global_test_names.append(name) - - # def check(self, stat, check_name): - # stat_str = "PASS" if stat else "FAIL" - # stat_clr = utils.bcolors.OKGREEN if stat else utils.bcolors.FAIL - # print(f"{self.curr_test + ' - ' + check_name:<50}: {stat_clr+'['+stat_str+']'+utils.bcolors.ENDC:>10}") - # if (not stat): - # self.curr_test_fail_count = self.curr_test_fail_count + 1 - # self.global_failed_checks.append((self.curr_test,check_name)) - # self.curr_test_count = self.curr_test_count + 1 - # self.global_check_count = self.global_check_count + 1 - # return stat - - # def check_within(self, val1, val2, thresh, check_name): - # self.check(abs(val1 - val2) <= thresh, check_name) - - # def end_test(self): - # print(f"{utils.bcolors.OKCYAN}{self.curr_test} failed {self.curr_test_fail_count} out of {self.curr_test_count} checks{utils.bcolors.ENDC}") - def handle_error(self, msg: str) -> None: utils.log_error(msg) self.shutdown() From e8844be4fe79cc40486b5e5d2547559fd508e3fc Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 21 Jan 2025 20:26:41 -0500 Subject: [PATCH 157/181] Type hinting signal_int_handler --- hil/hil.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hil/hil.py b/hil/hil.py index 490788e..3f1558f 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -1,3 +1,4 @@ +from types import FrameType import hil.utils as utils import os import signal @@ -203,9 +204,9 @@ def handle_error(self, msg: str) -> None: exit(0) -def signal_int_handler(signum, frame) -> None: +def signal_int_handler(signum: int, frame: FrameType) -> None: utils.log("Received signal interrupt, shutting down") - if (utils.hilProt): + if utils.hilProt: utils.hilProt.shutdown() sys.exit(0) From e93e80b06017f133fdb675dcc369018579136eb4 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 21 Jan 2025 20:31:19 -0500 Subject: [PATCH 158/181] Undoing CollTester --- configurations/config_collector_bench.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configurations/config_collector_bench.json b/configurations/config_collector_bench.json index dbf67a2..9a67bf7 100644 --- a/configurations/config_collector_bench.json +++ b/configurations/config_collector_bench.json @@ -10,6 +10,6 @@ ]} ], "hil_devices":[ - {"name":"CollTester", "type":"arduino_micro", "id":2} + {"name":"CollTester", "type":"arduino_uno", "id":5} ] } From 4d96e5f90edba2bbc74ff1891c317de8de28f637 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 21 Jan 2025 20:40:51 -0500 Subject: [PATCH 159/181] Removing TODO: type hint comments --- _old/hil.py | 1 - hil/communication/can_bus.py | 6 +----- hil/communication/daq_protocol.py | 9 --------- 3 files changed, 1 insertion(+), 15 deletions(-) diff --git a/_old/hil.py b/_old/hil.py index eeecdc8..e137314 100644 --- a/_old/hil.py +++ b/_old/hil.py @@ -193,7 +193,6 @@ def daq_var(self, board: str, var_name: str) -> DAQVariable: self.handle_error(f"Unable to locate DAQ variable {var_name} of {board}") def can_var(self, board: str, message_name: str, signal_name: str) -> BusSignal: - # TODO: not sure if any of the type hints are correct try: return utils.signals[utils.b_str][board][message_name][signal_name] except KeyError: diff --git a/hil/communication/can_bus.py b/hil/communication/can_bus.py index 2408d5a..3602e70 100644 --- a/hil/communication/can_bus.py +++ b/hil/communication/can_bus.py @@ -227,7 +227,6 @@ def sendLogCmd(self, option: bool) -> None: self.tcpbus.stop_logging() def sendFormatMsg(self, msg_name: str, msg_data: dict) -> None: - # TODO: not sure if the type hints are correct """ Sends a message using a dictionary of its data """ dbc_msg = self.db.get_message_by_name(msg_name) data = dbc_msg.encode(msg_data) @@ -389,7 +388,7 @@ def __init__( else: self.store_dtype: np.dtype = store_dtype - self.data: int = 0 # TODO: n + self.data: int = 0 self.time: float = 0 self.stale_timestamp: float = time.time() @@ -409,7 +408,6 @@ def fromCANMsg(cls, sig: dict, msg: dict, node: dict, bus: dict) -> BusSignal: msg_period=msg['msg_period']) def update(self, val: int, timestamp: float) -> None: - # TODO: not sure if the type hints are correct """ update the value of the signal """ self.data = val self.time = timestamp @@ -422,7 +420,6 @@ def clear(self) -> None: @property def curr_val(self) -> int: - # TODO: not sure if the type hints are correct """ last value recorded """ return self.data @@ -440,7 +437,6 @@ def is_stale(self) -> bool: @property def state(self) -> int: - # TODO: not sure if the type hints are correct start_t = time.time() while (self.is_stale): if (time.time() >= start_t + CAN_READ_TIMEOUT_S): diff --git a/hil/communication/daq_protocol.py b/hil/communication/daq_protocol.py index 290f3ed..b6e234b 100644 --- a/hil/communication/daq_protocol.py +++ b/hil/communication/daq_protocol.py @@ -89,7 +89,6 @@ def __init__(self, self.pub_period_ms: int = 0 - # TODO: not sure if the type hints are correct self.scale: int = scale self.offset: int = offset @@ -121,7 +120,6 @@ def fromDAQVar(cls, id: int, var: dict, node: dict, bus: dict) -> DAQVariable: @classmethod def fromDAQFileVar(cls, id: int, var: dict, file_name: str, file_lbl: str, node: dict, bus: dict) -> DAQVariable: - # TODO: not sure if the type hints are correct send_dtype = utils.data_types[var['type']] # If there is scaling going on, don't store as an integer on accident if ('scale' in var and var['scale'] != 1) or ('offset' in var and var['offset'] != 0): @@ -146,11 +144,9 @@ def update(self, bytes: int, timestamp: float) -> None: super().update(val, timestamp) def reverseScale(self, val: float) -> float: - # TODO: not sure if the type hint is correct return (val - self.offset) / self.scale def valueSendable(self, val: float) -> bool: - # TODO: not sure if the type hint is correct # TODO: check max and min from json config val = self.reverseScale(val) if 'uint' in str(self.send_dtype): @@ -168,7 +164,6 @@ def reverseToBytes(self, val: float) -> bytes | bool: return (np.array([self.reverseScale(val)], dtype=self.send_dtype).tobytes()) def getSendValue(self, val: float) -> float | bool: - # TODO: not sure if the type hint is correct if not self.valueSendable(val): return False # Value will not fit in the given dtype # Convert to send a = np.array([self.reverseScale(val)], dtype=self.send_dtype)[0] @@ -185,7 +180,6 @@ def updateDirty(self, dirty: bool) -> None: @property def state(self) -> int: - # TODO: not sure if the type hints are correct """ Read the value in blocking manner """ old_t = self.last_update_time utils.daqProt.readVar(self) @@ -199,7 +193,6 @@ def state(self) -> int: @state.setter def state(self, s: int) -> None: - # TODO: not sure if the type hint is correct """ Writes the value in blocking manner """ if (self.read_only): utils.log_error(f"Can't write to read-only DAQ variable {self.signal_name} of {self.node_name}") @@ -258,7 +251,6 @@ def readVar(self, var: DAQVariable) -> None: data=data)) def writeVar(self, var: DAQVariable, new_val: float) -> None: - # TODO: not sure if the type hint is correct """ Writes to a variable """ dbc_msg = self.can_bus.db.get_message_by_name(f"daq_command_{var.node_name.upper()}") data = [((var.id & DAQ_ID_MASK) << DAQ_CMD_LENGTH) | DAQ_CMD_WRITE] @@ -323,7 +315,6 @@ def pubVar(self, var: DAQVariable, period_ms: int) -> None: data=data)) def forceFault(self, id: int, state: int) -> None: - # TODO: not sure if the type hint is correct print(f"Id: {id}, State: {state}") fault_msg = self.can_bus.db.get_message_by_name(f"set_fault") data = fault_msg.encode({"id": id, "value": state}) From cb42b479010ffd734267925800bc741d84f9584d Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 21 Jan 2025 20:41:01 -0500 Subject: [PATCH 160/181] Cleaning comment --- hil/pin_mapper.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/hil/pin_mapper.py b/hil/pin_mapper.py index 218bf5d..0212453 100644 --- a/hil/pin_mapper.py +++ b/hil/pin_mapper.py @@ -42,10 +42,7 @@ def load_net_map(self, fname: str) -> None: def load_mcu_pin_map(self, fname: str) -> None: self.mcu_pin_name_fname = fname self.mcu_pin_map = {} - # CSV format: - # Designator,Pin Name,Type - # Create dictionary as follows - # [designator] = (bank, pin) + # CSV format: Designator,Pin Name,Type with open(self.mcu_pin_name_fname, mode='r') as f: csv_file = csv.DictReader(f) for row in csv_file: From 00cab7a60cfe66deeb61674dfa74f25637ea2011 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 21 Jan 2025 20:41:09 -0500 Subject: [PATCH 161/181] Apparently can delete --- hil/communication/daq_protocol.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/hil/communication/daq_protocol.py b/hil/communication/daq_protocol.py index b6e234b..6d0aceb 100644 --- a/hil/communication/daq_protocol.py +++ b/hil/communication/daq_protocol.py @@ -216,8 +216,6 @@ def __init__(self, bus: CanBus, daq_config: dict): self.can_bus: CanBus = bus self.can_bus.handle_daq_msg = self.handleDaqMsg - # self.can_bus.new_msg_sig.connect(self.handleDaqMsg) - self.updateVarDict(daq_config) # eeprom saving (prevent a load while save taking place) From 91142b8c81f2d2382246db81cc4258d289c87068 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 21 Jan 2025 20:41:22 -0500 Subject: [PATCH 162/181] Removing debug prints --- hil/hil.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/hil/hil.py b/hil/hil.py index 3f1558f..cacd05f 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -67,15 +67,12 @@ def clear_hil_devices(self) -> None: self.serial_manager.close_devices() def shutdown(self) -> None: - print(f"{utils.bcolors.OKCYAN}HIL shutdown START{utils.bcolors.ENDC}") self.clear_components() self.clear_hil_devices() self.stop_can() - print(f"{utils.bcolors.OKGREEN}HIL shutdown END{utils.bcolors.OKGREEN}") def stop_can(self) -> None: if not self.can_bus: return - print(f"{utils.bcolors.OKCYAN}HIL stop_can START{utils.bcolors.ENDC}") if self.can_bus.connected: self.can_bus.connected = False @@ -84,7 +81,6 @@ def stop_can(self) -> None: # # wait for bus receive to finish # pass self.can_bus.disconnect_bus() - print(f"{utils.bcolors.OKGREEN}HIL stop_can END{utils.bcolors.ENDC}") def load_config(self, config_name: str) -> None: config = utils.load_json_config(os.path.join(CONFIG_PATH, config_name), None) # TODO: validate w/ schema From 6b952a81f25d8cfee3f80192fffddc29faed4b88 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 21 Jan 2025 20:43:08 -0500 Subject: [PATCH 163/181] Undoing windows -> linux file conversions Should make a new branch/PR with this change (or just use python pages instead...) --- hil/hil.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hil/hil.py b/hil/hil.py index cacd05f..418c34d 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -17,12 +17,12 @@ """ HIL TESTER """ JSON_CONFIG_SCHEMA_PATH = "" -CONFIG_PATH = "../configurations" +CONFIG_PATH = "..\\configurations" -NET_MAP_PATH = "../net_maps" -PIN_MAP_PATH = "../pin_maps" +NET_MAP_PATH = "..\\net_maps" +PIN_MAP_PATH = "..\\pin_maps" -PARAMS_PATH = "../hil_params.json" +PARAMS_PATH = "..\\hil_params.json" class HIL(): From 56fad8d4e08d6627625cb7cb152c8a82113c1253 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 21 Jan 2025 20:43:54 -0500 Subject: [PATCH 164/181] Delete debug print --- hil/hil.py | 1 - 1 file changed, 1 deletion(-) diff --git a/hil/hil.py b/hil/hil.py index 418c34d..d14d10e 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -42,7 +42,6 @@ def init_can(self) -> None: self.daq_config = utils.load_json_config(os.path.join(config['firmware_path'], config['daq_config_path']), os.path.join(config['firmware_path'], config['daq_schema_path'])) self.can_config = utils.load_json_config(os.path.join(config['firmware_path'], config['can_config_path']), os.path.join(config['firmware_path'], config['can_schema_path'])) - print(f"PATH: {os.path.join(config['firmware_path'], config['dbc_path'])}") self.can_bus = CanBus(os.path.join(config['firmware_path'], config['dbc_path']), config['default_ip'], self.can_config) self.daq_protocol = DaqProtocol(self.can_bus, self.daq_config) From 7430b6188f279678a91f129561c1bfdaee9418ff Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 21 Jan 2025 20:45:29 -0500 Subject: [PATCH 165/181] Removing unused imports --- hil/hil.py | 1 - hil/hil_devices/hil_device.py | 3 --- 2 files changed, 4 deletions(-) diff --git a/hil/hil.py b/hil/hil.py index d14d10e..9e74907 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -3,7 +3,6 @@ import os import signal import sys -# import time from hil.pin_mapper import PinMapper from hil.hil_devices.hil_device import HilDevice from hil.hil_devices.serial_manager import SerialManager diff --git a/hil/hil_devices/hil_device.py b/hil/hil_devices/hil_device.py index a6743c0..c2df15a 100644 --- a/hil/hil_devices/hil_device.py +++ b/hil/hil_devices/hil_device.py @@ -1,7 +1,4 @@ import os -# import time -# import serial -# import serial.tools.list_ports from hil.hil_devices.serial_manager import SerialManager import hil.utils as utils From d5c47e0eb2ce11b5974b6d95cc448ad5db04b6ec Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 21 Jan 2025 20:45:35 -0500 Subject: [PATCH 166/181] Removing debug print --- hil/hil_devices/hil_device.py | 1 - 1 file changed, 1 deletion(-) diff --git a/hil/hil_devices/hil_device.py b/hil/hil_devices/hil_device.py index c2df15a..eebfd02 100644 --- a/hil/hil_devices/hil_device.py +++ b/hil/hil_devices/hil_device.py @@ -76,7 +76,6 @@ def get_port_number(self, port_name: str, mode: str) -> int: def write_gpio(self, pin: int, value: int) -> None: data = [(HIL_CMD_WRITE_GPIO & HIL_CMD_MASK), (pin & HIL_ID_MASK), value] - # print(f"write pin {pin} to {value}") self.sm.send_data(self.id, data) def write_dac(self, pin: int, voltage: float) -> None: From 0777fed351d083ffd5a3c39b6b3934a7f5c5e355 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 21 Jan 2025 20:45:55 -0500 Subject: [PATCH 167/181] Delete debug print --- hil/hil_devices/hil_device.py | 1 - 1 file changed, 1 deletion(-) diff --git a/hil/hil_devices/hil_device.py b/hil/hil_devices/hil_device.py index eebfd02..0ded20a 100644 --- a/hil/hil_devices/hil_device.py +++ b/hil/hil_devices/hil_device.py @@ -108,7 +108,6 @@ def read_analog(self, pin: int) -> float: def write_pot(self, pin: int, value: float) -> None: value = min(self.pot_max, max(0, int(value * self.pot_max))) data = [(HIL_CMD_WRITE_POT & HIL_CMD_MASK), (pin & HIL_ID_MASK), value] - #print(f"sending {value} to pin {pin}") self.sm.send_data(self.id, data) def write_pwm(self, pin: int, value: int) -> None: From b0f0a9fc8b2a0e17ee78c16d72629c72e2741ba8 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 21 Jan 2025 20:48:42 -0500 Subject: [PATCH 168/181] Renaming and making better use of MASK constants --- hil/hil_devices/hil_device.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/hil/hil_devices/hil_device.py b/hil/hil_devices/hil_device.py index 0ded20a..058d997 100644 --- a/hil/hil_devices/hil_device.py +++ b/hil/hil_devices/hil_device.py @@ -3,7 +3,6 @@ import hil.utils as utils -HIL_CMD_MASK = 0xFF HIL_CMD_READ_ADC = 0 # command, pin HIL_CMD_READ_GPIO = 1 # command, pin HIL_CMD_WRITE_DAC = 2 # command, pin, value (2 bytes) @@ -12,7 +11,8 @@ HIL_CMD_WRITE_POT = 5 # command, pin, value HIL_CMD_WRITE_PWM = 6 # command, pin, value -HIL_ID_MASK = 0xFF +SERIAL_MASK = 0xFF # 2^8 - 1 +SERIAL_BITS = 8 # char HIL_DEVICES_PATH = "../hil/hil_devices" @@ -75,19 +75,19 @@ def get_port_number(self, port_name: str, mode: str) -> int: return -1 def write_gpio(self, pin: int, value: int) -> None: - data = [(HIL_CMD_WRITE_GPIO & HIL_CMD_MASK), (pin & HIL_ID_MASK), value] + data = [(HIL_CMD_WRITE_GPIO & SERIAL_MASK), (pin & SERIAL_MASK), value] self.sm.send_data(self.id, data) def write_dac(self, pin: int, voltage: float) -> None: value = int(voltage * self.volts_to_dac) - char_1 = (value >> 8) & 0xFF - char_2 = value & 0xFF - data = [(HIL_CMD_WRITE_DAC & HIL_CMD_MASK), (pin & HIL_ID_MASK), char_1, char_2] + char_1 = (value >> SERIAL_BITS) & SERIAL_MASK + char_2 = value & SERIAL_MASK + data = [(HIL_CMD_WRITE_DAC & SERIAL_MASK), (pin & SERIAL_MASK), char_1, char_2] print(f"write pin {pin} to {voltage}V = {value} ({char_1}, {char_2})") self.sm.send_data(self.id, data) def read_gpio(self, pin: int) -> int: - data = [(HIL_CMD_READ_GPIO & HIL_CMD_MASK), (pin & HIL_ID_MASK)] + data = [(HIL_CMD_READ_GPIO & SERIAL_MASK), (pin & SERIAL_MASK)] self.sm.send_data(self.id, data) d = self.sm.read_data(self.id, 1) if len(d) == 1: @@ -96,7 +96,7 @@ def read_gpio(self, pin: int) -> int: utils.log_error(f"Failed to read gpio pin {pin} on {self.name}") def read_analog(self, pin: int) -> float: - data = [(HIL_CMD_READ_ADC & HIL_CMD_MASK), (pin & HIL_ID_MASK)] + data = [(HIL_CMD_READ_ADC & SERIAL_MASK), (pin & SERIAL_MASK)] self.sm.send_data(self.id, data) d = self.sm.read_data(self.id, 2) if len(d) == 2: @@ -107,10 +107,10 @@ def read_analog(self, pin: int) -> float: def write_pot(self, pin: int, value: float) -> None: value = min(self.pot_max, max(0, int(value * self.pot_max))) - data = [(HIL_CMD_WRITE_POT & HIL_CMD_MASK), (pin & HIL_ID_MASK), value] + data = [(HIL_CMD_WRITE_POT & SERIAL_MASK), (pin & SERIAL_MASK), value] self.sm.send_data(self.id, data) def write_pwm(self, pin: int, value: int) -> None: - data = [(HIL_CMD_WRITE_PWM & HIL_CMD_MASK), (pin & HIL_ID_MASK), value] + data = [(HIL_CMD_WRITE_PWM & SERIAL_MASK), (pin & SERIAL_MASK), value] print(f"writing {value} to pin {pin}") self.sm.send_data(self.id, data) From efa83884e373607af796bccaf1fd21aaaa3ebf39 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 21 Jan 2025 20:49:04 -0500 Subject: [PATCH 169/181] Remove debug print --- hil/hil_devices/hil_device.py | 1 - 1 file changed, 1 deletion(-) diff --git a/hil/hil_devices/hil_device.py b/hil/hil_devices/hil_device.py index 058d997..d8fa7b4 100644 --- a/hil/hil_devices/hil_device.py +++ b/hil/hil_devices/hil_device.py @@ -83,7 +83,6 @@ def write_dac(self, pin: int, voltage: float) -> None: char_1 = (value >> SERIAL_BITS) & SERIAL_MASK char_2 = value & SERIAL_MASK data = [(HIL_CMD_WRITE_DAC & SERIAL_MASK), (pin & SERIAL_MASK), char_1, char_2] - print(f"write pin {pin} to {voltage}V = {value} ({char_1}, {char_2})") self.sm.send_data(self.id, data) def read_gpio(self, pin: int) -> int: From 92084cb8d96ddff075e6992ff1e6d1d2b2a74fbd Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 21 Jan 2025 20:52:36 -0500 Subject: [PATCH 170/181] Delete test.sh --- scripts/test.sh | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100755 scripts/test.sh diff --git a/scripts/test.sh b/scripts/test.sh deleted file mode 100755 index 9a919dd..0000000 --- a/scripts/test.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -# If no file passed, run on all files -if [ "$#" -ne 1 ]; then - echo "Running tests on all files..." - pytest --cache-clear --no-header -v -else - echo "Running tests on $1..." - pytest --cache-clear --no-header -v "$1" -fi \ No newline at end of file From f034f0d160ceeb5b9b47c92b6d3937ace8852bcd Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 21 Jan 2025 20:53:42 -0500 Subject: [PATCH 171/181] Remove unused import --- _old/hil.py | 1 - hil/communication/can_bus.py | 1 - 2 files changed, 2 deletions(-) diff --git a/_old/hil.py b/_old/hil.py index e137314..80deb23 100644 --- a/_old/hil.py +++ b/_old/hil.py @@ -2,7 +2,6 @@ import os import signal import sys -# import time from hil.pin_mapper import PinMapper from hil.hil_devices.hil_device import HilDevice from hil.hil_devices.serial_manager import SerialManager diff --git a/hil/communication/can_bus.py b/hil/communication/can_bus.py index 3602e70..fefa1f7 100644 --- a/hil/communication/can_bus.py +++ b/hil/communication/can_bus.py @@ -13,7 +13,6 @@ import time import threading import numpy as np -# import math CAN_READ_TIMEOUT_S = 1.0 From df71ef5f3fcd870d751e445717ada0fc2c7691b9 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 21 Jan 2025 20:57:47 -0500 Subject: [PATCH 172/181] Revert --- hil/hil_devices/hil_device_arduino_micro.json | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/hil/hil_devices/hil_device_arduino_micro.json b/hil/hil_devices/hil_device_arduino_micro.json index c5af465..eb66a6d 100644 --- a/hil/hil_devices/hil_device_arduino_micro.json +++ b/hil/hil_devices/hil_device_arduino_micro.json @@ -2,30 +2,30 @@ "$schema": "./emulator_schema.json", "communication_mode":"serial", "ports":[ - {"port":0, "name":"0", "capabilities":["DI", "DO"], "notes":"5V dig (RX)"}, - {"port":1, "name":"1", "capabilities":["DI", "DO"], "notes":"5V dig (TX)"}, - {"port":2, "name":"2", "capabilities":[], "notes":"SDA (5V dig)"}, - {"port":3, "name":"3", "capabilities":[], "notes":"SCL (5V dig)"}, - {"port":4, "name":"4", "capabilities":["DI", "DO", "AI"], "notes":"5V dig / analog in"}, - {"port":5, "name":"5", "capabilities":["DI", "DO"], "notes":"5V dig"}, - {"port":6, "name":"6", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, - {"port":7, "name":"7", "capabilities":["DI", "DO"], "notes":"5V dig"}, - {"port":8, "name":"8", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, - {"port":9, "name":"9", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, - {"port":10, "name":"10", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, - {"port":11, "name":"11", "capabilities":["DI", "DO"], "notes":"5V digital"}, - {"port":12, "name":"12", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, - {"port":13, "name":"13", "capabilities":["DI", "DO"], "notes":"5V dig"}, - {"port":14, "name":"14", "capabilities":["DI", "AI", "DO"], "notes":"5V dig"}, - {"port":15, "name":"15", "capabilities":["DI", "AI", "DO"], "notes":"5V dig"}, - {"port":16, "name":"16", "capabilities":["DI", "AI", "DO"], "notes":"5V dig"}, - {"port":17, "name":"17", "capabilities":["DI", "AI", "DO"], "notes":"5V dig"}, - {"port":18, "name":"18", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, - {"port":19, "name":"19", "capabilities":["DI", "AI", "DO"], "notes":"5V dig / analog in"}, - {"port":200, "name":"DAC1", "capabilities":["AO"], "notes":"5V 12-bit DAC"}, - {"port":201, "name":"DAC2", "capabilities":["AO"], "notes":"5V 12-bit DAC"} - ], - "adc_config":{"bit_resolution":10, "reference_v":5.0}, - "dac_config":{"bit_resolution":12, "reference_v":5.0}, - "calibrate_rail":false + {"port":0, "name":"D0", "capabilities":["DI", "DO"], "notes":"5V digital"}, + {"port":1, "name":"D1", "capabilities":["DI", "DO"], "notes":"5V digital"}, + {"port":2, "name":"D2", "capabilities":["DI", "DO"], "notes":"5V digital"}, + {"port":3, "name":"D3", "capabilities":["DI", "DO"], "notes":"5V digital"}, + {"port":4, "name":"D4", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, + {"port":5, "name":"D5", "capabilities":["DI", "DO"], "notes":"5V digital"}, + {"port":6, "name":"D6", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, + {"port":7, "name":"D7", "capabilities":["DI", "DO"], "notes":"5V digital"}, + {"port":8, "name":"D8", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, + {"port":9, "name":"D9", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, + {"port":10, "name":"D10", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, + {"port":11, "name":"D11", "capabilities":["DI", "DO"], "notes":"5V digital"}, + {"port":12, "name":"D12", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, + {"port":13, "name":"D13", "capabilities":["DI", "DO"], "notes":"5V digital"}, + {"port":14, "name":"D14", "capabilities":["DI", "DO"], "notes":"5V digital"}, + {"port":15, "name":"D15", "capabilities":["DI", "DO"], "notes":"5V digital"}, + {"port":16, "name":"D16", "capabilities":["DI", "DO"], "notes":"5V digital"}, + {"port":17, "name":"D17", "capabilities":["DI", "DO"], "notes":"5V digital"}, + {"port":18, "name":"A0", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, + {"port":19, "name":"A1", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, + {"port":20, "name":"A2", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, + {"port":21, "name":"A3", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, + {"port":22, "name":"A4", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"}, + {"port":23, "name":"A5", "capabilities":["DI", "AI", "DO"], "notes":"analog / digital input 5V"} + ], + "adc_config":{"bit_resolution":10, "reference_v":5.0} } \ No newline at end of file From d93ba297eb4479216c5c029e8a7a33adf90d2e93 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 21 Jan 2025 20:59:18 -0500 Subject: [PATCH 173/181] Delete unused --- hil/utils.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/hil/utils.py b/hil/utils.py index 607c74a..16af398 100644 --- a/hil/utils.py +++ b/hil/utils.py @@ -48,13 +48,7 @@ def initGlobals(): # } # } - - # global plot_x_range_sec - # plot_x_range_sec = 10 - - # global events - # events = [] - + global b_str b_str = "Main" From 23af70aa960e338b03cf4079e4c21b0510588be6 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Tue, 21 Jan 2025 21:02:51 -0500 Subject: [PATCH 174/181] Removing PWM code --- TestBench/TestBench.ino | 9 --------- hil/components/component.py | 2 -- hil/hil.py | 3 --- hil/hil_devices/hil_device.py | 8 +------- 4 files changed, 1 insertion(+), 21 deletions(-) diff --git a/TestBench/TestBench.ino b/TestBench/TestBench.ino index c22909c..27acb6f 100644 --- a/TestBench/TestBench.ino +++ b/TestBench/TestBench.ino @@ -46,7 +46,6 @@ enum GpioCommand { WRITE_GPIO = 3, READ_ID = 4, WRITE_POT = 5, - WRITE_PWM = 6, }; int CHARS_TO_READ[] = { @@ -56,7 +55,6 @@ int CHARS_TO_READ[] = { 3, // WRITE_GPIO - command, pin, value 1, // READ_ID - command 3, // WRITE_POT - command, pin, value - 3, // WRITE_PWM - command, pin, value }; // 4: max CHARS_TO_READ @@ -181,13 +179,6 @@ void loop() { } break; } - case GpioCommand::WRITE_PWM: { - int pin = data[1]; - int value = data[2]; - pinMode(pin, OUTPUT); - analogWrite(pin, value & 0xFF); - break; - } } } else { if (SERIAL.available() > 0) { diff --git a/hil/components/component.py b/hil/components/component.py index ba03705..b38d8fa 100644 --- a/hil/components/component.py +++ b/hil/components/component.py @@ -86,8 +86,6 @@ def __init__(self, name: str, hil_con: tuple[str, str], mode: str, hil: 'HIL'): self.hiZ_func = lambda : dev.read_gpio(hil_port_num) elif(mode == "POT"): self.write_func = lambda s: dev.write_pot(hil_port_num, s) - elif mode == "PWM": - self.write_func = lambda s: dev.write_pwm(hil_port_num, s) else: utils.log_error(f"Unrecognized emulation/measurement mode {mode} for component {self.name}") else: diff --git a/hil/hil.py b/hil/hil.py index 9e74907..fefd45c 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -170,9 +170,6 @@ def aout(self, board: str, net: str) -> Component: def pot(self, board: str, net: str) -> Component: return self.add_component(board, net, 'POT') - def pwm(self, board: str, net: str) -> Component: - return self.add_component(board, net, 'PWM') - def daq_var(self, board: str, var_name: str) -> DAQVariable: try: return utils.signals[utils.b_str][board][f"daq_response_{board.upper()}"][var_name] diff --git a/hil/hil_devices/hil_device.py b/hil/hil_devices/hil_device.py index d8fa7b4..3cfc6cf 100644 --- a/hil/hil_devices/hil_device.py +++ b/hil/hil_devices/hil_device.py @@ -9,7 +9,6 @@ HIL_CMD_WRITE_GPIO = 3 # command, pin, value HIL_CMD_READ_ID = 4 # command HIL_CMD_WRITE_POT = 5 # command, pin, value -HIL_CMD_WRITE_PWM = 6 # command, pin, value SERIAL_MASK = 0xFF # 2^8 - 1 SERIAL_BITS = 8 # char @@ -107,9 +106,4 @@ def read_analog(self, pin: int) -> float: def write_pot(self, pin: int, value: float) -> None: value = min(self.pot_max, max(0, int(value * self.pot_max))) data = [(HIL_CMD_WRITE_POT & SERIAL_MASK), (pin & SERIAL_MASK), value] - self.sm.send_data(self.id, data) - - def write_pwm(self, pin: int, value: int) -> None: - data = [(HIL_CMD_WRITE_PWM & SERIAL_MASK), (pin & SERIAL_MASK), value] - print(f"writing {value} to pin {pin}") - self.sm.send_data(self.id, data) + self.sm.send_data(self.id, data) \ No newline at end of file From 84596b070f7613becf3f513f0d2df94defb1c8ff Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Wed, 22 Jan 2025 21:48:59 -0500 Subject: [PATCH 175/181] Deleting my personal test files from the PR --- configurations/config_mil_pcb.json | 35 ---------------- .../hil_device_arduino_mil_pcb.json | 40 ------------------- net_maps/mil_pcb_net_map.csv | 27 ------------- 3 files changed, 102 deletions(-) delete mode 100644 configurations/config_mil_pcb.json delete mode 100644 hil/hil_devices/hil_device_arduino_mil_pcb.json delete mode 100644 net_maps/mil_pcb_net_map.csv diff --git a/configurations/config_mil_pcb.json b/configurations/config_mil_pcb.json deleted file mode 100644 index d0e2b1a..0000000 --- a/configurations/config_mil_pcb.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "$schema": "./config_schema.json", - "dut_connections":[ - {"board":"Millan", "harness_connections":[ - {"dut":{"connector":"breadboard","pin":5, "_":"HIL_PWM1"}, "hil":{"device":"MilPcbTester", "port":"PWM1", "_":"PWM"}}, - {"dut":{"connector":"breadboard","pin":6, "_":"HIL_PWM2"}, "hil":{"device":"MilPcbTester", "port":"PWM2", "_":"PWM"}}, - {"dut":{"connector":"breadboard","pin":7, "_":"HIL_PWM3"}, "hil":{"device":"MilPcbTester", "port":"PWM3", "_":"PWM"}}, - {"dut":{"connector":"breadboard","pin":8, "_":"HIL_PWM4"}, "hil":{"device":"MilPcbTester", "port":"PWM4", "_":"PWM"}}, - - {"dut":{"connector":"breadboard","pin":9, "_":"HIL_A1"}, "hil":{"device":"MilPcbTester", "port":"A1", "_":"DI/DO/AI"}}, - {"dut":{"connector":"breadboard","pin":10, "_":"HIL_A2"}, "hil":{"device":"MilPcbTester", "port":"A2", "_":"DI/DO/AI"}}, - {"dut":{"connector":"breadboard","pin":11, "_":"HIL_A3"}, "hil":{"device":"MilPcbTester", "port":"A3", "_":"DI/DO/AI"}}, - {"dut":{"connector":"breadboard","pin":12, "_":"HIL_A4"}, "hil":{"device":"MilPcbTester", "port":"A4", "_":"DI/DO/AI"}}, - - {"dut":{"connector":"breadboard","pin":13, "_":"HIL_RLY1"}, "hil":{"device":"MilPcbTester", "port":"RLY1", "_":"DO"}}, - {"dut":{"connector":"breadboard","pin":14, "_":"HIL_RLY2"}, "hil":{"device":"MilPcbTester", "port":"RLY2", "_":"DO"}}, - {"dut":{"connector":"breadboard","pin":15, "_":"HIL_RLY3"}, "hil":{"device":"MilPcbTester", "port":"RLY3", "_":"DO"}}, - {"dut":{"connector":"breadboard","pin":16, "_":"HIL_RLY4"}, "hil":{"device":"MilPcbTester", "port":"RLY4", "_":"DO"}}, - - {"dut":{"connector":"breadboard","pin":17, "_":"HIL_D2"}, "hil":{"device":"MilPcbTester", "port":"D2", "_":"DI"}}, - {"dut":{"connector":"breadboard","pin":18, "_":"HIL_D3"}, "hil":{"device":"MilPcbTester", "port":"D3", "_":"DI"}}, - {"dut":{"connector":"breadboard","pin":19, "_":"HIL_D4"}, "hil":{"device":"MilPcbTester", "port":"D4", "_":"DI"}}, - {"dut":{"connector":"breadboard","pin":20, "_":"HIL_D5"}, "hil":{"device":"MilPcbTester", "port":"D5", "_":"DI"}}, - {"dut":{"connector":"breadboard","pin":21, "_":"HIL_D6"}, "hil":{"device":"MilPcbTester", "port":"D6", "_":"DI"}}, - {"dut":{"connector":"breadboard","pin":22, "_":"HIL_D7"}, "hil":{"device":"MilPcbTester", "port":"D7", "_":"DI"}}, - {"dut":{"connector":"breadboard","pin":23, "_":"HIL_D8"}, "hil":{"device":"MilPcbTester", "port":"D8", "_":"DI"}}, - - {"dut":{"connector":"breadboard","pin":24, "_":"HIL_DAC1"}, "hil":{"device":"MilPcbTester", "port":"DAC1", "_":"AO"}}, - {"dut":{"connector":"breadboard","pin":25, "_":"HIL_DAC2"}, "hil":{"device":"MilPcbTester", "port":"DAC2", "_":"AO"}} - ]} - ], - "hil_devices":[ - {"name":"MilPcbTester", "type":"arduino_mil_pcb", "id":1} - ] -} diff --git a/hil/hil_devices/hil_device_arduino_mil_pcb.json b/hil/hil_devices/hil_device_arduino_mil_pcb.json deleted file mode 100644 index 5c586d3..0000000 --- a/hil/hil_devices/hil_device_arduino_mil_pcb.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "communication_mode":"serial", - "ports":[ - {"port":18, "name":"A1", "capabilities":["DO", "AI"], "notes":"5V dig / analog in"}, - {"port":19, "name":"A2", "capabilities":["DO", "AI"], "notes":"5V dig / analog in"}, - {"port":20, "name":"A3", "capabilities":["DO", "AI"], "notes":"5V dig / analog in"}, - {"port":21, "name":"A4", "capabilities":["DO", "AI"], "notes":"5V dig / analog in"}, - - {"port":2, "name":"D1", "capabilities":[], "notes":"SDA (5V dig in)"}, - {"port":4, "name":"D2", "capabilities":[], "notes":"(5V dig in)"}, - {"port":16, "name":"D3", "capabilities":["DI"], "notes":"5V dig in (COPI/MISO)"}, - {"port":14, "name":"D4", "capabilities":["DI"], "notes":"5V dig in (COPI/MOSI)"}, - {"port":15, "name":"D5", "capabilities":["DI"], "notes":"5V dig in (SCK)"}, - {"port":8, "name":"D6", "capabilities":["DI"], "notes":"5V dig in"}, - {"port":4, "name":"D7", "capabilities":["DI"], "notes":"5V dig in"}, - {"port":0, "name":"D8", "capabilities":[], "notes":"RX"}, - - {"port":3, "name":"PWM1", "capabilities":["PWM"], "notes":"5V 8-bit PWM -> RC"}, - {"port":5, "name":"PWM2", "capabilities":["PWM"], "notes":"5V 8-bit PWM -> RC"}, - {"port":6, "name":"PWM3", "capabilities":["PWM"], "notes":"5V 8-bit PWM -> RC"}, - {"port":9, "name":"PWM4", "capabilities":["PWM"], "notes":"5V 8-bit PWM -> RC"}, - - {"port":10, "name":"RLY1", "capabilities":["DO"], "notes":"relay"}, - {"port":11, "name":"RLY2", "capabilities":["DO"], "notes":"relay"}, - {"port":13, "name":"RLY3", "capabilities":["DO"], "notes":"relay"}, - {"port":12, "name":"RLY4", "capabilities":["DO"], "notes":"relay"}, - - {"port":1, "name":"POT1", "capabilities":["POT"], "notes":"6-bit Digipot"}, - {"port":2, "name":"POT2", "capabilities":["POT"], "notes":"6-bit Digipot"}, - - {"port":9, "name":"3v3ref", "capabilities":["AI"], "notes":"3V3 input reference"}, - - {"port":200, "name":"DAC1", "capabilities":["AO"], "notes":"5V 12-bit DAC"}, - {"port":201, "name":"DAC2", "capabilities":["AO"], "notes":"5V 12-bit DAC"} - ], - "adc_config":{"bit_resolution":10, "reference_v":5.0}, - "dac_config":{"bit_resolution":12, "reference_v":5.0}, - "pot_config":{"bit_resolution":6}, - "calibrate_rail":false -} \ No newline at end of file diff --git a/net_maps/mil_pcb_net_map.csv b/net_maps/mil_pcb_net_map.csv deleted file mode 100644 index 48ff349..0000000 --- a/net_maps/mil_pcb_net_map.csv +++ /dev/null @@ -1,27 +0,0 @@ -Board,Net,Component,Designator,Connector Name,, - -Millan,HIL_PWM1,breadboard,5,FRED,, -Millan,HIL_PWM2,breadboard,6,FRED,, -Millan,HIL_PWM3,breadboard,7,FRED,, -Millan,HIL_PWM4,breadboard,8,FRED,, - -Millan,HIL_A1,breadboard,9,FRED,, -Millan,HIL_A2,breadboard,10,FRED,, -Millan,HIL_A3,breadboard,11,FRED,, -Millan,HIL_A4,breadboard,12,FRED,, - -Millan,HIL_RLY1,breadboard,13,FRED,, -Millan,HIL_RLY2,breadboard,14,FRED,, -Millan,HIL_RLY3,breadboard,15,FRED,, -Millan,HIL_RLY4,breadboard,16,FRED,, - -Millan,HIL_D2,breadboard,17,FRED,, -Millan,HIL_D3,breadboard,18,FRED,, -Millan,HIL_D4,breadboard,19,FRED,, -Millan,HIL_D5,breadboard,20,FRED,, -Millan,HIL_D6,breadboard,21,FRED,, -Millan,HIL_D7,breadboard,22,FRED,, -Millan,HIL_D8,breadboard,23,FRED,, - -Millan,HIL_DAC1,breadboard,24,FRED,, -Millan,HIL_DAC2,breadboard,25,FRED,, \ No newline at end of file From 12617d35827d8c52b78764634b7bb2caefcf00eb Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Wed, 22 Jan 2025 21:49:21 -0500 Subject: [PATCH 176/181] Removing collector plate tests from the PR --- configurations/config_mil_col.json | 15 ------- net_maps/mil_col_net_map.csv | 34 -------------- scripts/test_mil_col.py | 71 ------------------------------ 3 files changed, 120 deletions(-) delete mode 100644 configurations/config_mil_col.json delete mode 100644 net_maps/mil_col_net_map.csv delete mode 100644 scripts/test_mil_col.py diff --git a/configurations/config_mil_col.json b/configurations/config_mil_col.json deleted file mode 100644 index 42815b7..0000000 --- a/configurations/config_mil_col.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "./config_schema.json", - "dut_connections":[ - {"board":"Collector", "harness_connections":[ - {"dut":{"connector":"J4","pin":2,"_":"MUX_A"}, "hil":{"device":"MilColTester", "port":"A1", "_":"DO"}}, - {"dut":{"connector":"J4","pin":1,"_":"MUX_B"}, "hil":{"device":"MilColTester", "port":"A2", "_":"DO"}}, - {"dut":{"connector":"J4","pin":4,"_":"MUX_C"}, "hil":{"device":"MilColTester", "port":"A3", "_":"DO"}}, - {"dut":{"connector":"J4","pin":7,"_":"MUX_D"}, "hil":{"device":"MilColTester", "port":"RLY1", "_":"DO"}}, - {"dut":{"connector":"J4","pin":5,"_":"TEMP_OUT"}, "hil":{"device":"MilColTester", "port":"A4", "_":"AI"}} - ]} - ], - "hil_devices":[ - {"name":"MilColTester", "type":"arduino_mil_pcb", "id":1} - ] -} diff --git a/net_maps/mil_col_net_map.csv b/net_maps/mil_col_net_map.csv deleted file mode 100644 index 7420532..0000000 --- a/net_maps/mil_col_net_map.csv +++ /dev/null @@ -1,34 +0,0 @@ -Board,Net,Component,Designator,Connector Name,, -Collector,MUX_A,J4,2,ABOX,, -Collector,MUX_B,J4,1,ABOX,, -Collector,MUX_C,J4,4,ABOX,, -Collector,MUX_D,J4,7,ABOX,, -Collector,TEMP_OUT,J4,5,ABOX,, - -Collector,GND_I,J4,3,ABOX,, - -Collector,3V3,J4,8,ABOX,, -Collector,CELL_0,J3,1,ORION,, -Collector,CELL_2,J3,2,ORION,, -Collector,CELL_4,J3,3,ORION,, -Collector,CELL_6,J3,4,ORION,, -Collector,CELL_8,J3,5,ORION,, -Collector,CELL_10,J3,6,ORION,, -Collector,CELL_12,J3,7,ORION,, -Collector,CELL_13,J3,8,ORION,, -Collector,CELL_15,J3,9,ORION,, -Collector,CELL_17,J3,10,ORION,, -Collector,CELL_19,J3,11,ORION,, -Collector,CELL_19,J3,12,ORION,, -Collector,CELL_1,J3,13,ORION,, -Collector,CELL_3,J3,14,ORION,, -Collector,CELL_5,J3,15,ORION,, -Collector,CELL_7,J3,16,ORION,, -Collector,CELL_9,J3,17,ORION,, -Collector,CELL_11,J3,18,ORION,, -Collector,CELL_12,J3,19,ORION,, -Collector,CELL_14,J3,20,ORION,, -Collector,CELL_16,J3,21,ORION,, -Collector,CELL_18,J3,22,ORION,, -Collector,CELL_19,J3,23,ORION,, -Collector,CELL_19,J3,24,ORION,, diff --git a/scripts/test_mil_col.py b/scripts/test_mil_col.py deleted file mode 100644 index c2f9473..0000000 --- a/scripts/test_mil_col.py +++ /dev/null @@ -1,71 +0,0 @@ -from os import sys, path -# adds "./HIL-Testing" to the path, basically making it so these scripts were run one folder level higher -sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) - -from hil.hil import HIL -import hil.utils as utils -import time - - -# ---------------------------------------------------------------------------- # -def test_collector(hil: HIL): - mux_a = hil.dout("Collector", "MUX_A") # A1 - mux_b = hil.dout("Collector", "MUX_B") # A2 - mux_d = hil.dout("Collector", "MUX_C") # A3 - - mux_c = hil.dout("Collector", "MUX_D") # RLY1: have to wire: 5V -> RLY1 -> MUX_D - mux_c.state = 1 # turn on relay (it is inverted) - - temp_out = hil.ain("Collector", "TEMP_OUT") # A4 - - tolerance_v = 0.1 # volts - current_res = 9100.0 # ohms - pullup_res = 4700.0 # ohms - # test_voltage = 3.3 # volts - pullup_voltage = 5 # volts - num_therm = 10 - - test_voltage = (pullup_voltage / (current_res + pullup_res)) * current_res - utils.log_warning(f"Test voltage: {test_voltage}") - - - for thermistor in range(num_therm): - print(f"\nPlace test input on thermistor {thermistor}.") - input("Press Enter when ready...") - - for i in range(num_therm): - # MUX (multiplexer) = choose which output to return from the thermistor based on the input - # Like a giant switch statement (0 -> return thermistor 0, 1 -> return thermistor 1, etc.) - # Encode the current thermistor into binary where each bit corresponds to each pin being high or low - mux_a.state = i & 0x1 - mux_b.state = i & 0x2 - mux_c.state = not (i & 0x4) # relay is inverted - mux_d.state = i & 0x8 - - # Wait for relay - time.sleep(0.1) - - temp_out_state = temp_out.state - if i == thermistor: expected_voltage = test_voltage - else: expected_voltage = pullup_voltage - within = abs(temp_out_state - expected_voltage) < tolerance_v - - if within: within_text = utils.bcolors.OKGREEN + "PASS" + utils.bcolors.ENDC - else: within_text = utils.bcolors.FAIL + "FAIL" + utils.bcolors.ENDC - - if i == thermistor: print("- ", end="") - - print(f"({thermistor=}, {i=}) temp_out_state={temp_out_state:.1f} ?= expected_voltage={expected_voltage:.1f} -> {within_text}") -# ---------------------------------------------------------------------------- # - - -# ---------------------------------------------------------------------------- # -if __name__ == "__main__": - hil = HIL() - - hil.load_config("config_mil_col.json") - hil.load_pin_map("mil_col_net_map.csv", "stm32f407_pin_map.csv") - - test_collector(hil) - - hil.shutdown() \ No newline at end of file From f546efe6286cb4d585843740dbfe4726de8bbac6 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Thu, 23 Jan 2025 21:17:54 -0500 Subject: [PATCH 177/181] char != uint8_t --- TestBench/TestBench.ino | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/TestBench/TestBench.ino b/TestBench/TestBench.ino index 27acb6f..a0a80c1 100644 --- a/TestBench/TestBench.ino +++ b/TestBench/TestBench.ino @@ -48,7 +48,7 @@ enum GpioCommand { WRITE_POT = 5, }; -int CHARS_TO_READ[] = { +int TO_READ[] = { // Parrallel to GpioCommand 2, // READ_ADC - command, pin 2, // READ_GPIO - command, pin 4, // WRITE_DAC - command, pin, value (2 bytes) @@ -57,8 +57,8 @@ int CHARS_TO_READ[] = { 3, // WRITE_POT - command, pin, value }; -// 4: max CHARS_TO_READ -char data[4] = {-1, -1, -1, -1}; +// 4 = max(TO_READ) +uint8_t data[4] = {-1, -1, -1, -1}; int data_index = 0; bool data_ready = false; @@ -185,8 +185,8 @@ void loop() { data[data_index] = SERIAL.read(); data_index++; - char command = data[0]; - if (data_index == CHARS_TO_READ[command]) { + uint8_t command = data[0]; + if (data_index == TO_READ[command]) { data_ready = true; } } From 928237993f4058a316bfd51b5b1d1c44598752d8 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 25 Jan 2025 11:19:42 -0500 Subject: [PATCH 178/181] Deleting todo --- hil/hil.py | 1 - 1 file changed, 1 deletion(-) diff --git a/hil/hil.py b/hil/hil.py index fefd45c..9dc0d9b 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -177,7 +177,6 @@ def daq_var(self, board: str, var_name: str) -> DAQVariable: self.handle_error(f"Unable to locate DAQ variable {var_name} of {board}") def can_var(self, board: str, message_name: str, signal_name: str) -> BusSignal: - # TODO: not sure if any of the type hints are correct try: return utils.signals[utils.b_str][board][message_name][signal_name] except KeyError: From 34e3f9944fdcedd244d40756cc996fb762cdaff3 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 25 Jan 2025 11:19:59 -0500 Subject: [PATCH 179/181] Removing unused variable --- hil/hil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hil/hil.py b/hil/hil.py index 9dc0d9b..5214331 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -173,7 +173,7 @@ def pot(self, board: str, net: str) -> Component: def daq_var(self, board: str, var_name: str) -> DAQVariable: try: return utils.signals[utils.b_str][board][f"daq_response_{board.upper()}"][var_name] - except KeyError as e: + except KeyError: self.handle_error(f"Unable to locate DAQ variable {var_name} of {board}") def can_var(self, board: str, message_name: str, signal_name: str) -> BusSignal: From 663499258b8bc0ee11e97c4d9a7285cbfa8cd9e6 Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 25 Jan 2025 11:21:26 -0500 Subject: [PATCH 180/181] Adding comment --- hil/hil.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hil/hil.py b/hil/hil.py index 5214331..cc0b735 100644 --- a/hil/hil.py +++ b/hil/hil.py @@ -200,6 +200,8 @@ def signal_int_handler(signum: int, frame: FrameType) -> None: utils.hilProt.shutdown() sys.exit(0) + +# Old testing code. When run directly (python hil.py), this code will run. # if __name__ == "__main__": # hil = HIL() # hil.load_config("config_test.json") From d361046faf886a524ae6b6dddba70fff72a1910a Mon Sep 17 00:00:00 2001 From: Millan Kumar Date: Sat, 25 Jan 2025 11:23:07 -0500 Subject: [PATCH 181/181] Removing if (1) --- TestBench/TestBench.ino | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/TestBench/TestBench.ino b/TestBench/TestBench.ino index a0a80c1..c103572 100644 --- a/TestBench/TestBench.ino +++ b/TestBench/TestBench.ino @@ -151,13 +151,8 @@ void loop() { case GpioCommand::WRITE_GPIO: { int pin = data[1]; int value = data[2]; - // if (pin < DIGITAL_PIN_COUNT) - if (1) { - pinMode(pin, OUTPUT); - digitalWrite(pin, value); - } else { - error("GPIO PIN COUNT EXCEEDED"); - } + pinMode(pin, OUTPUT); + digitalWrite(pin, value); break; } case GpioCommand::READ_ID: {