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