foxBMS-UnitTests  1.0.0
The foxBMS Unit Tests API Documentation
sof.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2021, Fraunhofer-Gesellschaft zur Foerderung der
4  * angewandten Forschung e.V. All rights reserved.
5  *
6  * BSD 3-Clause License
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  * 1. Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the copyright holder nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *
30  * We kindly request you to use one or more of the following phrases to refer
31  * to foxBMS in your hardware, software, documentation or advertising
32  * materials:
33  *
34  * ″This product uses parts of foxBMS®″
35  *
36  * ″This product includes parts of foxBMS®″
37  *
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 2021-03-24 (date of last update)
47  * @ingroup APPLICATION_CONFIGURATION
48  * @prefix SOX
49  *
50  * @brief SOX module responsible for current derating calculation
51  *
52  */
53 
54 /*========== Includes =======================================================*/
55 #include "sof.h"
56 
57 #include "battery_cell_cfg.h"
58 #include "battery_system_cfg.h"
59 
60 #include "bms.h"
61 #include "database.h"
62 #include "foxmath.h"
63 
64 #include <float.h>
65 
66 /*========== Macros and Definitions =========================================*/
67 
68 /*========== Static Constant and Variable Definitions =======================*/
69 /** @{
70  * module-local static Variables that are calculated at startup and used later to avoid divisions at runtime
71  */
76 /** @} */
77 
78 /** local copies of database tables */
79 /**@{*/
82 /**@}*/
83 
84 /*========== Extern Constant and Variable Definitions =======================*/
85 
86 /*========== Static Function Prototypes =====================================*/
87 
88 /**
89  * @brief calculate SOF curve depending on configured configuration values
90  *
91  * @param[in] pConfigurationValues SOF curve configuration values
92  * @param[out] pCalculatedSofCurveValues calculate SOF curve
93  */
94 static void SOF_CalculateCurves(const SOF_CONFIG_s *pConfigurationValues, SOF_CURVE_s *pCalculatedSofCurveValues);
95 
96 /**
97  * @brief calculates the SoF from voltage data (i.e., minimum and maximum voltage)
98  *
99  * @param[in] minimumCellVoltage_mV minimum cell voltage
100  * @param[in] maximumCellVoltage_mV maximum cell voltage
101  * @param[out] pAllowedVoltageBasedCurrent Voltage-based SOF
102  * @param[in] pConfigLimitValues pointer to the SOF configuration structure
103  * @param[in] pCalculatedSofCurves pointer to the SOF curve structure
104  */
106  int16_t minimumCellVoltage_mV,
107  int16_t maximumCellVoltage_mV,
108  SOF_CURRENT_LIMITS_s *pAllowedVoltageBasedCurrent,
109  const SOF_CONFIG_s *pConfigLimitValues,
110  SOF_CURVE_s *pCalculatedSofCurves);
111 
112 /**
113  * @brief calculates the SoF from temperature data (i.e., minimum and maximum temperature of cells)
114  *
115  * @param[in] minimumCellTemperature_ddegC minimum temperature of cells
116  * @param[in] maximumCellTemperature_ddegC maximum temperature of cells
117  * @param[out] pAllowedTemperatureBasedCurrent pointer where to store the results
118  * @param[in] pConfigLimitValues pointer to the structure used for SOF calculation
119  * @param[in] pCalculatedSofCurves pointer to the structure containing limit values
120  */
122  int16_t minimumCellTemperature_ddegC,
123  int16_t maximumCellTemperature_ddegC,
124  SOF_CURRENT_LIMITS_s *pAllowedTemperatureBasedCurrent,
125  const SOF_CONFIG_s *pConfigLimitValues,
126  SOF_CURVE_s *pCalculatedSofCurves);
127 
128 /**
129  * @brief get the minimum current values of all variants of SoF calculation
130  *
131  * @param[in] voltageBasedLimits voltage constrained current derating values
132  * @param[in] temperatureBasedLimits temperature constrained current derating values
133  *
134  * @return minimum SoF current values
135  */
137  SOF_CURRENT_LIMITS_s voltageBasedLimits,
138  SOF_CURRENT_LIMITS_s temperatureBasedLimits);
139 
140 /*========== Static Function Implementations ================================*/
141 static void SOF_CalculateCurves(const SOF_CONFIG_s *pConfigurationValues, SOF_CURVE_s *pCalculatedSofCurveValues) {
142  FAS_ASSERT(pConfigurationValues != NULL_PTR);
143  FAS_ASSERT(pCalculatedSofCurveValues != NULL_PTR);
144 
145  /* Calculating SOF curve for the maximum allowed current for MOL/RSL/MSL */
146  pCalculatedSofCurveValues->slopeLowTemperatureDischarge =
147  (pConfigurationValues->maximumDischargeCurrent_mA - pConfigurationValues->limpHomeCurrent_mA) /
148  (pConfigurationValues->cutoffLowTemperatureDischarge_ddegC -
149  pConfigurationValues->limitLowTemperatureDischarge_ddegC);
150  pCalculatedSofCurveValues->offsetLowTemperatureDischarge =
151  pConfigurationValues->limpHomeCurrent_mA - (pCalculatedSofCurveValues->slopeLowTemperatureDischarge *
152  pConfigurationValues->limitLowTemperatureDischarge_ddegC);
153 
154  pCalculatedSofCurveValues->slopeHighTemperatureDischarge =
155  (0.0f - pConfigurationValues->maximumDischargeCurrent_mA) /
156  (pConfigurationValues->limitHighTemperatureDischarge_ddegC -
157  pConfigurationValues->cutoffHighTemperatureDischarge_ddegC);
158  pCalculatedSofCurveValues->offsetHighTemperatureDischarge =
159  0.0f - (pCalculatedSofCurveValues->slopeHighTemperatureDischarge *
160  pConfigurationValues->limitHighTemperatureDischarge_ddegC);
161 
162  pCalculatedSofCurveValues->slopeLowTemperatureCharge = (pConfigurationValues->maximumChargeCurrent_mA - 0.0f) /
163  (pConfigurationValues->cutoffLowTemperatureCharge_ddegC -
164  pConfigurationValues->limitLowTemperatureCharge_ddegC);
165  pCalculatedSofCurveValues->offsetLowTemperatureCharge =
166  0.0f -
167  (pCalculatedSofCurveValues->slopeLowTemperatureCharge * pConfigurationValues->limitLowTemperatureCharge_ddegC);
168 
169  pCalculatedSofCurveValues->slopeHighTemperatureCharge = (0.0f - pConfigurationValues->maximumChargeCurrent_mA) /
170  (pConfigurationValues->limitHighTemperatureCharge_ddegC -
171  pConfigurationValues->cutoffHighTemperatureCharge_ddegC);
172  pCalculatedSofCurveValues->offsetHighTemperatureCharge = 0.0f -
173  (pCalculatedSofCurveValues->slopeHighTemperatureCharge *
174  pConfigurationValues->limitHighTemperatureCharge_ddegC);
175 
176  pCalculatedSofCurveValues->slopeUpperCellVoltage =
177  (pConfigurationValues->maximumDischargeCurrent_mA - 0.0f) /
178  (pConfigurationValues->cutoffLowerCellVoltage_mV - pConfigurationValues->limitLowerCellVoltage_mV);
179  pCalculatedSofCurveValues->offsetUpperCellVoltage =
180  0.0f - (pCalculatedSofCurveValues->slopeUpperCellVoltage * pConfigurationValues->limitLowerCellVoltage_mV);
181 
182  pCalculatedSofCurveValues->slopeLowerCellVoltage =
183  (pConfigurationValues->maximumChargeCurrent_mA - 0.0f) /
184  (pConfigurationValues->cutoffUpperCellVoltage_mV - pConfigurationValues->limitUpperCellVoltage_mV);
185  pCalculatedSofCurveValues->offsetLowerCellVoltage =
186  0.0f - (pCalculatedSofCurveValues->slopeLowerCellVoltage * pConfigurationValues->limitLowerCellVoltage_mV);
187 }
188 
190  int16_t minimumCellVoltage_mV,
191  int16_t maximumCellVoltage_mV,
192  SOF_CURRENT_LIMITS_s *pAllowedVoltageBasedCurrent,
193  const SOF_CONFIG_s *pConfigLimitValues,
194  SOF_CURVE_s *pCalculatedSofCurves) {
195  FAS_ASSERT(pAllowedVoltageBasedCurrent != NULL_PTR);
196  FAS_ASSERT(pConfigLimitValues != NULL_PTR);
197  FAS_ASSERT(pCalculatedSofCurves != NULL_PTR);
198 
199  /* minimum cell voltage calculation */
200  if (minimumCellVoltage_mV <= pConfigLimitValues->limitLowerCellVoltage_mV) {
201  pAllowedVoltageBasedCurrent->continuousDischargeCurrent_mA = 0.0f;
202  pAllowedVoltageBasedCurrent->peakDischargeCurrent_mA = 0.0f;
203  } else {
204  if (minimumCellVoltage_mV <= pConfigLimitValues->cutoffLowerCellVoltage_mV) {
205  pAllowedVoltageBasedCurrent->continuousDischargeCurrent_mA =
206  (pCalculatedSofCurves->slopeUpperCellVoltage *
207  (minimumCellVoltage_mV - pConfigLimitValues->limitLowerCellVoltage_mV));
208  pAllowedVoltageBasedCurrent->peakDischargeCurrent_mA =
209  pAllowedVoltageBasedCurrent->continuousDischargeCurrent_mA;
210  } else {
211  pAllowedVoltageBasedCurrent->continuousDischargeCurrent_mA = pConfigLimitValues->maximumDischargeCurrent_mA;
212  pAllowedVoltageBasedCurrent->peakDischargeCurrent_mA = pConfigLimitValues->maximumDischargeCurrent_mA;
213  }
214  }
215  /* maximum cell voltage calculation */
216  if (maximumCellVoltage_mV >= pConfigLimitValues->limitUpperCellVoltage_mV) {
217  pAllowedVoltageBasedCurrent->continuousChargeCurrent_mA = 0.0f;
218  pAllowedVoltageBasedCurrent->peakChargeCurrent_mA = 0.0f;
219  } else {
220  if (maximumCellVoltage_mV >= pConfigLimitValues->cutoffUpperCellVoltage_mV) {
221  pAllowedVoltageBasedCurrent->continuousChargeCurrent_mA =
222  (pCalculatedSofCurves->slopeLowerCellVoltage *
223  (maximumCellVoltage_mV - pConfigLimitValues->limitUpperCellVoltage_mV));
224  pAllowedVoltageBasedCurrent->peakChargeCurrent_mA = pAllowedVoltageBasedCurrent->continuousChargeCurrent_mA;
225  } else {
226  pAllowedVoltageBasedCurrent->continuousChargeCurrent_mA = pConfigLimitValues->maximumChargeCurrent_mA;
227  pAllowedVoltageBasedCurrent->peakChargeCurrent_mA = pConfigLimitValues->maximumChargeCurrent_mA;
228  }
229  }
230 }
231 
233  int16_t minimumCellTemperature_ddegC,
234  int16_t maximumCellTemperature_ddegC,
235  SOF_CURRENT_LIMITS_s *pAllowedTemperatureBasedCurrent,
236  const SOF_CONFIG_s *pConfigLimitValues,
237  SOF_CURVE_s *pCalculatedSofCurves) {
238  FAS_ASSERT(pAllowedTemperatureBasedCurrent != NULL_PTR);
239  FAS_ASSERT(pConfigLimitValues != NULL_PTR);
240  FAS_ASSERT(pCalculatedSofCurves != NULL_PTR);
241 
242  SOF_CURRENT_LIMITS_s temporaryCurrentLimits = {0.0f, 0.0f, 0.0f, 0.0f};
243  /* Temperature low Discharge */
244  if (minimumCellTemperature_ddegC <= pConfigLimitValues->limitLowTemperatureDischarge_ddegC) {
245  pAllowedTemperatureBasedCurrent->continuousDischargeCurrent_mA = pConfigLimitValues->limpHomeCurrent_mA;
246  pAllowedTemperatureBasedCurrent->peakDischargeCurrent_mA = pConfigLimitValues->limpHomeCurrent_mA;
247  } else {
248  if (minimumCellTemperature_ddegC <= pConfigLimitValues->cutoffLowTemperatureDischarge_ddegC) {
249  pAllowedTemperatureBasedCurrent->continuousDischargeCurrent_mA =
250  (pCalculatedSofCurves->slopeLowTemperatureDischarge * minimumCellTemperature_ddegC) +
251  pCalculatedSofCurves->offsetLowTemperatureDischarge;
252  pAllowedTemperatureBasedCurrent->peakDischargeCurrent_mA =
253  pAllowedTemperatureBasedCurrent->continuousDischargeCurrent_mA;
254  } else {
255  pAllowedTemperatureBasedCurrent->continuousDischargeCurrent_mA =
256  pConfigLimitValues->maximumDischargeCurrent_mA;
257  pAllowedTemperatureBasedCurrent->peakDischargeCurrent_mA = pConfigLimitValues->maximumDischargeCurrent_mA;
258  }
259  }
260  /* Temperature low charge */
261  if (minimumCellTemperature_ddegC <= pConfigLimitValues->limitLowTemperatureCharge_ddegC) {
262  pAllowedTemperatureBasedCurrent->continuousChargeCurrent_mA = 0;
263  pAllowedTemperatureBasedCurrent->peakChargeCurrent_mA = 0;
264  } else {
265  if (minimumCellTemperature_ddegC <= pConfigLimitValues->cutoffLowTemperatureCharge_ddegC) {
266  pAllowedTemperatureBasedCurrent->continuousChargeCurrent_mA =
267  (pCalculatedSofCurves->slopeLowTemperatureCharge * minimumCellTemperature_ddegC) +
268  pCalculatedSofCurves->offsetLowTemperatureCharge;
269  pAllowedTemperatureBasedCurrent->peakChargeCurrent_mA =
270  pAllowedTemperatureBasedCurrent->continuousChargeCurrent_mA;
271  } else {
272  pAllowedTemperatureBasedCurrent->continuousChargeCurrent_mA = pConfigLimitValues->maximumChargeCurrent_mA;
273  pAllowedTemperatureBasedCurrent->peakChargeCurrent_mA = pConfigLimitValues->maximumChargeCurrent_mA;
274  }
275  }
276  /* Temperature high discharge */
277  if (maximumCellTemperature_ddegC >= pConfigLimitValues->limitHighTemperatureDischarge_ddegC) {
278  pAllowedTemperatureBasedCurrent->continuousDischargeCurrent_mA = 0.0f;
279  pAllowedTemperatureBasedCurrent->peakDischargeCurrent_mA = 0.0f;
280  } else {
281  if (maximumCellTemperature_ddegC >= pConfigLimitValues->cutoffHighTemperatureDischarge_ddegC) {
282  temporaryCurrentLimits.continuousDischargeCurrent_mA =
283  (pCalculatedSofCurves->slopeHighTemperatureDischarge * maximumCellTemperature_ddegC) +
284  pCalculatedSofCurves->offsetHighTemperatureDischarge;
285  temporaryCurrentLimits.peakDischargeCurrent_mA = temporaryCurrentLimits.continuousDischargeCurrent_mA;
286  } else {
287  /* do nothing because this situation is handled with minimumCellTemperature_ddegC */
288  temporaryCurrentLimits.continuousDischargeCurrent_mA = pConfigLimitValues->maximumDischargeCurrent_mA;
289  temporaryCurrentLimits.peakDischargeCurrent_mA = pConfigLimitValues->maximumDischargeCurrent_mA;
290  }
291  /* Derating value for minimum cell temperature has already been calculated and result is saved in
292  pAllowedTemperatureBasedCurrentCheck. Check now if newly calculated derating value for maximum
293  cell temperatures is smaller than the previously calculated value */
294  pAllowedTemperatureBasedCurrent->continuousDischargeCurrent_mA = MATH_minimumOfTwoFloats(
295  pAllowedTemperatureBasedCurrent->continuousDischargeCurrent_mA,
296  temporaryCurrentLimits.continuousDischargeCurrent_mA);
297  pAllowedTemperatureBasedCurrent->peakDischargeCurrent_mA = MATH_minimumOfTwoFloats(
298  pAllowedTemperatureBasedCurrent->peakDischargeCurrent_mA, temporaryCurrentLimits.peakDischargeCurrent_mA);
299  }
300  /* Temperature high Charge */
301  if (maximumCellTemperature_ddegC >= pConfigLimitValues->limitHighTemperatureCharge_ddegC) {
302  pAllowedTemperatureBasedCurrent->continuousChargeCurrent_mA = 0.0f;
303  pAllowedTemperatureBasedCurrent->peakChargeCurrent_mA = 0.0f;
304  } else {
305  if (maximumCellTemperature_ddegC >= pConfigLimitValues->cutoffHighTemperatureCharge_ddegC) {
306  temporaryCurrentLimits.continuousChargeCurrent_mA =
307  (pCalculatedSofCurves->slopeHighTemperatureCharge * maximumCellTemperature_ddegC) +
308  pCalculatedSofCurves->offsetHighTemperatureCharge;
309  temporaryCurrentLimits.peakChargeCurrent_mA = temporaryCurrentLimits.continuousChargeCurrent_mA;
310  } else {
311  /* do nothing because this situation is handled with minimumCellTemperature_ddegC */
312  temporaryCurrentLimits.continuousChargeCurrent_mA = pConfigLimitValues->maximumChargeCurrent_mA;
313  temporaryCurrentLimits.peakChargeCurrent_mA = pConfigLimitValues->maximumChargeCurrent_mA;
314  }
315  /* Derating value for minimum cell temperature has already been calculated and result is saved in
316  pAllowedTemperatureBasedCurrentCheck. Check now if newly calculated derating value for maximum
317  cell temperatures is smaller than the previously calculated value */
318  pAllowedTemperatureBasedCurrent->continuousChargeCurrent_mA = MATH_minimumOfTwoFloats(
319  pAllowedTemperatureBasedCurrent->continuousChargeCurrent_mA,
320  temporaryCurrentLimits.continuousChargeCurrent_mA);
321  pAllowedTemperatureBasedCurrent->peakChargeCurrent_mA = MATH_minimumOfTwoFloats(
322  pAllowedTemperatureBasedCurrent->peakChargeCurrent_mA, temporaryCurrentLimits.peakChargeCurrent_mA);
323  }
324 }
325 
327  SOF_CURRENT_LIMITS_s voltageBasedLimits,
328  SOF_CURRENT_LIMITS_s temperatureBasedLimits) {
329  SOF_CURRENT_LIMITS_s retval = {0};
331  voltageBasedLimits.continuousChargeCurrent_mA, temperatureBasedLimits.continuousChargeCurrent_mA);
332  retval.peakChargeCurrent_mA =
333  MATH_minimumOfTwoFloats(voltageBasedLimits.peakChargeCurrent_mA, temperatureBasedLimits.peakChargeCurrent_mA);
335  voltageBasedLimits.continuousDischargeCurrent_mA, temperatureBasedLimits.continuousDischargeCurrent_mA);
337  voltageBasedLimits.peakDischargeCurrent_mA, temperatureBasedLimits.peakDischargeCurrent_mA);
338  return retval;
339 }
340 
341 /*========== Extern Function Implementations ================================*/
342 extern void SOF_Init(void) {
343  /* Calculating SOF curve for the recommended operating current */
345 
346 #if BMS_CHECK_SOF_CURRENT_LIMITS == true
347  /* Calculating SOF curve for maximum operating limit */
349 
350  /* Calculating SOF curve for recommended safety limit */
352 
353  /* Calculating SOF curve for maximum safety limit */
355 #endif
356 }
357 
358 extern void SOF_Calculation(void) {
359  SOF_CURRENT_LIMITS_s allowedCurrent = {0};
360 
362 
363  /* Reset allowed current values */
368 
369  uint8_t nrClosedStrings = 0;
370  float minDischarge_mA = FLT_MAX;
371  float minCharge_mA = FLT_MAX;
372 
373  for (uint8_t stringNumber = 0u; stringNumber < BS_NR_OF_STRINGS; stringNumber++) {
374  SOF_CURRENT_LIMITS_s voltageBasedSof = {0};
375  SOF_CURRENT_LIMITS_s temperatureBasedSof = {0};
376  /* Calculate allowed current if string is connected */
377  if (true == BMS_IsStringClosed(stringNumber)) {
381  &voltageBasedSof,
387  &temperatureBasedSof,
390  allowedCurrent = SOF_MinimumOfTwoSofValues(voltageBasedSof, temperatureBasedSof);
391 
393  allowedCurrent.continuousChargeCurrent_mA;
395  allowedCurrent.continuousDischargeCurrent_mA;
398  allowedCurrent.peakDischargeCurrent_mA;
399 
400  nrClosedStrings++;
401  if (minCharge_mA > sof_tableSofValues.recommendedContinuousChargeCurrent_mA[stringNumber]) {
402  minCharge_mA = sof_tableSofValues.recommendedContinuousChargeCurrent_mA[stringNumber];
403  }
404  if (minDischarge_mA > sof_tableSofValues.recommendedContinuousDischargeCurrent_mA[stringNumber]) {
405  minDischarge_mA = sof_tableSofValues.recommendedContinuousDischargeCurrent_mA[stringNumber];
406  }
407  } else {
412  }
413 
414 #if BMS_CHECK_SOF_CURRENT_LIMITS == true
415  /* Calculate maximum allowed current MOL level */
419  &voltageBasedSof,
421  &sof_curveMol);
425  &temperatureBasedSof,
427  &sof_curveMol);
428  allowedCurrent = SOF_MinimumOfTwoSofValues(voltageBasedSof, temperatureBasedSof);
431  allowedCurrent.continuousDischargeCurrent_mA;
432  sof_tableSofValues.peakMolChargeCurrent_mA[stringNumber] = allowedCurrent.peakChargeCurrent_mA;
434 
435  /* Calculate maximum allowed current RSL level */
439  &voltageBasedSof,
441  &sof_curveRsl);
445  &temperatureBasedSof,
447  &sof_curveRsl);
448  allowedCurrent = SOF_MinimumOfTwoSofValues(voltageBasedSof, temperatureBasedSof);
451  allowedCurrent.continuousDischargeCurrent_mA;
452  sof_tableSofValues.peakRslChargeCurrent_mA[stringNumber] = allowedCurrent.peakChargeCurrent_mA;
454 
455  /* Calculate maximum allowed current MSL level */
459  &voltageBasedSof,
461  &sof_curveMsl);
465  &temperatureBasedSof,
467  &sof_curveMsl);
468  allowedCurrent = SOF_MinimumOfTwoSofValues(voltageBasedSof, temperatureBasedSof);
471  allowedCurrent.continuousDischargeCurrent_mA;
472  sof_tableSofValues.peakMslChargeCurrent_mA[stringNumber] = allowedCurrent.peakChargeCurrent_mA;
474 #else /* BMS_CHECK_SOF_CURRENT_LIMITS == false */
479 
484 
489 #endif /* BMS_CHECK_SOF_CURRENT_LIMITS == true */
490  }
491 
492  if ((minCharge_mA * 1000.0f) > (float)BS_MAXIMUM_STRING_CURRENT_mA) {
493  minCharge_mA = (float)BS_MAXIMUM_STRING_CURRENT_mA / 1000.f;
494  }
495  if ((minDischarge_mA * 1000.0f) > (float)BS_MAXIMUM_STRING_CURRENT_mA) {
496  minDischarge_mA = (float)BS_MAXIMUM_STRING_CURRENT_mA / 1000.f;
497  }
498 
499  /* Compute recommended pack values */
500  sof_tableSofValues.recommendedContinuousPackChargeCurrent_mA = (float)nrClosedStrings * minCharge_mA;
501  sof_tableSofValues.recommendedContinuousPackDischargeCurrent_mA = (float)nrClosedStrings * minDischarge_mA;
502  sof_tableSofValues.recommendedPeakPackChargeCurrent_mA = (float)nrClosedStrings * minCharge_mA;
503  sof_tableSofValues.recommendedPeakPackDischargeCurrent_mA = (float)nrClosedStrings * minDischarge_mA;
504 
506 }
507 
508 /*========== Externalized Static Function Implementations (Unit Test) =======*/
509 #ifdef UNITY_UNIT_TEST
510 extern void TEST_SOF_CalculateCurves(const SOF_CONFIG_s *pConfigurationValues, SOF_CURVE_s *pCalculatedSofCurveValues) {
511  SOF_CalculateCurves(pConfigurationValues, pCalculatedSofCurveValues);
512 }
514  int16_t minimumCellVoltage_mV,
515  int16_t maximumCellVoltage_mV,
516  SOF_CURRENT_LIMITS_s *pAllowedVoltageBasedCurrent,
517  const SOF_CONFIG_s *pConfigLimitValues,
518  SOF_CURVE_s *pCalculatedSofCurves) {
520  minimumCellVoltage_mV,
521  maximumCellVoltage_mV,
522  pAllowedVoltageBasedCurrent,
523  pConfigLimitValues,
524  pCalculatedSofCurves);
525 }
527  int16_t minimumCellTemperature_ddegC,
528  int16_t maximumCellTemperature_ddegC,
529  SOF_CURRENT_LIMITS_s *pAllowedTemperatureBasedCurrent,
530  const SOF_CONFIG_s *pConfigLimitValues,
531  SOF_CURVE_s *pCalculatedSofCurves) {
533  minimumCellTemperature_ddegC,
534  maximumCellTemperature_ddegC,
535  pAllowedTemperatureBasedCurrent,
536  pConfigLimitValues,
537  pCalculatedSofCurves);
538 }
540  SOF_CURRENT_LIMITS_s voltageBasedLimits,
541  SOF_CURRENT_LIMITS_s temperatureBasedLimits) {
542  return SOF_MinimumOfTwoSofValues(voltageBasedLimits, temperatureBasedLimits);
543 }
544 #endif
SOF_CONFIG::cutoffHighTemperatureDischarge_ddegC
int16_t cutoffHighTemperatureDischarge_ddegC
Definition: sof_cfg.h:336
DATA_BLOCK_SOF::recommendedContinuousPackDischargeCurrent_mA
float recommendedContinuousPackDischargeCurrent_mA
Definition: database_cfg.h:390
SOF_CURRENT_LIMITS
Definition: sof.h:65
sof_tableMinimumMaximumValues
static DATA_BLOCK_MIN_MAX_s sof_tableMinimumMaximumValues
Definition: sof.c:80
sof_tableSofValues
static DATA_BLOCK_SOF_s sof_tableSofValues
Definition: sof.c:81
SOF_CURVE::offsetHighTemperatureDischarge
float offsetHighTemperatureDischarge
Definition: sof.h:80
DATA_BLOCK_MIN_MAX::maximumTemperature_ddegC
int16_t maximumTemperature_ddegC[BS_NR_OF_STRINGS]
Definition: database_cfg.h:178
SOF_CONFIG::limitUpperCellVoltage_mV
int16_t limitUpperCellVoltage_mV
Definition: sof_cfg.h:344
SOF_CURVE::offsetUpperCellVoltage
float offsetUpperCellVoltage
Definition: sof.h:88
DATA_BLOCK_SOF::continuousRslChargeCurrent_mA
float continuousRslChargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:403
DATA_BLOCK_MIN_MAX::header
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:162
DATA_BLOCK_SOF::continuousMolChargeCurrent_mA
float continuousMolChargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:399
SOF_CURVE::offsetHighTemperatureCharge
float offsetHighTemperatureCharge
Definition: sof.h:85
DATA_BLOCK_SOF::continuousMolDischargeCurrent_mA
float continuousMolDischargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:400
SOF_CURVE::slopeHighTemperatureDischarge
float slopeHighTemperatureDischarge
Definition: sof.h:79
DATA_BLOCK_SOF::recommendedContinuousPackChargeCurrent_mA
float recommendedContinuousPackChargeCurrent_mA
Definition: database_cfg.h:389
DATA_BLOCK_SOF::continuousRslDischargeCurrent_mA
float continuousRslDischargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:404
bms.h
bms driver header
DATA_WRITE_DATA
#define DATA_WRITE_DATA(...)
Definition: database.h:82
BC_CURRENT_MAX_DISCHARGE_RSL_mA
#define BC_CURRENT_MAX_DISCHARGE_RSL_mA
Maximum discharge current limit.
Definition: battery_cell_cfg.h:195
SOF_CURVE::slopeLowTemperatureCharge
float slopeLowTemperatureCharge
Definition: sof.h:82
battery_system_cfg.h
Configuration of the battery system (e.g., number of battery modules, battery cells,...
BC_CURRENT_MAX_CHARGE_MSL_mA
#define BC_CURRENT_MAX_CHARGE_MSL_mA
Maximum charge current limit.
Definition: battery_cell_cfg.h:210
SOF_CONFIG::limitLowTemperatureCharge_ddegC
int16_t limitLowTemperatureCharge_ddegC
Definition: sof_cfg.h:332
SOF_CONFIG::limitLowTemperatureDischarge_ddegC
int16_t limitLowTemperatureDischarge_ddegC
Definition: sof_cfg.h:330
sof_curveMsl
static SOF_CURVE_s sof_curveMsl
Definition: sof.c:75
SOF_CONFIG::cutoffLowerCellVoltage_mV
int16_t cutoffLowerCellVoltage_mV
Definition: sof_cfg.h:345
sof_recommendedCurrent
const SOF_CONFIG_s sof_recommendedCurrent
Definition: sof_cfg.c:63
DATA_BLOCK_SOF::peakMslChargeCurrent_mA
float peakMslChargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:409
SOF_CalculateCurves
static void SOF_CalculateCurves(const SOF_CONFIG_s *pConfigurationValues, SOF_CURVE_s *pCalculatedSofCurveValues)
calculate SOF curve depending on configured configuration values
Definition: sof.c:141
DATA_BLOCK_SOF::peakMolChargeCurrent_mA
float peakMolChargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:401
SOF_CONFIG::limpHomeCurrent_mA
float limpHomeCurrent_mA
Definition: sof_cfg.h:325
SOF_CONFIG::limitHighTemperatureDischarge_ddegC
int16_t limitHighTemperatureDischarge_ddegC
Definition: sof_cfg.h:337
SOF_CONFIG::cutoffLowTemperatureDischarge_ddegC
int16_t cutoffLowTemperatureDischarge_ddegC
Definition: sof_cfg.h:329
SOF_CalculateTemperatureBasedCurrentLimit
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:232
TEST_SOF_MinimumOfTwoSofValues
SOF_CURRENT_LIMITS_s TEST_SOF_MinimumOfTwoSofValues(SOF_CURRENT_LIMITS_s voltageBasedLimits, SOF_CURRENT_LIMITS_s temperatureBasedLimits)
Definition: sof.c:539
SOF_MinimumOfTwoSofValues
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:326
FAS_ASSERT
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:233
DATA_BLOCK_SOF::continuousMslChargeCurrent_mA
float continuousMslChargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:407
DATA_BLOCK_SOF::recommendedContinuousChargeCurrent_mA
float recommendedContinuousChargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:394
DATA_BLOCK_SOF::peakMolDischargeCurrent_mA
float peakMolDischargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:402
MATH_minimumOfTwoFloats
float MATH_minimumOfTwoFloats(float value1, float value2)
Returns the minimum of the passed float values.
Definition: foxmath.c:101
DATA_BLOCK_SOF::recommendedPeakPackChargeCurrent_mA
float recommendedPeakPackChargeCurrent_mA
Definition: database_cfg.h:391
DATA_BLOCK_ID_SOF
@ DATA_BLOCK_ID_SOF
Definition: database_cfg.h:86
DATA_BLOCK_ID_MIN_MAX
@ DATA_BLOCK_ID_MIN_MAX
Definition: database_cfg.h:75
SOF_CONFIG::cutoffLowTemperatureCharge_ddegC
int16_t cutoffLowTemperatureCharge_ddegC
Definition: sof_cfg.h:331
SOF_CURVE::offsetLowTemperatureCharge
float offsetLowTemperatureCharge
Definition: sof.h:83
SOF_CURVE::slopeLowerCellVoltage
float slopeLowerCellVoltage
Definition: sof.h:89
foxmath.h
math library for often used math functions
TEST_SOF_CalculateCurves
void TEST_SOF_CalculateCurves(const SOF_CONFIG_s *pConfigurationValues, SOF_CURVE_s *pCalculatedSofCurveValues)
Definition: sof.c:510
DATA_BLOCK_SOF::recommendedPeakChargeCurrent_mA
float recommendedPeakChargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:397
SOF_CURVE::slopeLowTemperatureDischarge
float slopeLowTemperatureDischarge
Definition: sof.h:77
sof_curveRecommendedOperatingCurrent
static SOF_CURVE_s sof_curveRecommendedOperatingCurrent
Definition: sof.c:72
sof_configMaximumSafetyLimit
const SOF_CONFIG_s sof_configMaximumSafetyLimit
Definition: sof_cfg.c:114
SOF_CONFIG::limitHighTemperatureCharge_ddegC
int16_t limitHighTemperatureCharge_ddegC
Definition: sof_cfg.h:339
DATA_BLOCK_SOF
Definition: database_cfg.h:384
BMS_IsStringClosed
bool BMS_IsStringClosed(uint8_t stringNumber)
Returns string state (closed or open)
Definition: bms.c:1257
battery_cell_cfg.h
Configuration of the battery cell (e.g., minimum and maximum cell voltage)
DATA_BLOCK_SOF::header
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:388
DATA_BLOCK_SOF::recommendedPeakDischargeCurrent_mA
float recommendedPeakDischargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:398
SOF_CURVE::offsetLowerCellVoltage
float offsetLowerCellVoltage
Definition: sof.h:90
sof.h
Header for SOX module, responsible for current derating calculation.
TEST_SOF_CalculateTemperatureBasedCurrentLimit
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:526
sof_recommendedSafetyLimit
const SOF_CONFIG_s sof_recommendedSafetyLimit
Definition: sof_cfg.c:97
DATA_BLOCK_MIN_MAX::maximumCellVoltage_mV
int16_t maximumCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:167
SOF_CONFIG::maximumDischargeCurrent_mA
float maximumDischargeCurrent_mA
Definition: sof_cfg.h:323
SOF_CURVE
Definition: sof.h:76
BC_CURRENT_MAX_CHARGE_MOL_mA
#define BC_CURRENT_MAX_CHARGE_MOL_mA
Maximum charge current limit.
Definition: battery_cell_cfg.h:212
SOF_Init
void SOF_Init(void)
initializes the area for SOF (where derating starts and is fully active).
Definition: sof.c:342
BC_CURRENT_MAX_DISCHARGE_MOL_mA
#define BC_CURRENT_MAX_DISCHARGE_MOL_mA
Maximum discharge current limit.
Definition: battery_cell_cfg.h:196
SOF_CURRENT_LIMITS::continuousDischargeCurrent_mA
float continuousDischargeCurrent_mA
Definition: sof.h:68
BC_CURRENT_MAX_DISCHARGE_MSL_mA
#define BC_CURRENT_MAX_DISCHARGE_MSL_mA
Maximum discharge current limit.
Definition: battery_cell_cfg.h:194
SOF_CONFIG::maximumChargeCurrent_mA
float maximumChargeCurrent_mA
Definition: sof_cfg.h:324
TEST_SOF_CalculateVoltageBasedCurrentLimit
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:513
DATA_BLOCK_MIN_MAX
Definition: database_cfg.h:158
DATA_READ_DATA
#define DATA_READ_DATA(...)
Definition: database.h:72
DATA_BLOCK_SOF::recommendedContinuousDischargeCurrent_mA
float recommendedContinuousDischargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:396
SOF_CONFIG::limitLowerCellVoltage_mV
int16_t limitLowerCellVoltage_mV
Definition: sof_cfg.h:346
DATA_BLOCK_SOF::peakMslDischargeCurrent_mA
float peakMslDischargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:410
SOF_CalculateVoltageBasedCurrentLimit
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:189
SOF_CURVE::offsetLowTemperatureDischarge
float offsetLowTemperatureDischarge
Definition: sof.h:78
database.h
Database module header.
NULL_PTR
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:66
DATA_BLOCK_SOF::peakRslDischargeCurrent_mA
float peakRslDischargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:406
DATA_BLOCK_MIN_MAX::minimumTemperature_ddegC
int16_t minimumTemperature_ddegC[BS_NR_OF_STRINGS]
Definition: database_cfg.h:175
DATA_BLOCK_SOF::recommendedPeakPackDischargeCurrent_mA
float recommendedPeakPackDischargeCurrent_mA
Definition: database_cfg.h:392
SOF_CONFIG::cutoffUpperCellVoltage_mV
int16_t cutoffUpperCellVoltage_mV
Definition: sof_cfg.h:343
SOF_CURVE::slopeUpperCellVoltage
float slopeUpperCellVoltage
Definition: sof.h:87
SOF_CURVE::slopeHighTemperatureCharge
float slopeHighTemperatureCharge
Definition: sof.h:84
BC_CURRENT_MAX_CHARGE_RSL_mA
#define BC_CURRENT_MAX_CHARGE_RSL_mA
Maximum charge current limit.
Definition: battery_cell_cfg.h:211
SOF_CONFIG
Definition: sof_cfg.h:321
BS_MAXIMUM_STRING_CURRENT_mA
#define BS_MAXIMUM_STRING_CURRENT_mA
Maximum string current limit in mA that is used in the SOA module to check for string overcurrent.
Definition: battery_system_cfg.h:198
DATA_BLOCK_MIN_MAX::minimumCellVoltage_mV
int16_t minimumCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:165
sof_curveRsl
static SOF_CURVE_s sof_curveRsl
Definition: sof.c:74
SOF_CURRENT_LIMITS::peakDischargeCurrent_mA
float peakDischargeCurrent_mA
Definition: sof.h:69
DATA_BLOCK_SOF::peakRslChargeCurrent_mA
float peakRslChargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:405
sof_curveMol
static SOF_CURVE_s sof_curveMol
Definition: sof.c:73
sof_maximumOperatingLimit
const SOF_CONFIG_s sof_maximumOperatingLimit
Definition: sof_cfg.c:80
BS_NR_OF_STRINGS
#define BS_NR_OF_STRINGS
Definition: battery_system_cfg.h:89
SOF_CONFIG::cutoffHighTemperatureCharge_ddegC
int16_t cutoffHighTemperatureCharge_ddegC
Definition: sof_cfg.h:338
SOF_CURRENT_LIMITS::continuousChargeCurrent_mA
float continuousChargeCurrent_mA
Definition: sof.h:66
DATA_BLOCK_SOF::continuousMslDischargeCurrent_mA
float continuousMslDischargeCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:408
DATA_BLOCKHEADER::uniqueId
DATA_BLOCK_ID_e uniqueId
Definition: database_cfg.h:109
SOF_Calculation
void SOF_Calculation(void)
triggers SOF calculation
Definition: sof.c:358
SOF_CURRENT_LIMITS::peakChargeCurrent_mA
float peakChargeCurrent_mA
Definition: sof.h:67