foxBMS  1.6.0
The foxBMS Battery Management System API Documentation
soa.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2023, 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 2023-10-12 (date of last update)
47  * @version v1.6.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 #include <stdbool.h>
67 #include <stdint.h>
68 
69 /*========== Macros and Definitions =========================================*/
70 
71 /*========== Static Constant and Variable Definitions =======================*/
72 
73 /*========== Extern Constant and Variable Definitions =======================*/
74 
75 /*========== Static Function Prototypes =====================================*/
76 
77 /*========== Static Function Implementations ================================*/
78 
79 /*========== Extern Function Implementations ================================*/
80 
81 extern void SOA_CheckVoltages(DATA_BLOCK_MIN_MAX_s *pMinimumMaximumCellVoltages) {
82  FAS_ASSERT(pMinimumMaximumCellVoltages != NULL_PTR);
84 
85  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
86  int16_t voltageMax_mV = pMinimumMaximumCellVoltages->maximumCellVoltage_mV[s];
87  int16_t voltageMin_mV = pMinimumMaximumCellVoltages->minimumCellVoltage_mV[s];
88 
89  if (voltageMax_mV >= BC_VOLTAGE_MAX_MOL_mV) {
90  /* Over voltage maximum operating limit violated */
92  if (voltageMax_mV >= BC_VOLTAGE_MAX_RSL_mV) {
93  /* Over voltage recommended safety limit violated */
95  if (voltageMax_mV >= BC_VOLTAGE_MAX_MSL_mV) {
96  /* Over voltage maximum safety limit violated */
98  }
99  }
100  }
101  if (voltageMax_mV < BC_VOLTAGE_MAX_MSL_mV) {
102  /* over voltage maximum safety limit NOT violated */
104  if (voltageMax_mV < BC_VOLTAGE_MAX_RSL_mV) {
105  /* over voltage recommended safety limit NOT violated */
107  if (voltageMax_mV < BC_VOLTAGE_MAX_MOL_mV) {
108  /* over voltage maximum operating limit NOT violated */
110  }
111  }
112  }
113 
114  if (voltageMin_mV <= BC_VOLTAGE_MIN_MOL_mV) {
115  /* Under voltage maximum operating limit violated */
117  if (voltageMin_mV <= BC_VOLTAGE_MIN_RSL_mV) {
118  /* Under voltage recommended safety limit violated */
120  if (voltageMin_mV <= BC_VOLTAGE_MIN_MSL_mV) {
121  /* Under voltage maximum safety limit violated */
122  retvalUndervoltMSL =
124 
125  /* If under voltage flag is set and deep-discharge voltage is violated */
126  if ((retvalUndervoltMSL == DIAG_HANDLER_RETURN_ERR_OCCURRED) &&
127  (voltageMin_mV <= BC_VOLTAGE_DEEP_DISCHARGE_mV)) {
129  }
130  }
131  }
132  }
133  if (voltageMin_mV > BC_VOLTAGE_MIN_MSL_mV) {
134  /* under voltage maximum safety limit NOT violated */
136  if (voltageMin_mV > BC_VOLTAGE_MIN_RSL_mV) {
137  /* under voltage recommended safety limit NOT violated */
139  if (voltageMin_mV > BC_VOLTAGE_MIN_MOL_mV) {
140  /* under voltage maximum operating limit NOT violated */
142  }
143  }
144  }
145  }
146 }
147 
149  DATA_BLOCK_MIN_MAX_s *pMinimumMaximumCellTemperatures,
150  DATA_BLOCK_PACK_VALUES_s *pCurrent) {
151  FAS_ASSERT(pMinimumMaximumCellTemperatures != NULL_PTR);
152  FAS_ASSERT(pCurrent != NULL_PTR);
153  /* Iterate over each string and check temperatures */
154  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
155  int32_t i_current = pCurrent->stringCurrent_mA[s];
156  int16_t temperatureMin_ddegC = pMinimumMaximumCellTemperatures->minimumTemperature_ddegC[s];
157  int16_t temperatureMax_ddegC = pMinimumMaximumCellTemperatures->maximumTemperature_ddegC[s];
158 
159  /* Over temperature check */
160  if (BMS_GetCurrentFlowDirection(i_current) == BMS_DISCHARGING) {
161  /* Discharge */
162  if (temperatureMax_ddegC >= BC_TEMPERATURE_MAX_DISCHARGE_MOL_ddegC) {
163  /* Over temperature maximum operating limit violated*/
165  if (temperatureMax_ddegC >= BC_TEMPERATURE_MAX_DISCHARGE_RSL_ddegC) {
166  /* Over temperature recommended safety limit violated*/
168  if (temperatureMax_ddegC >= BC_TEMPERATURE_MAX_DISCHARGE_MSL_ddegC) {
169  /* Over temperature maximum safety limit violated */
171  }
172  }
173  }
174  if (temperatureMax_ddegC < BC_TEMPERATURE_MAX_DISCHARGE_MSL_ddegC) {
175  /* over temperature maximum safety limit NOT violated */
177  if (temperatureMax_ddegC < BC_TEMPERATURE_MAX_DISCHARGE_RSL_ddegC) {
178  /* over temperature recommended safety limit NOT violated */
180  if (temperatureMax_ddegC < BC_TEMPERATURE_MAX_DISCHARGE_MOL_ddegC) {
181  /* over temperature maximum operating limit NOT violated */
183  }
184  }
185  }
186  } else {
187  /* Charge */
188  if (temperatureMax_ddegC >= BC_TEMPERATURE_MAX_CHARGE_MOL_ddegC) {
189  /* Over temperature maximum operating limit violated */
191  if (temperatureMax_ddegC >= BC_TEMPERATURE_MAX_CHARGE_RSL_ddegC) {
192  /* Over temperature recommended safety limit violated */
194  /* Over temperature maximum safety limit violated */
195  if (temperatureMax_ddegC >= BC_TEMPERATURE_MAX_CHARGE_MSL_ddegC) {
197  }
198  }
199  }
200  if (temperatureMax_ddegC < BC_TEMPERATURE_MAX_CHARGE_MSL_ddegC) {
201  /* over temperature maximum safety limit NOT violated */
203  if (temperatureMax_ddegC < BC_TEMPERATURE_MAX_CHARGE_RSL_ddegC) {
204  /* over temperature recommended safety limit NOT violated */
206  if (temperatureMax_ddegC < BC_TEMPERATURE_MAX_CHARGE_MOL_ddegC) {
207  /* over temperature maximum operating limit NOT violated*/
209  }
210  }
211  }
212  }
213 
214  /* Under temperature check */
215  if (BMS_GetCurrentFlowDirection(i_current) == BMS_DISCHARGING) {
216  /* Discharge */
217  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_DISCHARGE_MOL_ddegC) {
218  /* Under temperature maximum operating limit violated */
220  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_DISCHARGE_RSL_ddegC) {
221  /* Under temperature recommended safety limit violated*/
223  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_DISCHARGE_MSL_ddegC) {
224  /* Under temperature maximum safety limit violated */
226  }
227  }
228  }
229  if (temperatureMin_ddegC > BC_TEMPERATURE_MIN_DISCHARGE_MSL_ddegC) {
230  /* under temperature maximum safety limit NOT violated */
232  if (temperatureMin_ddegC > BC_TEMPERATURE_MIN_DISCHARGE_RSL_ddegC) {
233  /* under temperature recommended safety limit NOT violated */
235  if (temperatureMin_ddegC > BC_TEMPERATURE_MIN_DISCHARGE_MOL_ddegC) {
236  /* under temperature maximum operating limit NOT violated*/
238  }
239  }
240  }
241  } else {
242  /* Charge */
243  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_CHARGE_MOL_ddegC) {
244  /* Under temperature maximum operating limit violated */
246  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_CHARGE_RSL_ddegC) {
247  /* Under temperature recommended safety limit violated */
249  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_CHARGE_MSL_ddegC) {
250  /* Under temperature maximum safety limit violated */
252  }
253  }
254  }
255  if (temperatureMin_ddegC > BC_TEMPERATURE_MIN_CHARGE_MSL_ddegC) {
256  /* under temperature maximum safety limit NOT violated */
258  if (temperatureMin_ddegC > BC_TEMPERATURE_MIN_CHARGE_RSL_ddegC) {
259  /* under temperature recommended safety limit NOT violated */
261  if (temperatureMin_ddegC > BC_TEMPERATURE_MIN_CHARGE_MOL_ddegC) {
262  /* under temperature maximum operating limit NOT violated*/
264  }
265  }
266  }
267  }
268  }
269 }
270 
271 extern void SOA_CheckCurrent(DATA_BLOCK_PACK_VALUES_s *pTablePackValues) {
272  FAS_ASSERT(pTablePackValues != NULL_PTR);
273 
274  /* Iterate over each string and check current */
275  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
276  /* Only perform check if current value is valid */
277  if (pTablePackValues->invalidStringCurrent[s] == 0u) {
278  BMS_CURRENT_FLOW_STATE_e currentDirection =
279  BMS_GetCurrentFlowDirection(pTablePackValues->stringCurrent_mA[s]);
280  uint32_t absStringCurrent_mA = (uint32_t)abs(pTablePackValues->stringCurrent_mA[s]);
281  /* Check various current limits depending on current direction */
282  bool stringOvercurrent = SOA_IsStringCurrentLimitViolated(absStringCurrent_mA, currentDirection);
283  bool cellOvercurrent = SOA_IsCellCurrentLimitViolated(absStringCurrent_mA, currentDirection);
284  if (currentDirection == BMS_CHARGING) {
285  /* Check string current limit */
286  if (stringOvercurrent == true) {
288  } else {
290  }
291  /* Check battery cell limit */
292  if (cellOvercurrent == true) {
294  } else {
296  }
297  } else if (currentDirection == BMS_DISCHARGING) {
298  /* Check string current limit */
299  if (stringOvercurrent == true) {
301  } else {
303  }
304  /* Check battery cell limit */
305  if (cellOvercurrent == true) {
307  } else {
309  }
310  } else {
311  /* No current floating -> everything okay */
316  }
317 
318  /* Check if current is floating while contactors are open */
319  if (SOA_IsCurrentOnOpenString(currentDirection, s) == false) {
321  } else {
323  }
324  }
325  }
326 
327  /* Check pack current */
328  if (pTablePackValues->invalidPackCurrent == 0u) {
329  BMS_CURRENT_FLOW_STATE_e currentDirection = BMS_GetCurrentFlowDirection(pTablePackValues->packCurrent_mA);
330  uint32_t absPackCurrent_mA = (uint32_t)abs(pTablePackValues->packCurrent_mA);
331  bool packOvercurrent = SOA_IsPackCurrentLimitViolated(absPackCurrent_mA, currentDirection);
332 
333  if (currentDirection == BMS_CHARGING) {
334  if (packOvercurrent == true) {
336  } else {
338  }
339  } else if (currentDirection == BMS_DISCHARGING) {
340  if (packOvercurrent == true) {
342  } else {
344  }
345  } else {
346  /* No current floating -> everything okay */
349  }
350  }
351 }
352 
353 extern void SOA_CheckSlaveTemperatures(void) { /* TODO: to be implemented */
354 }
355 
356 /*========== Externalized Static Function Implementations (Unit Test) =======*/
357 #ifdef UNITY_UNIT_TEST
358 #endif
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 charge.
#define BC_TEMPERATURE_MAX_CHARGE_MSL_ddegC
Maximum temperature limit during charge.
#define BC_TEMPERATURE_MIN_CHARGE_MSL_ddegC
Minimum temperature limit during charge.
#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 charge.
#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:1590
bms driver header
BMS_CURRENT_FLOW_STATE_e
Definition: bms.h:72
@ BMS_DISCHARGING
Definition: bms.h:74
@ BMS_CHARGING
Definition: bms.h:73
DIAG_RETURNTYPE_e DIAG_Handler(DIAG_ID_e diagId, 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:246
Diagnosis driver header.
DIAG_RETURNTYPE_e
Definition: diag.h:68
@ DIAG_HANDLER_RETURN_ERR_OCCURRED
Definition: diag.h:70
@ DIAG_EVENT_NOT_OK
Definition: diag_cfg.h:268
@ DIAG_EVENT_OK
Definition: diag_cfg.h:267
@ DIAG_SYSTEM
Definition: diag_cfg.h:280
@ DIAG_STRING
Definition: diag_cfg.h:281
@ DIAG_ID_TEMP_OVERTEMPERATURE_DISCHARGE_MSL
Definition: diag_cfg.h:205
@ DIAG_ID_CELL_VOLTAGE_UNDERVOLTAGE_MSL
Definition: diag_cfg.h:199
@ DIAG_ID_PACK_OVERCURRENT_CHARGE_MSL
Definition: diag_cfg.h:226
@ DIAG_ID_TEMP_UNDERTEMPERATURE_CHARGE_MSL
Definition: diag_cfg.h:208
@ DIAG_ID_TEMP_OVERTEMPERATURE_DISCHARGE_RSL
Definition: diag_cfg.h:206
@ DIAG_ID_TEMP_UNDERTEMPERATURE_DISCHARGE_RSL
Definition: diag_cfg.h:212
@ DIAG_ID_CELL_VOLTAGE_UNDERVOLTAGE_RSL
Definition: diag_cfg.h:200
@ DIAG_ID_CELL_VOLTAGE_OVERVOLTAGE_MSL
Definition: diag_cfg.h:196
@ DIAG_ID_OVERCURRENT_DISCHARGE_CELL_MSL
Definition: diag_cfg.h:217
@ DIAG_ID_TEMP_UNDERTEMPERATURE_CHARGE_RSL
Definition: diag_cfg.h:209
@ DIAG_ID_TEMP_OVERTEMPERATURE_DISCHARGE_MOL
Definition: diag_cfg.h:207
@ DIAG_ID_STRING_OVERCURRENT_CHARGE_MSL
Definition: diag_cfg.h:220
@ DIAG_ID_TEMP_OVERTEMPERATURE_CHARGE_MSL
Definition: diag_cfg.h:202
@ DIAG_ID_CELL_VOLTAGE_OVERVOLTAGE_RSL
Definition: diag_cfg.h:197
@ DIAG_ID_TEMP_OVERTEMPERATURE_CHARGE_MOL
Definition: diag_cfg.h:204
@ DIAG_ID_TEMP_UNDERTEMPERATURE_CHARGE_MOL
Definition: diag_cfg.h:210
@ DIAG_ID_PACK_OVERCURRENT_DISCHARGE_MSL
Definition: diag_cfg.h:227
@ DIAG_ID_DEEP_DISCHARGE_DETECTED
Definition: diag_cfg.h:229
@ DIAG_ID_TEMP_UNDERTEMPERATURE_DISCHARGE_MOL
Definition: diag_cfg.h:213
@ DIAG_ID_CELL_VOLTAGE_UNDERVOLTAGE_MOL
Definition: diag_cfg.h:201
@ DIAG_ID_CELL_VOLTAGE_OVERVOLTAGE_MOL
Definition: diag_cfg.h:198
@ DIAG_ID_CURRENT_ON_OPEN_STRING
Definition: diag_cfg.h:228
@ DIAG_ID_STRING_OVERCURRENT_DISCHARGE_MSL
Definition: diag_cfg.h:223
@ DIAG_ID_OVERCURRENT_CHARGE_CELL_MSL
Definition: diag_cfg.h:214
@ DIAG_ID_TEMP_OVERTEMPERATURE_CHARGE_RSL
Definition: diag_cfg.h:203
@ DIAG_ID_TEMP_UNDERTEMPERATURE_DISCHARGE_MSL
Definition: diag_cfg.h:211
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:255
math library for often used math functions
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:77
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:148
void SOA_CheckVoltages(DATA_BLOCK_MIN_MAX_s *pMinimumMaximumCellVoltages)
checks the abidance by the safe operating area
Definition: soa.c:81
void SOA_CheckSlaveTemperatures(void)
FOR FUTURE COMPATIBILITY; DUMMY FUNCTION; DO NOT USE.
Definition: soa.c:353
void SOA_CheckCurrent(DATA_BLOCK_PACK_VALUES_s *pTablePackValues)
checks the abidance by the safe operating area
Definition: soa.c:271
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:115
bool SOA_IsPackCurrentLimitViolated(uint32_t current_mA, BMS_CURRENT_FLOW_STATE_e currentDirection)
Checks if pack current limit is violated.
Definition: soa_cfg.c:75
bool SOA_IsStringCurrentLimitViolated(uint32_t current_mA, BMS_CURRENT_FLOW_STATE_e currentDirection)
Checks if string current limit is violated.
Definition: soa_cfg.c:86
bool SOA_IsCellCurrentLimitViolated(uint32_t current_mA, BMS_CURRENT_FLOW_STATE_e currentDirection)
Checks if cell current limit is violated.
Definition: soa_cfg.c:97
int16_t minimumTemperature_ddegC[BS_NR_OF_STRINGS]
Definition: database_cfg.h:180
int16_t maximumTemperature_ddegC[BS_NR_OF_STRINGS]
Definition: database_cfg.h:183
int16_t maximumCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:172
int16_t minimumCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:170
int32_t stringCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:208
uint8_t invalidStringCurrent[BS_NR_OF_STRINGS]
Definition: database_cfg.h:209