foxBMS  1.1.1
The foxBMS Battery Management System API Documentation
soa.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2021, 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 2021-03-24 (date of last update)
47  * @ingroup APPLICATION
48  * @prefix SOA
49  *
50  * @brief SOA module responsible for checking battery parameters against
51  * safety limits
52  *
53  */
54 
55 /*========== Includes =======================================================*/
56 #include "soa.h"
57 
58 #include "battery_cell_cfg.h"
59 #include "battery_system_cfg.h"
60 
61 #include "bms.h"
62 #include "diag.h"
63 #include "foxmath.h"
64 
65 /*========== Macros and Definitions =========================================*/
66 
67 /*========== Static Constant and Variable Definitions =======================*/
68 
69 /*========== Extern Constant and Variable Definitions =======================*/
70 
71 /*========== Static Function Prototypes =====================================*/
72 
73 /*========== Static Function Implementations ================================*/
74 
75 /*========== Extern Function Implementations ================================*/
76 
77 extern void SOA_CheckVoltages(DATA_BLOCK_MIN_MAX_s *pMinimumMaximumCellVoltages) {
79 
80  for (uint8_t stringNumber = 0u; stringNumber < BS_NR_OF_STRINGS; stringNumber++) {
81  int16_t voltageMax_mV = pMinimumMaximumCellVoltages->maximumCellVoltage_mV[stringNumber];
82  int16_t voltageMin_mV = pMinimumMaximumCellVoltages->minimumCellVoltage_mV[stringNumber];
83 
84  if (voltageMax_mV >= BC_VOLTAGE_MAX_MOL_mV) {
85  /* Over voltage maximum operating limit violated */
87  if (voltageMax_mV >= BC_VOLTAGE_MAX_RSL_mV) {
88  /* Over voltage recommended safety limit violated */
90  if (voltageMax_mV >= BC_VOLTAGE_MAX_MSL_mV) {
91  /* Over voltage maximum safety limit violated */
93  }
94  }
95  }
96  if (voltageMax_mV < BC_VOLTAGE_MAX_MSL_mV) {
97  /* over voltage maximum safety limit NOT violated */
99  if (voltageMax_mV < BC_VOLTAGE_MAX_RSL_mV) {
100  /* over voltage recommended safety limit NOT violated */
102  if (voltageMax_mV < BC_VOLTAGE_MAX_MOL_mV) {
103  /* over voltage maximum operating limit NOT violated */
105  }
106  }
107  }
108 
109  if (voltageMin_mV <= BC_VOLTAGE_MIN_MOL_mV) {
110  /* Under voltage maximum operating limit violated */
112  if (voltageMin_mV <= BC_VOLTAGE_MIN_RSL_mV) {
113  /* Under voltage recommended safety limit violated */
115  if (voltageMin_mV <= BC_VOLTAGE_MIN_MSL_mV) {
116  /* Under voltage maximum safety limit violated */
117  retvalUndervoltMSL = DIAG_Handler(
119 
120  /* If under voltage flag is set and deep-discharge voltage is violated */
121  if ((retvalUndervoltMSL == DIAG_HANDLER_RETURN_ERR_OCCURRED) &&
122  (voltageMin_mV <= BC_VOLTAGE_DEEP_DISCHARGE_mV)) {
124  }
125  }
126  }
127  }
128  if (voltageMin_mV > BC_VOLTAGE_MIN_MSL_mV) {
129  /* under voltage maximum safety limit NOT violated */
131  if (voltageMin_mV > BC_VOLTAGE_MIN_RSL_mV) {
132  /* under voltage recommended safety limit NOT violated */
134  if (voltageMin_mV > BC_VOLTAGE_MIN_MOL_mV) {
135  /* under voltage maximum operating limit NOT violated */
137  }
138  }
139  }
140  }
141 }
142 
144  DATA_BLOCK_MIN_MAX_s *pMinimumMaximumCellTemperatures,
145  DATA_BLOCK_PACK_VALUES_s *pCurrent) {
146  /* Iterate over each string and check temperatures */
147  for (uint8_t stringNumber = 0u; stringNumber < BS_NR_OF_STRINGS; stringNumber++) {
148  int32_t i_current = pCurrent->stringCurrent_mA[stringNumber];
149  int16_t temperatureMin_ddegC = pMinimumMaximumCellTemperatures->minimumTemperature_ddegC[stringNumber];
150  int16_t temperatureMax_ddegC = pMinimumMaximumCellTemperatures->maximumTemperature_ddegC[stringNumber];
151 
152  /* Over temperature check */
153  if (BMS_GetCurrentFlowDirection(i_current) == BMS_DISCHARGING) {
154  /* Discharge */
155  if (temperatureMax_ddegC >= BC_TEMPERATURE_MAX_DISCHARGE_MOL_ddegC) {
156  /* Over temperature maximum operating limit violated*/
158  if (temperatureMax_ddegC >= BC_TEMPERATURE_MAX_DISCHARGE_RSL_ddegC) {
159  /* Over temperature recommended safety limit violated*/
160  DIAG_Handler(
162  if (temperatureMax_ddegC >= BC_TEMPERATURE_MAX_DISCHARGE_MSL_ddegC) {
163  /* Over temperature maximum safety limit violated */
164  DIAG_Handler(
166  }
167  }
168  }
169  if (temperatureMax_ddegC < BC_TEMPERATURE_MAX_DISCHARGE_MSL_ddegC) {
170  /* over temperature maximum safety limit NOT violated */
172  if (temperatureMax_ddegC < BC_TEMPERATURE_MAX_DISCHARGE_RSL_ddegC) {
173  /* over temperature recommended safety limit NOT violated */
175  if (temperatureMax_ddegC < BC_TEMPERATURE_MAX_DISCHARGE_MOL_ddegC) {
176  /* over temperature maximum operating limit NOT violated */
177  DIAG_Handler(
179  }
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) {
193  DIAG_Handler(
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*/
220  DIAG_Handler(
222  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_DISCHARGE_MSL_ddegC) {
223  /* Under temperature maximum safety limit violated */
224  DIAG_Handler(
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*/
237  DIAG_Handler(
239  }
240  }
241  }
242  } else {
243  /* Charge */
244  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_CHARGE_MOL_ddegC) {
245  /* Under temperature maximum operating limit violated */
247  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_CHARGE_RSL_ddegC) {
248  /* Under temperature recommended safety limit violated */
249  DIAG_Handler(
251  if (temperatureMin_ddegC <= BC_TEMPERATURE_MIN_CHARGE_MSL_ddegC) {
252  /* Under temperature maximum safety limit violated */
253  DIAG_Handler(
255  }
256  }
257  }
258  if (temperatureMin_ddegC > BC_TEMPERATURE_MIN_CHARGE_MSL_ddegC) {
259  /* under temperature maximum safety limit NOT violated */
261  if (temperatureMin_ddegC > BC_TEMPERATURE_MIN_CHARGE_RSL_ddegC) {
262  /* under temperature recommended safety limit NOT violated */
264  if (temperatureMin_ddegC > BC_TEMPERATURE_MIN_CHARGE_MOL_ddegC) {
265  /* under temperature maximum operating limit NOT violated*/
266  DIAG_Handler(
268  }
269  }
270  }
271  }
272  }
273 }
274 
275 extern void SOA_CheckCurrent(DATA_BLOCK_PACK_VALUES_s *pTablePackValues) {
276  FAS_ASSERT(pTablePackValues != NULL_PTR);
277 
278  /* Iterate over each string and check current */
279  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
280  /* Only perform check if current value is valid */
281  if (0u == pTablePackValues->invalidStringCurrent[s]) {
282  BMS_CURRENT_FLOW_STATE_e currentDirection =
283  BMS_GetCurrentFlowDirection(pTablePackValues->stringCurrent_mA[s]);
284  uint32_t absStringCurrent_mA = (uint32_t)abs(pTablePackValues->stringCurrent_mA[s]);
285  /* Check various current limits depending on current direction */
286  bool stringOvercurrent = SOA_IsStringCurrentLimitViolated(absStringCurrent_mA, currentDirection);
287  bool cellOvercurrent = SOA_IsCellCurrentLimitViolated(absStringCurrent_mA, currentDirection);
288  if (BMS_CHARGING == currentDirection) {
289  /* Check string current limit */
290  if (true == stringOvercurrent) {
292  } else {
294  }
295  /* Check battery cell limit */
296  if (true == cellOvercurrent) {
298  } else {
300  }
301  } else if (BMS_DISCHARGING == currentDirection) {
302  /* Check string current limit */
303  if (true == stringOvercurrent) {
305  } else {
307  }
308  /* Check battery cell limit */
309  if (true == cellOvercurrent) {
311  } else {
313  }
314  } else {
315  /* No current floating -> everything okay */
320  }
321 
322  /* Check if current is floating while contactors are open */
323  if (false == SOA_IsCurrentOnOpenString(currentDirection, s)) {
325  } else {
327  }
328  }
329  }
330 
331  /* Check pack current */
332  if (0u == pTablePackValues->invalidPackCurrent) {
333  BMS_CURRENT_FLOW_STATE_e currentDirection = BMS_GetCurrentFlowDirection(pTablePackValues->packCurrent_mA);
334  uint32_t absPackCurrent_mA = (uint32_t)abs(pTablePackValues->packCurrent_mA);
335  bool packOvercurrent = SOA_IsCellCurrentLimitViolated(absPackCurrent_mA, currentDirection);
336 
337  if (BMS_CHARGING == currentDirection) {
338  if (true == packOvercurrent) {
340  } else {
342  }
343  } else if (BMS_DISCHARGING == currentDirection) {
344  if (true == packOvercurrent) {
346  } else {
348  }
349  } else {
350  /* No current floating -> everything okay */
353  }
354  }
355 }
356 
357 extern void SOA_CheckSlaveTemperatures(void) { /* TODO: to be implemented */
358 }
359 
360 /*========== 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
BMS_CURRENT_FLOW_STATE_e BMS_GetCurrentFlowDirection(int32_t current_mA)
Get current flow direction, current value as function parameter.
Definition: bms.c:1276
bms driver header
@ BMS_DISCHARGING
Definition: bms.h:67
@ BMS_CHARGING
Definition: bms.h:66
enum BMS_CURRENT_FLOW_STATE BMS_CURRENT_FLOW_STATE_e
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:226
Diagnosis driver header.
@ DIAG_HANDLER_RETURN_ERR_OCCURRED
Definition: diag.h:65
enum DIAG_RETURNTYPE DIAG_RETURNTYPE_e
@ DIAG_SYSTEM
Definition: diag_cfg.h:247
@ DIAG_STRING
Definition: diag_cfg.h:248
@ DIAG_EVENT_NOT_OK
Definition: diag_cfg.h:235
@ DIAG_EVENT_OK
Definition: diag_cfg.h:234
@ DIAG_ID_TEMP_OVERTEMPERATURE_DISCHARGE_MSL
Definition: diag_cfg.h:184
@ DIAG_ID_PACK_OVERCURRENT_CHARGE_MSL
Definition: diag_cfg.h:205
@ DIAG_ID_CELLVOLTAGE_UNDERVOLTAGE_RSL
Definition: diag_cfg.h:179
@ DIAG_ID_TEMP_UNDERTEMPERATURE_CHARGE_MSL
Definition: diag_cfg.h:187
@ DIAG_ID_TEMP_OVERTEMPERATURE_DISCHARGE_RSL
Definition: diag_cfg.h:185
@ DIAG_ID_TEMP_UNDERTEMPERATURE_DISCHARGE_RSL
Definition: diag_cfg.h:191
@ DIAG_ID_CELLVOLTAGE_OVERVOLTAGE_MOL
Definition: diag_cfg.h:177
@ DIAG_ID_OVERCURRENT_DISCHARGE_CELL_MSL
Definition: diag_cfg.h:196
@ DIAG_ID_CELLVOLTAGE_OVERVOLTAGE_RSL
Definition: diag_cfg.h:176
@ DIAG_ID_TEMP_UNDERTEMPERATURE_CHARGE_RSL
Definition: diag_cfg.h:188
@ DIAG_ID_TEMP_OVERTEMPERATURE_DISCHARGE_MOL
Definition: diag_cfg.h:186
@ DIAG_ID_STRING_OVERCURRENT_CHARGE_MSL
Definition: diag_cfg.h:199
@ DIAG_ID_TEMP_OVERTEMPERATURE_CHARGE_MSL
Definition: diag_cfg.h:181
@ DIAG_ID_TEMP_OVERTEMPERATURE_CHARGE_MOL
Definition: diag_cfg.h:183
@ DIAG_ID_TEMP_UNDERTEMPERATURE_CHARGE_MOL
Definition: diag_cfg.h:189
@ DIAG_ID_PACK_OVERCURRENT_DISCHARGE_MSL
Definition: diag_cfg.h:206
@ DIAG_ID_DEEP_DISCHARGE_DETECTED
Definition: diag_cfg.h:208
@ DIAG_ID_TEMP_UNDERTEMPERATURE_DISCHARGE_MOL
Definition: diag_cfg.h:192
@ DIAG_ID_CURRENT_ON_OPEN_STRING
Definition: diag_cfg.h:207
@ DIAG_ID_STRING_OVERCURRENT_DISCHARGE_MSL
Definition: diag_cfg.h:202
@ DIAG_ID_OVERCURRENT_CHARGE_CELL_MSL
Definition: diag_cfg.h:193
@ DIAG_ID_CELLVOLTAGE_UNDERVOLTAGE_MOL
Definition: diag_cfg.h:180
@ DIAG_ID_CELLVOLTAGE_OVERVOLTAGE_MSL
Definition: diag_cfg.h:175
@ DIAG_ID_TEMP_OVERTEMPERATURE_CHARGE_RSL
Definition: diag_cfg.h:182
@ DIAG_ID_CELLVOLTAGE_UNDERVOLTAGE_MSL
Definition: diag_cfg.h:178
@ DIAG_ID_TEMP_UNDERTEMPERATURE_DISCHARGE_MSL
Definition: diag_cfg.h:190
#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:66
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:143
void SOA_CheckVoltages(DATA_BLOCK_MIN_MAX_s *pMinimumMaximumCellVoltages)
checks the abidance by the safe operating area
Definition: soa.c:77
void SOA_CheckSlaveTemperatures(void)
FOR FUTURE COMPATIBILITY; DUMMY FUNCTION; DO NOT USE.
Definition: soa.c:357
void SOA_CheckCurrent(DATA_BLOCK_PACK_VALUES_s *pTablePackValues)
checks the abidance by the safe operating area
Definition: soa.c:275
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:111
bool SOA_IsStringCurrentLimitViolated(uint32_t current_mA, BMS_CURRENT_FLOW_STATE_e currentDirection)
Checks if string current limit is violated.
Definition: soa_cfg.c:82
bool SOA_IsCellCurrentLimitViolated(uint32_t current_mA, BMS_CURRENT_FLOW_STATE_e currentDirection)
Checks if cell current limit is violated.
Definition: soa_cfg.c:93
int16_t maximumTemperature_ddegC[BS_NR_OF_STRINGS]
Definition: database_cfg.h:179
int16_t minimumTemperature_ddegC[BS_NR_OF_STRINGS]
Definition: database_cfg.h:176
int16_t maximumCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:168
int16_t minimumCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:166
int32_t stringCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:204
uint8_t invalidStringCurrent[BS_NR_OF_STRINGS]
Definition: database_cfg.h:205