foxBMS  1.4.1
The foxBMS Battery Management System 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-10-27 (date of last update)
47  * @version v1.4.1
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  } else {
184  /* Charge */
185  if (temperatureMax_ddegC >= BC_TEMPERATURE_MAX_CHARGE_MOL_ddegC) {
186  /* Over temperature maximum operating limit violated */
188  if (temperatureMax_ddegC >= BC_TEMPERATURE_MAX_CHARGE_RSL_ddegC) {
189  /* Over temperature recommended safety limit violated */
191  /* Over temperature maximum safety limit violated */
192  if (temperatureMax_ddegC >= BC_TEMPERATURE_MAX_CHARGE_MSL_ddegC) {
194  }
195  }
196  }
197  if (temperatureMax_ddegC < BC_TEMPERATURE_MAX_CHARGE_MSL_ddegC) {
198  /* over temperature maximum safety limit NOT violated */
200  if (temperatureMax_ddegC < BC_TEMPERATURE_MAX_CHARGE_RSL_ddegC) {
201  /* over temperature recommended safety limit NOT violated */
203  if (temperatureMax_ddegC < BC_TEMPERATURE_MAX_CHARGE_MOL_ddegC) {
204  /* over temperature maximum operating limit NOT violated*/
206  }
207  }
208  }
209  }
210 
211  /* Under temperature check */
212  if (BMS_GetCurrentFlowDirection(i_current) == BMS_DISCHARGING) {
213  /* Discharge */
214  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_DISCHARGE_MOL_ddegC) {
215  /* Under temperature maximum operating limit violated */
217  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_DISCHARGE_RSL_ddegC) {
218  /* Under temperature recommended safety limit violated*/
220  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_DISCHARGE_MSL_ddegC) {
221  /* Under temperature maximum safety limit violated */
223  }
224  }
225  }
226  if (temperatureMin_ddegC > BC_TEMPERATURE_MIN_DISCHARGE_MSL_ddegC) {
227  /* under temperature maximum safety limit NOT violated */
229  if (temperatureMin_ddegC > BC_TEMPERATURE_MIN_DISCHARGE_RSL_ddegC) {
230  /* under temperature recommended safety limit NOT violated */
232  if (temperatureMin_ddegC > BC_TEMPERATURE_MIN_DISCHARGE_MOL_ddegC) {
233  /* under temperature maximum operating limit NOT violated*/
235  }
236  }
237  }
238  } else {
239  /* Charge */
240  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_CHARGE_MOL_ddegC) {
241  /* Under temperature maximum operating limit violated */
243  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_CHARGE_RSL_ddegC) {
244  /* Under temperature recommended safety limit violated */
246  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_CHARGE_MSL_ddegC) {
247  /* Under temperature maximum safety limit violated */
249  }
250  }
251  }
252  if (temperatureMin_ddegC > BC_TEMPERATURE_MIN_CHARGE_MSL_ddegC) {
253  /* under temperature maximum safety limit NOT violated */
255  if (temperatureMin_ddegC > BC_TEMPERATURE_MIN_CHARGE_RSL_ddegC) {
256  /* under temperature recommended safety limit NOT violated */
258  if (temperatureMin_ddegC > BC_TEMPERATURE_MIN_CHARGE_MOL_ddegC) {
259  /* under temperature maximum operating limit NOT violated*/
261  }
262  }
263  }
264  }
265  }
266 }
267 
268 extern void SOA_CheckCurrent(DATA_BLOCK_PACK_VALUES_s *pTablePackValues) {
269  FAS_ASSERT(pTablePackValues != NULL_PTR);
270 
271  /* Iterate over each string and check current */
272  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
273  /* Only perform check if current value is valid */
274  if (pTablePackValues->invalidStringCurrent[s] == 0u) {
275  BMS_CURRENT_FLOW_STATE_e currentDirection =
276  BMS_GetCurrentFlowDirection(pTablePackValues->stringCurrent_mA[s]);
277  uint32_t absStringCurrent_mA = (uint32_t)abs(pTablePackValues->stringCurrent_mA[s]);
278  /* Check various current limits depending on current direction */
279  bool stringOvercurrent = SOA_IsStringCurrentLimitViolated(absStringCurrent_mA, currentDirection);
280  bool cellOvercurrent = SOA_IsCellCurrentLimitViolated(absStringCurrent_mA, currentDirection);
281  if (currentDirection == BMS_CHARGING) {
282  /* Check string current limit */
283  if (stringOvercurrent == true) {
285  } else {
287  }
288  /* Check battery cell limit */
289  if (cellOvercurrent == true) {
291  } else {
293  }
294  } else if (currentDirection == BMS_DISCHARGING) {
295  /* Check string current limit */
296  if (stringOvercurrent == true) {
298  } else {
300  }
301  /* Check battery cell limit */
302  if (cellOvercurrent == true) {
304  } else {
306  }
307  } else {
308  /* No current floating -> everything okay */
313  }
314 
315  /* Check if current is floating while contactors are open */
316  if (SOA_IsCurrentOnOpenString(currentDirection, s) == false) {
318  } else {
320  }
321  }
322  }
323 
324  /* Check pack current */
325  if (pTablePackValues->invalidPackCurrent == 0u) {
326  BMS_CURRENT_FLOW_STATE_e currentDirection = BMS_GetCurrentFlowDirection(pTablePackValues->packCurrent_mA);
327  uint32_t absPackCurrent_mA = (uint32_t)abs(pTablePackValues->packCurrent_mA);
328  bool packOvercurrent = SOA_IsPackCurrentLimitViolated(absPackCurrent_mA, currentDirection);
329 
330  if (currentDirection == BMS_CHARGING) {
331  if (packOvercurrent == true) {
333  } else {
335  }
336  } else if (currentDirection == BMS_DISCHARGING) {
337  if (packOvercurrent == true) {
339  } else {
341  }
342  } else {
343  /* No current floating -> everything okay */
346  }
347  }
348 }
349 
350 extern void SOA_CheckSlaveTemperatures(void) { /* TODO: to be implemented */
351 }
352 
353 /*========== 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:1573
bms driver header
BMS_CURRENT_FLOW_STATE_e
Definition: bms.h:68
@ BMS_DISCHARGING
Definition: bms.h:70
@ BMS_CHARGING
Definition: bms.h:69
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:243
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:258
@ DIAG_EVENT_OK
Definition: diag_cfg.h:257
@ DIAG_SYSTEM
Definition: diag_cfg.h:270
@ DIAG_STRING
Definition: diag_cfg.h:271
@ DIAG_ID_TEMP_OVERTEMPERATURE_DISCHARGE_MSL
Definition: diag_cfg.h:202
@ DIAG_ID_CELL_VOLTAGE_UNDERVOLTAGE_MSL
Definition: diag_cfg.h:196
@ DIAG_ID_PACK_OVERCURRENT_CHARGE_MSL
Definition: diag_cfg.h:223
@ DIAG_ID_TEMP_UNDERTEMPERATURE_CHARGE_MSL
Definition: diag_cfg.h:205
@ DIAG_ID_TEMP_OVERTEMPERATURE_DISCHARGE_RSL
Definition: diag_cfg.h:203
@ DIAG_ID_TEMP_UNDERTEMPERATURE_DISCHARGE_RSL
Definition: diag_cfg.h:209
@ DIAG_ID_CELL_VOLTAGE_UNDERVOLTAGE_RSL
Definition: diag_cfg.h:197
@ DIAG_ID_CELL_VOLTAGE_OVERVOLTAGE_MSL
Definition: diag_cfg.h:193
@ DIAG_ID_OVERCURRENT_DISCHARGE_CELL_MSL
Definition: diag_cfg.h:214
@ DIAG_ID_TEMP_UNDERTEMPERATURE_CHARGE_RSL
Definition: diag_cfg.h:206
@ DIAG_ID_TEMP_OVERTEMPERATURE_DISCHARGE_MOL
Definition: diag_cfg.h:204
@ DIAG_ID_STRING_OVERCURRENT_CHARGE_MSL
Definition: diag_cfg.h:217
@ DIAG_ID_TEMP_OVERTEMPERATURE_CHARGE_MSL
Definition: diag_cfg.h:199
@ DIAG_ID_CELL_VOLTAGE_OVERVOLTAGE_RSL
Definition: diag_cfg.h:194
@ DIAG_ID_TEMP_OVERTEMPERATURE_CHARGE_MOL
Definition: diag_cfg.h:201
@ DIAG_ID_TEMP_UNDERTEMPERATURE_CHARGE_MOL
Definition: diag_cfg.h:207
@ DIAG_ID_PACK_OVERCURRENT_DISCHARGE_MSL
Definition: diag_cfg.h:224
@ DIAG_ID_DEEP_DISCHARGE_DETECTED
Definition: diag_cfg.h:226
@ DIAG_ID_TEMP_UNDERTEMPERATURE_DISCHARGE_MOL
Definition: diag_cfg.h:210
@ DIAG_ID_CELL_VOLTAGE_UNDERVOLTAGE_MOL
Definition: diag_cfg.h:198
@ DIAG_ID_CELL_VOLTAGE_OVERVOLTAGE_MOL
Definition: diag_cfg.h:195
@ DIAG_ID_CURRENT_ON_OPEN_STRING
Definition: diag_cfg.h:225
@ DIAG_ID_STRING_OVERCURRENT_DISCHARGE_MSL
Definition: diag_cfg.h:220
@ DIAG_ID_OVERCURRENT_CHARGE_CELL_MSL
Definition: diag_cfg.h:211
@ DIAG_ID_TEMP_OVERTEMPERATURE_CHARGE_RSL
Definition: diag_cfg.h:200
@ DIAG_ID_TEMP_UNDERTEMPERATURE_DISCHARGE_MSL
Definition: diag_cfg.h:208
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:252
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:350
void SOA_CheckCurrent(DATA_BLOCK_PACK_VALUES_s *pTablePackValues)
checks the abidance by the safe operating area
Definition: soa.c:268
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