hitl_tester.test_cases.bms.battery_tester
A duplicate of the older battery tester program.
For example, to charge 17 cells at 700mA for 14 hours, rest for 10 seconds, constant resistance discharge at 17V, 17Ω
./hitl_tester.py battery_tester -c DEBUG -DCHARGE_TYPE=custom -DCHARGE_RATE=700 -DCHARGE_TIME=50400 -DCELL_COUNT=17 -DDISCHARGE_VOLTAGE=17 -DDISCHARGE_RESISTANCE=17 -DRESTING_TIME=10
Used in these test plans:
- battery_tester_pack ⠀⠀⠀(bms/battery_tester_pack.plan)
- battery_tester ⠀⠀⠀(bms/battery_tester.plan)
Example Command (warning: test plan may run other test cases):
./hitl_tester.py battery_tester_pack -DSAMPLE_RATE=10 -DCELL_COUNT=None -DCAPACITY=None -DCHARGE_TYPE=UNDEFINED -DCHARGE_RATE=None -DCHARGE_TIME=None -DDISCHARGE_CURRENT=None -DDISCHARGE_RESISTANCE=None -DDISCHARGE_CURRENT_LIMIT=10 -DDISCHARGE_VOLTAGE=None -DRESTING_TIME=None
1""" 2A duplicate of the older battery tester program. 3 4For example, to charge 17 cells at 700mA for 14 hours, rest for 10 seconds, constant resistance discharge at 17V, 17Ω 5 - `./hitl_tester.py battery_tester -c DEBUG -DCHARGE_TYPE=custom -DCHARGE_RATE=700 -DCHARGE_TIME=50400 6-DCELL_COUNT=17 -DDISCHARGE_VOLTAGE=17 -DDISCHARGE_RESISTANCE=17 -DRESTING_TIME=10` 7""" 8 9from __future__ import annotations 10 11import pytest 12from colorama import Fore 13 14from hitl_tester.modules.bms.bms_hw import BMSHardware 15from hitl_tester.modules.bms_types import NiCdChargeCycle, DischargeType 16from hitl_tester.modules.file_lock import FileLock 17from hitl_tester.modules.logger import logger 18from hitl_tester.modules.bms.plateset import Plateset 19 20SAMPLE_RATE = 10 21"""How often to log data in seconds.""" 22CELL_COUNT: int | None = None 23"""How many cells are attached.""" 24CAPACITY: float | None = None 25"""Battery Capacity in mAh.""" 26 27CHARGE_TYPE: NiCdChargeCycle | str = "UNDEFINED" 28""" 29The charge profile 30- Standard: 0.1C for 16 hours 31- DV_DT: 0.5C for 2.5 hours 32- Custom: Current and time are defined separately by the user with CHARGE_RATE and CHARGE_TIME 33""" 34CHARGE_RATE: float | None = None 35"""Charge current in mAh. **Optional:** only needed for custom charge type.""" 36CHARGE_TIME: float | None = None 37"""How long to charge in seconds. **Optional:** only needed for custom charge type.""" 38 39DISCHARGE_CURRENT: float | None = None 40"""Current for discharge. **Optional:** only needed for constant current discharge.""" 41DISCHARGE_RESISTANCE: float | None = None 42"""Resistance for discharge. **Optional:** only needed for constant resistance discharge.""" 43DISCHARGE_CURRENT_LIMIT: float = 10 44"""Current limit for discharge. **Optional:** only needed for constant resistance discharge.""" 45DISCHARGE_VOLTAGE: float | None = None 46"""The discharge voltage in volts.""" 47 48RESTING_TIME: float | None = None 49"""How long to rest before discharging in seconds.""" 50 51bms_hardware = BMSHardware(pytest.flags) # type: ignore[arg-type] 52"""@private""" 53bms_hardware.init() 54plateset = Plateset() 55"""@private""" 56test_status_lock = FileLock("test_alive") 57"""Tell other processes if this test is running or not""" 58 59 60def test_nicd(): 61 """ 62 This test is ported from the older battery tester program. 63 It performs a charge, rest, and discharge, then rests for 100 years. 64 """ 65 global CHARGE_TYPE, CHARGE_RATE, CHARGE_TIME, DISCHARGE_CURRENT 66 67 test_status_lock.acquire() 68 69 if isinstance(CHARGE_TYPE, str): 70 CHARGE_TYPE = NiCdChargeCycle[CHARGE_TYPE.upper()] 71 if CHARGE_TYPE is NiCdChargeCycle.CUSTOM and (CHARGE_RATE is None or CHARGE_TIME is None): 72 raise RuntimeError('CHARGE_TYPE "Custom" requires CHARGE_RATE and CHARGE_TIME to be defined.') 73 74 if CHARGE_TYPE is NiCdChargeCycle.STANDARD: 75 CHARGE_RATE = CAPACITY / 10000 # 0.1C 76 CHARGE_TIME = 57600 # 16 hours 77 elif CHARGE_TYPE is NiCdChargeCycle.CUSTOM: 78 CHARGE_RATE = CHARGE_RATE / 1000 79 elif CHARGE_TYPE is NiCdChargeCycle.DV_DT: 80 CHARGE_RATE = CAPACITY / 1000 / 2 # C/2 charge rate 81 CHARGE_TIME = 3600 * 2.5 # 2.5 hour charging timeout 82 elif CHARGE_TYPE is NiCdChargeCycle.UNDEFINED: 83 raise RuntimeError("Charge type was undefined.") 84 85 if DISCHARGE_CURRENT is not None: 86 DISCHARGE_CURRENT = DISCHARGE_CURRENT / 1000 87 bms_hardware.discharge_type = DischargeType.CONSTANT_CURRENT 88 elif DISCHARGE_RESISTANCE is not None: 89 bms_hardware.discharge_type = DischargeType.CONSTANT_RESISTANCE 90 else: 91 raise RuntimeError("No discharge current/resistance provided.") 92 93 logger.write_info_to_report(f"Mode set to: {bms_hardware.discharge_type.name}") 94 logger.write_info_to_report("") 95 logger.write_info_to_report(f"{Fore.GREEN}Starting NiCd Charge Cycle...") 96 logger.write_info_to_report("") 97 bms_hardware.nicd_cell_count = CELL_COUNT 98 bms_hardware.current = CHARGE_RATE 99 bms_hardware.max_time = CHARGE_TIME 100 bms_hardware.sample_interval = SAMPLE_RATE 101 bms_hardware.nicd_charge_type = CHARGE_TYPE 102 charge_ah = bms_hardware.run_nicd_charge_cycle() 103 logger.write_info_to_report(f"{Fore.GREEN}Charge Added: {charge_ah} Ah") 104 logger.write_info_to_report("") 105 logger.write_info_to_report(f"{Fore.GREEN}Resting before discharge cycle...") 106 logger.write_info_to_report("") 107 bms_hardware.max_time = RESTING_TIME 108 bms_hardware.sample_interval = SAMPLE_RATE 109 bms_hardware.run_resting_cycle() 110 logger.write_info_to_report("") 111 logger.write_info_to_report(f"{Fore.GREEN}Starting Discharge Cycle...") 112 logger.write_info_to_report("") 113 114 bms_hardware.max_time = 86400 # 24 hours 115 bms_hardware.voltage = DISCHARGE_VOLTAGE 116 bms_hardware.current = DISCHARGE_CURRENT 117 bms_hardware.current_limit = DISCHARGE_CURRENT_LIMIT 118 bms_hardware.resistance = DISCHARGE_RESISTANCE 119 bms_hardware.uv_protection = max(bms_hardware.voltage - 1, 0.001) 120 bms_hardware.sample_interval = SAMPLE_RATE 121 discharge_ah = -1 * bms_hardware.run_discharge_cycle() 122 logger.write_info_to_report(f"{Fore.GREEN}Charge Removed: {discharge_ah} Ah") 123 logger.write_info_to_report("") 124 logger.write_info_to_report("-------------------------------------------------------------") 125 logger.write_info_to_report("") 126 logger.write_info_to_report(f"{Fore.GREEN}Test Completed!") 127 logger.write_info_to_report("") 128 logger.write_info_to_report(f"Charge Added to Battery: {charge_ah} Ah") 129 logger.write_info_to_report(f"Charge Removed from Battery: {discharge_ah} Ah") 130 logger.write_info_to_report("") 131 logger.write_info_to_report("Running infinite rest cycle!") 132 bms_hardware.max_time = 3156000000 # Rest for 100 years 133 bms_hardware.sample_interval = SAMPLE_RATE 134 bms_hardware.run_resting_cycle()
How often to log data in seconds.
How many cells are attached.
Battery Capacity in mAh.
The charge profile
- Standard: 0.1C for 16 hours
- DV_DT: 0.5C for 2.5 hours
- Custom: Current and time are defined separately by the user with CHARGE_RATE and CHARGE_TIME
Charge current in mAh. Optional: only needed for custom charge type.
How long to charge in seconds. Optional: only needed for custom charge type.
Current for discharge. Optional: only needed for constant current discharge.
Resistance for discharge. Optional: only needed for constant resistance discharge.
Current limit for discharge. Optional: only needed for constant resistance discharge.
The discharge voltage in volts.
How long to rest before discharging in seconds.
Tell other processes if this test is running or not
61def test_nicd(): 62 """ 63 This test is ported from the older battery tester program. 64 It performs a charge, rest, and discharge, then rests for 100 years. 65 """ 66 global CHARGE_TYPE, CHARGE_RATE, CHARGE_TIME, DISCHARGE_CURRENT 67 68 test_status_lock.acquire() 69 70 if isinstance(CHARGE_TYPE, str): 71 CHARGE_TYPE = NiCdChargeCycle[CHARGE_TYPE.upper()] 72 if CHARGE_TYPE is NiCdChargeCycle.CUSTOM and (CHARGE_RATE is None or CHARGE_TIME is None): 73 raise RuntimeError('CHARGE_TYPE "Custom" requires CHARGE_RATE and CHARGE_TIME to be defined.') 74 75 if CHARGE_TYPE is NiCdChargeCycle.STANDARD: 76 CHARGE_RATE = CAPACITY / 10000 # 0.1C 77 CHARGE_TIME = 57600 # 16 hours 78 elif CHARGE_TYPE is NiCdChargeCycle.CUSTOM: 79 CHARGE_RATE = CHARGE_RATE / 1000 80 elif CHARGE_TYPE is NiCdChargeCycle.DV_DT: 81 CHARGE_RATE = CAPACITY / 1000 / 2 # C/2 charge rate 82 CHARGE_TIME = 3600 * 2.5 # 2.5 hour charging timeout 83 elif CHARGE_TYPE is NiCdChargeCycle.UNDEFINED: 84 raise RuntimeError("Charge type was undefined.") 85 86 if DISCHARGE_CURRENT is not None: 87 DISCHARGE_CURRENT = DISCHARGE_CURRENT / 1000 88 bms_hardware.discharge_type = DischargeType.CONSTANT_CURRENT 89 elif DISCHARGE_RESISTANCE is not None: 90 bms_hardware.discharge_type = DischargeType.CONSTANT_RESISTANCE 91 else: 92 raise RuntimeError("No discharge current/resistance provided.") 93 94 logger.write_info_to_report(f"Mode set to: {bms_hardware.discharge_type.name}") 95 logger.write_info_to_report("") 96 logger.write_info_to_report(f"{Fore.GREEN}Starting NiCd Charge Cycle...") 97 logger.write_info_to_report("") 98 bms_hardware.nicd_cell_count = CELL_COUNT 99 bms_hardware.current = CHARGE_RATE 100 bms_hardware.max_time = CHARGE_TIME 101 bms_hardware.sample_interval = SAMPLE_RATE 102 bms_hardware.nicd_charge_type = CHARGE_TYPE 103 charge_ah = bms_hardware.run_nicd_charge_cycle() 104 logger.write_info_to_report(f"{Fore.GREEN}Charge Added: {charge_ah} Ah") 105 logger.write_info_to_report("") 106 logger.write_info_to_report(f"{Fore.GREEN}Resting before discharge cycle...") 107 logger.write_info_to_report("") 108 bms_hardware.max_time = RESTING_TIME 109 bms_hardware.sample_interval = SAMPLE_RATE 110 bms_hardware.run_resting_cycle() 111 logger.write_info_to_report("") 112 logger.write_info_to_report(f"{Fore.GREEN}Starting Discharge Cycle...") 113 logger.write_info_to_report("") 114 115 bms_hardware.max_time = 86400 # 24 hours 116 bms_hardware.voltage = DISCHARGE_VOLTAGE 117 bms_hardware.current = DISCHARGE_CURRENT 118 bms_hardware.current_limit = DISCHARGE_CURRENT_LIMIT 119 bms_hardware.resistance = DISCHARGE_RESISTANCE 120 bms_hardware.uv_protection = max(bms_hardware.voltage - 1, 0.001) 121 bms_hardware.sample_interval = SAMPLE_RATE 122 discharge_ah = -1 * bms_hardware.run_discharge_cycle() 123 logger.write_info_to_report(f"{Fore.GREEN}Charge Removed: {discharge_ah} Ah") 124 logger.write_info_to_report("") 125 logger.write_info_to_report("-------------------------------------------------------------") 126 logger.write_info_to_report("") 127 logger.write_info_to_report(f"{Fore.GREEN}Test Completed!") 128 logger.write_info_to_report("") 129 logger.write_info_to_report(f"Charge Added to Battery: {charge_ah} Ah") 130 logger.write_info_to_report(f"Charge Removed from Battery: {discharge_ah} Ah") 131 logger.write_info_to_report("") 132 logger.write_info_to_report("Running infinite rest cycle!") 133 bms_hardware.max_time = 3156000000 # Rest for 100 years 134 bms_hardware.sample_interval = SAMPLE_RATE 135 bms_hardware.run_resting_cycle()
This test is ported from the older battery tester program. It performs a charge, rest, and discharge, then rests for 100 years.