foxBMS - Unit Tests  1.3.0
The foxBMS Unit Tests API Documentation
sof.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 sof.c
44  * @author foxBMS Team
45  * @date 2020-10-07 (date of creation)
46  * @updated 2022-05-30 (date of last update)
47  * @version v1.3.0
48  * @ingroup APPLICATION_CONFIGURATION
49  * @prefix SOF
50  *
51  * @brief SOX module responsible for current derating calculation
52  *
53  */
54 
55 /*========== Includes =======================================================*/
56 #include "sof.h"
57 
58 #include "battery_cell_cfg.h"
59 #include "battery_system_cfg.h"
60 
61 #include "bms.h"
62 #include "database.h"
63 #include "foxmath.h"
64 
65 #include <float.h>
66 
67 /*========== Macros and Definitions =========================================*/
68 
69 /*========== Static Constant and Variable Definitions =======================*/
70 /** @{
71  * module-local static Variables that are calculated at startup and used later to avoid divisions at runtime
72  */
77 /** @} */
78 
79 /** local copies of database tables */
80 /**@{*/
83 /**@}*/
84 
85 /*========== Extern Constant and Variable Definitions =======================*/
86 
87 /*========== Static Function Prototypes =====================================*/
88 
89 /**
90  * @brief calculate SOF curve depending on configured configuration values
91  *
92  * @param[in] pConfigurationValues SOF curve configuration values
93  * @param[out] pCalculatedSofCurveValues calculate SOF curve
94  */
95 static void SOF_CalculateCurves(const SOF_CONFIG_s *pConfigurationValues, SOF_CURVE_s *pCalculatedSofCurveValues);
96 
97 /**
98  * @brief calculates the SoF from voltage data (i.e., minimum and maximum voltage)
99  *
100  * @param[in] minimumCellVoltage_mV minimum cell voltage
101  * @param[in] maximumCellVoltage_mV maximum cell voltage
102  * @param[out] pAllowedVoltageBasedCurrent Voltage-based SOF
103  * @param[in] pConfigLimitValues pointer to the SOF configuration structure
104  * @param[in] pCalculatedSofCurves pointer to the SOF curve structure
105  */
107  int16_t minimumCellVoltage_mV,
108  int16_t maximumCellVoltage_mV,
109  SOF_CURRENT_LIMITS_s *pAllowedVoltageBasedCurrent,
110  const SOF_CONFIG_s *pConfigLimitValues,
111  SOF_CURVE_s *pCalculatedSofCurves);
112 
113 /**
114  * @brief calculates the SoF from temperature data (i.e., minimum and maximum temperature of cells)
115  *
116  * @param[in] minimumCellTemperature_ddegC minimum temperature of cells
117  * @param[in] maximumCellTemperature_ddegC maximum temperature of cells
118  * @param[out] pAllowedTemperatureBasedCurrent pointer where to store the results
119  * @param[in] pConfigLimitValues pointer to the structure used for SOF calculation
120  * @param[in] pCalculatedSofCurves pointer to the structure containing limit values
121  */
123  int16_t minimumCellTemperature_ddegC,
124  int16_t maximumCellTemperature_ddegC,
125  SOF_CURRENT_LIMITS_s *pAllowedTemperatureBasedCurrent,
126  const SOF_CONFIG_s *pConfigLimitValues,
127  SOF_CURVE_s *pCalculatedSofCurves);
128 
129 /**
130  * @brief get the minimum current values of all variants of SoF calculation
131  *
132  * @param[in] voltageBasedLimits voltage constrained current derating values
133  * @param[in] temperatureBasedLimits temperature constrained current derating values
134  *
135  * @return minimum SoF current values
136  */
138  SOF_CURRENT_LIMITS_s voltageBasedLimits,
139  SOF_CURRENT_LIMITS_s temperatureBasedLimits);
140 
141 /*========== Static Function Implementations ================================*/
142 static void SOF_CalculateCurves(const SOF_CONFIG_s *pConfigurationValues, SOF_CURVE_s *pCalculatedSofCurveValues) {
143  FAS_ASSERT(pConfigurationValues != NULL_PTR);
144  FAS_ASSERT(pCalculatedSofCurveValues != NULL_PTR);
145 
146  /* Calculating SOF curve for the maximum allowed current for MOL/RSL/MSL */
147  pCalculatedSofCurveValues->slopeLowTemperatureDischarge =
148  (pConfigurationValues->maximumDischargeCurrent_mA - pConfigurationValues->limpHomeCurrent_mA) /
149  (pConfigurationValues->cutoffLowTemperatureDischarge_ddegC -
150  pConfigurationValues->limitLowTemperatureDischarge_ddegC);
151  pCalculatedSofCurveValues->offsetLowTemperatureDischarge =
152  pConfigurationValues->limpHomeCurrent_mA - (pCalculatedSofCurveValues->slopeLowTemperatureDischarge *
153  pConfigurationValues->limitLowTemperatureDischarge_ddegC);
154 
155  pCalculatedSofCurveValues->slopeHighTemperatureDischarge =
156  (0.0f - pConfigurationValues->maximumDischargeCurrent_mA) /
157  (pConfigurationValues->limitHighTemperatureDischarge_ddegC -
158  pConfigurationValues->cutoffHighTemperatureDischarge_ddegC);
159  pCalculatedSofCurveValues->offsetHighTemperatureDischarge =
160  0.0f - (pCalculatedSofCurveValues->slopeHighTemperatureDischarge *
161  pConfigurationValues->limitHighTemperatureDischarge_ddegC);
162 
163  pCalculatedSofCurveValues->slopeLowTemperatureCharge = (pConfigurationValues->maximumChargeCurrent_mA - 0.0f) /
164  (pConfigurationValues->cutoffLowTemperatureCharge_ddegC -
165  pConfigurationValues->limitLowTemperatureCharge_ddegC);
166  pCalculatedSofCurveValues->offsetLowTemperatureCharge =
167  0.0f -
168  (pCalculatedSofCurveValues->slopeLowTemperatureCharge * pConfigurationValues->limitLowTemperatureCharge_ddegC);
169 
170  pCalculatedSofCurveValues->slopeHighTemperatureCharge = (0.0f - pConfigurationValues->maximumChargeCurrent_mA) /
171  (pConfigurationValues->limitHighTemperatureCharge_ddegC -
172  pConfigurationValues->cutoffHighTemperatureCharge_ddegC);
173  pCalculatedSofCurveValues->offsetHighTemperatureCharge = 0.0f -
174  (pCalculatedSofCurveValues->slopeHighTemperatureCharge *
175  pConfigurationValues->limitHighTemperatureCharge_ddegC);
176 
177  pCalculatedSofCurveValues->slopeUpperCellVoltage =
178  (pConfigurationValues->maximumDischargeCurrent_mA - 0.0f) /
179  (pConfigurationValues->cutoffLowerCellVoltage_mV - pConfigurationValues->limitLowerCellVoltage_mV);
180  pCalculatedSofCurveValues->offsetUpperCellVoltage =
181  0.0f - (pCalculatedSofCurveValues->slopeUpperCellVoltage * pConfigurationValues->limitLowerCellVoltage_mV);
182 
183  pCalculatedSofCurveValues->slopeLowerCellVoltage =
184  (pConfigurationValues->maximumChargeCurrent_mA - 0.0f) /
185  (pConfigurationValues->cutoffUpperCellVoltage_mV - pConfigurationValues->limitUpperCellVoltage_mV);
186  pCalculatedSofCurveValues->offsetLowerCellVoltage =
187  0.0f - (pCalculatedSofCurveValues->slopeLowerCellVoltage * pConfigurationValues->limitLowerCellVoltage_mV);
188 }
189 
191  int16_t minimumCellVoltage_mV,
192  int16_t maximumCellVoltage_mV,
193  SOF_CURRENT_LIMITS_s *pAllowedVoltageBasedCurrent,
194  const SOF_CONFIG_s *pConfigLimitValues,
195  SOF_CURVE_s *pCalculatedSofCurves) {
196  FAS_ASSERT(pAllowedVoltageBasedCurrent != NULL_PTR);
197  FAS_ASSERT(pConfigLimitValues != NULL_PTR);
198  FAS_ASSERT(pCalculatedSofCurves != NULL_PTR);
199  /* AXIVION Routine Generic-MissingParameterAssert: minimumCellVoltage_mV: parameter accept whole range */
200  /* AXIVION Routine Generic-MissingParameterAssert: maximumCellVoltage_mV: parameter accept whole range */
201 
202  /* minimum cell voltage calculation */
203  if (minimumCellVoltage_mV <= pConfigLimitValues->limitLowerCellVoltage_mV) {
204  pAllowedVoltageBasedCurrent->continuousDischargeCurrent_mA = 0.0f;
205  pAllowedVoltageBasedCurrent->peakDischargeCurrent_mA = 0.0f;
206  } else {
207  if (minimumCellVoltage_mV <= pConfigLimitValues->cutoffLowerCellVoltage_mV) {
208  pAllowedVoltageBasedCurrent->continuousDischargeCurrent_mA =
209  (pCalculatedSofCurves->slopeUpperCellVoltage *
210  (minimumCellVoltage_mV - pConfigLimitValues->limitLowerCellVoltage_mV));
211  pAllowedVoltageBasedCurrent->peakDischargeCurrent_mA =
212  pAllowedVoltageBasedCurrent->continuousDischargeCurrent_mA;
213  } else {
214  pAllowedVoltageBasedCurrent->continuousDischargeCurrent_mA = pConfigLimitValues->maximumDischargeCurrent_mA;
215  pAllowedVoltageBasedCurrent->peakDischargeCurrent_mA = pConfigLimitValues->maximumDischargeCurrent_mA;
216  }
217  }
218  /* maximum cell voltage calculation */
219  if (maximumCellVoltage_mV >= pConfigLimitValues->limitUpperCellVoltage_mV) {
220  pAllowedVoltageBasedCurrent->continuousChargeCurrent_mA = 0.0f;
221  pAllowedVoltageBasedCurrent->peakChargeCurrent_mA = 0.0f;
222  } else {
223  if (maximumCellVoltage_mV >= pConfigLimitValues->cutoffUpperCellVoltage_mV) {
224  pAllowedVoltageBasedCurrent->continuousChargeCurrent_mA =
225  (pCalculatedSofCurves->slopeLowerCellVoltage *
226  (maximumCellVoltage_mV - pConfigLimitValues->limitUpperCellVoltage_mV));
227  pAllowedVoltageBasedCurrent->peakChargeCurrent_mA = pAllowedVoltageBasedCurrent->continuousChargeCurrent_mA;
228  } else {
229  pAllowedVoltageBasedCurrent->continuousChargeCurrent_mA = pConfigLimitValues->maximumChargeCurrent_mA;
230  pAllowedVoltageBasedCurrent->peakChargeCurrent_mA = pConfigLimitValues->maximumChargeCurrent_mA;
231  }
232  }
233 }
234 
236  int16_t minimumCellTemperature_ddegC,
237  int16_t maximumCellTemperature_ddegC,
238  SOF_CURRENT_LIMITS_s *pAllowedTemperatureBasedCurrent,
239  const SOF_CONFIG_s *pConfigLimitValues,
240  SOF_CURVE_s *pCalculatedSofCurves) {
241  FAS_ASSERT(pAllowedTemperatureBasedCurrent != NULL_PTR);
242  FAS_ASSERT(pConfigLimitValues != NULL_PTR);
243  FAS_ASSERT(pCalculatedSofCurves != NULL_PTR);
244  /* AXIVION Routine Generic-MissingParameterAssert: minimumCellTemperature_ddegC: parameter accepts whole range */
245  /* AXIVION Routine Generic-MissingParameterAssert: maximumCellTemperature_ddegC: parameter accepts whole range */
246 
247  SOF_CURRENT_LIMITS_s temporaryCurrentLimits = {0.0f, 0.0f, 0.0f, 0.0f};
248  /* Temperature low Discharge */
249  if (minimumCellTemperature_ddegC <= pConfigLimitValues->limitLowTemperatureDischarge_ddegC) {
250  pAllowedTemperatureBasedCurrent->continuousDischargeCurrent_mA = pConfigLimitValues->limpHomeCurrent_mA;
251  pAllowedTemperatureBasedCurrent->peakDischargeCurrent_mA = pConfigLimitValues->limpHomeCurrent_mA;
252  } else {
253  if (minimumCellTemperature_ddegC <= pConfigLimitValues->cutoffLowTemperatureDischarge_ddegC) {
254  pAllowedTemperatureBasedCurrent->continuousDischargeCurrent_mA =
255  (pCalculatedSofCurves->slopeLowTemperatureDischarge * minimumCellTemperature_ddegC) +
256  pCalculatedSofCurves->offsetLowTemperatureDischarge;
257  pAllowedTemperatureBasedCurrent->peakDischargeCurrent_mA =
258  pAllowedTemperatureBasedCurrent->continuousDischargeCurrent_mA;
259  } else {
260  pAllowedTemperatureBasedCurrent->continuousDischargeCurrent_mA =
261  pConfigLimitValues->maximumDischargeCurrent_mA;
262  pAllowedTemperatureBasedCurrent->peakDischargeCurrent_mA = pConfigLimitValues->maximumDischargeCurrent_mA;
263  }
264  }
265  /* Temperature low charge */
266  if (minimumCellTemperature_ddegC <= pConfigLimitValues->limitLowTemperatureCharge_ddegC) {
267  pAllowedTemperatureBasedCurrent->continuousChargeCurrent_mA = 0;
268  pAllowedTemperatureBasedCurrent->peakChargeCurrent_mA = 0;
269  } else {
270  if (minimumCellTemperature_ddegC <= pConfigLimitValues->cutoffLowTemperatureCharge_ddegC) {
271  pAllowedTemperatureBasedCurrent->continuousChargeCurrent_mA =
272  (pCalculatedSofCurves->slopeLowTemperatureCharge * minimumCellTemperature_ddegC) +
273  pCalculatedSofCurves->offsetLowTemperatureCharge;
274  pAllowedTemperatureBasedCurrent->peakChargeCurrent_mA =
275  pAllowedTemperatureBasedCurrent->continuousChargeCurrent_mA;
276  } else {
277  pAllowedTemperatureBasedCurrent->continuousChargeCurrent_mA = pConfigLimitValues->maximumChargeCurrent_mA;
278  pAllowedTemperatureBasedCurrent->peakChargeCurrent_mA = pConfigLimitValues->maximumChargeCurrent_mA;
279  }
280  }
281  /* Temperature high discharge */
282  if (maximumCellTemperature_ddegC >= pConfigLimitValues->limitHighTemperatureDischarge_ddegC) {
283  pAllowedTemperatureBasedCurrent->continuousDischargeCurrent_mA = 0.0f;
284  pAllowedTemperatureBasedCurrent->peakDischargeCurrent_mA = 0.0f;
285  } else {
286  if (maximumCellTemperature_ddegC >= pConfigLimitValues->cutoffHighTemperatureDischarge_ddegC) {
287  temporaryCurrentLimits.continuousDischargeCurrent_mA =
288  (pCalculatedSofCurves->slopeHighTemperatureDischarge * maximumCellTemperature_ddegC) +
289  pCalculatedSofCurves->offsetHighTemperatureDischarge;
290  temporaryCurrentLimits.peakDischargeCurrent_mA = temporaryCurrentLimits.continuousDischargeCurrent_mA;
291  } else {
292  /* do nothing because this situation is handled with minimumCellTemperature_ddegC */
293  temporaryCurrentLimits.continuousDischargeCurrent_mA = pConfigLimitValues->maximumDischargeCurrent_mA;
294  temporaryCurrentLimits.peakDischargeCurrent_mA = pConfigLimitValues->maximumDischargeCurrent_mA;
295  }
296  /* Derating value for minimum cell temperature has already been calculated and result is saved in
297  pAllowedTemperatureBasedCurrentCheck. Check now if newly calculated derating value for maximum
298  cell temperatures is smaller than the previously calculated value */
299  pAllowedTemperatureBasedCurrent->continuousDischargeCurrent_mA = MATH_MinimumOfTwoFloats(
300  pAllowedTemperatureBasedCurrent->continuousDischargeCurrent_mA,
301  temporaryCurrentLimits.continuousDischargeCurrent_mA);
302  pAllowedTemperatureBasedCurrent->peakDischargeCurrent_mA = MATH_MinimumOfTwoFloats(
303  pAllowedTemperatureBasedCurrent->peakDischargeCurrent_mA, temporaryCurrentLimits.peakDischargeCurrent_mA);
304  }
305  /* Temperature high Charge */
306  if (maximumCellTemperature_ddegC >= pConfigLimitValues->limitHighTemperatureCharge_ddegC) {
307  pAllowedTemperatureBasedCurrent->continuousChargeCurrent_mA = 0.0f;
308  pAllowedTemperatureBasedCurrent->peakChargeCurrent_mA = 0.0f;
309  } else {
310  if (maximumCellTemperature_ddegC >= pConfigLimitValues->cutoffHighTemperatureCharge_ddegC) {
311  temporaryCurrentLimits.continuousChargeCurrent_mA =
312  (pCalculatedSofCurves->slopeHighTemperatureCharge * maximumCellTemperature_ddegC) +
313  pCalculatedSofCurves->offsetHighTemperatureCharge;
314  temporaryCurrentLimits.peakChargeCurrent_mA = temporaryCurrentLimits.continuousChargeCurrent_mA;
315  } else {
316  /* do nothing because this situation is handled with minimumCellTemperature_ddegC */
317  temporaryCurrentLimits.continuousChargeCurrent_mA = pConfigLimitValues->maximumChargeCurrent_mA;
318  temporaryCurrentLimits.peakChargeCurrent_mA = pConfigLimitValues->maximumChargeCurrent_mA;
319  }
320  /* Derating value for minimum cell temperature has already been calculated and result is saved in
321  pAllowedTemperatureBasedCurrentCheck. Check now if newly calculated derating value for maximum
322  cell temperatures is smaller than the previously calculated value */
323  pAllowedTemperatureBasedCurrent->continuousChargeCurrent_mA = MATH_MinimumOfTwoFloats(
324  pAllowedTemperatureBasedCurrent->continuousChargeCurrent_mA,
325  temporaryCurrentLimits.continuousChargeCurrent_mA);
326  pAllowedTemperatureBasedCurrent->peakChargeCurrent_mA = MATH_MinimumOfTwoFloats(
327  pAllowedTemperatureBasedCurrent->peakChargeCurrent_mA, temporaryCurrentLimits.peakChargeCurrent_mA);
328  }
329 }
330 
332  SOF_CURRENT_LIMITS_s voltageBasedLimits,
333  SOF_CURRENT_LIMITS_s temperatureBasedLimits) {
334  /* AXIVION Routine Generic-MissingParameterAssert: voltageBasedLimits: parameter accepts whole range */
335  /* AXIVION Routine Generic-MissingParameterAssert: temperatureBasedLimits: parameter accepts whole range */
336  SOF_CURRENT_LIMITS_s retval = {0};
338  voltageBasedLimits.continuousChargeCurrent_mA, temperatureBasedLimits.continuousChargeCurrent_mA);
339  retval.peakChargeCurrent_mA =
340  MATH_MinimumOfTwoFloats(voltageBasedLimits.peakChargeCurrent_mA, temperatureBasedLimits.peakChargeCurrent_mA);
342  voltageBasedLimits.continuousDischargeCurrent_mA, temperatureBasedLimits.continuousDischargeCurrent_mA);
344  voltageBasedLimits.peakDischargeCurrent_mA, temperatureBasedLimits.peakDischargeCurrent_mA);
345  return retval;
346 }
347 
348 /*========== Extern Function Implementations ================================*/
349 extern void SOF_Init(void) {
350  /* Calculating SOF curve for the recommended operating current */
352 
353 #if BMS_CHECK_SOF_CURRENT_LIMITS == true
354  /* Calculating SOF curve for maximum operating limit */
356 
357  /* Calculating SOF curve for recommended safety limit */
359 
360  /* Calculating SOF curve for maximum safety limit */
362 #endif
363 }
364 
365 extern void SOF_Calculation(void) {
366  SOF_CURRENT_LIMITS_s allowedCurrent = {0};
367 
369 
370  /* Reset allowed current values */
375 
376  uint8_t nrClosedStrings = 0;
377  float minDischarge_mA = FLT_MAX;
378  float minCharge_mA = FLT_MAX;
379 
380  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
381  SOF_CURRENT_LIMITS_s voltageBasedSof = {0};
382  SOF_CURRENT_LIMITS_s temperatureBasedSof = {0};
383  /* Calculate allowed current if string is connected */
384  if (BMS_IsStringClosed(s) == true) {
388  &voltageBasedSof,
394  &temperatureBasedSof,
397  allowedCurrent = SOF_MinimumOfTwoSofValues(voltageBasedSof, temperatureBasedSof);
398 
401  allowedCurrent.continuousDischargeCurrent_mA;
404 
405  nrClosedStrings++;
408  }
411  }
412  } else {
417  }
418 
419 #if BMS_CHECK_SOF_CURRENT_LIMITS == true
420  /* Calculate maximum allowed current MOL level */
424  &voltageBasedSof,
426  &sof_curveMol);
430  &temperatureBasedSof,
432  &sof_curveMol);
433  allowedCurrent = SOF_MinimumOfTwoSofValues(voltageBasedSof, temperatureBasedSof);
438 
439  /* Calculate maximum allowed current RSL level */
443  &voltageBasedSof,
445  &sof_curveRsl);
449  &temperatureBasedSof,
451  &sof_curveRsl);
452  allowedCurrent = SOF_MinimumOfTwoSofValues(voltageBasedSof, temperatureBasedSof);
457 
458  /* Calculate maximum allowed current MSL level */
462  &voltageBasedSof,
464  &sof_curveMsl);
468  &temperatureBasedSof,
470  &sof_curveMsl);
471  allowedCurrent = SOF_MinimumOfTwoSofValues(voltageBasedSof, temperatureBasedSof);
476 #else /* BMS_CHECK_SOF_CURRENT_LIMITS == false */
481 
486 
491 #endif /* BMS_CHECK_SOF_CURRENT_LIMITS == true */
492  }
493 
494  if (minCharge_mA > (float)BS_MAXIMUM_STRING_CURRENT_mA) {
495  minCharge_mA = (float)BS_MAXIMUM_STRING_CURRENT_mA;
496  }
497  if (minDischarge_mA > (float)BS_MAXIMUM_STRING_CURRENT_mA) {
498  minDischarge_mA = (float)BS_MAXIMUM_STRING_CURRENT_mA;
499  }
500 
501  /* Compute recommended pack values */
502  sof_tableSofValues.recommendedContinuousPackChargeCurrent_mA = (float)nrClosedStrings * minCharge_mA;
503  sof_tableSofValues.recommendedContinuousPackDischargeCurrent_mA = (float)nrClosedStrings * minDischarge_mA;
504  sof_tableSofValues.recommendedPeakPackChargeCurrent_mA = (float)nrClosedStrings * minCharge_mA;
505  sof_tableSofValues.recommendedPeakPackDischargeCurrent_mA = (float)nrClosedStrings * minDischarge_mA;
506 
508 }
509 
510 /*========== Externalized Static Function Implementations (Unit Test) =======*/
511 #ifdef UNITY_UNIT_TEST
512 extern void TEST_SOF_CalculateCurves(const SOF_CONFIG_s *pConfigurationValues, SOF_CURVE_s *pCalculatedSofCurveValues) {
513  SOF_CalculateCurves(pConfigurationValues, pCalculatedSofCurveValues);
514 }
516  int16_t minimumCellVoltage_mV,
517  int16_t maximumCellVoltage_mV,
518  SOF_CURRENT_LIMITS_s *pAllowedVoltageBasedCurrent,
519  const SOF_CONFIG_s *pConfigLimitValues,
520  SOF_CURVE_s *pCalculatedSofCurves) {
522  minimumCellVoltage_mV,
523  maximumCellVoltage_mV,
524  pAllowedVoltageBasedCurrent,
525  pConfigLimitValues,
526  pCalculatedSofCurves);
527 }
529  int16_t minimumCellTemperature_ddegC,
530  int16_t maximumCellTemperature_ddegC,
531  SOF_CURRENT_LIMITS_s *pAllowedTemperatureBasedCurrent,
532  const SOF_CONFIG_s *pConfigLimitValues,
533  SOF_CURVE_s *pCalculatedSofCurves) {
535  minimumCellTemperature_ddegC,
536  maximumCellTemperature_ddegC,
537  pAllowedTemperatureBasedCurrent,
538  pConfigLimitValues,
539  pCalculatedSofCurves);
540 }
542  SOF_CURRENT_LIMITS_s voltageBasedLimits,
543  SOF_CURRENT_LIMITS_s temperatureBasedLimits) {
544  return SOF_MinimumOfTwoSofValues(voltageBasedLimits, temperatureBasedLimits);
545 }
546 #endif
Configuration of the battery cell (e.g., minimum and maximum cell voltage)
#define BC_CURRENT_MAX_CHARGE_RSL_mA
Maximum charge current limit.
#define BC_CURRENT_MAX_DISCHARGE_MOL_mA
Maximum discharge current limit.
#define BC_CURRENT_MAX_DISCHARGE_MSL_mA
Maximum discharge current limit.
#define BC_CURRENT_MAX_DISCHARGE_RSL_mA
Maximum discharge current limit.
#define BC_CURRENT_MAX_CHARGE_MSL_mA
Maximum charge current limit.
#define BC_CURRENT_MAX_CHARGE_MOL_mA
Maximum charge current 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.
#define BS_MAXIMUM_STRING_CURRENT_mA
Maximum string current limit in mA that is used in the SOA module to check for string overcurrent.
bool BMS_IsStringClosed(uint8_t stringNumber)
Returns string state (closed or open)
Definition: bms.c:1302
bms driver header
Database module header.
#define DATA_READ_DATA(...)
Definition: database.h:83
#define DATA_WRITE_DATA(...)
Definition: database.h:93
@ DATA_BLOCK_ID_MIN_MAX
Definition: database_cfg.h:78
@ DATA_BLOCK_ID_SOF
Definition: database_cfg.h:89
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:237
float MATH_MinimumOfTwoFloats(const float value1, const float value2)
Returns the minimum of the passed float values.
Definition: foxmath.c:133
math library for often used math functions
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:76
static SOF_CURVE_s sof_curveMol
Definition: sof.c:74
static void SOF_CalculateTemperatureBasedCurrentLimit(int16_t minimumCellTemperature_ddegC, int16_t maximumCellTemperature_ddegC, SOF_CURRENT_LIMITS_s *pAllowedTemperatureBasedCurrent, const SOF_CONFIG_s *pConfigLimitValues, SOF_CURVE_s *pCalculatedSofCurves)
calculates the SoF from temperature data (i.e., minimum and maximum temperature of cells)
Definition: sof.c:235
void SOF_Calculation(void)
triggers SOF calculation
Definition: sof.c:365
void TEST_SOF_CalculateVoltageBasedCurrentLimit(int16_t minimumCellVoltage_mV, int16_t maximumCellVoltage_mV, SOF_CURRENT_LIMITS_s *pAllowedVoltageBasedCurrent, const SOF_CONFIG_s *pConfigLimitValues, SOF_CURVE_s *pCalculatedSofCurves)
Definition: sof.c:515
void TEST_SOF_CalculateTemperatureBasedCurrentLimit(int16_t minimumCellTemperature_ddegC, int16_t maximumCellTemperature_ddegC, SOF_CURRENT_LIMITS_s *pAllowedTemperatureBasedCurrent, const SOF_CONFIG_s *pConfigLimitValues, SOF_CURVE_s *pCalculatedSofCurves)
Definition: sof.c:528
static DATA_BLOCK_SOF_s sof_tableSofValues
Definition: sof.c:82
void TEST_SOF_CalculateCurves(const SOF_CONFIG_s *pConfigurationValues, SOF_CURVE_s *pCalculatedSofCurveValues)
Definition: sof.c:512
static SOF_CURVE_s sof_curveRsl
Definition: sof.c:75
static DATA_BLOCK_MIN_MAX_s sof_tableMinimumMaximumValues
Definition: sof.c:81
static void SOF_CalculateVoltageBasedCurrentLimit(int16_t minimumCellVoltage_mV, int16_t maximumCellVoltage_mV, SOF_CURRENT_LIMITS_s *pAllowedVoltageBasedCurrent, const SOF_CONFIG_s *pConfigLimitValues, SOF_CURVE_s *pCalculatedSofCurves)
calculates the SoF from voltage data (i.e., minimum and maximum voltage)
Definition: sof.c:190
static void SOF_CalculateCurves(const SOF_CONFIG_s *pConfigurationValues, SOF_CURVE_s *pCalculatedSofCurveValues)
calculate SOF curve depending on configured configuration values
Definition: sof.c:142
static SOF_CURVE_s sof_curveMsl
Definition: sof.c:76
SOF_CURRENT_LIMITS_s TEST_SOF_MinimumOfTwoSofValues(SOF_CURRENT_LIMITS_s voltageBasedLimits, SOF_CURRENT_LIMITS_s temperatureBasedLimits)
Definition: sof.c:541
static SOF_CURRENT_LIMITS_s SOF_MinimumOfTwoSofValues(SOF_CURRENT_LIMITS_s voltageBasedLimits, SOF_CURRENT_LIMITS_s temperatureBasedLimits)
get the minimum current values of all variants of SoF calculation
Definition: sof.c:331
static SOF_CURVE_s sof_curveRecommendedOperatingCurrent
Definition: sof.c:73
void SOF_Init(void)
initializes the area for SOF (where derating starts and is fully active).
Definition: sof.c:349
Header for SOX module, responsible for current derating calculation.
const SOF_CONFIG_s sof_recommendedCurrent
Definition: sof_cfg.c:64
const SOF_CONFIG_s sof_recommendedSafetyLimit
Definition: sof_cfg.c:98
const SOF_CONFIG_s sof_configMaximumSafetyLimit
Definition: sof_cfg.c:115
const SOF_CONFIG_s sof_maximumOperatingLimit
Definition: sof_cfg.c:81
DATA_BLOCK_ID_e uniqueId
Definition: database_cfg.h:119
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
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:159
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
float continuousMslChargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:430
float continuousRslDischargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:427
float peakMslDischargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:433
float peakRslDischargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:429
float continuousMolChargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:422
float continuousMolDischargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:423
float recommendedPeakPackChargeCurrent_mA
Definition: database_cfg.h:414
float recommendedPeakPackDischargeCurrent_mA
Definition: database_cfg.h:415
float recommendedContinuousPackChargeCurrent_mA
Definition: database_cfg.h:412
float recommendedContinuousChargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:417
float peakMolChargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:424
float continuousMslDischargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:431
float recommendedContinuousPackDischargeCurrent_mA
Definition: database_cfg.h:413
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:411
float continuousRslChargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:426
float peakRslChargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:428
float peakMslChargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:432
float recommendedPeakDischargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:421
float recommendedContinuousDischargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:419
float recommendedPeakChargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:420
float peakMolDischargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:425
float maximumDischargeCurrent_mA
Definition: sof_cfg.h:324
float maximumChargeCurrent_mA
Definition: sof_cfg.h:325
int16_t limitLowTemperatureCharge_ddegC
Definition: sof_cfg.h:333
int16_t limitLowerCellVoltage_mV
Definition: sof_cfg.h:347
int16_t limitUpperCellVoltage_mV
Definition: sof_cfg.h:345
int16_t cutoffHighTemperatureDischarge_ddegC
Definition: sof_cfg.h:337
int16_t cutoffHighTemperatureCharge_ddegC
Definition: sof_cfg.h:339
int16_t limitHighTemperatureCharge_ddegC
Definition: sof_cfg.h:340
int16_t cutoffLowerCellVoltage_mV
Definition: sof_cfg.h:346
float limpHomeCurrent_mA
Definition: sof_cfg.h:326
int16_t limitHighTemperatureDischarge_ddegC
Definition: sof_cfg.h:338
int16_t limitLowTemperatureDischarge_ddegC
Definition: sof_cfg.h:331
int16_t cutoffLowTemperatureCharge_ddegC
Definition: sof_cfg.h:332
int16_t cutoffLowTemperatureDischarge_ddegC
Definition: sof_cfg.h:330
int16_t cutoffUpperCellVoltage_mV
Definition: sof_cfg.h:344
float continuousDischargeCurrent_mA
Definition: sof.h:69
float peakChargeCurrent_mA
Definition: sof.h:68
float peakDischargeCurrent_mA
Definition: sof.h:70
float continuousChargeCurrent_mA
Definition: sof.h:67
float offsetLowTemperatureDischarge
Definition: sof.h:79
float offsetHighTemperatureCharge
Definition: sof.h:86
float slopeHighTemperatureDischarge
Definition: sof.h:80
float offsetHighTemperatureDischarge
Definition: sof.h:81
float offsetUpperCellVoltage
Definition: sof.h:89
float slopeHighTemperatureCharge
Definition: sof.h:85
float slopeUpperCellVoltage
Definition: sof.h:88
float offsetLowerCellVoltage
Definition: sof.h:91
float slopeLowerCellVoltage
Definition: sof.h:90
float offsetLowTemperatureCharge
Definition: sof.h:84
float slopeLowTemperatureDischarge
Definition: sof.h:78
float slopeLowTemperatureCharge
Definition: sof.h:83