foxBMS  1.5.1
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-02-23 (date of last update)
47  * @version v1.5.1
48  * @ingroup APPLICATION
49  * @prefix SOE
50  *
51  * @brief SOE module responsible for calculation of SOE
52  *
53  */
54 
55 /*========== Includes =======================================================*/
56 #include "soe_counting.h"
57 
58 #include "battery_cell_cfg.h"
59 #include "battery_system_cfg.h"
60 #include "soe_counting_cfg.h"
61 
62 #include "bms.h"
63 #include "database.h"
64 #include "foxmath.h"
65 #include "fram.h"
66 
67 #include <math.h>
68 #include <stdbool.h>
69 #include <stdint.h>
70 
71 /*========== Macros and Definitions =========================================*/
72 /**
73  * This structure contains all the variables relevant for the SOX.
74  */
75 typedef struct {
76  bool soeInitialized; /*!< true if the initialization has passed, false otherwise */
77  bool sensorEcUsed[BS_NR_OF_STRINGS]; /*!< true if energy counting functionality of current sensor is used */
78  float_t ecScalingAverage[BS_NR_OF_STRINGS]; /*!< current sensor offset scaling for average SOE */
79  float_t ecScalingMinimum[BS_NR_OF_STRINGS]; /*!< current sensor offset scaling for minimum SOE */
80  float_t ecScalingMaximum[BS_NR_OF_STRINGS]; /*!< current sensor offset scaling for maximum SOE */
81  uint32_t previousTimestamp
82  [BS_NR_OF_STRINGS]; /*!< last used timestamp of current or energy counting value for SOE estimation */
83 } SOE_STATE_s;
84 
85 /** defines for maximum and minimum SOE */
86 #define MAXIMUM_SOE_PERC (100.0f)
87 #define MINIMUM_SOE_PERC (0.0f)
88 
89 /*========== Static Constant and Variable Definitions =======================*/
90 
91 /**
92  * contains the state of the SOE estimation
93  */
95  .soeInitialized = false,
96  .sensorEcUsed = {GEN_REPEAT_U(false, GEN_STRIP(BS_NR_OF_STRINGS))},
97  .ecScalingAverage = {GEN_REPEAT_U(0.0f, GEN_STRIP(BS_NR_OF_STRINGS))},
98  .ecScalingMinimum = {GEN_REPEAT_U(0.0f, GEN_STRIP(BS_NR_OF_STRINGS))},
99  .ecScalingMaximum = {GEN_REPEAT_U(0.0f, GEN_STRIP(BS_NR_OF_STRINGS))},
100  .previousTimestamp = {GEN_REPEAT_U(0u, GEN_STRIP(BS_NR_OF_STRINGS))},
101 };
102 
103 /** local copies of database tables */
104 /**@{*/
106 /**@}*/
107 
108 /*========== Extern Constant and Variable Definitions =======================*/
109 
110 /*========== Static Function Prototypes =====================================*/
111 
112 /**
113  * @brief calculates string energy in Wh from passed SOE in percentage
114  *
115  * @param[in] stringSoe_perc string SOE in percentage [0.0, 100.0]
116  *
117  * @return returns corresponding string energy in Wh
118  */
119 static uint32_t SOE_GetStringEnergyFromSoePercentage(float_t stringSoe_perc);
120 
121 /**
122  * @brief calculates string SOE in percentage from passed string energy in Wh
123  *
124  * @param[in] energy_Wh string energy in Wh
125  *
126  * @return returns corresponding string SOE in percentage [0.0, 100.0]
127  */
128 static float_t SOE_GetStringSoePercentageFromEnergy(uint32_t energy_Wh);
129 
130 /**
131  * @brief initializes database and FRAM SOE values via lookup table (average, min and max).
132  * @param[out] pSoeValues pointer to SOE database entry
133  */
134 static void SOE_RecalibrateViaLookupTable(DATA_BLOCK_SOX_s *pSoeValues);
135 
136 /**
137  * @brief look-up table for SOE initialization
138  *
139  * @param[in] voltage_mV cell voltage of battery cell
140  *
141  * @return SOE value in percentage [0.0 - 100.0]
142  */
143 static float_t SOE_GetFromVoltage(int16_t voltage_mV);
144 
145 /**
146  * @brief sets SOE value with a parameter between 0.0 and 100.0.
147  * @details limits the SOE value to 0.0 respectively 100.0 if a value outside
148  * of the allowed SOE range is passed. Updates local fram and database
149  * struct but does *NOT* write them
150  * @param[out] pSoeValues pointer to SOE database enty
151  * @param[in] soeMinimumValue_perc SOE min value to set
152  * @param[in] soeMaximumValue_perc SOE max value to set
153  * @param[in] soeAverageValue_perc SOE average value to set
154  * @param[in] stringNumber string addressed
155  */
156 static void SOE_SetValue(
157  DATA_BLOCK_SOX_s *pSoeValues,
158  float_t soeMinimumValue_perc,
159  float_t soeMaximumValue_perc,
160  float_t soeAverageValue_perc,
161  uint8_t stringNumber);
162 
163 /**
164  * @brief Check if all database SOE percentage values are within [0.0, 100.0]
165  * Limits SOE values to limit values if outside of this range.
166  *
167  * @param[in,out] pTableSoe pointer to database struct with SOE values
168  * @param[in] stringNumber string that is checked
169  */
170 static void SOE_CheckDatabaseSoePercentageLimits(DATA_BLOCK_SOX_s *pTableSoe, uint8_t stringNumber);
171 
172 /*========== Static Function Implementations ================================*/
173 static float_t SOE_GetStringSoePercentageFromEnergy(uint32_t energy_Wh) {
174  float_t stringSoe_perc = 0.0f;
175  const float_t stringEnergy_Wh = (float_t)energy_Wh;
176  if (stringEnergy_Wh >= SOE_STRING_ENERGY_Wh) {
177  stringSoe_perc = MAXIMUM_SOE_PERC;
178  } else {
179  stringSoe_perc = UNIT_CONVERSION_FACTOR_100_FLOAT * (stringEnergy_Wh / SOE_STRING_ENERGY_Wh);
180  }
181  return stringSoe_perc;
182 }
183 
184 static uint32_t SOE_GetStringEnergyFromSoePercentage(float_t stringSoe_perc) {
185  float_t energy_Wh = 0.0f;
186  if (stringSoe_perc >= MAXIMUM_SOE_PERC) {
187  energy_Wh = SOE_STRING_ENERGY_Wh;
188  } else if (stringSoe_perc <= MINIMUM_SOE_PERC) {
189  energy_Wh = MINIMUM_SOE_PERC;
190  } else {
191  energy_Wh = SOE_STRING_ENERGY_Wh * (stringSoe_perc / UNIT_CONVERSION_FACTOR_100_FLOAT);
192  }
193  return (uint32_t)energy_Wh;
194 }
195 
197  FAS_ASSERT(pSoeValues != NULL_PTR);
198  DATA_BLOCK_MIN_MAX_s tableMinimumMaximumAverage = {.header.uniqueId = DATA_BLOCK_ID_MIN_MAX};
199 
200  DATA_READ_DATA(&tableMinimumMaximumAverage);
201 
202  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
203  SOE_SetValue(
204  pSoeValues,
205  SOE_GetFromVoltage(tableMinimumMaximumAverage.minimumCellVoltage_mV[s]),
206  SOE_GetFromVoltage(tableMinimumMaximumAverage.maximumCellVoltage_mV[s]),
207  SOE_GetFromVoltage(tableMinimumMaximumAverage.averageCellVoltage_mV[s]),
208  s);
209  }
211 }
212 
213 static float_t SOE_GetFromVoltage(int16_t voltage_mV) {
214  float_t soe_perc = 50.0f;
215  /* Variables for interpolating LUT value */
216  uint16_t between_high = 0;
217  uint16_t between_low = 0;
218 
219  /* Cell voltages are inserted in LUT in descending order -> start with 1 as we do not want to extrapolate. */
220  for (uint16_t i = 1u; i < bc_stateOfEnergyLookupTableLength; i++) {
221  if (voltage_mV < bc_stateOfEnergyLookupTable[i].voltage_mV) {
222  between_low = i + 1u;
223  between_high = i;
224  }
225  }
226 
227  /* Interpolate between LUT values, but do not extrapolate LUT! */
228  if (!(((between_high == 0u) && (between_low == 0u)) || /* cell voltage > maximum LUT voltage */
229  (between_low >= bc_stateOfEnergyLookupTableLength))) { /* cell voltage < minimum LUT voltage */
230  soe_perc = MATH_LinearInterpolation(
231  (float_t)bc_stateOfEnergyLookupTable[between_low].voltage_mV,
232  bc_stateOfEnergyLookupTable[between_low].value,
233  (float_t)bc_stateOfEnergyLookupTable[between_high].voltage_mV,
234  bc_stateOfEnergyLookupTable[between_high].value,
235  (float_t)voltage_mV);
236  } else if ((between_low >= bc_stateOfEnergyLookupTableLength)) {
237  /* LUT SOE values are in descending order: cell voltage < minimum LUT voltage */
238  soe_perc = MINIMUM_SOE_PERC;
239  } else {
240  /* cell voltage > maximum LUT voltage */
241  soe_perc = MAXIMUM_SOE_PERC;
242  }
243  return soe_perc;
244 }
245 
246 static void SOE_SetValue(
247  DATA_BLOCK_SOX_s *pSoeValues,
248  float_t soeMinimumValue_perc,
249  float_t soeMaximumValue_perc,
250  float_t soeAverageValue_perc,
251  uint8_t stringNumber) {
252  FAS_ASSERT(pSoeValues != NULL_PTR);
253 
254  /* Update FRAM value */
255  fram_soe.averageSoe_perc[stringNumber] = soeAverageValue_perc;
256  fram_soe.minimumSoe_perc[stringNumber] = soeMinimumValue_perc;
257  fram_soe.maximumSoe_perc[stringNumber] = soeMaximumValue_perc;
258 
259  /* Update database values */
260  pSoeValues->averageSoe_perc[stringNumber] = soeAverageValue_perc;
261  pSoeValues->minimumSoe_perc[stringNumber] = soeMinimumValue_perc;
262  pSoeValues->maximumSoe_perc[stringNumber] = soeMaximumValue_perc;
263 
264  pSoeValues->maximumSoe_Wh[stringNumber] = SOE_GetStringEnergyFromSoePercentage(soeMaximumValue_perc);
265  pSoeValues->averageSoe_Wh[stringNumber] = SOE_GetStringEnergyFromSoePercentage(soeAverageValue_perc);
266  pSoeValues->minimumSoe_Wh[stringNumber] = SOE_GetStringEnergyFromSoePercentage(soeMinimumValue_perc);
267 
268  /* Calculate scaling values depending on EC counting value and current SOE */
269  if (soe_state.sensorEcUsed[stringNumber] == true) {
271 
272  float_t ecOffset =
274 
275  if (soe_tableCurrentSensor.energyCounter_Wh[stringNumber] < 0) {
276  ecOffset *= (-1.0f);
277  }
278 
279 #if BS_POSITIVE_DISCHARGE_CURRENT == false
280  ecOffset *= (-1.0f); /* negate calculated delta SOE in perc */
281 
282 #endif /* BS_POSITIVE_DISCHARGE_CURRENT == false */
283 
284  soe_state.ecScalingAverage[stringNumber] = fram_soe.averageSoe_perc[stringNumber] + ecOffset;
285  soe_state.ecScalingMinimum[stringNumber] = fram_soe.minimumSoe_perc[stringNumber] + ecOffset;
286  soe_state.ecScalingMaximum[stringNumber] = fram_soe.maximumSoe_perc[stringNumber] + ecOffset;
287  }
288 }
289 
290 static void SOE_CheckDatabaseSoePercentageLimits(DATA_BLOCK_SOX_s *pTableSoe, uint8_t stringNumber) {
291  FAS_ASSERT(pTableSoe != NULL_PTR);
292  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
293 
294  if (pTableSoe->averageSoe_perc[stringNumber] > MAXIMUM_SOE_PERC) {
295  pTableSoe->averageSoe_perc[stringNumber] = MAXIMUM_SOE_PERC;
296  }
297  if (pTableSoe->averageSoe_perc[stringNumber] < MINIMUM_SOE_PERC) {
298  pTableSoe->averageSoe_perc[stringNumber] = MINIMUM_SOE_PERC;
299  }
300  if (pTableSoe->minimumSoe_perc[stringNumber] > MAXIMUM_SOE_PERC) {
301  pTableSoe->minimumSoe_perc[stringNumber] = MAXIMUM_SOE_PERC;
302  }
303  if (pTableSoe->minimumSoe_perc[stringNumber] < MINIMUM_SOE_PERC) {
304  pTableSoe->minimumSoe_perc[stringNumber] = MINIMUM_SOE_PERC;
305  }
306  if (pTableSoe->maximumSoe_perc[stringNumber] > MAXIMUM_SOE_PERC) {
307  pTableSoe->maximumSoe_perc[stringNumber] = MAXIMUM_SOE_PERC;
308  }
309  if (pTableSoe->maximumSoe_perc[stringNumber] < MINIMUM_SOE_PERC) {
310  pTableSoe->maximumSoe_perc[stringNumber] = MINIMUM_SOE_PERC;
311  }
312 }
313 
314 /*========== Extern Function Implementations ================================*/
315 
316 extern void SE_InitializeStateOfEnergy(DATA_BLOCK_SOX_s *pSoeValues, bool ec_present, uint8_t stringNumber) {
317  FAS_ASSERT(pSoeValues != NULL_PTR);
318  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
320 
321  pSoeValues->averageSoe_perc[stringNumber] = fram_soe.averageSoe_perc[stringNumber];
322  pSoeValues->minimumSoe_perc[stringNumber] = fram_soe.minimumSoe_perc[stringNumber];
323  pSoeValues->maximumSoe_perc[stringNumber] = fram_soe.maximumSoe_perc[stringNumber];
324 
325  /* Limit SOE values [0.0f, 100.0f] */
326  SOE_CheckDatabaseSoePercentageLimits(pSoeValues, stringNumber);
327 
328  /* Calculate string energy in Wh */
329  pSoeValues->maximumSoe_Wh[stringNumber] =
330  SOE_GetStringEnergyFromSoePercentage(pSoeValues->maximumSoe_perc[stringNumber]);
331  pSoeValues->minimumSoe_Wh[stringNumber] =
332  SOE_GetStringEnergyFromSoePercentage(pSoeValues->minimumSoe_perc[stringNumber]);
333  pSoeValues->averageSoe_Wh[stringNumber] =
334  SOE_GetStringEnergyFromSoePercentage(pSoeValues->averageSoe_perc[stringNumber]);
335 
336  if (ec_present == true) {
338  soe_state.sensorEcUsed[stringNumber] = true;
339 
340  /* Set scaling values */
341  float_t ecOffset =
343 
344  if (soe_tableCurrentSensor.energyCounter_Wh[stringNumber] < 0) {
345  ecOffset *= (-1.0f);
346  }
347 
348 #if BS_POSITIVE_DISCHARGE_CURRENT == false
349  ecOffset *= (-1.0f); /* negate calculated delta SOE in perc */
350 
351 #endif /* BS_POSITIVE_DISCHARGE_CURRENT == false */
352 
353  soe_state.ecScalingMinimum[stringNumber] = fram_soe.minimumSoe_perc[stringNumber] + ecOffset;
354  soe_state.ecScalingMaximum[stringNumber] = fram_soe.maximumSoe_perc[stringNumber] + ecOffset;
355  soe_state.ecScalingAverage[stringNumber] = fram_soe.averageSoe_perc[stringNumber] + ecOffset;
356  }
357  soe_state.soeInitialized = true;
358 }
359 
361  FAS_ASSERT(pSoeValues != NULL_PTR);
362  bool continueFunction = true;
363  if (soe_state.soeInitialized == false) {
364  /* Exit if SOE not initialized yet */
365  continueFunction = false;
366  }
367 
368  if (continueFunction == true) {
369  /* Use energy counting/integrate */
371 
373  /* Recalibrate SOE via LUT */
374  SOE_RecalibrateViaLookupTable(pSoeValues);
375  } else {
376  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
377  if (soe_state.sensorEcUsed[s] == false) {
378  /* no energy counting activated -> manually integrate energy */
379  uint32_t timestamp = soe_tableCurrentSensor.timestampCurrent[s];
380  uint32_t previous_timestamp = soe_tableCurrentSensor.previousTimestampCurrent[s];
381 
382  /* check if current measurement has been updated */
383  if (soe_state.previousTimestamp[s] != timestamp) {
384  float_t timestep_s = (((float_t)timestamp - (float_t)previous_timestamp)) / 1000.0f;
385  if (timestep_s > 0.0f) {
386  /* Current in charge direction negative means SOE increasing --> BAT naming, not ROB */
387  float_t deltaSOE_Wh =
388  ((((float_t)soe_tableCurrentSensor.current_mA[s] / 1000.0f) * /* convert to A */
389  ((float_t)soe_tableCurrentSensor.highVoltage_mV[s][0] / 1000.0f)) / /* convert to V */
390  timestep_s) / /* unit: s */
391  3600.0f; /* convert Ws -> Wh */
392 
393 #if BS_POSITIVE_DISCHARGE_CURRENT == false
394  /* negate calculated delta SOE_Wh */
395  deltaSOE_Wh *= (-1.0f);
396 #endif /* BS_POSITIVE_DISCHARGE_CURRENT == false */
397 
398  pSoeValues->averageSoe_Wh[s] -= (uint32_t)deltaSOE_Wh;
399  pSoeValues->minimumSoe_Wh[s] -= (uint32_t)deltaSOE_Wh;
400  pSoeValues->maximumSoe_Wh[s] -= (uint32_t)deltaSOE_Wh;
401 
402  pSoeValues->averageSoe_perc[s] =
404  pSoeValues->minimumSoe_perc[s] =
406  pSoeValues->maximumSoe_perc[s] =
408 
409  /* update timestamp SOE state variable for next iteration */
410  soe_state.previousTimestamp[s] = timestamp;
411  }
412  } /* end check if current measurement has been updated */
413  } else {
414  /* check if ec measurement has been updated */
416  /* Calculate SOE value with current sensor EC value */
417  float_t deltaSoe_perc =
420 
421 #if BS_POSITIVE_DISCHARGE_CURRENT == false
422  /* negate calculated delta SOE_perc */
423  deltaSoe_perc *= (-1.0f);
424 #endif
425  /* Apply EC scaling offset to get actual string energy */
426  pSoeValues->averageSoe_perc[s] = soe_state.ecScalingAverage[s] - deltaSoe_perc;
427  pSoeValues->minimumSoe_perc[s] = soe_state.ecScalingMinimum[s] - deltaSoe_perc;
428  pSoeValues->maximumSoe_perc[s] = soe_state.ecScalingMaximum[s] - deltaSoe_perc;
429 
430  /* Limit SOE values to [0.0, 100.0] */
432 
433  /* Calculate new Wh values */
434  pSoeValues->maximumSoe_Wh[s] =
436  pSoeValues->averageSoe_Wh[s] =
438  pSoeValues->minimumSoe_Wh[s] =
440 
441  /* Update timestamp for next iteration */
443  }
444  }
445 
446  fram_soe.averageSoe_perc[s] = pSoeValues->averageSoe_perc[s];
447  fram_soe.minimumSoe_perc[s] = pSoeValues->minimumSoe_perc[s];
448  fram_soe.maximumSoe_perc[s] = pSoeValues->maximumSoe_perc[s];
449  }
450 
451  /* Update database and FRAM value */
453  }
454  }
455 }
456 
457 /*========== Externalized Static Function Implementations (Unit Test) =======*/
458 #ifdef UNITY_UNIT_TEST
459 #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:81
@ DATA_BLOCK_ID_CURRENT_SENSOR
Definition: database_cfg.h:82
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:254
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_SOX_s *pSoeValues, bool ec_present, uint8_t stringNumber)
initializes startup state-of-energy (SOE) related values
Definition: soe_counting.c:316
void SE_CalculateStateOfEnergy(DATA_BLOCK_SOX_s *pSoeValues)
periodically called algorithm to calculate state-of-energy (SOE)
Definition: soe_counting.c:360
#define MINIMUM_SOE_PERC
Definition: soe_counting.c:87
#define MAXIMUM_SOE_PERC
Definition: soe_counting.c:86
static void SOE_RecalibrateViaLookupTable(DATA_BLOCK_SOX_s *pSoeValues)
initializes database and FRAM SOE values via lookup table (average, min and max).
Definition: soe_counting.c:196
static void SOE_SetValue(DATA_BLOCK_SOX_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:246
static float_t SOE_GetFromVoltage(int16_t voltage_mV)
look-up table for SOE initialization
Definition: soe_counting.c:213
static DATA_BLOCK_CURRENT_SENSOR_s soe_tableCurrentSensor
Definition: soe_counting.c:105
static SOE_STATE_s soe_state
Definition: soe_counting.c:94
static float_t SOE_GetStringSoePercentageFromEnergy(uint32_t energy_Wh)
calculates string SOE in percentage from passed string energy in Wh
Definition: soe_counting.c:173
static uint32_t SOE_GetStringEnergyFromSoePercentage(float_t stringSoe_perc)
calculates string energy in Wh from passed SOE in percentage
Definition: soe_counting.c:184
static void SOE_CheckDatabaseSoePercentageLimits(DATA_BLOCK_SOX_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:290
Header for SOE module, responsible for calculation of SOE.
Header for SOE configuration.
#define SOE_STRING_ENERGY_Wh
uint32_t previousTimestampCurrent[BS_NR_OF_STRINGS]
Definition: database_cfg.h:218
uint32_t timestampCurrent[BS_NR_OF_STRINGS]
Definition: database_cfg.h:219
int32_t current_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:215
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:214
int32_t energyCounter_Wh[BS_NR_OF_STRINGS]
Definition: database_cfg.h:231
int32_t highVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_VOLTAGES_FROM_CURRENT_SENSOR]
Definition: database_cfg.h:237
uint32_t timestampEnergyCounting[BS_NR_OF_STRINGS]
Definition: database_cfg.h:234
DATA_BLOCK_ID_e uniqueId
Definition: database_cfg.h:122
int16_t averageCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:164
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:162
int16_t maximumCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:167
int16_t minimumCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:165
float_t minimumSoe_perc[BS_NR_OF_STRINGS]
Definition: database_cfg.h:515
float_t averageSoe_perc[BS_NR_OF_STRINGS]
Definition: database_cfg.h:514
float_t maximumSoe_perc[BS_NR_OF_STRINGS]
Definition: database_cfg.h:516
uint32_t averageSoe_Wh[BS_NR_OF_STRINGS]
Definition: database_cfg.h:521
uint32_t maximumSoe_Wh[BS_NR_OF_STRINGS]
Definition: database_cfg.h:520
uint32_t minimumSoe_Wh[BS_NR_OF_STRINGS]
Definition: database_cfg.h:522
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:77
float_t ecScalingMinimum[BS_NR_OF_STRINGS]
Definition: soe_counting.c:79
bool soeInitialized
Definition: soe_counting.c:76
uint32_t previousTimestamp[BS_NR_OF_STRINGS]
Definition: soe_counting.c:82
float_t ecScalingAverage[BS_NR_OF_STRINGS]
Definition: soe_counting.c:78
float_t ecScalingMaximum[BS_NR_OF_STRINGS]
Definition: soe_counting.c:80