hitl_tester.test_cases.bms.test_current_calibration
| Test | Current Calibration |
|---|---|
| GitHub Issue(s) | turnaroundfactor/HITL#367 |
| Description | Calibrate a unique BMS current with SMBus commands. |
Used in these test plans:
- calibrate_current ⠀⠀⠀(bms/calibrate_current.plan)
Example Command (warning: test plan may run other test cases):
./hitl_tester.py calibrate_current -DCELL_SOC_PERCENT=0.5 -DBMS_TEMPERATURE_C=23 -DCURRENT_OFFSET=None
1""" 2| Test | Current Calibration | 3| :------------------- | :-------------------------------------------------- | 4| GitHub Issue(s) | turnaroundfactor/HITL#367 | 5| Description | Calibrate a unique BMS current with SMBus commands. | 6""" 7 8from __future__ import annotations 9 10import ctypes 11import time 12 13import pytest 14 15from hitl_tester.modules.bms.bms_hw import BMSHardware 16from hitl_tester.modules.bms.plateset import Plateset 17from hitl_tester.modules.bms.smbus import SMBus 18from hitl_tester.modules.bms.smbus_types import BMSCommands, SMBusReg 19from hitl_tester.modules.logger import logger 20 21CELL_SOC_PERCENT = 0.50 22"""The cell sim SOC.""" 23 24BMS_TEMPERATURE_C = 23 25"""Simulated temperature.""" 26 27CURRENT_OFFSET: int | None = None 28"""The calibration value to upload.""" 29 30_bms = BMSHardware(pytest.flags) # type: ignore[arg-type] 31_bms.init() 32_plateset = Plateset() 33_smbus = SMBus() 34 35 36def bms_current(): 37 """Measure serial current and calculate an average.""" 38 new_reading = _bms.csv.cycle.last_serial_data["mamps"] 39 40 try: 41 bms_current.average = (new_reading + bms_current.readings * bms_current.average) / (bms_current.readings + 1) 42 bms_current.readings += 1 43 except AttributeError: 44 bms_current.average = new_reading 45 bms_current.readings = 1 46 47 logger.write_info_to_report(f"BMS Serial Current (mA): {new_reading}") # Output current on every sample 48 49 50@pytest.fixture(scope="function", autouse=True) 51def reset_test_environment(): 52 """Before each test, reset cell sims / BMS and set appropriate temperatures.""" 53 54 # Reset cell sims 55 if len(_bms.cells) > 0: 56 logger.write_info_to_report(f"Setting temperature to {BMS_TEMPERATURE_C}°C") 57 _plateset.thermistor1 = _plateset.thermistor2 = BMS_TEMPERATURE_C 58 logger.write_info_to_report("Powering down cell sims") 59 for cell in _bms.cells.values(): 60 cell.disengage_safety_protocols = True 61 cell.volts = 0.0001 62 time.sleep(5) 63 for cell in _bms.cells.values(): 64 logger.write_info_to_report(f"Powering up cell sim {cell.id} to {CELL_SOC_PERCENT:%}") 65 cell.state_of_charge = CELL_SOC_PERCENT 66 cell.disengage_safety_protocols = False 67 68 # Wait after powering on 69 if len(_bms.cells) > 0: 70 logger.write_info_to_report("Sleeping for 10 seconds before starting...") 71 time.sleep(10) 72 73 old_cycle_function = _bms.csv.cycle # Save logging function 74 _bms.csv.cycle = _bms.csv.cycle_smbus # Record serial and SMBus 75 _bms.csv.cycle.postfix_fn = bms_current # Get current on each sample 76 77 yield # Run test 78 79 _bms.csv.cycle = old_cycle_function 80 81 82def standard_rest(seconds: float = 2 * 3600, sample_interval: int = 10): 83 """Helper function to stabilize the batteries for 2+ hours.""" 84 _bms.max_time = seconds 85 _bms.sample_interval = sample_interval 86 _bms.run_resting_cycle() 87 88 89def test_calibrate(): 90 """ 91 | Requirement | Write calibration current to BMS | 92 | :------------------- | :-------------------------------------------------------------------------- | 93 | GitHub Issue | turnaroundfactor/HITL#367 | 94 | Instructions | 1. Measure average current while resting </br>\ 95 2. Write this value to the manufacturing register via the CALIBRATE command | 96 | Pass / Fail Criteria | Current reads 0mA at rest | 97 | Estimated Duration | 2 minutes | 98 """ 99 acceptable_error_ma = 5 100 101 # Measure and apply offset 102 standard_rest(30, 5) 103 offset = int(round(bms_current.average if CURRENT_OFFSET is None else CURRENT_OFFSET, 0)) 104 logger.write_info_to_report(f"Setting offset current to {offset} mA") 105 data = (ctypes.c_uint8(offset).value << 8) | BMSCommands.CALIBRATE 106 _smbus.write_register(SMBusReg.MANUFACTURING_ACCESS, data) 107 108 data = _smbus.read_register(SMBusReg.MANUFACTURING_ACCESS)[0] 109 logger.write_info_to_report(f"{SMBusReg.MANUFACTURING_ACCESS.fname}: {data:04X}") 110 111 # Confirm current is in acceptable range 112 bms_current.readings = 0 # Reset average 113 standard_rest(30, 5) 114 assert acceptable_error_ma > bms_current.average > -acceptable_error_ma
CELL_SOC_PERCENT =
0.5
The cell sim SOC.
BMS_TEMPERATURE_C =
23
Simulated temperature.
CURRENT_OFFSET: int | None =
None
The calibration value to upload.
def
bms_current():
37def bms_current(): 38 """Measure serial current and calculate an average.""" 39 new_reading = _bms.csv.cycle.last_serial_data["mamps"] 40 41 try: 42 bms_current.average = (new_reading + bms_current.readings * bms_current.average) / (bms_current.readings + 1) 43 bms_current.readings += 1 44 except AttributeError: 45 bms_current.average = new_reading 46 bms_current.readings = 1 47 48 logger.write_info_to_report(f"BMS Serial Current (mA): {new_reading}") # Output current on every sample
Measure serial current and calculate an average.
@pytest.fixture(scope='function', autouse=True)
def
reset_test_environment():
51@pytest.fixture(scope="function", autouse=True) 52def reset_test_environment(): 53 """Before each test, reset cell sims / BMS and set appropriate temperatures.""" 54 55 # Reset cell sims 56 if len(_bms.cells) > 0: 57 logger.write_info_to_report(f"Setting temperature to {BMS_TEMPERATURE_C}°C") 58 _plateset.thermistor1 = _plateset.thermistor2 = BMS_TEMPERATURE_C 59 logger.write_info_to_report("Powering down cell sims") 60 for cell in _bms.cells.values(): 61 cell.disengage_safety_protocols = True 62 cell.volts = 0.0001 63 time.sleep(5) 64 for cell in _bms.cells.values(): 65 logger.write_info_to_report(f"Powering up cell sim {cell.id} to {CELL_SOC_PERCENT:%}") 66 cell.state_of_charge = CELL_SOC_PERCENT 67 cell.disengage_safety_protocols = False 68 69 # Wait after powering on 70 if len(_bms.cells) > 0: 71 logger.write_info_to_report("Sleeping for 10 seconds before starting...") 72 time.sleep(10) 73 74 old_cycle_function = _bms.csv.cycle # Save logging function 75 _bms.csv.cycle = _bms.csv.cycle_smbus # Record serial and SMBus 76 _bms.csv.cycle.postfix_fn = bms_current # Get current on each sample 77 78 yield # Run test 79 80 _bms.csv.cycle = old_cycle_function
Before each test, reset cell sims / BMS and set appropriate temperatures.
def
standard_rest(seconds: float = 7200, sample_interval: int = 10):
83def standard_rest(seconds: float = 2 * 3600, sample_interval: int = 10): 84 """Helper function to stabilize the batteries for 2+ hours.""" 85 _bms.max_time = seconds 86 _bms.sample_interval = sample_interval 87 _bms.run_resting_cycle()
Helper function to stabilize the batteries for 2+ hours.
def
test_calibrate():
90def test_calibrate(): 91 """ 92 | Requirement | Write calibration current to BMS | 93 | :------------------- | :-------------------------------------------------------------------------- | 94 | GitHub Issue | turnaroundfactor/HITL#367 | 95 | Instructions | 1. Measure average current while resting </br>\ 96 2. Write this value to the manufacturing register via the CALIBRATE command | 97 | Pass / Fail Criteria | Current reads 0mA at rest | 98 | Estimated Duration | 2 minutes | 99 """ 100 acceptable_error_ma = 5 101 102 # Measure and apply offset 103 standard_rest(30, 5) 104 offset = int(round(bms_current.average if CURRENT_OFFSET is None else CURRENT_OFFSET, 0)) 105 logger.write_info_to_report(f"Setting offset current to {offset} mA") 106 data = (ctypes.c_uint8(offset).value << 8) | BMSCommands.CALIBRATE 107 _smbus.write_register(SMBusReg.MANUFACTURING_ACCESS, data) 108 109 data = _smbus.read_register(SMBusReg.MANUFACTURING_ACCESS)[0] 110 logger.write_info_to_report(f"{SMBusReg.MANUFACTURING_ACCESS.fname}: {data:04X}") 111 112 # Confirm current is in acceptable range 113 bms_current.readings = 0 # Reset average 114 standard_rest(30, 5) 115 assert acceptable_error_ma > bms_current.average > -acceptable_error_ma
| Requirement | Write calibration current to BMS |
|---|---|
| GitHub Issue | turnaroundfactor/HITL#367 |
| Instructions | 1. Measure average current while resting 2. Write this value to the manufacturing register via the CALIBRATE command |
| Pass / Fail Criteria | Current reads 0mA at rest |
| Estimated Duration | 2 minutes |