foxBMS - Unit Tests  1.3.0
The foxBMS Unit Tests API Documentation
soa.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2022, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice, this
12  * list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  *
18  * 3. Neither the name of the copyright holder nor the names of its
19  * contributors may be used to endorse or promote products derived from
20  * this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * We kindly request you to use one or more of the following phrases to refer to
34  * foxBMS in your hardware, software, documentation or advertising materials:
35  *
36  * - ″This product uses parts of foxBMS®″
37  * - ″This product includes parts of foxBMS®″
38  * - ″This product is derived from foxBMS®″
39  *
40  */
41 
42 /**
43  * @file soa.c
44  * @author foxBMS Team
45  * @date 2020-10-14 (date of creation)
46  * @updated 2022-05-30 (date of last update)
47  * @version v1.3.0
48  * @ingroup APPLICATION
49  * @prefix SOA
50  *
51  * @brief SOA module responsible for checking battery parameters against
52  * safety limits
53  *
54  */
55 
56 /*========== Includes =======================================================*/
57 #include "soa.h"
58 
59 #include "battery_cell_cfg.h"
60 #include "battery_system_cfg.h"
61 
62 #include "bms.h"
63 #include "diag.h"
64 #include "foxmath.h"
65 
66 /*========== Macros and Definitions =========================================*/
67 
68 /*========== Static Constant and Variable Definitions =======================*/
69 
70 /*========== Extern Constant and Variable Definitions =======================*/
71 
72 /*========== Static Function Prototypes =====================================*/
73 
74 /*========== Static Function Implementations ================================*/
75 
76 /*========== Extern Function Implementations ================================*/
77 
78 extern void SOA_CheckVoltages(DATA_BLOCK_MIN_MAX_s *pMinimumMaximumCellVoltages) {
79  FAS_ASSERT(pMinimumMaximumCellVoltages != NULL_PTR);
81 
82  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
83  int16_t voltageMax_mV = pMinimumMaximumCellVoltages->maximumCellVoltage_mV[s];
84  int16_t voltageMin_mV = pMinimumMaximumCellVoltages->minimumCellVoltage_mV[s];
85 
86  if (voltageMax_mV >= BC_VOLTAGE_MAX_MOL_mV) {
87  /* Over voltage maximum operating limit violated */
89  if (voltageMax_mV >= BC_VOLTAGE_MAX_RSL_mV) {
90  /* Over voltage recommended safety limit violated */
92  if (voltageMax_mV >= BC_VOLTAGE_MAX_MSL_mV) {
93  /* Over voltage maximum safety limit violated */
95  }
96  }
97  }
98  if (voltageMax_mV < BC_VOLTAGE_MAX_MSL_mV) {
99  /* over voltage maximum safety limit NOT violated */
101  if (voltageMax_mV < BC_VOLTAGE_MAX_RSL_mV) {
102  /* over voltage recommended safety limit NOT violated */
104  if (voltageMax_mV < BC_VOLTAGE_MAX_MOL_mV) {
105  /* over voltage maximum operating limit NOT violated */
107  }
108  }
109  }
110 
111  if (voltageMin_mV <= BC_VOLTAGE_MIN_MOL_mV) {
112  /* Under voltage maximum operating limit violated */
114  if (voltageMin_mV <= BC_VOLTAGE_MIN_RSL_mV) {
115  /* Under voltage recommended safety limit violated */
117  if (voltageMin_mV <= BC_VOLTAGE_MIN_MSL_mV) {
118  /* Under voltage maximum safety limit violated */
119  retvalUndervoltMSL =
121 
122  /* If under voltage flag is set and deep-discharge voltage is violated */
123  if ((retvalUndervoltMSL == DIAG_HANDLER_RETURN_ERR_OCCURRED) &&
124  (voltageMin_mV <= BC_VOLTAGE_DEEP_DISCHARGE_mV)) {
126  }
127  }
128  }
129  }
130  if (voltageMin_mV > BC_VOLTAGE_MIN_MSL_mV) {
131  /* under voltage maximum safety limit NOT violated */
133  if (voltageMin_mV > BC_VOLTAGE_MIN_RSL_mV) {
134  /* under voltage recommended safety limit NOT violated */
136  if (voltageMin_mV > BC_VOLTAGE_MIN_MOL_mV) {
137  /* under voltage maximum operating limit NOT violated */
139  }
140  }
141  }
142  }
143 }
144 
146  DATA_BLOCK_MIN_MAX_s *pMinimumMaximumCellTemperatures,
147  DATA_BLOCK_PACK_VALUES_s *pCurrent) {
148  FAS_ASSERT(pMinimumMaximumCellTemperatures != NULL_PTR);
149  FAS_ASSERT(pCurrent != NULL_PTR);
150  /* Iterate over each string and check temperatures */
151  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
152  int32_t i_current = pCurrent->stringCurrent_mA[s];
153  int16_t temperatureMin_ddegC = pMinimumMaximumCellTemperatures->minimumTemperature_ddegC[s];
154  int16_t temperatureMax_ddegC = pMinimumMaximumCellTemperatures->maximumTemperature_ddegC[s];
155 
156  /* Over temperature check */
157  if (BMS_GetCurrentFlowDirection(i_current) == BMS_DISCHARGING) {
158  /* Discharge */
159  if (temperatureMax_ddegC >= BC_TEMPERATURE_MAX_DISCHARGE_MOL_ddegC) {
160  /* Over temperature maximum operating limit violated*/
162  if (temperatureMax_ddegC >= BC_TEMPERATURE_MAX_DISCHARGE_RSL_ddegC) {
163  /* Over temperature recommended safety limit violated*/
165  if (temperatureMax_ddegC >= BC_TEMPERATURE_MAX_DISCHARGE_MSL_ddegC) {
166  /* Over temperature maximum safety limit violated */
168  }
169  }
170  }
171  if (temperatureMax_ddegC < BC_TEMPERATURE_MAX_DISCHARGE_MSL_ddegC) {
172  /* over temperature maximum safety limit NOT violated */
174  if (temperatureMax_ddegC < BC_TEMPERATURE_MAX_DISCHARGE_RSL_ddegC) {
175  /* over temperature recommended safety limit NOT violated */
177  if (temperatureMax_ddegC < BC_TEMPERATURE_MAX_DISCHARGE_MOL_ddegC) {
178  /* over temperature maximum operating limit NOT violated */
180  }
181  }
182  }
183 
184  } else {
185  /* Charge */
186  if (temperatureMax_ddegC >= BC_TEMPERATURE_MAX_CHARGE_MOL_ddegC) {
187  /* Over temperature maximum operating limit violated */
189  if (temperatureMax_ddegC >= BC_TEMPERATURE_MAX_CHARGE_RSL_ddegC) {
190  /* Over temperature recommended safety limit violated */
192  /* Over temperature maximum safety limit violated */
193  if (temperatureMax_ddegC >= BC_TEMPERATURE_MAX_CHARGE_MSL_ddegC) {
195  }
196  }
197  }
198  if (temperatureMax_ddegC < BC_TEMPERATURE_MAX_CHARGE_MSL_ddegC) {
199  /* over temperature maximum safety limit NOT violated */
201  if (temperatureMax_ddegC < BC_TEMPERATURE_MAX_CHARGE_RSL_ddegC) {
202  /* over temperature recommended safety limit NOT violated */
204  if (temperatureMax_ddegC < BC_TEMPERATURE_MAX_CHARGE_MOL_ddegC) {
205  /* over temperature maximum operating limit NOT violated*/
207  }
208  }
209  }
210  }
211 
212  /* Under temperature check */
213  if (BMS_GetCurrentFlowDirection(i_current) == BMS_DISCHARGING) {
214  /* Discharge */
215  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_DISCHARGE_MOL_ddegC) {
216  /* Under temperature maximum operating limit violated */
218  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_DISCHARGE_RSL_ddegC) {
219  /* Under temperature recommended safety limit violated*/
221  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_DISCHARGE_MSL_ddegC) {
222  /* Under temperature maximum safety limit violated */
224  }
225  }
226  }
227  if (temperatureMin_ddegC > BC_TEMPERATURE_MIN_DISCHARGE_MSL_ddegC) {
228  /* under temperature maximum safety limit NOT violated */
230  if (temperatureMin_ddegC > BC_TEMPERATURE_MIN_DISCHARGE_RSL_ddegC) {
231  /* under temperature recommended safety limit NOT violated */
233  if (temperatureMin_ddegC > BC_TEMPERATURE_MIN_DISCHARGE_MOL_ddegC) {
234  /* under temperature maximum operating limit NOT violated*/
236  }
237  }
238  }
239  } else {
240  /* Charge */
241  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_CHARGE_MOL_ddegC) {
242  /* Under temperature maximum operating limit violated */
244  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_CHARGE_RSL_ddegC) {
245  /* Under temperature recommended safety limit violated */
247  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_CHARGE_MSL_ddegC) {
248  /* Under temperature maximum safety limit violated */
250  }
251  }
252  }
253  if (temperatureMin_ddegC > BC_TEMPERATURE_MIN_CHARGE_MSL_ddegC) {
254  /* under temperature maximum safety limit NOT violated */
256  if (temperatureMin_ddegC > BC_TEMPERATURE_MIN_CHARGE_RSL_ddegC) {
257  /* under temperature recommended safety limit NOT violated */
259  if (temperatureMin_ddegC > BC_TEMPERATURE_MIN_CHARGE_MOL_ddegC) {
260  /* under temperature maximum operating limit NOT violated*/
262  }
263  }
264  }
265  }
266  }
267 }
268 
269 extern void SOA_CheckCurrent(DATA_BLOCK_PACK_VALUES_s *pTablePackValues) {
270  FAS_ASSERT(pTablePackValues != NULL_PTR);
271 
272  /* Iterate over each string and check current */
273  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
274  /* Only perform check if current value is valid */
275  if (pTablePackValues->invalidStringCurrent[s] == 0u) {
276  BMS_CURRENT_FLOW_STATE_e currentDirection =
277  BMS_GetCurrentFlowDirection(pTablePackValues->stringCurrent_mA[s]);
278  uint32_t absStringCurrent_mA = (uint32_t)abs(pTablePackValues->stringCurrent_mA[s]);
279  /* Check various current limits depending on current direction */
280  bool stringOvercurrent = SOA_IsStringCurrentLimitViolated(absStringCurrent_mA, currentDirection);
281  bool cellOvercurrent = SOA_IsCellCurrentLimitViolated(absStringCurrent_mA, currentDirection);
282  if (currentDirection == BMS_CHARGING) {
283  /* Check string current limit */
284  if (stringOvercurrent == true) {
286  } else {
288  }
289  /* Check battery cell limit */
290  if (cellOvercurrent == true) {
292  } else {
294  }
295  } else if (currentDirection == BMS_DISCHARGING) {
296  /* Check string current limit */
297  if (stringOvercurrent == true) {
299  } else {
301  }
302  /* Check battery cell limit */
303  if (cellOvercurrent == true) {
305  } else {
307  }
308  } else {
309  /* No current floating -> everything okay */
314  }
315 
316  /* Check if current is floating while contactors are open */
317  if (SOA_IsCurrentOnOpenString(currentDirection, s) == false) {
319  } else {
321  }
322  }
323  }
324 
325  /* Check pack current */
326  if (pTablePackValues->invalidPackCurrent == 0u) {
327  BMS_CURRENT_FLOW_STATE_e currentDirection = BMS_GetCurrentFlowDirection(pTablePackValues->packCurrent_mA);
328  uint32_t absPackCurrent_mA = (uint32_t)abs(pTablePackValues->packCurrent_mA);
329  bool packOvercurrent = SOA_IsPackCurrentLimitViolated(absPackCurrent_mA, currentDirection);
330 
331  if (currentDirection == BMS_CHARGING) {
332  if (packOvercurrent == true) {
334  } else {
336  }
337  } else if (currentDirection == BMS_DISCHARGING) {
338  if (packOvercurrent == true) {
340  } else {
342  }
343  } else {
344  /* No current floating -> everything okay */
347  }
348  }
349 }
350 
351 extern void SOA_CheckSlaveTemperatures(void) { /* TODO: to be implemented */
352 }
353 
354 /*========== Externalized Static Function Implementations (Unit Test) =======*/
Configuration of the battery cell (e.g., minimum and maximum cell voltage)
#define BC_TEMPERATURE_MAX_CHARGE_RSL_ddegC
Maximum temperature limit during charge.
#define BC_VOLTAGE_MIN_MSL_mV
Minimum cell voltage limit.
#define BC_TEMPERATURE_MIN_DISCHARGE_RSL_ddegC
Minimum temperature limit during discharge.
#define BC_TEMPERATURE_MIN_DISCHARGE_MOL_ddegC
Minimum temperature limit during discharge.
#define BC_TEMPERATURE_MIN_CHARGE_RSL_ddegC
Minimum temperature limit during discharge.
#define BC_TEMPERATURE_MAX_CHARGE_MSL_ddegC
Maximum temperature limit during charge.
#define BC_TEMPERATURE_MIN_CHARGE_MSL_ddegC
Minimum temperature limit during discharge.
#define BC_TEMPERATURE_MAX_DISCHARGE_RSL_ddegC
Maximum temperature limit during discharge.
#define BC_TEMPERATURE_MAX_DISCHARGE_MSL_ddegC
Maximum temperature limit during discharge.
#define BC_VOLTAGE_MAX_MOL_mV
Maximum cell voltage limit.
#define BC_VOLTAGE_MIN_MOL_mV
Minimum cell voltage limit.
#define BC_TEMPERATURE_MIN_DISCHARGE_MSL_ddegC
Minimum temperature limit during discharge.
#define BC_VOLTAGE_MAX_RSL_mV
Maximum cell voltage limit.
#define BC_VOLTAGE_DEEP_DISCHARGE_mV
Deep-discharge cell voltage limit.
#define BC_TEMPERATURE_MIN_CHARGE_MOL_ddegC
Minimum temperature limit during discharge.
#define BC_TEMPERATURE_MAX_CHARGE_MOL_ddegC
Maximum temperature limit during charge.
#define BC_TEMPERATURE_MAX_DISCHARGE_MOL_ddegC
Maximum temperature limit during discharge.
#define BC_VOLTAGE_MAX_MSL_mV
Maximum cell voltage limit.
#define BC_VOLTAGE_MIN_RSL_mV
Minimum cell voltage limit.
Configuration of the battery system (e.g., number of battery modules, battery cells,...
#define BS_NR_OF_STRINGS
Number of parallel strings in the battery pack.
BMS_CURRENT_FLOW_STATE_e BMS_GetCurrentFlowDirection(int32_t current_mA)
Get current flow direction, current value as function parameter.
Definition: bms.c:1278
bms driver header
BMS_CURRENT_FLOW_STATE_e
Definition: bms.h:66
@ BMS_DISCHARGING
Definition: bms.h:68
@ BMS_CHARGING
Definition: bms.h:67
DIAG_RETURNTYPE_e DIAG_Handler(DIAG_ID_e diag_id, DIAG_EVENT_e event, DIAG_IMPACT_LEVEL_e impact, uint32_t data)
DIAG_Handler provides generic error handling, based on diagnosis group.
Definition: diag.c:229
Diagnosis driver header.
DIAG_RETURNTYPE_e
Definition: diag.h:64
@ DIAG_HANDLER_RETURN_ERR_OCCURRED
Definition: diag.h:66
@ DIAG_EVENT_NOT_OK
Definition: diag_cfg.h:239
@ DIAG_EVENT_OK
Definition: diag_cfg.h:238
@ DIAG_SYSTEM
Definition: diag_cfg.h:251
@ DIAG_STRING
Definition: diag_cfg.h:252
@ DIAG_ID_TEMP_OVERTEMPERATURE_DISCHARGE_MSL
Definition: diag_cfg.h:185
@ DIAG_ID_PACK_OVERCURRENT_CHARGE_MSL
Definition: diag_cfg.h:206
@ DIAG_ID_CELLVOLTAGE_UNDERVOLTAGE_RSL
Definition: diag_cfg.h:180
@ DIAG_ID_TEMP_UNDERTEMPERATURE_CHARGE_MSL
Definition: diag_cfg.h:188
@ DIAG_ID_TEMP_OVERTEMPERATURE_DISCHARGE_RSL
Definition: diag_cfg.h:186
@ DIAG_ID_TEMP_UNDERTEMPERATURE_DISCHARGE_RSL
Definition: diag_cfg.h:192
@ DIAG_ID_CELLVOLTAGE_OVERVOLTAGE_MOL
Definition: diag_cfg.h:178
@ DIAG_ID_OVERCURRENT_DISCHARGE_CELL_MSL
Definition: diag_cfg.h:197
@ DIAG_ID_CELLVOLTAGE_OVERVOLTAGE_RSL
Definition: diag_cfg.h:177
@ DIAG_ID_TEMP_UNDERTEMPERATURE_CHARGE_RSL
Definition: diag_cfg.h:189
@ DIAG_ID_TEMP_OVERTEMPERATURE_DISCHARGE_MOL
Definition: diag_cfg.h:187
@ DIAG_ID_STRING_OVERCURRENT_CHARGE_MSL
Definition: diag_cfg.h:200
@ DIAG_ID_TEMP_OVERTEMPERATURE_CHARGE_MSL
Definition: diag_cfg.h:182
@ DIAG_ID_TEMP_OVERTEMPERATURE_CHARGE_MOL
Definition: diag_cfg.h:184
@ DIAG_ID_TEMP_UNDERTEMPERATURE_CHARGE_MOL
Definition: diag_cfg.h:190
@ DIAG_ID_PACK_OVERCURRENT_DISCHARGE_MSL
Definition: diag_cfg.h:207
@ DIAG_ID_DEEP_DISCHARGE_DETECTED
Definition: diag_cfg.h:209
@ DIAG_ID_TEMP_UNDERTEMPERATURE_DISCHARGE_MOL
Definition: diag_cfg.h:193
@ DIAG_ID_CURRENT_ON_OPEN_STRING
Definition: diag_cfg.h:208
@ DIAG_ID_STRING_OVERCURRENT_DISCHARGE_MSL
Definition: diag_cfg.h:203
@ DIAG_ID_OVERCURRENT_CHARGE_CELL_MSL
Definition: diag_cfg.h:194
@ DIAG_ID_CELLVOLTAGE_UNDERVOLTAGE_MOL
Definition: diag_cfg.h:181
@ DIAG_ID_CELLVOLTAGE_OVERVOLTAGE_MSL
Definition: diag_cfg.h:176
@ DIAG_ID_TEMP_OVERTEMPERATURE_CHARGE_RSL
Definition: diag_cfg.h:183
@ DIAG_ID_CELLVOLTAGE_UNDERVOLTAGE_MSL
Definition: diag_cfg.h:179
@ DIAG_ID_TEMP_UNDERTEMPERATURE_DISCHARGE_MSL
Definition: diag_cfg.h:191
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:237
math library for often used math functions
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:76
void SOA_CheckTemperatures(DATA_BLOCK_MIN_MAX_s *pMinimumMaximumCellTemperatures, DATA_BLOCK_PACK_VALUES_s *pCurrent)
checks the abidance by the safe operating area
Definition: soa.c:145
void SOA_CheckVoltages(DATA_BLOCK_MIN_MAX_s *pMinimumMaximumCellVoltages)
checks the abidance by the safe operating area
Definition: soa.c:78
void SOA_CheckSlaveTemperatures(void)
FOR FUTURE COMPATIBILITY; DUMMY FUNCTION; DO NOT USE.
Definition: soa.c:351
void SOA_CheckCurrent(DATA_BLOCK_PACK_VALUES_s *pTablePackValues)
checks the abidance by the safe operating area
Definition: soa.c:269
Header for SOA module, responsible for checking battery parameters against safety limits.
bool SOA_IsCurrentOnOpenString(BMS_CURRENT_FLOW_STATE_e currentDirection, uint8_t stringNumber)
Checks if string current is floating while contactors are open.
Definition: soa_cfg.c:112
bool SOA_IsPackCurrentLimitViolated(uint32_t current_mA, BMS_CURRENT_FLOW_STATE_e currentDirection)
Checks if pack current limit is violated.
Definition: soa_cfg.c:72
bool SOA_IsStringCurrentLimitViolated(uint32_t current_mA, BMS_CURRENT_FLOW_STATE_e currentDirection)
Checks if string current limit is violated.
Definition: soa_cfg.c:83
bool SOA_IsCellCurrentLimitViolated(uint32_t current_mA, BMS_CURRENT_FLOW_STATE_e currentDirection)
Checks if cell current limit is violated.
Definition: soa_cfg.c:94
int16_t minimumTemperature_ddegC[BS_NR_OF_STRINGS]
Definition: database_cfg.h:172
int16_t maximumTemperature_ddegC[BS_NR_OF_STRINGS]
Definition: database_cfg.h:175
int16_t maximumCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:164
int16_t minimumCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:162
int32_t stringCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:200
uint8_t invalidStringCurrent[BS_NR_OF_STRINGS]
Definition: database_cfg.h:201