hitl_tester.test_cases.bms.test_lfp_2590

Test LFP testing
GitHub Issue(s) turnaroundfactor/HITL#681
Description Tests to confirm nothing is broken or malfunctioning.

Used in these test plans:

  • lfp ⠀⠀⠀(bms/lfp.plan)

Example Command (warning: test plan may run other test cases):

  • ./hitl_tester.py lfp
  1"""
  2| Test                 | LFP testing                                                  |
  3| :------------------- | :----------------------------------------------------------- |
  4| GitHub Issue(s)      | turnaroundfactor/HITL#681                             |
  5| Description          | Tests to confirm nothing is broken or malfunctioning.        |
  6"""
  7
  8from __future__ import annotations
  9
 10import time
 11
 12import pytest
 13
 14from hitl_tester.modules.bms.adc_plate import ADCPlate
 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 SMBusReg, SMBusError
 19from hitl_tester.modules.logger import logger
 20
 21_bms = BMSHardware(pytest.flags)  # type: ignore[arg-type]
 22_bms.init()
 23_plateset = Plateset()
 24_adc_plate = ADCPlate()
 25_smbus = SMBus()
 26
 27
 28def test_discharge():
 29    """
 30    | Description          | Confirm discharging works as normal                                    |
 31    | :------------------- | :--------------------------------------------------------------------- |
 32    | GitHub Issue         | turnaroundfactor/HITL#681                                       |
 33    | Instructions         | 1. Record cell voltages                                           </br>\
 34                             2. Discharge at 7.2A                                              </br>\
 35                             3. Record terminal voltage and cell voltage after 10 seconds           |
 36    | Pass / Fail Criteria | Before Discharging:                                               </br>\
 37                               current < 10mA, all cell_v = 3200 mV +/- 100mV, term_v = 12600 +/- 200 mV </br>\
 38                             During Discharge:                                                 </br>\
 39                               delta_current = -7200 +/- 100 mA, all delta_cell_v < 150 mV,    </br>\
 40                               delta_term_v > 600 mV, sum of cells = terminal +/- 100 mV            |
 41    | Estimated Duration   | 20 seconds                                                             |
 42    """
 43    # Log data before discharge
 44    latest_current = _bms.load.amps
 45    terminal_voltage = _bms.dmm.volts
 46    try:
 47        cell_volts = [
 48            _smbus.read_register(reg)[0] / 1000
 49            for reg in (SMBusReg.CELL_VOLTAGE1, SMBusReg.CELL_VOLTAGE2, SMBusReg.CELL_VOLTAGE3, SMBusReg.CELL_VOLTAGE4)
 50        ]
 51    except SMBusError:
 52        cell_volts = [0.0, 0.0, 0.0, 0.0]
 53    logger.write_result_to_html_report(f"Resting Current: {latest_current:.3f}")
 54    logger.write_result_to_html_report(f"Resting Terminal Voltage: {terminal_voltage:.3f} V")
 55    cell_string = ", ".join(f"{cell_volts[i]:.3f} V" for i in range(4))
 56    logger.write_result_to_html_report(f"Resting Individual Cell Voltages: {cell_string}")
 57    failed = False
 58
 59    # Current is less than 10mA
 60    if (latest_current) < 0.010:
 61        logger.write_result_to_html_report(f"Resting Current: {latest_current:.3f} A < 0.010 A")
 62    else:
 63        logger.write_failure_to_html_report(f"Resting Current: {latest_current:.3f} A ≮ 0.010 A")
 64        failed = True
 65
 66    # Cell voltage is 3.2V
 67    for cell_volt in cell_volts:
 68        if 3.1 <= cell_volt <= 3.3:
 69            logger.write_result_to_html_report(f"Resting Cell Voltage: {cell_volt:.3f} V = 3.2 ± 0.100 V")
 70        else:
 71            logger.write_failure_to_html_report(f"Resting Cell Voltage: {cell_volt:.3f} V ≠ 3.2 ± 0.100 V")
 72            failed = True
 73
 74    # Terminal voltage is 12.6 volts
 75    if 12.4 <= terminal_voltage <= 12.8:
 76        logger.write_result_to_html_report(f"Resting Terminal Voltage: {terminal_voltage:.3f} V = 12.6 ± 0.200 V")
 77    else:
 78        logger.write_failure_to_html_report(f"Resting Terminal Voltage: {terminal_voltage:.3f} V ≠ 12.6 ± 0.200 V")
 79        failed = True
 80
 81    _bms.load.amps_range = 60
 82    with _bms.load(7.2):
 83        time.sleep(10)
 84
 85        discharge_latest_current = _bms.load.amps
 86        discharge_terminal_voltage = _bms.dmm.volts
 87        try:
 88            discharge_cell_volts = [
 89                _smbus.read_register(reg)[0] / 1000
 90                for reg in (
 91                    SMBusReg.CELL_VOLTAGE1,
 92                    SMBusReg.CELL_VOLTAGE2,
 93                    SMBusReg.CELL_VOLTAGE3,
 94                    SMBusReg.CELL_VOLTAGE4,
 95                )
 96            ]
 97        except SMBusError:
 98            discharge_cell_volts = [0.0, 0.0, 0.0, 0.0]
 99        logger.write_result_to_html_report(f"Discharging Current: {discharge_latest_current:.3f}")
100        logger.write_result_to_html_report(f"Discharging Terminal Voltage: {discharge_terminal_voltage:.3f} V")
101        cell_string = ", ".join(f"{discharge_cell_volts[i]:.3f} V" for i in range(4))
102        logger.write_result_to_html_report(f"Discharging Individual Cell Voltages: {cell_string}")
103
104        # Current drops by 7.2A
105        if (
106            7.1 <= (current_diff := abs(latest_current - discharge_latest_current)) <= 7.3
107            and discharge_latest_current < 0
108        ):
109            logger.write_result_to_html_report(f"Discharging Current Δ: {current_diff:.3f} A = 7.2 ± 0.100 A")
110        else:
111            logger.write_failure_to_html_report(f"Discharging Current Δ: {current_diff:.3f} A ≠ 7.2 ± 0.100 A")
112            failed = True
113
114        # Cell volts drop less than 150mV
115        for cell_volt, discharge_cell_volt in zip(cell_volts, discharge_cell_volts):
116            if (cell_diff := abs(cell_volt - discharge_cell_volt)) < 0.150:
117                logger.write_result_to_html_report(f"Discharging Cell Voltage Δ: {cell_diff:.3f} V < 0.150 V")
118            else:
119                logger.write_failure_to_html_report(f"Discharging Cell Voltage Δ: {cell_diff:.3f} V ≮ 0.150 V")
120                failed = True
121
122        # Terminal voltage rises by over 600mV
123        if (terminal_diff := abs(terminal_voltage - discharge_terminal_voltage)) > 0.600:
124            logger.write_result_to_html_report(f"Discharging Terminal Voltage Δ: {terminal_diff:.3f} V > 0.600 V")
125        else:
126            logger.write_failure_to_html_report(f"Discharging Terminal Voltage Δ: {terminal_diff:.3f} V ≯ 0.600 V")
127            failed = True
128
129        # Cell total and terminals are the same voltage
130        if discharge_terminal_voltage - 0.100 <= sum(discharge_cell_volts) <= discharge_terminal_voltage + 0.100:
131            logger.write_result_to_html_report(
132                f"Discharging Cell Voltages: {sum(discharge_cell_volts):.3f} V = "
133                f"{discharge_terminal_voltage:.3f} ± 0.100 V"
134            )
135        else:
136            logger.write_failure_to_html_report(
137                f"Discharging Cell Voltages: {sum(discharge_cell_volts):.3f} V ≠ "
138                f"{discharge_terminal_voltage:.3f} ± 0.100 V"
139            )
140            failed = True
141
142        if failed:
143            pytest.fail("Test had failures.")
144
145
146def test_charge_enable_on():
147    """
148    | Description          | Confirm charging works when CE is active                         |
149    | :------------------- | :--------------------------------------------------------------- |
150    | GitHub Issue         | turnaroundfactor/HITL#681                                 |
151    | MIL-PRF Section      | 3.5.6.2 (Charge Enable)                                          |
152    | MIL-PRF Requirements | The charge enable terminal shall comply with the following: </br>\
153                              ⠀⠀a. Maximum charge without enable: 400 mA                 </br>\
154                              ⠀⠀b. Equivalent resistor: 235 Ω                            </br>\
155                              ⠀⠀c. Equivalent diode VF: 1.3 V                            </br>\
156                              ⠀⠀d. Approximate activation current: 7 mA                       |
157    | Instructions         | 1. Excite charge enable                                     </br>\
158                             2. Charge both sides at 1A, 13.2V                           </br>\
159                             3. Record terminal current after 10 seconds                      |
160    | Pass / Fail Criteria | Current = 1000 +/- 100 mA, sum of cells = terminal +/- 125mV     |
161    | Estimated Duration   | 20 seconds                                                       |
162    | Note                 | This test can fail if the battery is sufficiently charged.       |
163    """
164    with _bms.charger(13.2, 1):
165        time.sleep(10)
166
167        latest_current = _bms.charger.amps
168        terminal_voltage = _bms.dmm.volts
169        try:
170            cell_volts = [
171                _smbus.read_register(reg)[0] / 1000
172                for reg in (
173                    SMBusReg.CELL_VOLTAGE1,
174                    SMBusReg.CELL_VOLTAGE2,
175                    SMBusReg.CELL_VOLTAGE3,
176                    SMBusReg.CELL_VOLTAGE4,
177                )
178            ]
179        except SMBusError:
180            cell_volts = [0.0, 0.0, 0.0, 0.0]
181        cell_string = ", ".join(f"{cell_volts[i]:.3f} V" for i in range(4))
182        logger.write_result_to_html_report(f"Charging Individual Cell Voltages: {cell_string}")
183        logger.write_result_to_html_report(f"Charging Terminal Voltage: {terminal_voltage:.3f} V")
184
185        failed = False
186        if 0.9 <= (latest_current) <= 1.1:
187            logger.write_result_to_html_report(f"Charging Current: {latest_current:.3f} A = 1 ± 0.1 A")
188        else:
189            logger.write_failure_to_html_report(f"Charging Current: {latest_current:.3f} A ≠ 1 ± 0.1 A")
190            failed = True
191
192        if terminal_voltage - 0.125 <= sum(cell_volts) <= terminal_voltage + 0.125:
193            logger.write_result_to_html_report(
194                f"Charging Cell Voltages: {sum(cell_volts):.3f} V = {terminal_voltage:.3f} ± 0.125 V"
195            )
196        else:
197            logger.write_failure_to_html_report(
198                f"Charging Cell Voltages: {sum(cell_volts):.3f} V ≠ {terminal_voltage:.3f} ± 0.125 V"
199            )
200            failed = True
201
202        if failed:
203            pytest.fail("Test had failures.")
204
205
206def test_charge_enable_off():
207    """
208    | Description          | Confirm charging doesn't work when CE is inactive                      |
209    | :------------------- | :--------------------------------------------------------------------- |
210    | GitHub Issue         | turnaroundfactor/HITL#681                                       |
211    | MIL-PRF Section      | 3.5.6.2 (Charge Enable)                                                |
212    | MIL-PRF Requirements | The charge enable terminal shall comply with the following:       </br>\
213                              ⠀⠀a. Maximum charge without enable: 400 mA                       </br>\
214                              ⠀⠀b. Equivalent resistor: 235 Ω                                  </br>\
215                              ⠀⠀c. Equivalent diode VF: 1.3 V                                  </br>\
216                              ⠀⠀d. Approximate activation current: 7 mA                             |
217    | Instructions         | 1. Do not excite charge enable                                    </br>\
218                             2. Charge both sides at 1A, 13.2V                                 </br>\
219                             3. Record terminal current after 10 seconds                            |
220    | Pass / Fail Criteria | Charging:                                                         </br>\
221                               Current = 0, cells < terminal +/- 125mV, terminal = 13200 +/- 150 mV </br>\
222                             After Charging:                                                   </br>\
223                               Current = 0,  terminal = 0 mV +/- 4000 mV                            |
224    | Estimated Duration   | 20 seconds                                                             |
225    """
226    with _bms.charger(13.2, 1, False):
227        time.sleep(10)
228
229        latest_current = _bms.charger.amps
230        terminal_voltage = _bms.dmm.volts
231        try:
232            cell_volts = [
233                _smbus.read_register(reg)[0] / 1000
234                for reg in (
235                    SMBusReg.CELL_VOLTAGE1,
236                    SMBusReg.CELL_VOLTAGE2,
237                    SMBusReg.CELL_VOLTAGE3,
238                    SMBusReg.CELL_VOLTAGE4,
239                )
240            ]
241        except SMBusError:
242            cell_volts = [0.0, 0.0, 0.0, 0.0]
243        cell_string = ", ".join(f"{cell_volts[i]:.3f} V" for i in range(4))
244        logger.write_result_to_html_report(f"Charging Individual Cell Voltages: {cell_string}")
245        logger.write_result_to_html_report(f"Charging Terminal Voltage: {terminal_voltage:.3f} V")
246        failed = False
247
248        # Current is zero amps
249        if -0.010 <= (latest_current) <= 0.010:
250            logger.write_result_to_html_report(f"Charging Current: {latest_current:.3f} A = 0 ± 0.010 A")
251        else:
252            logger.write_failure_to_html_report(f"Charging Current: {latest_current:.3f} A ≠ 0 ± 0.010 A")
253            failed = True
254
255        # Cell volts are less than the terminal voltage
256        if sum(cell_volts) < terminal_voltage - 0.125:
257            logger.write_result_to_html_report(
258                f"Charging Cell Voltages: {sum(cell_volts):.3f} V < {terminal_voltage:.3f} ± 0.125 V"
259            )
260        else:
261            logger.write_failure_to_html_report(
262                f"Charging Cell Voltages: {sum(cell_volts):.3f} V ≮ {terminal_voltage:.3f} ± 0.125 V"
263            )
264            failed = True
265
266        # Terminal voltage is 13.2 volts
267        if 13.2 - 0.150 <= terminal_voltage <= 13.2 + 0.150:
268            logger.write_result_to_html_report(f"Charging Terminal Voltage: {terminal_voltage:.3f} V = 13.2 ± 0.150 V")
269        else:
270            logger.write_failure_to_html_report(f"Charging Terminal Voltage: {terminal_voltage:.3f} V ≠ 13.2 ± 0.150 V")
271            failed = True
272    time.sleep(5)
273
274    # Current is zero amps
275    if -0.010 <= (latest_current) <= 0.010:
276        logger.write_result_to_html_report(f"Resting Current: {latest_current:.3f} A = 0 ± 0.010 A")
277    else:
278        logger.write_failure_to_html_report(f"Resting Current: {latest_current:.3f} A ≠ 0 ± 0.010 A")
279        failed = True
280
281    # Terminal voltage is zero volts
282    if -4 <= (terminal_voltage) <= 4:
283        logger.write_result_to_html_report(f"Resting Terminal Voltage: {terminal_voltage:.3f} V = 0 ± 4 V")
284    else:
285        logger.write_failure_to_html_report(f"Resting Terminal Voltage: {terminal_voltage:.3f} V ≠ 0 ± 4 V")
286        failed = True
287
288    if failed:
289        pytest.fail("Test had failures.")
def test_discharge():
 29def test_discharge():
 30    """
 31    | Description          | Confirm discharging works as normal                                    |
 32    | :------------------- | :--------------------------------------------------------------------- |
 33    | GitHub Issue         | turnaroundfactor/HITL#681                                       |
 34    | Instructions         | 1. Record cell voltages                                           </br>\
 35                             2. Discharge at 7.2A                                              </br>\
 36                             3. Record terminal voltage and cell voltage after 10 seconds           |
 37    | Pass / Fail Criteria | Before Discharging:                                               </br>\
 38                               current < 10mA, all cell_v = 3200 mV +/- 100mV, term_v = 12600 +/- 200 mV </br>\
 39                             During Discharge:                                                 </br>\
 40                               delta_current = -7200 +/- 100 mA, all delta_cell_v < 150 mV,    </br>\
 41                               delta_term_v > 600 mV, sum of cells = terminal +/- 100 mV            |
 42    | Estimated Duration   | 20 seconds                                                             |
 43    """
 44    # Log data before discharge
 45    latest_current = _bms.load.amps
 46    terminal_voltage = _bms.dmm.volts
 47    try:
 48        cell_volts = [
 49            _smbus.read_register(reg)[0] / 1000
 50            for reg in (SMBusReg.CELL_VOLTAGE1, SMBusReg.CELL_VOLTAGE2, SMBusReg.CELL_VOLTAGE3, SMBusReg.CELL_VOLTAGE4)
 51        ]
 52    except SMBusError:
 53        cell_volts = [0.0, 0.0, 0.0, 0.0]
 54    logger.write_result_to_html_report(f"Resting Current: {latest_current:.3f}")
 55    logger.write_result_to_html_report(f"Resting Terminal Voltage: {terminal_voltage:.3f} V")
 56    cell_string = ", ".join(f"{cell_volts[i]:.3f} V" for i in range(4))
 57    logger.write_result_to_html_report(f"Resting Individual Cell Voltages: {cell_string}")
 58    failed = False
 59
 60    # Current is less than 10mA
 61    if (latest_current) < 0.010:
 62        logger.write_result_to_html_report(f"Resting Current: {latest_current:.3f} A < 0.010 A")
 63    else:
 64        logger.write_failure_to_html_report(f"Resting Current: {latest_current:.3f} A ≮ 0.010 A")
 65        failed = True
 66
 67    # Cell voltage is 3.2V
 68    for cell_volt in cell_volts:
 69        if 3.1 <= cell_volt <= 3.3:
 70            logger.write_result_to_html_report(f"Resting Cell Voltage: {cell_volt:.3f} V = 3.2 ± 0.100 V")
 71        else:
 72            logger.write_failure_to_html_report(f"Resting Cell Voltage: {cell_volt:.3f} V ≠ 3.2 ± 0.100 V")
 73            failed = True
 74
 75    # Terminal voltage is 12.6 volts
 76    if 12.4 <= terminal_voltage <= 12.8:
 77        logger.write_result_to_html_report(f"Resting Terminal Voltage: {terminal_voltage:.3f} V = 12.6 ± 0.200 V")
 78    else:
 79        logger.write_failure_to_html_report(f"Resting Terminal Voltage: {terminal_voltage:.3f} V ≠ 12.6 ± 0.200 V")
 80        failed = True
 81
 82    _bms.load.amps_range = 60
 83    with _bms.load(7.2):
 84        time.sleep(10)
 85
 86        discharge_latest_current = _bms.load.amps
 87        discharge_terminal_voltage = _bms.dmm.volts
 88        try:
 89            discharge_cell_volts = [
 90                _smbus.read_register(reg)[0] / 1000
 91                for reg in (
 92                    SMBusReg.CELL_VOLTAGE1,
 93                    SMBusReg.CELL_VOLTAGE2,
 94                    SMBusReg.CELL_VOLTAGE3,
 95                    SMBusReg.CELL_VOLTAGE4,
 96                )
 97            ]
 98        except SMBusError:
 99            discharge_cell_volts = [0.0, 0.0, 0.0, 0.0]
100        logger.write_result_to_html_report(f"Discharging Current: {discharge_latest_current:.3f}")
101        logger.write_result_to_html_report(f"Discharging Terminal Voltage: {discharge_terminal_voltage:.3f} V")
102        cell_string = ", ".join(f"{discharge_cell_volts[i]:.3f} V" for i in range(4))
103        logger.write_result_to_html_report(f"Discharging Individual Cell Voltages: {cell_string}")
104
105        # Current drops by 7.2A
106        if (
107            7.1 <= (current_diff := abs(latest_current - discharge_latest_current)) <= 7.3
108            and discharge_latest_current < 0
109        ):
110            logger.write_result_to_html_report(f"Discharging Current Δ: {current_diff:.3f} A = 7.2 ± 0.100 A")
111        else:
112            logger.write_failure_to_html_report(f"Discharging Current Δ: {current_diff:.3f} A ≠ 7.2 ± 0.100 A")
113            failed = True
114
115        # Cell volts drop less than 150mV
116        for cell_volt, discharge_cell_volt in zip(cell_volts, discharge_cell_volts):
117            if (cell_diff := abs(cell_volt - discharge_cell_volt)) < 0.150:
118                logger.write_result_to_html_report(f"Discharging Cell Voltage Δ: {cell_diff:.3f} V < 0.150 V")
119            else:
120                logger.write_failure_to_html_report(f"Discharging Cell Voltage Δ: {cell_diff:.3f} V ≮ 0.150 V")
121                failed = True
122
123        # Terminal voltage rises by over 600mV
124        if (terminal_diff := abs(terminal_voltage - discharge_terminal_voltage)) > 0.600:
125            logger.write_result_to_html_report(f"Discharging Terminal Voltage Δ: {terminal_diff:.3f} V > 0.600 V")
126        else:
127            logger.write_failure_to_html_report(f"Discharging Terminal Voltage Δ: {terminal_diff:.3f} V ≯ 0.600 V")
128            failed = True
129
130        # Cell total and terminals are the same voltage
131        if discharge_terminal_voltage - 0.100 <= sum(discharge_cell_volts) <= discharge_terminal_voltage + 0.100:
132            logger.write_result_to_html_report(
133                f"Discharging Cell Voltages: {sum(discharge_cell_volts):.3f} V = "
134                f"{discharge_terminal_voltage:.3f} ± 0.100 V"
135            )
136        else:
137            logger.write_failure_to_html_report(
138                f"Discharging Cell Voltages: {sum(discharge_cell_volts):.3f} V ≠ "
139                f"{discharge_terminal_voltage:.3f} ± 0.100 V"
140            )
141            failed = True
142
143        if failed:
144            pytest.fail("Test had failures.")
Description Confirm discharging works as normal
GitHub Issue turnaroundfactor/HITL#681
Instructions 1. Record cell voltages
2. Discharge at 7.2A
3. Record terminal voltage and cell voltage after 10 seconds
Pass / Fail Criteria Before Discharging:
current < 10mA, all cell_v = 3200 mV +/- 100mV, term_v = 12600 +/- 200 mV
During Discharge:
delta_current = -7200 +/- 100 mA, all delta_cell_v < 150 mV,
delta_term_v > 600 mV, sum of cells = terminal +/- 100 mV
Estimated Duration 20 seconds
def test_charge_enable_on():
147def test_charge_enable_on():
148    """
149    | Description          | Confirm charging works when CE is active                         |
150    | :------------------- | :--------------------------------------------------------------- |
151    | GitHub Issue         | turnaroundfactor/HITL#681                                 |
152    | MIL-PRF Section      | 3.5.6.2 (Charge Enable)                                          |
153    | MIL-PRF Requirements | The charge enable terminal shall comply with the following: </br>\
154                              ⠀⠀a. Maximum charge without enable: 400 mA                 </br>\
155                              ⠀⠀b. Equivalent resistor: 235 Ω                            </br>\
156                              ⠀⠀c. Equivalent diode VF: 1.3 V                            </br>\
157                              ⠀⠀d. Approximate activation current: 7 mA                       |
158    | Instructions         | 1. Excite charge enable                                     </br>\
159                             2. Charge both sides at 1A, 13.2V                           </br>\
160                             3. Record terminal current after 10 seconds                      |
161    | Pass / Fail Criteria | Current = 1000 +/- 100 mA, sum of cells = terminal +/- 125mV     |
162    | Estimated Duration   | 20 seconds                                                       |
163    | Note                 | This test can fail if the battery is sufficiently charged.       |
164    """
165    with _bms.charger(13.2, 1):
166        time.sleep(10)
167
168        latest_current = _bms.charger.amps
169        terminal_voltage = _bms.dmm.volts
170        try:
171            cell_volts = [
172                _smbus.read_register(reg)[0] / 1000
173                for reg in (
174                    SMBusReg.CELL_VOLTAGE1,
175                    SMBusReg.CELL_VOLTAGE2,
176                    SMBusReg.CELL_VOLTAGE3,
177                    SMBusReg.CELL_VOLTAGE4,
178                )
179            ]
180        except SMBusError:
181            cell_volts = [0.0, 0.0, 0.0, 0.0]
182        cell_string = ", ".join(f"{cell_volts[i]:.3f} V" for i in range(4))
183        logger.write_result_to_html_report(f"Charging Individual Cell Voltages: {cell_string}")
184        logger.write_result_to_html_report(f"Charging Terminal Voltage: {terminal_voltage:.3f} V")
185
186        failed = False
187        if 0.9 <= (latest_current) <= 1.1:
188            logger.write_result_to_html_report(f"Charging Current: {latest_current:.3f} A = 1 ± 0.1 A")
189        else:
190            logger.write_failure_to_html_report(f"Charging Current: {latest_current:.3f} A ≠ 1 ± 0.1 A")
191            failed = True
192
193        if terminal_voltage - 0.125 <= sum(cell_volts) <= terminal_voltage + 0.125:
194            logger.write_result_to_html_report(
195                f"Charging Cell Voltages: {sum(cell_volts):.3f} V = {terminal_voltage:.3f} ± 0.125 V"
196            )
197        else:
198            logger.write_failure_to_html_report(
199                f"Charging Cell Voltages: {sum(cell_volts):.3f} V ≠ {terminal_voltage:.3f} ± 0.125 V"
200            )
201            failed = True
202
203        if failed:
204            pytest.fail("Test had failures.")
Description Confirm charging works when CE is active
GitHub Issue turnaroundfactor/HITL#681
MIL-PRF Section 3.5.6.2 (Charge Enable)
MIL-PRF Requirements The charge enable terminal shall comply with the following:
⠀⠀a. Maximum charge without enable: 400 mA
⠀⠀b. Equivalent resistor: 235 Ω
⠀⠀c. Equivalent diode VF: 1.3 V
⠀⠀d. Approximate activation current: 7 mA
Instructions 1. Excite charge enable
2. Charge both sides at 1A, 13.2V
3. Record terminal current after 10 seconds
Pass / Fail Criteria Current = 1000 +/- 100 mA, sum of cells = terminal +/- 125mV
Estimated Duration 20 seconds
Note This test can fail if the battery is sufficiently charged.
def test_charge_enable_off():
207def test_charge_enable_off():
208    """
209    | Description          | Confirm charging doesn't work when CE is inactive                      |
210    | :------------------- | :--------------------------------------------------------------------- |
211    | GitHub Issue         | turnaroundfactor/HITL#681                                       |
212    | MIL-PRF Section      | 3.5.6.2 (Charge Enable)                                                |
213    | MIL-PRF Requirements | The charge enable terminal shall comply with the following:       </br>\
214                              ⠀⠀a. Maximum charge without enable: 400 mA                       </br>\
215                              ⠀⠀b. Equivalent resistor: 235 Ω                                  </br>\
216                              ⠀⠀c. Equivalent diode VF: 1.3 V                                  </br>\
217                              ⠀⠀d. Approximate activation current: 7 mA                             |
218    | Instructions         | 1. Do not excite charge enable                                    </br>\
219                             2. Charge both sides at 1A, 13.2V                                 </br>\
220                             3. Record terminal current after 10 seconds                            |
221    | Pass / Fail Criteria | Charging:                                                         </br>\
222                               Current = 0, cells < terminal +/- 125mV, terminal = 13200 +/- 150 mV </br>\
223                             After Charging:                                                   </br>\
224                               Current = 0,  terminal = 0 mV +/- 4000 mV                            |
225    | Estimated Duration   | 20 seconds                                                             |
226    """
227    with _bms.charger(13.2, 1, False):
228        time.sleep(10)
229
230        latest_current = _bms.charger.amps
231        terminal_voltage = _bms.dmm.volts
232        try:
233            cell_volts = [
234                _smbus.read_register(reg)[0] / 1000
235                for reg in (
236                    SMBusReg.CELL_VOLTAGE1,
237                    SMBusReg.CELL_VOLTAGE2,
238                    SMBusReg.CELL_VOLTAGE3,
239                    SMBusReg.CELL_VOLTAGE4,
240                )
241            ]
242        except SMBusError:
243            cell_volts = [0.0, 0.0, 0.0, 0.0]
244        cell_string = ", ".join(f"{cell_volts[i]:.3f} V" for i in range(4))
245        logger.write_result_to_html_report(f"Charging Individual Cell Voltages: {cell_string}")
246        logger.write_result_to_html_report(f"Charging Terminal Voltage: {terminal_voltage:.3f} V")
247        failed = False
248
249        # Current is zero amps
250        if -0.010 <= (latest_current) <= 0.010:
251            logger.write_result_to_html_report(f"Charging Current: {latest_current:.3f} A = 0 ± 0.010 A")
252        else:
253            logger.write_failure_to_html_report(f"Charging Current: {latest_current:.3f} A ≠ 0 ± 0.010 A")
254            failed = True
255
256        # Cell volts are less than the terminal voltage
257        if sum(cell_volts) < terminal_voltage - 0.125:
258            logger.write_result_to_html_report(
259                f"Charging Cell Voltages: {sum(cell_volts):.3f} V < {terminal_voltage:.3f} ± 0.125 V"
260            )
261        else:
262            logger.write_failure_to_html_report(
263                f"Charging Cell Voltages: {sum(cell_volts):.3f} V ≮ {terminal_voltage:.3f} ± 0.125 V"
264            )
265            failed = True
266
267        # Terminal voltage is 13.2 volts
268        if 13.2 - 0.150 <= terminal_voltage <= 13.2 + 0.150:
269            logger.write_result_to_html_report(f"Charging Terminal Voltage: {terminal_voltage:.3f} V = 13.2 ± 0.150 V")
270        else:
271            logger.write_failure_to_html_report(f"Charging Terminal Voltage: {terminal_voltage:.3f} V ≠ 13.2 ± 0.150 V")
272            failed = True
273    time.sleep(5)
274
275    # Current is zero amps
276    if -0.010 <= (latest_current) <= 0.010:
277        logger.write_result_to_html_report(f"Resting Current: {latest_current:.3f} A = 0 ± 0.010 A")
278    else:
279        logger.write_failure_to_html_report(f"Resting Current: {latest_current:.3f} A ≠ 0 ± 0.010 A")
280        failed = True
281
282    # Terminal voltage is zero volts
283    if -4 <= (terminal_voltage) <= 4:
284        logger.write_result_to_html_report(f"Resting Terminal Voltage: {terminal_voltage:.3f} V = 0 ± 4 V")
285    else:
286        logger.write_failure_to_html_report(f"Resting Terminal Voltage: {terminal_voltage:.3f} V ≠ 0 ± 4 V")
287        failed = True
288
289    if failed:
290        pytest.fail("Test had failures.")
Description Confirm charging doesn't work when CE is inactive
GitHub Issue turnaroundfactor/HITL#681
MIL-PRF Section 3.5.6.2 (Charge Enable)
MIL-PRF Requirements The charge enable terminal shall comply with the following:
⠀⠀a. Maximum charge without enable: 400 mA
⠀⠀b. Equivalent resistor: 235 Ω
⠀⠀c. Equivalent diode VF: 1.3 V
⠀⠀d. Approximate activation current: 7 mA
Instructions 1. Do not excite charge enable
2. Charge both sides at 1A, 13.2V
3. Record terminal current after 10 seconds
Pass / Fail Criteria Charging:
Current = 0, cells < terminal +/- 125mV, terminal = 13200 +/- 150 mV
After Charging:
Current = 0, terminal = 0 mV +/- 4000 mV
Estimated Duration 20 seconds