foxBMS  1.1.2
The foxBMS Battery Management System API Documentation
redundancy.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2021, 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 redundancy.c
44  * @author foxBMS Team
45  * @date 2020-07-31 (date of creation)
46  * @updated 2021-03-24 (date of last update)
47  * @ingroup APPLICATION
48  * @prefix MRC
49  *
50  * @brief Source file for handling redundancy between redundant cell voltage
51  * and cell temperature measurements
52  *
53  */
54 
55 /*========== Includes =======================================================*/
56 #include "redundancy.h"
57 
58 #include "bms.h"
59 #include "database.h"
60 #include "diag.h"
61 #include "foxmath.h"
62 #include "os.h"
63 #include "plausibility.h"
64 
65 /*========== Macros and Definitions =========================================*/
66 
67 /*========== Static Constant and Variable Definitions =======================*/
68 /** local copies of database tables */
69 /**@{*/
74 /**@}*/
75 
76 /** state of the redundancy module */
79  .lastRedundancy0CellvoltageTimestamp = 0u,
80  .lastBaseCelltemperatureTimestamp = 0u,
81  .lastRedundancy0CelltemperatureTimestamp = 0u,
82  .lastStringCurrentTimestamp = {0u},
83 };
84 
85 /*========== Extern Constant and Variable Definitions =======================*/
86 
87 /*========== Static Function Prototypes =====================================*/
88 /**
89  * @brief Check timestamp if measurement has been updated at least once.
90  * @param[in] timestamp timestamp of last measurement update
91  * @param[in] previousTimestamp timestamp of previously updated measurement
92  * @return true if measurement has been updated at least once, otherwise false
93  */
94 static bool MRC_MeasurementUpdatedAtLeastOnce(uint32_t timestamp, uint32_t previousTimestamp);
95 
96 /**
97  * @brief Check timestamp if measurement has been updated recently.
98  * @param[in] timestamp timestamp of last measurement update
99  * @param[in] previousTimestamp timestamp of previously updated measurement
100  * @param[in] timeInterval in systicks (type: uint32_t)
101  * @return true if measurement has recently been updated, otherwise false
102  */
104  uint32_t timestamp,
105  uint32_t previousTimestamp,
106  uint32_t timeInterval);
107 
108 /**
109  * @brief Function to validate results of cell voltage measurement
110  *
111  * @param[in] pCellVoltageBase base cell voltage measurement
112  * @param[in] pCellVoltageRedundancy0 redundant cell voltage measurement
113  *
114  * @return bool true, if measurement has been validated successfully and
115  * database entry needs to be updated, otherwise false.
116  */
118  DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageBase,
119  DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageRedundancy0);
120 
121 /**
122  * @brief Function to validate results of cell temperature measurement
123  *
124  * @param[in] pCellTemperatureBase base cell temperature measurement
125  * @param[in] pCellTemperatureRedundancy0 redundant cell temperature measurement
126  *
127  * @return bool true, if measurement has been validated successfully and
128  * database entry needs to be updated, otherwise false.
129  */
131  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureBase,
132  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureRedundancy0);
133 
134 /**
135  * @brief Function to validate results of current measurement
136  *
137  * @param[in] pTableCurrentSensor pointer to current measurements
138  */
139 static void MRC_ValidateCurrentMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor);
140 
141 /**
142  * @brief Function to validate results of string voltage measurement
143  *
144  * @param[in] pTableCurrentSensor pointer current sensor high voltage measurements
145  * @param[in] pTableCellVoltage pointer to cell voltage measurements
146  */
148  DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor,
149  DATA_BLOCK_CELL_VOLTAGE_s *pTableCellVoltage);
150 
151 /**
152  * @brief Function to validate results of high voltage measurement and calculate
153  * battery voltage and high voltage bus voltage.
154  *
155  * @param[in] pTableCurrentSensor pointer current sensor high voltage measurements
156  */
158 
159 /**
160  * @brief Function to validate results of power measurement
161  *
162  * @param[in] pTableCurrentSensor pointer to power/current measurements
163  */
164 static void MRC_ValidatePowerMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor);
165 
166 /**
167  * @brief Function calculates minimum, maximum and average cell voltages.
168  *
169  * @param[in] pValidatedVoltages validated voltages from base and/or redundant measurements
170  * @param[out] pMinMaxAverageValues calculated cell voltage min/max/average values
171  *
172  * @return #STD_NOT_OK if all cell voltage are invalid and no minimum, maximum
173  * and average cell voltage values could be calculated, otherwise #STD_OK
174  */
176  const DATA_BLOCK_CELL_VOLTAGE_s *const pValidatedVoltages,
177  DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues);
178 
179 /**
180  * @brief Function calculates minimum, maximum and average cell temperatures.
181  *
182  * @param[in] pValidatedTemperatures validated temperatures from base and/or redundant measurements
183  * @param[out] pMinMaxAverageValues calculated cell temperature min/max/average values
184  *
185  * @return #STD_NOT_OK if all cell temperatures are invalid and no minimum, maximum
186  * and average cell temperature values could be calculated, otherwise #STD_OK
187  */
189  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures,
190  DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues);
191 
192 /**
193  * @brief Function compares cell voltage measurements from base measurement with
194  * one redundant measurement and writes result in pValidatedVoltages.
195  *
196  * @param[in] pCellvoltageBase base cell voltage measurement
197  * @param[in] pCellvoltageRedundancy0 redundant cell voltage measurement
198  * @param[out] pValidatedVoltages validated voltages from redundant measurement values
199  *
200  * @return #STD_NOT_OK if not all cell voltages could be validated, otherwise
201  * #STD_OK
202  */
204  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageBase,
205  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageRedundancy0,
206  DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages);
207 
208 /**
209  * @brief Function updates validated cell voltage measurement with data from a
210  * single measurement source. This can be the case if no redundancy is
211  * used at all or if one or more of the redundant measurements are not
212  * working properly.
213  *
214  * @param[in] pCellvoltage cell voltage measurement
215  * @param[out] pValidatedVoltages validated voltage values
216  *
217  * @return #STD_NOT_OK if not all cell voltages could be validated, otherwise
218  * #STD_OK
219  */
221  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltage,
222  DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages);
223 
224 /**
225  * @brief Function compares cell temperature measurements from base measurement
226  * with one redundant measurement and writes result in pValidatedTemperatures.
227  *
228  * @param[in] pCelltemperatureBase base cell temperature measurement
229  * @param[in] pCelltemperatureRedundancy0 redundant cell temperature measurement
230  * @param[out] pValidatedTemperatures validated temperatures from redundant measurement values
231  *
232  * @return #STD_NOT_OK if not all cell voltages could be validated, otherwise
233  * #STD_OK
234  */
236  DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureBase,
237  DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureRedundancy0,
238  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures);
239 
240 /**
241  * @brief Function updates validated cell temperature measurement with data from a
242  * single measurement source. This can be the case if no redundancy is
243  * used at all or if one or more of the redundant measurements are not
244  * working properly.
245  *
246  * @param[in] pCellTemperature cell temperature measurement
247  * @param[out] pValidatedTemperature validated temperature values
248  *
249  * @return #STD_NOT_OK if not all cell voltages could be validated, otherwise
250  * #STD_OK
251  */
253  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperature,
254  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperature);
255 
256 /*========== Static Function Implementations ================================*/
257 static bool MRC_MeasurementUpdatedAtLeastOnce(uint32_t timestamp, uint32_t previousTimestamp) {
258  bool retval = false;
259  if (!((timestamp == 0u) && (previousTimestamp == 0u))) {
260  /* Only possibility for timestamp AND previous timestamp to be 0 is, if
261  the measurement has never been updated. Thus if this is not the case
262  the measurement must have been updated */
263  retval = true;
264  }
265  return retval;
266 }
267 
269  uint32_t timestamp,
270  uint32_t previousTimestamp,
271  uint32_t timeInterval) {
272  STD_RETURN_TYPE_e retval = STD_NOT_OK;
273  uint32_t currentTimestamp = OS_GetTickCount();
274 
275  /* Unsigned integer arithmetic also works correctly if currentTimestap is
276  larger than pHeader->timestamp (timer overflow), thus no need to use abs() */
277  if (((currentTimestamp - timestamp) <= timeInterval) &&
278  (MRC_MeasurementUpdatedAtLeastOnce(timestamp, previousTimestamp) == true)) {
279  /* Difference between current timestamp and last update timestamp is
280  smaller than passed time interval */
281  retval = STD_OK;
282  }
283  return retval;
284 }
285 
287  DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageBase,
288  DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageRedundancy0) {
289  FAS_ASSERT(pCellVoltageBase != NULL_PTR);
290  FAS_ASSERT(pCellVoltageRedundancy0 != NULL_PTR);
291 
292  bool updatedValidatedVoltageDatbaseEntry = false;
293 
294  bool baseCellvoltageUpdated = false;
295 
296  bool useCellvoltageRedundancy = false;
297  bool baseCellvoltageMeasurementTimeoutReached = true;
298  bool redundancy0CellvoltageMeasurementTimeoutReached = true;
299 
300  /* Following decision will be undertaken:
301  *
302  * - Use redundancy only if timestamp of redundant database entry != 0
303  * - Perform redundant check if both timestamps have been updated
304  * - Add timeout and trigger error if timestamps have not been updated in the last XXXXms
305  * - If timeout reached and only one of the two redundant measurements has been updated use this measurement value
306  * but throw an error that one measurement has not been updated recently.
307  */
308 
309  /* -------------- Check if cell voltage redundant measurement is used -- */
310  /* Use redundant cell voltage measurements if measurement values have been acquired once */
311  useCellvoltageRedundancy = DATA_DatabaseEntryUpdatedAtLeastOnce(pCellVoltageRedundancy0->header);
312 
313  /* ----------------- Check timestamp of base measurements--------------- */
315  baseCellvoltageMeasurementTimeoutReached = false;
317  } else {
318  baseCellvoltageMeasurementTimeoutReached = true;
319  /* Set error flag */
321  }
322 
323  /* Check if base measurement values have been updated since last MRC */
324  if (mrc_state.lastBaseCellvoltageTimestamp != pCellVoltageBase->header.timestamp) {
325  baseCellvoltageUpdated = true;
326  } else {
327  baseCellvoltageUpdated = false;
328  }
329 
330  /* ----------------- Check timestamp of redundant measurements --------- */
332  false) &&
333  (useCellvoltageRedundancy == true)) {
334  redundancy0CellvoltageMeasurementTimeoutReached = true;
335  /* Set error flag */
337  } else {
338  redundancy0CellvoltageMeasurementTimeoutReached = false;
340  }
341 
342  /* ----------------- Validate cell voltages ---------------------------- */
343  if (useCellvoltageRedundancy == true) {
344  bool redundany0CellvoltageUpdated = false;
345  /* Check if redundant measurement values have been updated since last MRC */
346  if (mrc_state.lastRedundancy0CellvoltageTimestamp != pCellVoltageRedundancy0->header.timestamp) {
347  redundany0CellvoltageUpdated = true;
348  } else {
349  redundany0CellvoltageUpdated = false;
350  }
351  /* Make sure cell voltage timestamps have been updated since last call */
352  if ((baseCellvoltageUpdated == true) && (redundany0CellvoltageUpdated == true)) {
353  /* Update timestamp */
356 
357  /* Validate cell voltages */
358  MRC_ValidateCellVoltage(pCellVoltageBase, pCellVoltageRedundancy0, &mrc_tableCellVoltages);
359  /* Set to true for following minimum, maximum and average calculation */
360  updatedValidatedVoltageDatbaseEntry = true;
361 
362  } else if ((baseCellvoltageUpdated == true) || (redundany0CellvoltageUpdated == true)) {
363  /* At least one measurement has been updated */
364  if (baseCellvoltageUpdated == true) {
365  /* Has redundant measurement timeout been reached? If yes, update. */
366  if (redundancy0CellvoltageMeasurementTimeoutReached == true) {
367  /* Copy cell voltage base measurement values into validated database struct */
369  /* Set to true for following minimum, maximum and average calculation */
370  updatedValidatedVoltageDatbaseEntry = true;
371  }
372  } else if (redundany0CellvoltageUpdated == true) {
373  /* Has base measurement timeout been reached? If yes, update. */
374  if (baseCellvoltageMeasurementTimeoutReached == true) {
375  /* Copy cell voltage base measurement values into validated database struct */
376  MRC_UpdateCellVoltageValidation(pCellVoltageRedundancy0, &mrc_tableCellVoltages);
377  /* Set to true for following minimum, maximum and average calculation */
378  updatedValidatedVoltageDatbaseEntry = true;
379  }
380  } else {
382  }
383  } else {
384  /* No cell voltage measurement has been updated -> do nothing */
385  }
386  } else {
387  if (baseCellvoltageUpdated == true) {
388  /* Only update database entries if new raw data has been acquired */
389  /* Update timestamp */
391 
392  /* Copy cell voltage base measurement values into validated database struct */
394 
395  /* Set to true for following minimum, maximum and average calculation */
396  updatedValidatedVoltageDatbaseEntry = true;
397  }
398  }
399 
400  if (updatedValidatedVoltageDatbaseEntry == true) {
401  /* Calculate min/max/average cell voltages */
403 
404  /* Individual cell voltages validated and min/max/average calculated -> check voltage spread */
406  /* Recalculate min/max/average cell voltages as at least one cell voltage has been detected as invalid */
408  }
409  }
410 
411  return updatedValidatedVoltageDatbaseEntry;
412 }
413 
415  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureBase,
416  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureRedundancy0) {
417  FAS_ASSERT(pCellTemperatureBase != NULL_PTR);
418  FAS_ASSERT(pCellTemperatureRedundancy0 != NULL_PTR);
419 
420  bool baseCelltemperatureUpdated = false;
421  bool useCelltemperatureRedundancy = false;
422  bool updatedValidatedTemperatureDatbaseEntry = false;
423 
424  bool baseCellTemperatureMeasurementTimeoutReached = true;
425  bool redundancy0CellTemperatureMeasurementTimeoutReached = true;
426 
427  /* Following decision will be undertaken:
428  *
429  * - Use redundancy only if timestamp of redundant database entry != 0
430  * - Perform redundant check if both timestamps have been updated
431  * - Add timeout and trigger error if timestamps have not been updated in the last XXXXms
432  * - If timeout reached and only one of the two redundant measurements has been updated use this measurement value
433  * but throw an error that one measurement has not been updated recently.
434  */
435 
436  /* -------------- Check if cell cell temperature redundant measurement is used ---------- */
437  /* Use redundant cell voltage measurements if measurement values have been acquired once */
438  useCelltemperatureRedundancy = DATA_DatabaseEntryUpdatedAtLeastOnce(pCellTemperatureRedundancy0->header);
439 
440  /* ----------------- Check timestamp of base measurements--------------- */
442  baseCellTemperatureMeasurementTimeoutReached = false;
444  } else {
445  baseCellTemperatureMeasurementTimeoutReached = true;
446  /* Set error flag */
448  }
449  /* Check if base measurement values have been updated since last MRC */
450  if (mrc_state.lastBaseCelltemperatureTimestamp != pCellTemperatureBase->header.timestamp) {
451  baseCelltemperatureUpdated = true;
452  } else {
453  baseCelltemperatureUpdated = false;
454  }
455 
456  /* ----------------- Check timestamp of redundant measurements --------- */
458  false) &&
459  (useCelltemperatureRedundancy == true)) {
460  redundancy0CellTemperatureMeasurementTimeoutReached = true;
461  /* Set error flag */
463  } else {
464  redundancy0CellTemperatureMeasurementTimeoutReached = false;
466  }
467 
468  /* ----------------- Validate cell temperatures ------------------------ */
469  if (useCelltemperatureRedundancy == true) {
470  bool redundancy0CelltemperatureUpdated = false;
471  /* Check if redundant measurement values have been updated since last MRC */
472  if (mrc_state.lastRedundancy0CelltemperatureTimestamp != pCellTemperatureRedundancy0->header.timestamp) {
473  redundancy0CelltemperatureUpdated = true;
474  } else {
475  redundancy0CelltemperatureUpdated = false;
476  }
477  /* Make sure cell voltage timestamps have been updated since last call */
478  if ((baseCelltemperatureUpdated == true) && (redundancy0CelltemperatureUpdated == true)) {
479  /* Update timestamp */
481  mrc_state.lastRedundancy0CelltemperatureTimestamp = pCellTemperatureRedundancy0->header.timestamp;
482 
483  /* Validate cell temperatures */
484  MRC_ValidateCellTemperature(pCellTemperatureBase, pCellTemperatureRedundancy0, &mrc_tableCellTemperatures);
485  /* Set to true for following minimum, maximum and average calculation */
486  updatedValidatedTemperatureDatbaseEntry = true;
487 
488  } else if ((baseCelltemperatureUpdated == true) || (redundancy0CelltemperatureUpdated == true)) {
489  /* At least one measurement has been updated */
490  if (baseCelltemperatureUpdated == true) {
491  /* Has redundant measurement timeout been reached? If yes, update. */
492  if (redundancy0CellTemperatureMeasurementTimeoutReached == true) {
493  /* Copy cell temperature base measurement values into validated database struct */
495  /* Set to true for following minimum, maximum and average calculation */
496  updatedValidatedTemperatureDatbaseEntry = true;
497  }
498  } else if (redundancy0CelltemperatureUpdated == true) {
499  /* Has base measurement timeout been reached? If yes, update. */
500  if (baseCellTemperatureMeasurementTimeoutReached == true) {
501  /* Copy cell temperature redundant measurement values into validated database struct */
502  MRC_UpdateCellTemperatureValidation(pCellTemperatureRedundancy0, &mrc_tableCellTemperatures);
503  /* Set to true for following minimum, maximum and average calculation */
504  updatedValidatedTemperatureDatbaseEntry = true;
505  }
506  } else {
508  }
509  } else {
510  /* No cell temperature measurement has been updated -> do nothing */
511  }
512  } else { /* useCelltemperatureRedundancy == true */
513  if (baseCelltemperatureUpdated == true) {
514  /* Only update database entries if new raw data has been acquired */
515  /* Update timestamp */
517 
518  /* Copy cell temperature base measurement values into validated database struct */
520 
521  /* Set to true for following minimum, maximum and average calculation */
522  updatedValidatedTemperatureDatbaseEntry = true;
523  }
524  }
525 
526  if (updatedValidatedTemperatureDatbaseEntry == true) {
527  /* Calculate min/max/average cell temperatures */
529 
530  /* Individual cell temperatures validated and min/max/average calculated -> check temperature spread */
532  /* Recalculate min/max/average temperatures as at least one temperature has been detected as invalid */
534  }
535  }
536 
537  return updatedValidatedTemperatureDatbaseEntry;
538 }
539 
541  FAS_ASSERT(pTableCurrentSensor != NULL_PTR);
542  int32_t packCurrent_mA = 0;
543 
544  /* Validate pack current. Will be invalidated if not all current measurement values are valid */
546 
547  /* Iterate over all strings to calculate pack current */
548  for (uint8_t stringNumber = 0u; stringNumber < BS_NR_OF_STRINGS; stringNumber++) {
549  /* Check timestamp of measurement */
551  pTableCurrentSensor->timestampCurrent[stringNumber],
552  pTableCurrentSensor->previousTimestampCurrent[stringNumber],
554  (void)DIAG_CheckEvent(noTimeout, DIAG_ID_CURRENT_MEASUREMENT_TIMEOUT, DIAG_STRING, stringNumber);
555 
556  if (STD_OK == noTimeout) {
557  /* Check if current entry has been updated since last call */
558  if (mrc_state.lastStringCurrentTimestamp[stringNumber] !=
559  pTableCurrentSensor->timestampCurrent[stringNumber]) {
560  mrc_state.lastStringCurrentTimestamp[stringNumber] =
561  pTableCurrentSensor->timestampCurrent[stringNumber];
562  mrc_tablePackValues.stringCurrent_mA[stringNumber] = pTableCurrentSensor->current_mA[stringNumber];
563  if (pTableCurrentSensor->invalidCurrentMeasurement[stringNumber] == 0u) {
564  /* String current measurement valid -> set valid flag */
565  mrc_tablePackValues.invalidStringCurrent[stringNumber] = 0u;
567  } else {
568  /* String current measurement invalid -> set invalid flag */
570  mrc_tablePackValues.invalidStringCurrent[stringNumber] = 1u;
571  }
572  } else {
573  /* Nothing to do. Measurement has not been updated but still within timeout */
574  }
575  } else {
576  /* Measurement timeout reached -> set string current invalid */
577  mrc_tablePackValues.invalidStringCurrent[stringNumber] = 1u;
578  }
579 
580  if (0u == mrc_tablePackValues.invalidStringCurrent[stringNumber]) {
581  packCurrent_mA += mrc_tablePackValues.stringCurrent_mA[stringNumber];
582  } else {
583  /* One string current is invalid -> pack current cannot be correct.
584  * Set pack current invalid */
586  }
587  }
588  mrc_tablePackValues.packCurrent_mA = packCurrent_mA;
589 }
590 
592  DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor,
593  DATA_BLOCK_CELL_VOLTAGE_s *pTableCellVoltage) {
594  /* Pointer validity check */
595  FAS_ASSERT(pTableCurrentSensor != NULL_PTR);
596  FAS_ASSERT(pTableCellVoltage != NULL_PTR);
597 
598  for (uint8_t stringNumber = 0u; stringNumber < BS_NR_OF_STRINGS; stringNumber++) {
599  /* Check timeout of current sensor measurement */
601  pTableCurrentSensor->timestampHighVoltage[stringNumber][0u],
602  pTableCurrentSensor->previousTimestampHighVoltage[stringNumber][0u],
605 
606  /* Perform plausibility check if MIC and new current sensor measurement is valid */
607  if ((STD_OK == updatedMeasurement) &&
608  (pTableCurrentSensor->invalidHighVoltageMeasurement[stringNumber][0u] == 0u) &&
609  (pTableCellVoltage->nrValidCellVoltages[stringNumber] == BS_NR_OF_BAT_CELLS)) {
610  STD_RETURN_TYPE_e voltagePlausible = PL_CheckStringVoltage(
611  pTableCellVoltage->packVoltage_mV[stringNumber], pTableCurrentSensor->highVoltage_mV[stringNumber][0u]);
612  (void)DIAG_CheckEvent(voltagePlausible, DIAG_ID_PLAUSIBILITY_PACK_VOLTAGE, DIAG_STRING, stringNumber);
613 
614  /* Use current sensor measurement */ /* TODO: use really current sensor? Average of both? MIC measurement? */
615  mrc_tablePackValues.stringVoltage_mV[stringNumber] = pTableCurrentSensor->highVoltage_mV[stringNumber][0u];
616 
617  if (STD_OK == voltagePlausible) {
618  mrc_tablePackValues.invalidStringVoltage[stringNumber] = 0u;
619  } else {
620  mrc_tablePackValues.invalidStringVoltage[stringNumber] = 1u;
621  }
622  } else {
623  /* Plausibility check cannot be performed if we do not have valid
624  * values from MIC and current sensor measurement */
626 
627  if ((STD_OK == updatedMeasurement) &&
628  (pTableCurrentSensor->invalidHighVoltageMeasurement[stringNumber][0u] == 0u)) {
629  /* Current sensor measurement valid -> use this measurement */
630  mrc_tablePackValues.stringVoltage_mV[stringNumber] =
631  pTableCurrentSensor->highVoltage_mV[stringNumber][0u];
632  mrc_tablePackValues.invalidStringVoltage[stringNumber] = 0u;
633  } else if (pTableCellVoltage->nrValidCellVoltages[stringNumber] == BS_NR_OF_BAT_CELLS) {
634  /* MIC measurement valid -> use this measurement */
635  mrc_tablePackValues.stringVoltage_mV[stringNumber] = pTableCellVoltage->packVoltage_mV[stringNumber];
636  mrc_tablePackValues.invalidStringVoltage[stringNumber] = 0u;
637  } else {
638  /* MIC and current sensor measurement invalid -> try to construct
639  * a valid from the number of valid cell voltages and substitute
640  * invalid cell voltages with the average cell voltage. */
641  uint16_t numberInvalidCellVoltages =
642  (BS_NR_OF_BAT_CELLS - pTableCellVoltage->nrValidCellVoltages[stringNumber]);
643 
644  mrc_tablePackValues.stringVoltage_mV[stringNumber] =
645  pTableCellVoltage->packVoltage_mV[stringNumber] +
647  (int16_t)numberInvalidCellVoltages);
648 
649  /* Only use this as valid value if not more than five cell voltages are invalid */
650  if (numberInvalidCellVoltages > MRC_ALLOWED_NUMBER_OF_INVALID_CELL_VOLTAGES) {
651  mrc_tablePackValues.invalidStringVoltage[stringNumber] = 1u;
652  } else {
653  mrc_tablePackValues.invalidStringVoltage[stringNumber] = 0u;
654  }
655  }
656  }
657  }
658 }
659 
661  FAS_ASSERT(pTableCurrentSensor != NULL_PTR);
662 
663  int32_t sum_mV = 0;
664  uint8_t validVoltages = 0u;
665  for (uint8_t stringNumber = 0u; stringNumber < BS_NR_OF_STRINGS; stringNumber++) {
666  /* Check timeout of current sensor measurement */
668  pTableCurrentSensor->timestampHighVoltage[stringNumber][2u],
669  pTableCurrentSensor->previousTimestampHighVoltage[stringNumber][2u],
672 
673  const bool stringClosed = BMS_IsStringClosed(stringNumber);
674  const bool stringPrecharging = BMS_IsStringPrecharging(stringNumber);
675  if (((true == stringPrecharging) || (true == stringClosed)) && (STD_OK == updatedMeasurement)) {
676  /* Only voltages of connected strings can be used */
677  if (0u == pTableCurrentSensor->invalidHighVoltageMeasurement[stringNumber][2]) {
678  /* Measured high voltage is valid */
679  validVoltages++;
680  sum_mV += pTableCurrentSensor->highVoltage_mV[stringNumber][2];
681  }
682  }
683  }
684 
685  if (validVoltages > 0u) {
686  mrc_tablePackValues.highVoltageBusVoltage_mV = (sum_mV / (int32_t)validVoltages);
688  } else {
689  /* TODO: do we want to write special data if no valid values can be read? */
691  }
692 }
693 
695  FAS_ASSERT(pTableCurrentSensor != NULL_PTR);
696  bool calculatePower = false;
697  int32_t packPower_W = 0;
698 
699  /* Validate pack power. Will be invalidated if not all power measurement values are valid */
701 
702  for (uint8_t stringNumber = 0u; stringNumber < BS_NR_OF_STRINGS; stringNumber++) {
703  /* Check timeout of current sensor measurement */
705  pTableCurrentSensor->timestampPower[stringNumber],
706  pTableCurrentSensor->previousTimestampPower[stringNumber],
709 
710  if (STD_OK == noTimeout) {
711  /* Check if current sensor measurement has been updated */
712  if (pTableCurrentSensor->timestampPower[stringNumber] != mrc_state.lastStringPowerTimestamp[stringNumber]) {
713  mrc_state.lastStringPowerTimestamp[stringNumber] = pTableCurrentSensor->timestampPower[stringNumber];
714  /* Check if measurement is valid */
715  if (pTableCurrentSensor->invalidPowerMeasurement[stringNumber] == 0u) {
716  mrc_tablePackValues.stringPower_W[stringNumber] = pTableCurrentSensor->power_W[stringNumber];
717  mrc_tablePackValues.invalidStringPower[stringNumber] = 0u;
718  } else {
719  /* Measurement has been updated but value is invalid -> calculate from current and string voltage */
720  calculatePower = true;
721  /* TODO: do we want to calculate values by hand if we are within time limit but value is invalid? */
722  }
723  } else {
724  /* Nothing to do. Measurement has not been updated but still within timeout */
725  }
726  } else {
727  /* Timeout reached. Set invalid flag */
728  calculatePower = true;
729  mrc_tablePackValues.invalidStringPower[stringNumber] = 1u;
730  }
731  if ((true == calculatePower) && (0u == mrc_tablePackValues.invalidStringCurrent[stringNumber]) &&
732  (0u == mrc_tablePackValues.invalidStringVoltage[stringNumber])) {
733  /* Power measurement is invalid, but current and string voltage measurement are valid */
734  int64_t stringPower_W =
735  ((mrc_tablePackValues.stringCurrent_mA[stringNumber] *
736  mrc_tablePackValues.stringVoltage_mV[stringNumber]) /
737  (UNIT_CONVERSION_FACTOR_1000_INTEGER * /* convert: mV -> V */
738  UNIT_CONVERSION_FACTOR_1000_INTEGER)); /* convert: mA -> A */
739  mrc_tablePackValues.stringPower_W[stringNumber] = (int32_t)stringPower_W;
740  mrc_tablePackValues.invalidStringPower[stringNumber] = 0u;
741  }
742  if (0u == mrc_tablePackValues.invalidStringPower[stringNumber]) {
743  packPower_W += mrc_tablePackValues.stringPower_W[stringNumber];
745  } else {
746  /* One string power is invalid -> pack power cannot be correct.
747  * Set pack power invalid */
750  }
751  }
752  mrc_tablePackValues.packPower_W = packPower_W;
753 }
754 
756  const DATA_BLOCK_CELL_VOLTAGE_s *const pValidatedVoltages,
757  DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues) {
758  /* Pointer validity check */
759  FAS_ASSERT(pValidatedVoltages != NULL_PTR);
760  FAS_ASSERT(pMinMaxAverageValues != NULL_PTR);
761 
762  STD_RETURN_TYPE_e retval = STD_OK;
763 
764  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
765  uint16_t nrValidCellvoltages = 0u;
766  int16_t min = INT16_MAX;
767  int16_t max = INT16_MIN;
768  int32_t sum = 0;
769  uint16_t moduleNumberMinimum = 0u;
770  uint16_t cellNumberMinimum = 0u;
771  uint16_t moduleNumberMaximum = 0u;
772  uint16_t cellNumberMaximum = 0u;
773  /* Iterate over all cells in each string */
774  for (uint8_t m = 0u; m < BS_NR_OF_MODULES; m++) {
775  for (uint8_t c = 0u; c < BS_NR_OF_CELLS_PER_MODULE; c++) {
776  if ((pValidatedVoltages->invalidCellVoltage[s][m] & (0x01u << c)) == 0u) {
777  /* Cell voltage is valid -> use this voltage for subsequent calculations */
778  nrValidCellvoltages++;
779  sum += pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c];
780 
781  if (pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c] < min) {
782  min = pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c];
783  moduleNumberMinimum = m;
784  cellNumberMinimum = c;
785  }
786  if (pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c] > max) {
787  max = pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c];
788  moduleNumberMaximum = m;
789  cellNumberMaximum = c;
790  }
791  }
792  }
793  }
794  pMinMaxAverageValues->minimumCellVoltage_mV[s] = min;
795  pMinMaxAverageValues->nrCellMinimumCellVoltage[s] = cellNumberMinimum;
796  pMinMaxAverageValues->nrModuleMinimumCellVoltage[s] = moduleNumberMinimum;
797  pMinMaxAverageValues->maximumCellVoltage_mV[s] = max;
798  pMinMaxAverageValues->nrCellMaximumCellVoltage[s] = cellNumberMaximum;
799  pMinMaxAverageValues->nrModuleMaximumCellVoltage[s] = moduleNumberMaximum;
800  pMinMaxAverageValues->validMeasuredCellVoltages[s] = nrValidCellvoltages;
801 
802  /* Prevent division by 0, if all cell voltages are invalid */
803  if (nrValidCellvoltages > 0u) {
804  pMinMaxAverageValues->averageCellVoltage_mV[s] = (int16_t)(sum / (int32_t)nrValidCellvoltages);
805  } else {
806  pMinMaxAverageValues->averageCellVoltage_mV[s] = 0;
807  retval = STD_NOT_OK;
808  }
809  }
810  return retval;
811 }
812 
814  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures,
815  DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues) {
816  /* Pointer validity check */
817  FAS_ASSERT(pValidatedTemperatures != NULL_PTR);
818  FAS_ASSERT(pMinMaxAverageValues != NULL_PTR);
819 
820  STD_RETURN_TYPE_e retval = STD_OK;
821 
822  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
823  uint16_t moduleNumberMinimum = 0u;
824  uint16_t sensorNumberMinimum = 0u;
825  uint16_t moduleNumberMaximum = 0u;
826  uint16_t sensorNumberMaximum = 0u;
827  uint16_t nrValidCelltemperatures = 0u;
828  int16_t min = INT16_MAX;
829  int16_t max = INT16_MIN;
830  float sum_ddegC = 0.0f;
831 
832  for (uint8_t m = 0u; m < BS_NR_OF_MODULES; m++) {
833  for (uint8_t c = 0u; c < BS_NR_OF_TEMP_SENSORS_PER_MODULE; c++) {
834  if ((pValidatedTemperatures->invalidCellTemperature[s][m] & (0x01u << c)) == 0u) {
835  /* Cell temperature is valid -> use this voltage for subsequent calculations */
836  nrValidCelltemperatures++;
837  sum_ddegC += (float)pValidatedTemperatures
838  ->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c];
839 
840  if (pValidatedTemperatures->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] <
841  min) {
842  min = pValidatedTemperatures
844  moduleNumberMinimum = m;
845  sensorNumberMinimum = c;
846  }
847  if (pValidatedTemperatures->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] >
848  max) {
849  max = pValidatedTemperatures
851  moduleNumberMaximum = m;
852  sensorNumberMaximum = c;
853  }
854  }
855  }
856  }
857  pMinMaxAverageValues->minimumTemperature_ddegC[s] = min;
858  pMinMaxAverageValues->nrSensorMinimumTemperature[s] = sensorNumberMinimum;
859  pMinMaxAverageValues->nrModuleMinimumTemperature[s] = moduleNumberMinimum;
860  pMinMaxAverageValues->maximumTemperature_ddegC[s] = max;
861  pMinMaxAverageValues->nrSensorMaximumTemperature[s] = sensorNumberMaximum;
862  pMinMaxAverageValues->nrModuleMaximumTemperature[s] = moduleNumberMaximum;
863  pMinMaxAverageValues->validMeasuredCellTemperatures[s] = nrValidCelltemperatures;
864 
865  /* Prevent division by 0, if all cell voltages are invalid */
866  if (nrValidCelltemperatures > 0u) {
867  pMinMaxAverageValues->averageTemperature_ddegC[s] = (sum_ddegC / (float)nrValidCelltemperatures);
868  } else {
869  pMinMaxAverageValues->averageTemperature_ddegC[s] = 0.0f;
870  retval = STD_NOT_OK;
871  }
872  }
873  return retval;
874 }
875 
877  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageBase,
878  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageRedundancy0,
879  DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages) {
880  /* Pointer validity check */
881  FAS_ASSERT(pCellvoltageBase != NULL_PTR);
882  FAS_ASSERT(pCellvoltageRedundancy0 != NULL_PTR);
883  FAS_ASSERT(pValidatedVoltages != NULL_PTR);
884 
885  uint16_t numberValidMeasurements = 0u;
886  STD_RETURN_TYPE_e noPlausibilityIssueDetected = STD_OK; /* Flag if implausable value detected */
887  STD_RETURN_TYPE_e retval = STD_OK;
888 
889  /* Iterate over all cell measurements */
890  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
891  int32_t sum = 0;
892  for (uint8_t m = 0; m < BS_NR_OF_MODULES; m++) {
893  for (uint8_t c = 0; c < BS_NR_OF_CELLS_PER_MODULE; c++) {
894  if (((pCellvoltageBase->invalidCellVoltage[s][m] & (1u << c)) == 0u) &&
895  ((pCellvoltageRedundancy0->invalidCellVoltage[s][m] & (1u << c)) == 0u)) {
896  /* Check if cell voltage of base AND redundant measurement is valid -> do plausibility check */
898  pCellvoltageBase->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c],
899  pCellvoltageRedundancy0->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c],
900  &pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c])) {
901  /* Clear valid flag */
902  pValidatedVoltages->invalidCellVoltage[s][m] = pValidatedVoltages->invalidCellVoltage[s][m] &
903  (~(1u << c));
904  numberValidMeasurements++;
905  sum += pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c];
906  } else {
907  /* Set invalid flag */
908  noPlausibilityIssueDetected = STD_NOT_OK;
909  pValidatedVoltages->invalidCellVoltage[s][m] |= (1u << c);
910  /* Set return value to #STD_NOT_OK as not all cell voltages have a valid measurement value */
911  retval = STD_NOT_OK;
912  }
913  } else if ((pCellvoltageBase->invalidCellVoltage[s][m] & (1u << c)) == 0u) {
914  /* Only base measurement value is valid -> use this voltage without further plausibility checks */
915  pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c] =
916  pCellvoltageBase->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c];
917  /* Reset valid flag */
918  pValidatedVoltages->invalidCellVoltage[s][m] = pValidatedVoltages->invalidCellVoltage[s][m] &
919  (~(1u << c));
920  numberValidMeasurements++;
921  sum += pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c];
922  } else if ((pCellvoltageRedundancy0->invalidCellVoltage[s][m] & (1u << c)) == 0u) {
923  /* Only redundant measurement value is valid -> use this voltage without further plausibility checks */
924  pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c] =
925  pCellvoltageRedundancy0->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c];
926  /* Reset valid flag */
927  pValidatedVoltages->invalidCellVoltage[s][m] = pValidatedVoltages->invalidCellVoltage[s][m] &
928  (~(1u << c));
929  numberValidMeasurements++;
930  sum += pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c];
931  } else {
932  /* Both, base and redundant measurement value are invalid */
933  /* Save average cell voltage value of base and redundant */
934  pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c] =
935  (pCellvoltageBase->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c] +
936  pCellvoltageRedundancy0->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c]) /
937  2u;
938  /* Set invalid flag */
939  pValidatedVoltages->invalidCellVoltage[s][m] |= (1u << c);
940  /* Set return value to #STD_NOT_OK as not all cell voltages have a valid measurement value */
941  retval = STD_NOT_OK;
942  }
943  }
944  }
945  pValidatedVoltages->nrValidCellVoltages[s] = numberValidMeasurements;
946  pValidatedVoltages->packVoltage_mV[s] = sum;
947  numberValidMeasurements = 0u; /* Reset counter for next string */
948 
949  (void)DIAG_CheckEvent(noPlausibilityIssueDetected, DIAG_ID_PLAUSIBILITY_CELL_VOLTAGE, DIAG_STRING, s);
950  noPlausibilityIssueDetected = STD_OK; /* Reset flag for next string */
951  }
952  return retval;
953 }
954 
956  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltage,
957  DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages) {
958  /* Pointer validity check */
959  FAS_ASSERT(pCellvoltage != NULL_PTR);
960  FAS_ASSERT(pValidatedVoltages != NULL_PTR);
961 
962  /* Save header struct to copy to correct database entry */
963  DATA_BLOCK_HEADER_s tmpHeader = pValidatedVoltages->header;
964  /* Copy whole database entry */
965  *pValidatedVoltages = *pCellvoltage;
966  /* Restore previous header */
967  pValidatedVoltages->header = tmpHeader;
968 
969  return STD_OK;
970 }
971 
973  DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureBase,
974  DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureRedundancy0,
975  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures) {
976  /* Pointer validity check */
977  FAS_ASSERT(pCelltemperatureBase != NULL_PTR);
978  FAS_ASSERT(pCelltemperatureRedundancy0 != NULL_PTR);
979  FAS_ASSERT(pValidatedTemperatures != NULL_PTR);
980 
981  uint16_t numberValidMeasurements = 0u;
982  STD_RETURN_TYPE_e noPlausibilityIssueDetected = STD_OK; /* Flag if implausable value detected */
983  STD_RETURN_TYPE_e retval = STD_OK;
984 
985  /* Iterate over all cell measurements */
986  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
987  for (uint8_t m = 0u; m < BS_NR_OF_MODULES; m++) {
988  for (uint8_t c = 0u; c < BS_NR_OF_TEMP_SENSORS_PER_MODULE; c++) {
989  if (((pCelltemperatureBase->invalidCellTemperature[s][m] & (1u << c)) == 0u) &&
990  ((pCelltemperatureRedundancy0->invalidCellTemperature[s][m] & (1u << c)) == 0u)) {
991  /* Check if cell voltage of base AND redundant measurement is valid -> do plausibility check */
992  if (STD_OK ==
994  pCelltemperatureBase->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c],
995  pCelltemperatureRedundancy0
997  &pValidatedTemperatures
999  /* Clear valid flag */
1000  pValidatedTemperatures->invalidCellTemperature[s][m] =
1001  pValidatedTemperatures->invalidCellTemperature[s][m] & (~(1u << c));
1002  numberValidMeasurements++;
1003  } else {
1004  /* Set invalid flag */
1005  noPlausibilityIssueDetected = STD_NOT_OK;
1006  pValidatedTemperatures->invalidCellTemperature[s][m] |= (1u << c);
1007  /* Set return value to #STD_NOT_OK as not all cell temperatures have a valid measurement value */
1008  retval = STD_NOT_OK;
1009  }
1010  } else if ((pCelltemperatureBase->invalidCellTemperature[s][m] & (1u << c)) == 0u) {
1011  /* Only base measurement value is valid -> use this temperature without further plausibility checks */
1012  pValidatedTemperatures->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] =
1013  pCelltemperatureBase->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c];
1014  /* Reset valid flag */
1015  pValidatedTemperatures->invalidCellTemperature[s][m] =
1016  pValidatedTemperatures->invalidCellTemperature[s][m] & (~(1u << c));
1017  numberValidMeasurements++;
1018  } else if ((pCelltemperatureRedundancy0->invalidCellTemperature[s][m] & (1u << c)) == 0u) {
1019  /* Only redundant measurement value is valid -> use this temperature without further plausibility checks */
1020  pValidatedTemperatures->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] =
1021  pCelltemperatureRedundancy0
1022  ->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c];
1023  /* Reset valid flag */
1024  pValidatedTemperatures->invalidCellTemperature[s][m] =
1025  pValidatedTemperatures->invalidCellTemperature[s][m] & (~(1u << c));
1026  numberValidMeasurements++;
1027  } else {
1028  /* Both, base and redundant measurement value are invalid */
1029  /* Save average cell voltage value of base and redundant */
1030  pValidatedTemperatures->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] =
1031  (pCelltemperatureBase->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] +
1032  pCelltemperatureRedundancy0
1034  2u;
1035  /* Set invalid flag */
1036  pValidatedTemperatures->invalidCellTemperature[s][m] |= (1u << c);
1037  /* Set return value to #STD_NOT_OK as not all cell temperatures have a valid measurement value */
1038  retval = STD_NOT_OK;
1039  }
1040  }
1041  }
1042  pValidatedTemperatures->nrValidTemperatures[s] = numberValidMeasurements;
1043  numberValidMeasurements = 0u; /* Reset counter for next string */
1044 
1045  (void)DIAG_CheckEvent(noPlausibilityIssueDetected, DIAG_ID_PLAUSIBILITY_CELL_TEMP, DIAG_STRING, s);
1046  noPlausibilityIssueDetected = STD_OK; /* Reset flag for next string */
1047  }
1048 
1049  return retval;
1050 }
1051 
1053  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperature,
1054  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperature) {
1055  /* Pointer validity check */
1056  FAS_ASSERT(pCellTemperature != NULL_PTR);
1057  FAS_ASSERT(pValidatedTemperature != NULL_PTR);
1058 
1059  /* Save header struct to copy to correct database entry */
1060  DATA_BLOCK_HEADER_s tmpHeader = pValidatedTemperature->header;
1061  /* Copy whole database entry */
1062  *pValidatedTemperature = *pCellTemperature;
1063  /* Restore previous header */
1064  pValidatedTemperature->header = tmpHeader;
1065  return STD_OK;
1066 }
1067 
1068 /*========== Extern Function Implementations ================================*/
1070  STD_RETURN_TYPE_e retval = STD_NOT_OK;
1071  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
1072  for (uint8_t m = 0u; m < BS_NR_OF_MODULES; m++) {
1073  /* Invalidate cell voltage values */
1074  mrc_tableCellVoltages.invalidCellVoltage[s][m] = 0xFFFFFFFFFFFFFFFFULL;
1076  /* Invalidate cell temperature values */
1078  }
1079  /* Invalidate string values */
1083  }
1084  /* Invalidate pack values */
1085  mrc_tablePackValues.invalidPackCurrent = 0x01; /*!< bitmask if current is valid. 0->valid, 1->invalid */
1086  mrc_tablePackValues.invalidBatteryVoltage = 0x01; /*!< bitmask if voltage is valid. 0->valid, 1->invalid */
1087  mrc_tablePackValues.invalidHvBusVoltage = 0x01; /*!< bitmask if voltage is valid. 0->valid, 1->invalid */
1088  mrc_tablePackValues.invalidPackPower = 0x01; /*!< bitmask if power is valid. 0->valid, 1->invalid */
1089 
1091  return retval;
1092 }
1093 
1095  STD_RETURN_TYPE_e retval = STD_OK;
1096 
1099 
1101  DATA_BLOCK_CELL_TEMPERATURE_s celltemperatureRedundancy0 = {
1103 
1104  /* Get measurement values */
1105  DATA_READ_DATA(&cellvoltageBase, &cellvoltageRedundancy0, &celltemperatureBase, &celltemperatureRedundancy0);
1106 
1107  /* Perform validation of cell voltage measurement */
1108  bool updateCellVoltages = MRC_ValidateCellVoltageMeasurement(&cellvoltageBase, &cellvoltageRedundancy0);
1109 
1110  /* Perform validation of cell temperature measurement */
1111  bool updateCellTemperatures =
1112  MRC_ValidateCellTemperatureMeasurement(&celltemperatureBase, &celltemperatureRedundancy0);
1113 
1114  /* Update database entries if necessary */
1115  if ((updateCellVoltages == true) && (updateCellTemperatures == true)) {
1117  } else if (updateCellVoltages == true) {
1119  } else if (updateCellTemperatures == true) {
1121  } else {
1122  retval = STD_NOT_OK;
1123  }
1124  return retval;
1125 }
1126 
1128  STD_RETURN_TYPE_e retval = STD_OK;
1130 
1131  DATA_READ_DATA(&tableCurrentSensor);
1132 
1133  MRC_ValidateCurrentMeasurement(&tableCurrentSensor);
1135  MRC_ValidateHighVoltageBusMeasurement(&tableCurrentSensor);
1136  MRC_ValidatePowerMeasurement(&tableCurrentSensor);
1137 
1139 
1140  return retval;
1141 }
1142 
1143 /*========== Externalized Static Function Implementations (Unit Test) =======*/
1144 #ifdef UNITY_UNIT_TEST
1145 extern bool TEST_MRC_MeasurementUpdatedAtLeastOnce(uint32_t timestamp, uint32_t previousTimestamp) {
1146  return MRC_MeasurementUpdatedAtLeastOnce(timestamp, previousTimestamp);
1147 }
1148 extern STD_RETURN_TYPE_e TEST_MRC_MeasurementUpdatedRecently(
1149  uint32_t timestamp,
1150  uint32_t previousTimestamp,
1151  uint32_t timeInterval) {
1152  return MRC_MeasurementUpdatedRecently(timestamp, previousTimestamp, timeInterval);
1153 }
1154 extern bool TEST_MRC_ValidateCellVoltageMeasurement(
1155  DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageBase,
1156  DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageRedundancy0) {
1157  return MRC_ValidateCellVoltageMeasurement(pCellVoltageBase, pCellVoltageRedundancy0);
1158 }
1159 extern bool TEST_MRC_ValidateCellTemperatureMeasurement(
1160  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureBase,
1161  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureRedundancy0) {
1162  return MRC_ValidateCellTemperatureMeasurement(pCellTemperatureBase, pCellTemperatureRedundancy0);
1163 }
1164 
1165 extern void TEST_MRC_ValidateCurrentMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor) {
1166  MRC_ValidateCurrentMeasurement(pTableCurrentSensor);
1167 }
1168 
1169 extern void TEST_MRC_ValidatePowerMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor) {
1170  MRC_ValidatePowerMeasurement(pTableCurrentSensor);
1171 }
1172 extern void TEST_MRC_ValidateStringVoltageMeasurement(
1173  DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor,
1174  DATA_BLOCK_CELL_VOLTAGE_s *pTableCellVoltage) {
1175  MRC_ValidateStringVoltageMeasurement(pTableCurrentSensor, pTableCellVoltage);
1176 }
1177 extern void TEST_MRC_ValidateHighVoltageMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor) {
1178  MRC_ValidateHighVoltageBusMeasurement(pTableCurrentSensor);
1179 }
1180 extern STD_RETURN_TYPE_e TEST_MRC_CalculateCellVoltageMinMaxAverage(
1181  DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages,
1182  DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues) {
1183  return MRC_CalculateCellVoltageMinMaxAverage(pValidatedVoltages, pMinMaxAverageValues);
1184 }
1185 extern STD_RETURN_TYPE_e TEST_MRC_CalculateCellTemperatureMinMaxAverage(
1186  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures,
1187  DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues) {
1188  return MRC_CalculateCellTemperatureMinMaxAverage(pValidatedTemperatures, pMinMaxAverageValues);
1189 }
1190 extern STD_RETURN_TYPE_e TEST_MRC_ValidateCellVoltage(
1191  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageBase,
1192  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageRedundancy0,
1193  DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages) {
1194  return MRC_ValidateCellVoltage(pCellvoltageBase, pCellvoltageRedundancy0, pValidatedVoltages);
1195 }
1196 extern STD_RETURN_TYPE_e TEST_MRC_UpdateCellVoltageValidation(
1197  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltage,
1198  DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages) {
1199  return MRC_UpdateCellVoltageValidation(pCellvoltage, pValidatedVoltages);
1200 }
1201 extern STD_RETURN_TYPE_e TEST_MRC_ValidateCellTemperature(
1202  DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureBase,
1203  DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureRedundancy0,
1204  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures) {
1205  return MRC_ValidateCellTemperature(pCelltemperatureBase, pCelltemperatureRedundancy0, pValidatedTemperatures);
1206 }
1207 extern STD_RETURN_TYPE_e TEST_MRC_UpdateCellTemperatureValidation(
1208  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperature,
1209  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperature) {
1210  return MRC_UpdateCellTemperatureValidation(pCellTemperature, pValidatedTemperature);
1211 }
1212 #endif
#define BS_NR_OF_STRINGS
#define BS_NR_OF_CELLS_PER_MODULE
number of battery cells per battery module (parallel cells are counted as one)
#define BS_NR_OF_MODULES
number of modules in battery pack
#define BS_NR_OF_TEMP_SENSORS_PER_MODULE
number of temperature sensors per battery module
#define BS_NR_OF_BAT_CELLS
bool BMS_IsStringPrecharging(uint8_t stringNumber)
Returns if string is currently precharging or not.
Definition: bms.c:1308
bool BMS_IsStringClosed(uint8_t stringNumber)
Returns string state (closed or open)
Definition: bms.c:1299
bms driver header
Database module header.
#define DATA_READ_DATA(...)
Definition: database.h:76
#define DATA_WRITE_DATA(...)
Definition: database.h:86
@ DATA_BLOCK_ID_CELL_VOLTAGE_REDUNDANCY0
Definition: database_cfg.h:96
@ DATA_BLOCK_ID_MIN_MAX
Definition: database_cfg.h:75
@ DATA_BLOCK_ID_CELL_VOLTAGE
Definition: database_cfg.h:73
@ DATA_BLOCK_ID_CELL_TEMPERATURE_REDUNDANCY0
Definition: database_cfg.h:97
@ DATA_BLOCK_ID_CELL_TEMPERATURE_BASE
Definition: database_cfg.h:95
@ DATA_BLOCK_ID_CURRENT_SENSOR
Definition: database_cfg.h:76
@ DATA_BLOCK_ID_CELL_VOLTAGE_BASE
Definition: database_cfg.h:94
@ DATA_BLOCK_ID_PACK_VALUES
Definition: database_cfg.h:103
@ DATA_BLOCK_ID_CELL_TEMPERATURE
Definition: database_cfg.h:74
bool DATA_DatabaseEntryUpdatedAtLeastOnce(DATA_BLOCK_HEADER_s dataBlockHeader)
Checks if passed database entry has been updated at least once.
bool DATA_EntryUpdatedWithinInterval(DATA_BLOCK_HEADER_s dataBlockHeader, uint32_t timeInterval)
Checks if passed database entry has been updated within the last time interval.
DIAG_RETURNTYPE_e DIAG_Handler(DIAG_ID_e diag_id, DIAG_EVENT_e event, DIAG_IMPACT_LEVEL_e impact, uint32_t data)
DIAG_Handler provides generic error handling, based on diagnosis group.
Definition: diag.c:226
STD_RETURN_TYPE_e DIAG_CheckEvent(STD_RETURN_TYPE_e cond, DIAG_ID_e diag_id, DIAG_IMPACT_LEVEL_e impact, uint32_t data)
DIAG_CheckEvent provides a simple interface to check an event for STD_OK.
Definition: diag.c:353
Diagnosis driver header.
@ DIAG_SYSTEM
Definition: diag_cfg.h:247
@ DIAG_STRING
Definition: diag_cfg.h:248
@ DIAG_EVENT_NOT_OK
Definition: diag_cfg.h:235
@ DIAG_EVENT_OK
Definition: diag_cfg.h:234
@ DIAG_ID_POWER_MEASUREMENT_ERROR
Definition: diag_cfg.h:225
@ DIAG_ID_CURRENT_MEASUREMENT_TIMEOUT
Definition: diag_cfg.h:220
@ DIAG_ID_BASE_CELL_TEMPERATURE_MESUREMENT_TIMEOUT
Definition: diag_cfg.h:218
@ DIAG_ID_PLAUSIBILITY_PACK_VOLTAGE
Definition: diag_cfg.h:210
@ DIAG_ID_REDUNDANCY0_CELL_TEMPERATURE_MESUREMENT_TIMEOUT
Definition: diag_cfg.h:219
@ DIAG_ID_PLAUSIBILITY_CELL_VOLTAGE
Definition: diag_cfg.h:169
@ DIAG_ID_PLAUSIBILITY_CELL_TEMP
Definition: diag_cfg.h:172
@ DIAG_ID_CURRENT_SENSOR_POWER_MEASUREMENT_TIMEOUT
Definition: diag_cfg.h:224
@ DIAG_ID_REDUNDANCY0_CELL_VOLTAGE_MESUREMENT_TIMEOUT
Definition: diag_cfg.h:217
@ DIAG_ID_CURRENT_SENSOR_V1_MEASUREMENT_TIMEOUT
Definition: diag_cfg.h:222
@ DIAG_ID_CURRENT_SENSOR_V3_MEASUREMENT_TIMEOUT
Definition: diag_cfg.h:223
@ DIAG_ID_BASE_CELL_VOLTAGE_MESUREMENT_TIMEOUT
Definition: diag_cfg.h:216
@ DIAG_ID_CURRENT_MEASUREMENT_ERROR
Definition: diag_cfg.h:221
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:237
#define FAS_TRAP
Define that evaluates to essential boolean false thus tripping an assert.
Definition: fassert.h:108
math library for often used math functions
#define UNIT_CONVERSION_FACTOR_1000_INTEGER
Definition: foxmath.h:74
@ STD_NOT_OK
Definition: fstd_types.h:73
@ STD_OK
Definition: fstd_types.h:72
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:66
enum STD_RETURN_TYPE STD_RETURN_TYPE_e
uint32_t OS_GetTickCount(void)
Returns OS based system tick value.
Definition: os.c:182
Implementation of the tasks used by the system, headers.
STD_RETURN_TYPE_e PL_CheckStringVoltage(int32_t voltageMic_mV, int32_t voltageCurrentSensor_mV)
Pack voltage plausibility check between LTC and current sensor values.
Definition: plausibility.c:73
STD_RETURN_TYPE_e PL_CheckTemperatureSpread(DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatures, DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues)
Cell temperature spread plausibility check.
Definition: plausibility.c:151
STD_RETURN_TYPE_e PL_CheckCellvoltage(int16_t baseCellVoltage, int16_t redundancy0CellVoltage, int16_t *pCellVoltage)
Cell voltage plausibility check between two redundant cell voltage measurement values.
Definition: plausibility.c:85
STD_RETURN_TYPE_e PL_CheckCelltemperature(int16_t baseCelltemperature, int16_t redundancy0Celltemperature, int16_t *pCelltemperature)
Cell temperature plausibility check between two redundant cell temperature measurement values.
Definition: plausibility.c:102
STD_RETURN_TYPE_e PL_CheckVoltageSpread(DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltages, DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues)
Cell voltage spread plausibility check.
Definition: plausibility.c:119
plausibility checks for cell voltage and cell temperatures
static DATA_BLOCK_CELL_TEMPERATURE_s mrc_tableCellTemperatures
Definition: redundancy.c:72
static DATA_BLOCK_CELL_VOLTAGE_s mrc_tableCellVoltages
Definition: redundancy.c:71
static DATA_BLOCK_MIN_MAX_s mrc_tableMinimumMaximumValues
Definition: redundancy.c:70
static void MRC_ValidatePowerMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor)
Function to validate results of power measurement.
Definition: redundancy.c:694
static void MRC_ValidateStringVoltageMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor, DATA_BLOCK_CELL_VOLTAGE_s *pTableCellVoltage)
Function to validate results of string voltage measurement.
Definition: redundancy.c:591
STD_RETURN_TYPE_e MRC_Initialize(void)
Function to initalize redundancy module.
Definition: redundancy.c:1069
static void MRC_ValidateHighVoltageBusMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor)
Function to validate results of high voltage measurement and calculate battery voltage and high volta...
Definition: redundancy.c:660
static STD_RETURN_TYPE_e MRC_ValidateCellVoltage(DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageBase, DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageRedundancy0, DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages)
Function compares cell voltage measurements from base measurement with one redundant measurement and ...
Definition: redundancy.c:876
static STD_RETURN_TYPE_e MRC_UpdateCellVoltageValidation(DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltage, DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages)
Function updates validated cell voltage measurement with data from a single measurement source....
Definition: redundancy.c:955
static DATA_BLOCK_PACK_VALUES_s mrc_tablePackValues
Definition: redundancy.c:73
static bool MRC_ValidateCellTemperatureMeasurement(DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureBase, DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureRedundancy0)
Function to validate results of cell temperature measurement.
Definition: redundancy.c:414
static void MRC_ValidateCurrentMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor)
Function to validate results of current measurement.
Definition: redundancy.c:540
static bool MRC_MeasurementUpdatedAtLeastOnce(uint32_t timestamp, uint32_t previousTimestamp)
Check timestamp if measurement has been updated at least once.
Definition: redundancy.c:257
STD_RETURN_TYPE_e MRC_ValidatePackMeasurement(void)
Function to validate the measurements of pack values (string values, pack values)
Definition: redundancy.c:1127
static STD_RETURN_TYPE_e MRC_CalculateCellVoltageMinMaxAverage(const DATA_BLOCK_CELL_VOLTAGE_s *const pValidatedVoltages, DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues)
Function calculates minimum, maximum and average cell voltages.
Definition: redundancy.c:755
static STD_RETURN_TYPE_e MRC_UpdateCellTemperatureValidation(DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperature, DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperature)
Function updates validated cell temperature measurement with data from a single measurement source....
Definition: redundancy.c:1052
static STD_RETURN_TYPE_e MRC_ValidateCellTemperature(DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureBase, DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureRedundancy0, DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures)
Function compares cell temperature measurements from base measurement with one redundant measurement ...
Definition: redundancy.c:972
static MRC_STATE_s mrc_state
Definition: redundancy.c:77
static STD_RETURN_TYPE_e MRC_CalculateCellTemperatureMinMaxAverage(DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures, DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues)
Function calculates minimum, maximum and average cell temperatures.
Definition: redundancy.c:813
STD_RETURN_TYPE_e MRC_ValidateMicMeasurement(void)
Function to validate the measurement between redundant measurement values for cell voltage and cell t...
Definition: redundancy.c:1094
static bool MRC_ValidateCellVoltageMeasurement(DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageBase, DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageRedundancy0)
Function to validate results of cell voltage measurement.
Definition: redundancy.c:286
static STD_RETURN_TYPE_e MRC_MeasurementUpdatedRecently(uint32_t timestamp, uint32_t previousTimestamp, uint32_t timeInterval)
Check timestamp if measurement has been updated recently.
Definition: redundancy.c:268
Header fileS for handling redundancy between redundant cell voltage and cell temperature measurements...
#define MRC_ALLOWED_NUMBER_OF_INVALID_CELL_VOLTAGES
Definition: redundancy.h:110
#define MRC_MIC_MEASUREMENT_PERIOD_TIMEOUT_ms
Definition: redundancy.h:87
#define MRC_CURRENT_MEASUREMENT_PERIOD_TIMEOUT_ms
Definition: redundancy.h:73
#define MRC_CURRENT_SENSOR_MEASUREMENT_TIMEOUT_ms
Definition: redundancy.h:100
DATA_BLOCK_ID_e uniqueId
Definition: database_cfg.h:110
uint32_t timestamp
Definition: database_cfg.h:111
int16_t cellTemperature_ddegC[BS_NR_OF_STRINGS][BS_NR_OF_TEMP_SENSORS_PER_STRING]
Definition: database_cfg.h:138
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:136
uint16_t invalidCellTemperature[BS_NR_OF_STRINGS][BS_NR_OF_MODULES]
Definition: database_cfg.h:140
uint16_t nrValidTemperatures[BS_NR_OF_STRINGS]
Definition: database_cfg.h:141
uint16_t nrValidCellVoltages[BS_NR_OF_STRINGS]
Definition: database_cfg.h:126
int16_t cellVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_BAT_CELLS]
Definition: database_cfg.h:123
uint64_t invalidCellVoltage[BS_NR_OF_STRINGS][BS_NR_OF_MODULES]
Definition: database_cfg.h:125
bool validModuleVoltage[BS_NR_OF_STRINGS][BS_NR_OF_MODULES]
Definition: database_cfg.h:128
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:120
int32_t packVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:122
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:215
uint8_t invalidCurrentMeasurement[BS_NR_OF_STRINGS]
Definition: database_cfg.h:217
uint32_t timestampCurrent[BS_NR_OF_STRINGS]
Definition: database_cfg.h:220
uint32_t timestampPower[BS_NR_OF_STRINGS]
Definition: database_cfg.h:227
int32_t power_W[BS_NR_OF_STRINGS]
Definition: database_cfg.h:223
uint8_t invalidHighVoltageMeasurement[BS_NR_OF_STRINGS][BS_NR_OF_VOLTAGES_FROM_CURRENT_SENSOR]
Definition: database_cfg.h:237
uint32_t previousTimestampPower[BS_NR_OF_STRINGS]
Definition: database_cfg.h:226
int32_t current_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:216
uint32_t timestampHighVoltage[BS_NR_OF_STRINGS][BS_NR_OF_VOLTAGES_FROM_CURRENT_SENSOR]
Definition: database_cfg.h:243
uint8_t invalidPowerMeasurement[BS_NR_OF_STRINGS]
Definition: database_cfg.h:224
uint32_t previousTimestampHighVoltage[BS_NR_OF_STRINGS][BS_NR_OF_VOLTAGES_FROM_CURRENT_SENSOR]
Definition: database_cfg.h:241
int32_t highVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_VOLTAGES_FROM_CURRENT_SENSOR]
Definition: database_cfg.h:238
uint32_t previousTimestampCurrent[BS_NR_OF_STRINGS]
Definition: database_cfg.h:219
uint16_t nrCellMinimumCellVoltage[BS_NR_OF_STRINGS]
Definition: database_cfg.h:171
uint16_t validMeasuredCellTemperatures[BS_NR_OF_STRINGS]
Definition: database_cfg.h:182
uint16_t nrSensorMinimumTemperature[BS_NR_OF_STRINGS]
Definition: database_cfg.h:178
int16_t maximumTemperature_ddegC[BS_NR_OF_STRINGS]
Definition: database_cfg.h:179
int16_t minimumTemperature_ddegC[BS_NR_OF_STRINGS]
Definition: database_cfg.h:176
float averageTemperature_ddegC[BS_NR_OF_STRINGS]
Definition: database_cfg.h:175
uint16_t nrModuleMaximumCellVoltage[BS_NR_OF_STRINGS]
Definition: database_cfg.h:172
uint16_t nrCellMaximumCellVoltage[BS_NR_OF_STRINGS]
Definition: database_cfg.h:173
uint16_t nrSensorMaximumTemperature[BS_NR_OF_STRINGS]
Definition: database_cfg.h:181
uint16_t validMeasuredCellVoltages[BS_NR_OF_STRINGS]
Definition: database_cfg.h:174
int16_t maximumCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:168
uint16_t nrModuleMinimumCellVoltage[BS_NR_OF_STRINGS]
Definition: database_cfg.h:170
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:163
uint16_t nrModuleMaximumTemperature[BS_NR_OF_STRINGS]
Definition: database_cfg.h:180
int16_t averageCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:165
uint16_t nrModuleMinimumTemperature[BS_NR_OF_STRINGS]
Definition: database_cfg.h:177
int16_t minimumCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:166
int32_t stringCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:204
int32_t stringPower_W[BS_NR_OF_STRINGS]
Definition: database_cfg.h:206
int32_t highVoltageBusVoltage_mV
Definition: database_cfg.h:198
uint8_t invalidStringCurrent[BS_NR_OF_STRINGS]
Definition: database_cfg.h:205
int32_t stringVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:202
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:191
uint8_t invalidStringPower[BS_NR_OF_STRINGS]
Definition: database_cfg.h:207
uint8_t invalidStringVoltage[BS_NR_OF_STRINGS]
Definition: database_cfg.h:203
uint32_t lastRedundancy0CellvoltageTimestamp
Definition: redundancy.h:118
uint32_t lastRedundancy0CelltemperatureTimestamp
Definition: redundancy.h:120
uint32_t lastStringCurrentTimestamp[BS_NR_OF_STRINGS]
Definition: redundancy.h:121
uint32_t lastBaseCellvoltageTimestamp
Definition: redundancy.h:117
uint32_t lastBaseCelltemperatureTimestamp
Definition: redundancy.h:119
uint32_t lastStringPowerTimestamp[BS_NR_OF_STRINGS]
Definition: redundancy.h:122