foxBMS  1.6.0
The foxBMS Battery Management System API Documentation
soe_counting.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice, this
12  * list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  *
18  * 3. Neither the name of the copyright holder nor the names of its
19  * contributors may be used to endorse or promote products derived from
20  * this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * We kindly request you to use one or more of the following phrases to refer to
34  * foxBMS in your hardware, software, documentation or advertising materials:
35  *
36  * - ″This product uses parts of foxBMS®″
37  * - ″This product includes parts of foxBMS®″
38  * - ″This product is derived from foxBMS®″
39  *
40  */
41 
42 /**
43  * @file soe_counting.c
44  * @author foxBMS Team
45  * @date 2020-10-07 (date of creation)
46  * @updated 2023-10-12 (date of last update)
47  * @version v1.6.0
48  * @ingroup APPLICATION
49  * @prefix SOE
50  *
51  * @brief SOE module responsible for calculation of SOE
52  *
53  */
54 
55 /*========== Includes =======================================================*/
56 #include "battery_cell_cfg.h"
57 #include "battery_system_cfg.h"
58 #include "soe_counting_cfg.h"
59 
60 #include "bms.h"
61 #include "database.h"
62 #include "foxmath.h"
63 #include "fram.h"
64 #include "state_estimation.h"
65 
66 #include <math.h>
67 #include <stdbool.h>
68 #include <stdint.h>
69 
70 /*========== Macros and Definitions =========================================*/
71 /**
72  * This structure contains all the variables relevant for the SOE.
73  */
74 typedef struct {
75  bool soeInitialized; /*!< true if the initialization has passed, false otherwise */
76  bool sensorEcUsed[BS_NR_OF_STRINGS]; /*!< true if energy counting functionality of current sensor is used */
77  float_t ecScalingAverage[BS_NR_OF_STRINGS]; /*!< current sensor offset scaling for average SOE */
78  float_t ecScalingMinimum[BS_NR_OF_STRINGS]; /*!< current sensor offset scaling for minimum SOE */
79  float_t ecScalingMaximum[BS_NR_OF_STRINGS]; /*!< current sensor offset scaling for maximum SOE */
80  uint32_t previousTimestamp
81  [BS_NR_OF_STRINGS]; /*!< last used timestamp of current or energy counting value for SOE estimation */
82 } SOE_STATE_s;
83 
84 /** defines for maximum and minimum SOE */
85 #define MAXIMUM_SOE_PERC (100.0f)
86 #define MINIMUM_SOE_PERC (0.0f)
87 
88 /*========== Static Constant and Variable Definitions =======================*/
89 
90 /**
91  * contains the state of the SOE estimation
92  */
94  .soeInitialized = false,
95  .sensorEcUsed = {GEN_REPEAT_U(false, GEN_STRIP(BS_NR_OF_STRINGS))},
96  .ecScalingAverage = {GEN_REPEAT_U(0.0f, GEN_STRIP(BS_NR_OF_STRINGS))},
97  .ecScalingMinimum = {GEN_REPEAT_U(0.0f, GEN_STRIP(BS_NR_OF_STRINGS))},
98  .ecScalingMaximum = {GEN_REPEAT_U(0.0f, GEN_STRIP(BS_NR_OF_STRINGS))},
99  .previousTimestamp = {GEN_REPEAT_U(0u, GEN_STRIP(BS_NR_OF_STRINGS))},
100 };
101 
102 /** local copies of database tables */
103 /**@{*/
105 /**@}*/
106 
107 /*========== Extern Constant and Variable Definitions =======================*/
108 
109 /*========== Static Function Prototypes =====================================*/
110 
111 /**
112  * @brief calculates string energy in Wh from passed SOE in percentage
113  *
114  * @param[in] stringSoe_perc string SOE in percentage [0.0, 100.0]
115  *
116  * @return returns corresponding string energy in Wh
117  */
118 static uint32_t SOE_GetStringEnergyFromSoePercentage(float_t stringSoe_perc);
119 
120 /**
121  * @brief calculates string SOE in percentage from passed string energy in Wh
122  *
123  * @param[in] energy_Wh string energy in Wh
124  *
125  * @return returns corresponding string SOE in percentage [0.0, 100.0]
126  */
127 static float_t SOE_GetStringSoePercentageFromEnergy(uint32_t energy_Wh);
128 
129 /**
130  * @brief initializes database and FRAM SOE values via lookup table (average, min and max).
131  * @param[out] pSoeValues pointer to SOE database entry
132  */
133 static void SOE_RecalibrateViaLookupTable(DATA_BLOCK_SOE_s *pSoeValues);
134 
135 /**
136  * @brief look-up table for SOE initialization
137  *
138  * @param[in] voltage_mV cell voltage of battery cell
139  *
140  * @return SOE value in percentage [0.0 - 100.0]
141  */
142 static float_t SOE_GetFromVoltage(int16_t voltage_mV);
143 
144 /**
145  * @brief sets SOE value with a parameter between 0.0 and 100.0.
146  * @details limits the SOE value to 0.0 respectively 100.0 if a value outside
147  * of the allowed SOE range is passed. Updates local fram and database
148  * struct but does *NOT* write them
149  * @param[out] pSoeValues pointer to SOE database entry
150  * @param[in] soeMinimumValue_perc SOE min value to set
151  * @param[in] soeMaximumValue_perc SOE max value to set
152  * @param[in] soeAverageValue_perc SOE average value to set
153  * @param[in] stringNumber string addressed
154  */
155 static void SOE_SetValue(
156  DATA_BLOCK_SOE_s *pSoeValues,
157  float_t soeMinimumValue_perc,
158  float_t soeMaximumValue_perc,
159  float_t soeAverageValue_perc,
160  uint8_t stringNumber);
161 
162 /**
163  * @brief Check if all database SOE percentage values are within [0.0, 100.0]
164  * Limits SOE values to limit values if outside of this range.
165  *
166  * @param[in,out] pTableSoe pointer to database struct with SOE values
167  * @param[in] stringNumber string that is checked
168  */
169 static void SOE_CheckDatabaseSoePercentageLimits(DATA_BLOCK_SOE_s *pTableSoe, uint8_t stringNumber);
170 
171 /*========== Static Function Implementations ================================*/
172 static float_t SOE_GetStringSoePercentageFromEnergy(uint32_t energy_Wh) {
173  float_t stringSoe_perc = 0.0f;
174  const float_t stringEnergy_Wh = (float_t)energy_Wh;
175  if (stringEnergy_Wh >= SOE_STRING_ENERGY_Wh) {
176  stringSoe_perc = MAXIMUM_SOE_PERC;
177  } else {
178  stringSoe_perc = UNIT_CONVERSION_FACTOR_100_FLOAT * (stringEnergy_Wh / SOE_STRING_ENERGY_Wh);
179  }
180  return stringSoe_perc;
181 }
182 
183 static uint32_t SOE_GetStringEnergyFromSoePercentage(float_t stringSoe_perc) {
184  float_t energy_Wh = 0.0f;
185  if (stringSoe_perc >= MAXIMUM_SOE_PERC) {
186  energy_Wh = SOE_STRING_ENERGY_Wh;
187  } else if (stringSoe_perc <= MINIMUM_SOE_PERC) {
188  energy_Wh = MINIMUM_SOE_PERC;
189  } else {
190  energy_Wh = SOE_STRING_ENERGY_Wh * (stringSoe_perc / UNIT_CONVERSION_FACTOR_100_FLOAT);
191  }
192  return (uint32_t)energy_Wh;
193 }
194 
196  FAS_ASSERT(pSoeValues != NULL_PTR);
197  DATA_BLOCK_MIN_MAX_s tableMinimumMaximumAverage = {.header.uniqueId = DATA_BLOCK_ID_MIN_MAX};
198 
199  DATA_READ_DATA(&tableMinimumMaximumAverage);
200 
201  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
202  SOE_SetValue(
203  pSoeValues,
204  SOE_GetFromVoltage(tableMinimumMaximumAverage.minimumCellVoltage_mV[s]),
205  SOE_GetFromVoltage(tableMinimumMaximumAverage.maximumCellVoltage_mV[s]),
206  SOE_GetFromVoltage(tableMinimumMaximumAverage.averageCellVoltage_mV[s]),
207  s);
208  }
210 }
211 
212 static float_t SOE_GetFromVoltage(int16_t voltage_mV) {
213  float_t soe_perc = 50.0f;
214  /* Variables for interpolating LUT value */
215  uint16_t between_high = 0;
216  uint16_t between_low = 0;
217 
218  /* Cell voltages are inserted in LUT in descending order -> start with 1 as we do not want to extrapolate. */
219  for (uint16_t i = 1u; i < bc_stateOfEnergyLookupTableLength; i++) {
220  if (voltage_mV < bc_stateOfEnergyLookupTable[i].voltage_mV) {
221  between_low = i + 1u;
222  between_high = i;
223  }
224  }
225 
226  /* Interpolate between LUT values, but do not extrapolate LUT! */
227  if (!(((between_high == 0u) && (between_low == 0u)) || /* cell voltage > maximum LUT voltage */
228  (between_low >= bc_stateOfEnergyLookupTableLength))) { /* cell voltage < minimum LUT voltage */
229  soe_perc = MATH_LinearInterpolation(
230  (float_t)bc_stateOfEnergyLookupTable[between_low].voltage_mV,
231  bc_stateOfEnergyLookupTable[between_low].value,
232  (float_t)bc_stateOfEnergyLookupTable[between_high].voltage_mV,
233  bc_stateOfEnergyLookupTable[between_high].value,
234  (float_t)voltage_mV);
235  } else if ((between_low >= bc_stateOfEnergyLookupTableLength)) {
236  /* LUT SOE values are in descending order: cell voltage < minimum LUT voltage */
237  soe_perc = MINIMUM_SOE_PERC;
238  } else {
239  /* cell voltage > maximum LUT voltage */
240  soe_perc = MAXIMUM_SOE_PERC;
241  }
242  return soe_perc;
243 }
244 
245 static void SOE_SetValue(
246  DATA_BLOCK_SOE_s *pSoeValues,
247  float_t soeMinimumValue_perc,
248  float_t soeMaximumValue_perc,
249  float_t soeAverageValue_perc,
250  uint8_t stringNumber) {
251  FAS_ASSERT(pSoeValues != NULL_PTR);
252 
253  /* Update FRAM value */
254  fram_soe.averageSoe_perc[stringNumber] = soeAverageValue_perc;
255  fram_soe.minimumSoe_perc[stringNumber] = soeMinimumValue_perc;
256  fram_soe.maximumSoe_perc[stringNumber] = soeMaximumValue_perc;
257 
258  /* Update database values */
259  pSoeValues->averageSoe_perc[stringNumber] = soeAverageValue_perc;
260  pSoeValues->minimumSoe_perc[stringNumber] = soeMinimumValue_perc;
261  pSoeValues->maximumSoe_perc[stringNumber] = soeMaximumValue_perc;
262 
263  pSoeValues->maximumSoe_Wh[stringNumber] = SOE_GetStringEnergyFromSoePercentage(soeMaximumValue_perc);
264  pSoeValues->averageSoe_Wh[stringNumber] = SOE_GetStringEnergyFromSoePercentage(soeAverageValue_perc);
265  pSoeValues->minimumSoe_Wh[stringNumber] = SOE_GetStringEnergyFromSoePercentage(soeMinimumValue_perc);
266 
267  /* Calculate scaling values depending on EC counting value and current SOE */
268  if (soe_state.sensorEcUsed[stringNumber] == true) {
270 
271  float_t ecOffset =
273 
274  if (soe_tableCurrentSensor.energyCounter_Wh[stringNumber] < 0) {
275  ecOffset *= (-1.0f);
276  }
277 
278 #if BS_POSITIVE_DISCHARGE_CURRENT == false
279  ecOffset *= (-1.0f); /* negate calculated delta SOE in perc */
280 
281 #endif /* BS_POSITIVE_DISCHARGE_CURRENT == false */
282 
283  soe_state.ecScalingAverage[stringNumber] = fram_soe.averageSoe_perc[stringNumber] + ecOffset;
284  soe_state.ecScalingMinimum[stringNumber] = fram_soe.minimumSoe_perc[stringNumber] + ecOffset;
285  soe_state.ecScalingMaximum[stringNumber] = fram_soe.maximumSoe_perc[stringNumber] + ecOffset;
286  }
287 }
288 
289 static void SOE_CheckDatabaseSoePercentageLimits(DATA_BLOCK_SOE_s *pTableSoe, uint8_t stringNumber) {
290  FAS_ASSERT(pTableSoe != NULL_PTR);
291  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
292 
293  if (pTableSoe->averageSoe_perc[stringNumber] > MAXIMUM_SOE_PERC) {
294  pTableSoe->averageSoe_perc[stringNumber] = MAXIMUM_SOE_PERC;
295  }
296  if (pTableSoe->averageSoe_perc[stringNumber] < MINIMUM_SOE_PERC) {
297  pTableSoe->averageSoe_perc[stringNumber] = MINIMUM_SOE_PERC;
298  }
299  if (pTableSoe->minimumSoe_perc[stringNumber] > MAXIMUM_SOE_PERC) {
300  pTableSoe->minimumSoe_perc[stringNumber] = MAXIMUM_SOE_PERC;
301  }
302  if (pTableSoe->minimumSoe_perc[stringNumber] < MINIMUM_SOE_PERC) {
303  pTableSoe->minimumSoe_perc[stringNumber] = MINIMUM_SOE_PERC;
304  }
305  if (pTableSoe->maximumSoe_perc[stringNumber] > MAXIMUM_SOE_PERC) {
306  pTableSoe->maximumSoe_perc[stringNumber] = MAXIMUM_SOE_PERC;
307  }
308  if (pTableSoe->maximumSoe_perc[stringNumber] < MINIMUM_SOE_PERC) {
309  pTableSoe->maximumSoe_perc[stringNumber] = MINIMUM_SOE_PERC;
310  }
311 }
312 
313 /*========== Extern Function Implementations ================================*/
314 
315 extern void SE_InitializeStateOfEnergy(DATA_BLOCK_SOE_s *pSoeValues, bool ec_present, uint8_t stringNumber) {
316  FAS_ASSERT(pSoeValues != NULL_PTR);
317  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
319 
320  pSoeValues->averageSoe_perc[stringNumber] = fram_soe.averageSoe_perc[stringNumber];
321  pSoeValues->minimumSoe_perc[stringNumber] = fram_soe.minimumSoe_perc[stringNumber];
322  pSoeValues->maximumSoe_perc[stringNumber] = fram_soe.maximumSoe_perc[stringNumber];
323 
324  /* Limit SOE values [0.0f, 100.0f] */
325  SOE_CheckDatabaseSoePercentageLimits(pSoeValues, stringNumber);
326 
327  /* Calculate string energy in Wh */
328  pSoeValues->maximumSoe_Wh[stringNumber] =
329  SOE_GetStringEnergyFromSoePercentage(pSoeValues->maximumSoe_perc[stringNumber]);
330  pSoeValues->minimumSoe_Wh[stringNumber] =
331  SOE_GetStringEnergyFromSoePercentage(pSoeValues->minimumSoe_perc[stringNumber]);
332  pSoeValues->averageSoe_Wh[stringNumber] =
333  SOE_GetStringEnergyFromSoePercentage(pSoeValues->averageSoe_perc[stringNumber]);
334 
335  if (ec_present == true) {
337  soe_state.sensorEcUsed[stringNumber] = true;
338 
339  /* Set scaling values */
340  float_t ecOffset =
342 
343  if (soe_tableCurrentSensor.energyCounter_Wh[stringNumber] < 0) {
344  ecOffset *= (-1.0f);
345  }
346 
347 #if BS_POSITIVE_DISCHARGE_CURRENT == false
348  ecOffset *= (-1.0f); /* negate calculated delta SOE in perc */
349 
350 #endif /* BS_POSITIVE_DISCHARGE_CURRENT == false */
351 
352  soe_state.ecScalingMinimum[stringNumber] = fram_soe.minimumSoe_perc[stringNumber] + ecOffset;
353  soe_state.ecScalingMaximum[stringNumber] = fram_soe.maximumSoe_perc[stringNumber] + ecOffset;
354  soe_state.ecScalingAverage[stringNumber] = fram_soe.averageSoe_perc[stringNumber] + ecOffset;
355  }
356  soe_state.soeInitialized = true;
357 }
358 
360  FAS_ASSERT(pSoeValues != NULL_PTR);
361  bool continueFunction = true;
362  if (soe_state.soeInitialized == false) {
363  /* Exit if SOE not initialized yet */
364  continueFunction = false;
365  }
366 
367  if (continueFunction == true) {
368  /* Use energy counting/integrate */
370 
372  /* Recalibrate SOE via LUT */
373  SOE_RecalibrateViaLookupTable(pSoeValues);
374  } else {
375  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
376  if (soe_state.sensorEcUsed[s] == false) {
377  /* no energy counting activated -> manually integrate energy */
378  uint32_t timestamp = soe_tableCurrentSensor.timestampCurrent[s];
379  uint32_t previous_timestamp = soe_tableCurrentSensor.previousTimestampCurrent[s];
380 
381  /* check if current measurement has been updated */
382  if (soe_state.previousTimestamp[s] != timestamp) {
383  float_t timestep_s = (((float_t)timestamp - (float_t)previous_timestamp)) / 1000.0f;
384  if (timestep_s > 0.0f) {
385  /* Current in charge direction negative means SOE increasing --> BAT naming, not ROB */
386  float_t deltaSOE_Wh =
387  ((((float_t)soe_tableCurrentSensor.current_mA[s] / 1000.0f) * /* convert to A */
388  ((float_t)soe_tableCurrentSensor.highVoltage_mV[s][0] / 1000.0f)) / /* convert to V */
389  timestep_s) / /* unit: s */
390  3600.0f; /* convert Ws -> Wh */
391 
392 #if BS_POSITIVE_DISCHARGE_CURRENT == false
393  /* negate calculated delta SOE_Wh */
394  deltaSOE_Wh *= (-1.0f);
395 #endif /* BS_POSITIVE_DISCHARGE_CURRENT == false */
396 
397  pSoeValues->averageSoe_Wh[s] -= (uint32_t)deltaSOE_Wh;
398  pSoeValues->minimumSoe_Wh[s] -= (uint32_t)deltaSOE_Wh;
399  pSoeValues->maximumSoe_Wh[s] -= (uint32_t)deltaSOE_Wh;
400 
401  pSoeValues->averageSoe_perc[s] =
403  pSoeValues->minimumSoe_perc[s] =
405  pSoeValues->maximumSoe_perc[s] =
407 
408  /* update timestamp SOE state variable for next iteration */
409  soe_state.previousTimestamp[s] = timestamp;
410  }
411  } /* end check if current measurement has been updated */
412  } else {
413  /* check if ec measurement has been updated */
415  /* Calculate SOE value with current sensor EC value */
416  float_t deltaSoe_perc =
419 
420 #if BS_POSITIVE_DISCHARGE_CURRENT == false
421  /* negate calculated delta SOE_perc */
422  deltaSoe_perc *= (-1.0f);
423 #endif
424  /* Apply EC scaling offset to get actual string energy */
425  pSoeValues->averageSoe_perc[s] = soe_state.ecScalingAverage[s] - deltaSoe_perc;
426  pSoeValues->minimumSoe_perc[s] = soe_state.ecScalingMinimum[s] - deltaSoe_perc;
427  pSoeValues->maximumSoe_perc[s] = soe_state.ecScalingMaximum[s] - deltaSoe_perc;
428 
429  /* Limit SOE values to [0.0, 100.0] */
431 
432  /* Calculate new Wh values */
433  pSoeValues->maximumSoe_Wh[s] =
435  pSoeValues->averageSoe_Wh[s] =
437  pSoeValues->minimumSoe_Wh[s] =
439 
440  /* Update timestamp for next iteration */
442  }
443  }
444 
445  fram_soe.averageSoe_perc[s] = pSoeValues->averageSoe_perc[s];
446  fram_soe.minimumSoe_perc[s] = pSoeValues->minimumSoe_perc[s];
447  fram_soe.maximumSoe_perc[s] = pSoeValues->maximumSoe_perc[s];
448  }
449 
450  /* Update database and FRAM value */
452  }
453  }
454 }
455 
456 /*========== Externalized Static Function Implementations (Unit Test) =======*/
457 #ifdef UNITY_UNIT_TEST
458 #endif
uint16_t bc_stateOfEnergyLookupTableLength
const BC_LUT_s bc_stateOfEnergyLookupTable[]
Configuration of the battery cell (e.g., minimum and maximum cell voltage)
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_GetBatterySystemState(void)
Returns current battery system state (charging/discharging, resting or in relaxation phase)
Definition: bms.c:1586
bms driver header
@ BMS_AT_REST
Definition: bms.h:76
Database module header.
#define DATA_READ_DATA(...)
Definition: database.h:86
@ DATA_BLOCK_ID_MIN_MAX
Definition: database_cfg.h:99
@ DATA_BLOCK_ID_CURRENT_SENSOR
Definition: database_cfg.h:93
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:255
float_t MATH_LinearInterpolation(const float_t x1, const float_t y1, const float_t x2, const float_t y2, const float_t x_interpolate)
Linear inter-/extrapolates a third point according to two given points.
Definition: foxmath.c:84
math library for often used math functions
#define UNIT_CONVERSION_FACTOR_100_FLOAT
Definition: foxmath.h:77
FRAM_RETURN_TYPE_e FRAM_ReadData(FRAM_BLOCK_ID_e blockId)
Reads a variable from the FRAM.
Definition: fram.c:211
FRAM_RETURN_TYPE_e FRAM_WriteData(FRAM_BLOCK_ID_e blockId)
Writes a variable to the FRAM.
Definition: fram.c:133
Header for the driver for the FRAM module.
FRAM_SOE_s fram_soe
Definition: fram_cfg.c:72
@ FRAM_BLOCK_ID_SOE
Definition: fram_cfg.h:109
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:77
#define GEN_REPEAT_U(x, n)
Macro that helps to generate a series of literals (for array initializers).
Definition: general.h:250
#define GEN_STRIP(x)
Definition: general.h:261
void SE_InitializeStateOfEnergy(DATA_BLOCK_SOE_s *pSoeValues, bool ec_present, uint8_t stringNumber)
initializes startup state-of-energy (SOE) related values
Definition: soe_counting.c:315
void SE_CalculateStateOfEnergy(DATA_BLOCK_SOE_s *pSoeValues)
periodically called algorithm to calculate state-of-energy (SOE)
Definition: soe_counting.c:359
#define MINIMUM_SOE_PERC
Definition: soe_counting.c:86
#define MAXIMUM_SOE_PERC
Definition: soe_counting.c:85
static float_t SOE_GetFromVoltage(int16_t voltage_mV)
look-up table for SOE initialization
Definition: soe_counting.c:212
static DATA_BLOCK_CURRENT_SENSOR_s soe_tableCurrentSensor
Definition: soe_counting.c:104
static SOE_STATE_s soe_state
Definition: soe_counting.c:93
static float_t SOE_GetStringSoePercentageFromEnergy(uint32_t energy_Wh)
calculates string SOE in percentage from passed string energy in Wh
Definition: soe_counting.c:172
static void SOE_SetValue(DATA_BLOCK_SOE_s *pSoeValues, float_t soeMinimumValue_perc, float_t soeMaximumValue_perc, float_t soeAverageValue_perc, uint8_t stringNumber)
sets SOE value with a parameter between 0.0 and 100.0.
Definition: soe_counting.c:245
static uint32_t SOE_GetStringEnergyFromSoePercentage(float_t stringSoe_perc)
calculates string energy in Wh from passed SOE in percentage
Definition: soe_counting.c:183
static void SOE_RecalibrateViaLookupTable(DATA_BLOCK_SOE_s *pSoeValues)
initializes database and FRAM SOE values via lookup table (average, min and max).
Definition: soe_counting.c:195
static void SOE_CheckDatabaseSoePercentageLimits(DATA_BLOCK_SOE_s *pTableSoe, uint8_t stringNumber)
Check if all database SOE percentage values are within [0.0, 100.0] Limits SOE values to limit values...
Definition: soe_counting.c:289
Header for SOE configuration.
#define SOE_STRING_ENERGY_Wh
Header for state-estimation module responsible for the estimation of state-of-charge (SOC),...
uint32_t previousTimestampCurrent[BS_NR_OF_STRINGS]
Definition: database_cfg.h:223
uint32_t timestampCurrent[BS_NR_OF_STRINGS]
Definition: database_cfg.h:224
int32_t current_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:220
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:219
int32_t energyCounter_Wh[BS_NR_OF_STRINGS]
Definition: database_cfg.h:236
int32_t highVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_VOLTAGES_FROM_CURRENT_SENSOR]
Definition: database_cfg.h:242
uint32_t timestampEnergyCounting[BS_NR_OF_STRINGS]
Definition: database_cfg.h:239
DATA_BLOCK_ID_e uniqueId
Definition: database_cfg.h:125
int16_t averageCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:169
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:167
int16_t maximumCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:172
int16_t minimumCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:170
uint32_t minimumSoe_Wh[BS_NR_OF_STRINGS]
Definition: database_cfg.h:545
float_t maximumSoe_perc[BS_NR_OF_STRINGS]
Definition: database_cfg.h:542
uint32_t maximumSoe_Wh[BS_NR_OF_STRINGS]
Definition: database_cfg.h:543
uint32_t averageSoe_Wh[BS_NR_OF_STRINGS]
Definition: database_cfg.h:544
float_t averageSoe_perc[BS_NR_OF_STRINGS]
Definition: database_cfg.h:540
float_t minimumSoe_perc[BS_NR_OF_STRINGS]
Definition: database_cfg.h:541
float_t maximumSoe_perc[BS_NR_OF_STRINGS]
Definition: fram_cfg.h:153
float_t minimumSoe_perc[BS_NR_OF_STRINGS]
Definition: fram_cfg.h:152
float_t averageSoe_perc[BS_NR_OF_STRINGS]
Definition: fram_cfg.h:154
bool sensorEcUsed[BS_NR_OF_STRINGS]
Definition: soe_counting.c:76
float_t ecScalingMinimum[BS_NR_OF_STRINGS]
Definition: soe_counting.c:78
bool soeInitialized
Definition: soe_counting.c:75
uint32_t previousTimestamp[BS_NR_OF_STRINGS]
Definition: soe_counting.c:81
float_t ecScalingAverage[BS_NR_OF_STRINGS]
Definition: soe_counting.c:77
float_t ecScalingMaximum[BS_NR_OF_STRINGS]
Definition: soe_counting.c:79