foxBMS  1.2.1
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-12-08 (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  * @param[in] pCellVoltageBase base cell voltage measurement
111  * @param[in] pCellVoltageRedundancy0 redundant cell voltage measurement
112  * @return bool true, if measurement has been validated successfully and
113  * database entry needs to be updated, otherwise false.
114  */
116  DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageBase,
117  DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageRedundancy0);
118 
119 /**
120  * @brief Function to validate results of cell temperature measurement
121  * @param[in] pCellTemperatureBase base cell temperature measurement
122  * @param[in] pCellTemperatureRedundancy0 redundant cell temperature measurement
123  * @return bool true, if measurement has been validated successfully and
124  * database entry needs to be updated, otherwise false.
125  */
127  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureBase,
128  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureRedundancy0);
129 
130 /**
131  * @brief Function to validate results of current measurement
132  * @param[in] pTableCurrentSensor pointer to current measurements
133  */
134 static void MRC_ValidateCurrentMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor);
135 
136 /**
137  * @brief Function to validate results of string voltage measurement
138  * @param[in] pTableCurrentSensor pointer current sensor high voltage measurements
139  * @param[in] pTableCellVoltage pointer to cell voltage measurements
140  */
142  DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor,
143  DATA_BLOCK_CELL_VOLTAGE_s *pTableCellVoltage);
144 
145 /**
146  * @brief Function to validate HV battery voltage measurement
147  */
148 static void MRC_ValidateBatteryVoltageMeasurement(void);
149 
150 /**
151  * @brief Function to validate results of high voltage measurement and calculate
152  * battery voltage and high voltage bus voltage.
153  * @param[in] pTableCurrentSensor pointer current sensor high voltage measurements
154  */
156 
157 /**
158  * @brief Function to validate results of power measurement
159  * @param[in] pTableCurrentSensor pointer to power/current measurements
160  */
161 static void MRC_ValidatePowerMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor);
162 
163 /**
164  * @brief Function calculates minimum, maximum and average cell voltages.
165  * @param[in] pValidatedVoltages validated voltages from base and/or redundant measurements
166  * @param[out] pMinMaxAverageValues calculated cell voltage min/max/average values
167  * @return #STD_NOT_OK if all cell voltage are invalid and no minimum, maximum
168  * and average cell voltage values could be calculated, otherwise #STD_OK
169  */
171  const DATA_BLOCK_CELL_VOLTAGE_s *const pValidatedVoltages,
172  DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues);
173 
174 /**
175  * @brief Function calculates minimum, maximum and average cell temperatures.
176  * @param[in] pValidatedTemperatures validated temperatures from base and/or redundant measurements
177  * @param[out] pMinMaxAverageValues calculated cell temperature min/max/average values
178  * @return #STD_NOT_OK if all cell temperatures are invalid and no minimum, maximum
179  * and average cell temperature values could be calculated, otherwise #STD_OK
180  */
182  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures,
183  DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues);
184 
185 /**
186  * @brief Function compares cell voltage measurements from base measurement with
187  * one redundant measurement and writes result in pValidatedVoltages.
188  * @param[in] pCellvoltageBase base cell voltage measurement
189  * @param[in] pCellvoltageRedundancy0 redundant cell voltage measurement
190  * @param[out] pValidatedVoltages validated voltages from redundant measurement values
191  * @return #STD_NOT_OK if not all cell voltages could be validated, otherwise
192  * #STD_OK
193  */
195  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageBase,
196  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageRedundancy0,
197  DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages);
198 
199 /**
200  * @brief Function updates validated cell voltage measurement with data from a
201  * single measurement source. This can be the case if no redundancy is
202  * used at all or if one or more of the redundant measurements are not
203  * working properly.
204  * @param[in] pCellvoltage cell voltage measurement
205  * @param[out] pValidatedVoltages validated voltage values
206  * @return #STD_NOT_OK if not all cell voltages could be validated, otherwise
207  * #STD_OK
208  */
210  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltage,
211  DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages);
212 
213 /**
214  * @brief Function compares cell temperature measurements from base measurement
215  * with one redundant measurement and writes result in pValidatedTemperatures.
216  * @param[in] pCelltemperatureBase base cell temperature measurement
217  * @param[in] pCelltemperatureRedundancy0 redundant cell temperature measurement
218  * @param[out] pValidatedTemperatures validated temperatures from redundant measurement values
219  * @return #STD_NOT_OK if not all cell voltages could be validated, otherwise
220  * #STD_OK
221  */
223  DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureBase,
224  DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureRedundancy0,
225  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures);
226 
227 /**
228  * @brief Function updates validated cell temperature measurement with data from a
229  * single measurement source. This can be the case if no redundancy is
230  * used at all or if one or more of the redundant measurements are not
231  * working properly.
232  * @param[in] pCellTemperature cell temperature measurement
233  * @param[out] pValidatedTemperature validated temperature values
234  * @return #STD_NOT_OK if not all cell voltages could be validated, otherwise
235  * #STD_OK
236  */
238  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperature,
239  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperature);
240 
241 /*========== Static Function Implementations ================================*/
242 static bool MRC_MeasurementUpdatedAtLeastOnce(uint32_t timestamp, uint32_t previousTimestamp) {
243  bool retval = false;
244  if (!((timestamp == 0u) && (previousTimestamp == 0u))) {
245  /* Only possibility for timestamp AND previous timestamp to be 0 is, if
246  the measurement has never been updated. Thus, if this is not the case
247  the measurement must have been updated */
248  retval = true;
249  }
250  return retval;
251 }
252 
254  uint32_t timestamp,
255  uint32_t previousTimestamp,
256  uint32_t timeInterval) {
257  STD_RETURN_TYPE_e retval = STD_NOT_OK;
258  uint32_t currentTimestamp = OS_GetTickCount();
259 
260  /* Unsigned integer arithmetic also works correctly if currentTimestap is
261  larger than pHeader->timestamp (timer overflow), thus no need to use abs() */
262  if (((currentTimestamp - timestamp) <= timeInterval) &&
263  (MRC_MeasurementUpdatedAtLeastOnce(timestamp, previousTimestamp) == true)) {
264  /* Difference between current timestamp and last update timestamp is
265  smaller than passed time interval */
266  retval = STD_OK;
267  }
268  return retval;
269 }
270 
272  DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageBase,
273  DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageRedundancy0) {
274  FAS_ASSERT(pCellVoltageBase != NULL_PTR);
275  FAS_ASSERT(pCellVoltageRedundancy0 != NULL_PTR);
276 
277  bool updatedValidatedVoltageDatbaseEntry = false;
278 
279  bool baseCellvoltageUpdated = false;
280 
281  bool useCellvoltageRedundancy = false;
282  bool baseCellvoltageMeasurementTimeoutReached = true;
283  bool redundancy0CellvoltageMeasurementTimeoutReached = true;
284 
285  /* Following decision will be undertaken:
286  *
287  * - Use redundancy only if timestamp of redundant database entry != 0
288  * - Perform redundant check if both timestamps have been updated
289  * - Add timeout and trigger error if timestamps have not been updated in the last XXXXms
290  * - If timeout reached and only one of the two redundant measurements has been updated use this measurement value
291  * but throw an error that one measurement has not been updated recently.
292  */
293 
294  /* -------------- Check if cell voltage redundant measurement is used -- */
295  /* Use redundant cell voltage measurements if measurement values have been acquired once */
296  useCellvoltageRedundancy = DATA_DatabaseEntryUpdatedAtLeastOnce(pCellVoltageRedundancy0->header);
297 
298  /* ----------------- Check timestamp of base measurements--------------- */
300  baseCellvoltageMeasurementTimeoutReached = false;
302  } else {
303  baseCellvoltageMeasurementTimeoutReached = true;
304  /* Set error flag */
306  }
307 
308  /* Check if base measurement values have been updated since last MRC */
309  if (mrc_state.lastBaseCellvoltageTimestamp != pCellVoltageBase->header.timestamp) {
310  baseCellvoltageUpdated = true;
311  } else {
312  baseCellvoltageUpdated = false;
313  }
314 
315  /* ----------------- Check timestamp of redundant measurements --------- */
317  false) &&
318  (useCellvoltageRedundancy == true)) {
319  redundancy0CellvoltageMeasurementTimeoutReached = true;
320  /* Set error flag */
322  } else {
323  redundancy0CellvoltageMeasurementTimeoutReached = false;
325  }
326 
327  /* ----------------- Validate cell voltages ---------------------------- */
328  if (useCellvoltageRedundancy == true) {
329  bool redundany0CellvoltageUpdated = false;
330  /* Check if redundant measurement values have been updated since last MRC */
331  if (mrc_state.lastRedundancy0CellvoltageTimestamp != pCellVoltageRedundancy0->header.timestamp) {
332  redundany0CellvoltageUpdated = true;
333  } else {
334  redundany0CellvoltageUpdated = false;
335  }
336  /* Make sure cell voltage timestamps have been updated since last call */
337  if ((baseCellvoltageUpdated == true) && (redundany0CellvoltageUpdated == true)) {
338  /* Update timestamp */
341 
342  /* Validate cell voltages */
343  MRC_ValidateCellVoltage(pCellVoltageBase, pCellVoltageRedundancy0, &mrc_tableCellVoltages);
344  /* Set to true for following minimum, maximum and average calculation */
345  updatedValidatedVoltageDatbaseEntry = true;
346 
347  } else if ((baseCellvoltageUpdated == true) || (redundany0CellvoltageUpdated == true)) {
348  /* At least one measurement has been updated */
349  if (baseCellvoltageUpdated == true) {
350  /* Has redundant measurement timeout been reached? If yes, update. */
351  if (redundancy0CellvoltageMeasurementTimeoutReached == true) {
352  /* Copy cell voltage base measurement values into validated database struct */
354  /* Set to true for following minimum, maximum and average calculation */
355  updatedValidatedVoltageDatbaseEntry = true;
356  }
357  } else if (redundany0CellvoltageUpdated == true) {
358  /* Has base measurement timeout been reached? If yes, update. */
359  if (baseCellvoltageMeasurementTimeoutReached == true) {
360  /* Copy cell voltage base measurement values into validated database struct */
361  MRC_UpdateCellVoltageValidation(pCellVoltageRedundancy0, &mrc_tableCellVoltages);
362  /* Set to true for following minimum, maximum and average calculation */
363  updatedValidatedVoltageDatbaseEntry = true;
364  }
365  } else {
367  }
368  } else {
369  /* No cell voltage measurement has been updated -> do nothing */
370  }
371  } else {
372  if (baseCellvoltageUpdated == true) {
373  /* Only update database entries if new raw data has been acquired */
374  /* Update timestamp */
376 
377  /* Copy cell voltage base measurement values into validated database struct */
379 
380  /* Set to true for following minimum, maximum and average calculation */
381  updatedValidatedVoltageDatbaseEntry = true;
382  }
383  }
384 
385  if (updatedValidatedVoltageDatbaseEntry == true) {
386  /* Calculate min/max/average cell voltages */
388 
389  /* Individual cell voltages validated and min/max/average calculated -> check voltage spread */
391  /* Recalculate min/max/average cell voltages as at least one cell voltage has been detected as invalid */
393  }
394  }
395 
396  return updatedValidatedVoltageDatbaseEntry;
397 }
398 
400  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureBase,
401  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureRedundancy0) {
402  FAS_ASSERT(pCellTemperatureBase != NULL_PTR);
403  FAS_ASSERT(pCellTemperatureRedundancy0 != NULL_PTR);
404 
405  bool baseCelltemperatureUpdated = false;
406  bool useCelltemperatureRedundancy = false;
407  bool updatedValidatedTemperatureDatbaseEntry = false;
408 
409  bool baseCellTemperatureMeasurementTimeoutReached = true;
410  bool redundancy0CellTemperatureMeasurementTimeoutReached = true;
411 
412  /* Following decision will be undertaken:
413  *
414  * - Use redundancy only if timestamp of redundant database entry != 0
415  * - Perform redundant check if both timestamps have been updated
416  * - Add timeout and trigger error if timestamps have not been updated in the last XXXXms
417  * - If timeout reached and only one of the two redundant measurements has been updated use this measurement value
418  * but throw an error that one measurement has not been updated recently.
419  */
420 
421  /* -------------- Check if cell cell temperature redundant measurement is used ---------- */
422  /* Use redundant cell voltage measurements if measurement values have been acquired once */
423  useCelltemperatureRedundancy = DATA_DatabaseEntryUpdatedAtLeastOnce(pCellTemperatureRedundancy0->header);
424 
425  /* ----------------- Check timestamp of base measurements--------------- */
427  baseCellTemperatureMeasurementTimeoutReached = false;
429  } else {
430  baseCellTemperatureMeasurementTimeoutReached = true;
431  /* Set error flag */
433  }
434  /* Check if base measurement values have been updated since last MRC */
435  if (mrc_state.lastBaseCelltemperatureTimestamp != pCellTemperatureBase->header.timestamp) {
436  baseCelltemperatureUpdated = true;
437  } else {
438  baseCelltemperatureUpdated = false;
439  }
440 
441  /* ----------------- Check timestamp of redundant measurements --------- */
443  false) &&
444  (useCelltemperatureRedundancy == true)) {
445  redundancy0CellTemperatureMeasurementTimeoutReached = true;
446  /* Set error flag */
448  } else {
449  redundancy0CellTemperatureMeasurementTimeoutReached = false;
451  }
452 
453  /* ----------------- Validate cell temperatures ------------------------ */
454  if (useCelltemperatureRedundancy == true) {
455  bool redundancy0CelltemperatureUpdated = false;
456  /* Check if redundant measurement values have been updated since last MRC */
457  if (mrc_state.lastRedundancy0CelltemperatureTimestamp != pCellTemperatureRedundancy0->header.timestamp) {
458  redundancy0CelltemperatureUpdated = true;
459  } else {
460  redundancy0CelltemperatureUpdated = false;
461  }
462  /* Make sure cell voltage timestamps have been updated since last call */
463  if ((baseCelltemperatureUpdated == true) && (redundancy0CelltemperatureUpdated == true)) {
464  /* Update timestamp */
466  mrc_state.lastRedundancy0CelltemperatureTimestamp = pCellTemperatureRedundancy0->header.timestamp;
467 
468  /* Validate cell temperatures */
469  MRC_ValidateCellTemperature(pCellTemperatureBase, pCellTemperatureRedundancy0, &mrc_tableCellTemperatures);
470  /* Set to true for following minimum, maximum and average calculation */
471  updatedValidatedTemperatureDatbaseEntry = true;
472 
473  } else if ((baseCelltemperatureUpdated == true) || (redundancy0CelltemperatureUpdated == true)) {
474  /* At least one measurement has been updated */
475  if (baseCelltemperatureUpdated == true) {
476  /* Has redundant measurement timeout been reached? If yes, update. */
477  if (redundancy0CellTemperatureMeasurementTimeoutReached == true) {
478  /* Copy cell temperature base measurement values into validated database struct */
480  /* Set to true for following minimum, maximum and average calculation */
481  updatedValidatedTemperatureDatbaseEntry = true;
482  }
483  } else if (redundancy0CelltemperatureUpdated == true) {
484  /* Has base measurement timeout been reached? If yes, update. */
485  if (baseCellTemperatureMeasurementTimeoutReached == true) {
486  /* Copy cell temperature redundant measurement values into validated database struct */
487  MRC_UpdateCellTemperatureValidation(pCellTemperatureRedundancy0, &mrc_tableCellTemperatures);
488  /* Set to true for following minimum, maximum and average calculation */
489  updatedValidatedTemperatureDatbaseEntry = true;
490  }
491  } else {
493  }
494  } else {
495  /* No cell temperature measurement has been updated -> do nothing */
496  }
497  } else { /* useCelltemperatureRedundancy == true */
498  if (baseCelltemperatureUpdated == true) {
499  /* Only update database entries if new raw data has been acquired */
500  /* Update timestamp */
502 
503  /* Copy cell temperature base measurement values into validated database struct */
505 
506  /* Set to true for following minimum, maximum and average calculation */
507  updatedValidatedTemperatureDatbaseEntry = true;
508  }
509  }
510 
511  if (updatedValidatedTemperatureDatbaseEntry == true) {
512  /* Calculate min/max/average cell temperatures */
514 
515  /* Individual cell temperatures validated and min/max/average calculated -> check temperature spread */
517  /* Recalculate min/max/average temperatures as at least one temperature has been detected as invalid */
519  }
520  }
521 
522  return updatedValidatedTemperatureDatbaseEntry;
523 }
524 
526  FAS_ASSERT(pTableCurrentSensor != NULL_PTR);
527  int32_t packCurrent_mA = 0;
528 
529  /* Validate pack current. Will be invalidated if not all current measurement values are valid */
531 
532  /* Iterate over all strings to calculate pack current */
533  for (uint8_t stringNumber = 0u; stringNumber < BS_NR_OF_STRINGS; stringNumber++) {
534  /* Check timestamp of measurement */
536  pTableCurrentSensor->timestampCurrent[stringNumber],
537  pTableCurrentSensor->previousTimestampCurrent[stringNumber],
539  (void)DIAG_CheckEvent(noTimeout, DIAG_ID_CURRENT_MEASUREMENT_TIMEOUT, DIAG_STRING, stringNumber);
540 
541  if (STD_OK == noTimeout) {
542  /* Check if current entry has been updated since last call */
543  if (mrc_state.lastStringCurrentTimestamp[stringNumber] !=
544  pTableCurrentSensor->timestampCurrent[stringNumber]) {
545  mrc_state.lastStringCurrentTimestamp[stringNumber] =
546  pTableCurrentSensor->timestampCurrent[stringNumber];
547  mrc_tablePackValues.stringCurrent_mA[stringNumber] = pTableCurrentSensor->current_mA[stringNumber];
548  if (pTableCurrentSensor->invalidCurrentMeasurement[stringNumber] == 0u) {
549  /* String current measurement valid -> set valid flag */
550  mrc_tablePackValues.invalidStringCurrent[stringNumber] = 0u;
552  } else {
553  /* String current measurement invalid -> set invalid flag */
555  mrc_tablePackValues.invalidStringCurrent[stringNumber] = 1u;
556  }
557  } else {
558  /* Nothing to do. Measurement has not been updated but still within timeout */
559  }
560  } else {
561  /* Measurement timeout reached -> set string current invalid */
562  mrc_tablePackValues.invalidStringCurrent[stringNumber] = 1u;
563  }
564 
565  if (0u == mrc_tablePackValues.invalidStringCurrent[stringNumber]) {
566  packCurrent_mA += mrc_tablePackValues.stringCurrent_mA[stringNumber];
567  } else {
568  /* One string current is invalid -> pack current cannot be correct.
569  * Set pack current invalid */
571  }
572  }
573  mrc_tablePackValues.packCurrent_mA = packCurrent_mA;
574 }
575 
577  DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor,
578  DATA_BLOCK_CELL_VOLTAGE_s *pTableCellVoltage) {
579  /* Pointer validity check */
580  FAS_ASSERT(pTableCurrentSensor != NULL_PTR);
581  FAS_ASSERT(pTableCellVoltage != NULL_PTR);
582 
583  for (uint8_t stringNumber = 0u; stringNumber < BS_NR_OF_STRINGS; stringNumber++) {
584  /* Check timeout of current sensor measurement */
586  pTableCurrentSensor->timestampHighVoltage[stringNumber][0u],
587  pTableCurrentSensor->previousTimestampHighVoltage[stringNumber][0u],
590 
591  /* Perform plausibility check if AFE and new current sensor measurement is valid */
592  if ((STD_OK == updatedMeasurement) &&
593  (pTableCurrentSensor->invalidHighVoltageMeasurement[stringNumber][0u] == 0u) &&
594  (pTableCellVoltage->nrValidCellVoltages[stringNumber] == BS_NR_OF_BAT_CELLS)) {
595  STD_RETURN_TYPE_e voltagePlausible = PL_CheckStringVoltage(
596  pTableCellVoltage->packVoltage_mV[stringNumber], pTableCurrentSensor->highVoltage_mV[stringNumber][0u]);
597  (void)DIAG_CheckEvent(voltagePlausible, DIAG_ID_PLAUSIBILITY_PACK_VOLTAGE, DIAG_STRING, stringNumber);
598 
599  /* Use current sensor measurement */ /* TODO: use really current sensor? Average of both? AFE measurement? */
600  mrc_tablePackValues.stringVoltage_mV[stringNumber] = pTableCurrentSensor->highVoltage_mV[stringNumber][0u];
601 
602  if (STD_OK == voltagePlausible) {
603  mrc_tablePackValues.invalidStringVoltage[stringNumber] = 0u;
604  } else {
605  mrc_tablePackValues.invalidStringVoltage[stringNumber] = 1u;
606  }
607  } else {
608  /* Plausibility check cannot be performed if we do not have valid
609  * values from AFE and current sensor measurement */
611 
612  if ((STD_OK == updatedMeasurement) &&
613  (pTableCurrentSensor->invalidHighVoltageMeasurement[stringNumber][0u] == 0u)) {
614  /* Current sensor measurement valid -> use this measurement */
615  mrc_tablePackValues.stringVoltage_mV[stringNumber] =
616  pTableCurrentSensor->highVoltage_mV[stringNumber][0u];
617  mrc_tablePackValues.invalidStringVoltage[stringNumber] = 0u;
618  } else if (pTableCellVoltage->nrValidCellVoltages[stringNumber] == BS_NR_OF_BAT_CELLS) {
619  /* AFE measurement valid -> use this measurement */
620  mrc_tablePackValues.stringVoltage_mV[stringNumber] = pTableCellVoltage->packVoltage_mV[stringNumber];
621  mrc_tablePackValues.invalidStringVoltage[stringNumber] = 0u;
622  } else {
623  /* AFE and current sensor measurement invalid -> try to construct
624  * a valid from the number of valid cell voltages and substitute
625  * invalid cell voltages with the average cell voltage. */
626  uint16_t numberInvalidCellVoltages =
627  (BS_NR_OF_BAT_CELLS - pTableCellVoltage->nrValidCellVoltages[stringNumber]);
628 
629  mrc_tablePackValues.stringVoltage_mV[stringNumber] =
630  pTableCellVoltage->packVoltage_mV[stringNumber] +
632  (int16_t)numberInvalidCellVoltages);
633 
634  /* Only use this as valid value if not more than five cell voltages are invalid */
635  if (numberInvalidCellVoltages > MRC_ALLOWED_NUMBER_OF_INVALID_CELL_VOLTAGES) {
636  mrc_tablePackValues.invalidStringVoltage[stringNumber] = 1u;
637  } else {
638  mrc_tablePackValues.invalidStringVoltage[stringNumber] = 0u;
639  }
640  }
641  }
642  }
643 }
644 
646  int64_t sumOfStringValues_mV = 0;
647  int8_t numberOfValidStringVoltages = 0;
648  uint8_t numberOfConnectedStrings = BMS_GetNumberOfConnectedStrings();
649 
650  if (0u != numberOfConnectedStrings) {
651  /* Iterate over all strings to see which strings are connected */
652  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
653  bool isStringConnected = BMS_IsStringClosed(s);
654  if ((0u == mrc_tablePackValues.invalidStringVoltage[s]) && (true == isStringConnected)) {
655  /* AXIVION Disable Style MisraC2012Directive-4.1: Values start with 0, iteration is less than UINT8_MAX; overflow impossible */
656  sumOfStringValues_mV += mrc_tablePackValues.stringVoltage_mV[s];
657  numberOfValidStringVoltages++;
658  /* AXIVION Enable Style MisraC2012Directive-4.1: */
659  }
660  }
661  } else {
662  /* Take average of all strings if no strings are connected */
663  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
665  /* AXIVION Disable Style MisraC2012Directive-4.1: Values start with 0, iteration is less than UINT8_MAX; overflow impossible */
666  sumOfStringValues_mV += mrc_tablePackValues.stringVoltage_mV[s];
667  numberOfValidStringVoltages++;
668  /* AXIVION Enable Style MisraC2012Directive-4.1: */
669  }
670  }
671  }
672 
673  /* Only calculate average if at least one string voltage is valid */
674  if (0 != numberOfValidStringVoltages) {
675  /* AXIVION Disable Style MisraC2012Directive-4.1: truncation impossible; we sum INT32 values x times and divide by x, resulting in INT32 */
676  mrc_tablePackValues.batteryVoltage_mV = (int32_t)(sumOfStringValues_mV / numberOfValidStringVoltages);
677  /* AXIVION Enable Style MisraC2012Directive-4.1: */
678  } else {
680  }
681 }
682 
684  FAS_ASSERT(pTableCurrentSensor != NULL_PTR);
685 
686  int32_t sum_mV = 0;
687  uint8_t validVoltages = 0u;
688  for (uint8_t stringNumber = 0u; stringNumber < BS_NR_OF_STRINGS; stringNumber++) {
689  /* Check timeout of current sensor measurement */
691  pTableCurrentSensor->timestampHighVoltage[stringNumber][2u],
692  pTableCurrentSensor->previousTimestampHighVoltage[stringNumber][2u],
695 
696  const bool stringClosed = BMS_IsStringClosed(stringNumber);
697  const bool stringPrecharging = BMS_IsStringPrecharging(stringNumber);
698  if (((true == stringPrecharging) || (true == stringClosed)) && (STD_OK == updatedMeasurement)) {
699  /* Only voltages of connected strings can be used */
700  if (0u == pTableCurrentSensor->invalidHighVoltageMeasurement[stringNumber][2]) {
701  /* Measured high voltage is valid */
702  validVoltages++;
703  sum_mV += pTableCurrentSensor->highVoltage_mV[stringNumber][2];
704  }
705  }
706  }
707 
708  if (validVoltages > 0u) {
709  mrc_tablePackValues.highVoltageBusVoltage_mV = (sum_mV / (int32_t)validVoltages);
711  } else {
712  /* TODO: do we want to write special data if no valid values can be read? */
714  }
715 }
716 
718  FAS_ASSERT(pTableCurrentSensor != NULL_PTR);
719  bool calculatePower = false;
720  int32_t packPower_W = 0;
721 
722  /* Validate pack power. Will be invalidated if not all power measurement values are valid */
724 
725  for (uint8_t stringNumber = 0u; stringNumber < BS_NR_OF_STRINGS; stringNumber++) {
726  /* Check timeout of current sensor measurement */
728  pTableCurrentSensor->timestampPower[stringNumber],
729  pTableCurrentSensor->previousTimestampPower[stringNumber],
732 
733  if (STD_OK == noTimeout) {
734  /* Check if current sensor measurement has been updated */
735  if (pTableCurrentSensor->timestampPower[stringNumber] != mrc_state.lastStringPowerTimestamp[stringNumber]) {
736  mrc_state.lastStringPowerTimestamp[stringNumber] = pTableCurrentSensor->timestampPower[stringNumber];
737  /* Check if measurement is valid */
738  if (pTableCurrentSensor->invalidPowerMeasurement[stringNumber] == 0u) {
739  mrc_tablePackValues.stringPower_W[stringNumber] = pTableCurrentSensor->power_W[stringNumber];
740  mrc_tablePackValues.invalidStringPower[stringNumber] = 0u;
741  } else {
742  /* Measurement has been updated but value is invalid -> calculate from current and string voltage */
743  calculatePower = true;
744  /* TODO: do we want to calculate values by hand if we are within time limit but value is invalid? */
745  }
746  } else {
747  /* Nothing to do. Measurement has not been updated but still within timeout */
748  }
749  } else {
750  /* Timeout reached. Set invalid flag */
751  calculatePower = true;
752  mrc_tablePackValues.invalidStringPower[stringNumber] = 1u;
753  }
754  if ((true == calculatePower) && (0u == mrc_tablePackValues.invalidStringCurrent[stringNumber]) &&
755  (0u == mrc_tablePackValues.invalidStringVoltage[stringNumber])) {
756  /* Power measurement is invalid, but current and string voltage measurement are valid */
757  int64_t stringPower_W =
758  ((mrc_tablePackValues.stringCurrent_mA[stringNumber] *
759  mrc_tablePackValues.stringVoltage_mV[stringNumber]) /
760  (UNIT_CONVERSION_FACTOR_1000_INTEGER * /* convert: mV -> V */
761  UNIT_CONVERSION_FACTOR_1000_INTEGER)); /* convert: mA -> A */
762  mrc_tablePackValues.stringPower_W[stringNumber] = (int32_t)stringPower_W;
763  mrc_tablePackValues.invalidStringPower[stringNumber] = 0u;
764  }
765  if (0u == mrc_tablePackValues.invalidStringPower[stringNumber]) {
766  packPower_W += mrc_tablePackValues.stringPower_W[stringNumber];
768  } else {
769  /* One string power is invalid -> pack power cannot be correct.
770  * Set pack power invalid */
773  }
774  }
775  mrc_tablePackValues.packPower_W = packPower_W;
776 }
777 
779  const DATA_BLOCK_CELL_VOLTAGE_s *const pValidatedVoltages,
780  DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues) {
781  /* Pointer validity check */
782  FAS_ASSERT(pValidatedVoltages != NULL_PTR);
783  FAS_ASSERT(pMinMaxAverageValues != NULL_PTR);
784 
785  STD_RETURN_TYPE_e retval = STD_OK;
786 
787  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
788  uint16_t nrValidCellvoltages = 0u;
789  int16_t min = INT16_MAX;
790  int16_t max = INT16_MIN;
791  int32_t sum = 0;
792  uint16_t moduleNumberMinimum = 0u;
793  uint16_t cellNumberMinimum = 0u;
794  uint16_t moduleNumberMaximum = 0u;
795  uint16_t cellNumberMaximum = 0u;
796  /* Iterate over all cells in each string */
797  for (uint8_t m = 0u; m < BS_NR_OF_MODULES; m++) {
798  for (uint8_t c = 0u; c < BS_NR_OF_CELLS_PER_MODULE; c++) {
799  if ((pValidatedVoltages->invalidCellVoltage[s][m] & (0x01u << c)) == 0u) {
800  /* Cell voltage is valid -> use this voltage for subsequent calculations */
801  nrValidCellvoltages++;
802  sum += pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c];
803 
804  if (pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c] < min) {
805  min = pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c];
806  moduleNumberMinimum = m;
807  cellNumberMinimum = c;
808  }
809  if (pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c] > max) {
810  max = pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c];
811  moduleNumberMaximum = m;
812  cellNumberMaximum = c;
813  }
814  }
815  }
816  }
817  pMinMaxAverageValues->minimumCellVoltage_mV[s] = min;
818  pMinMaxAverageValues->nrCellMinimumCellVoltage[s] = cellNumberMinimum;
819  pMinMaxAverageValues->nrModuleMinimumCellVoltage[s] = moduleNumberMinimum;
820  pMinMaxAverageValues->maximumCellVoltage_mV[s] = max;
821  pMinMaxAverageValues->nrCellMaximumCellVoltage[s] = cellNumberMaximum;
822  pMinMaxAverageValues->nrModuleMaximumCellVoltage[s] = moduleNumberMaximum;
823  pMinMaxAverageValues->validMeasuredCellVoltages[s] = nrValidCellvoltages;
824 
825  /* Prevent division by 0, if all cell voltages are invalid */
826  if (nrValidCellvoltages > 0u) {
827  pMinMaxAverageValues->averageCellVoltage_mV[s] = (int16_t)(sum / (int32_t)nrValidCellvoltages);
828  } else {
829  pMinMaxAverageValues->averageCellVoltage_mV[s] = 0;
830  retval = STD_NOT_OK;
831  }
832  }
833  return retval;
834 }
835 
837  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures,
838  DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues) {
839  /* Pointer validity check */
840  FAS_ASSERT(pValidatedTemperatures != NULL_PTR);
841  FAS_ASSERT(pMinMaxAverageValues != NULL_PTR);
842 
843  STD_RETURN_TYPE_e retval = STD_OK;
844 
845  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
846  uint16_t moduleNumberMinimum = 0u;
847  uint16_t sensorNumberMinimum = 0u;
848  uint16_t moduleNumberMaximum = 0u;
849  uint16_t sensorNumberMaximum = 0u;
850  uint16_t nrValidCelltemperatures = 0u;
851  int16_t min = INT16_MAX;
852  int16_t max = INT16_MIN;
853  float sum_ddegC = 0.0f;
854 
855  for (uint8_t m = 0u; m < BS_NR_OF_MODULES; m++) {
856  for (uint8_t c = 0u; c < BS_NR_OF_TEMP_SENSORS_PER_MODULE; c++) {
857  if ((pValidatedTemperatures->invalidCellTemperature[s][m] & (0x01u << c)) == 0u) {
858  /* Cell temperature is valid -> use this voltage for subsequent calculations */
859  nrValidCelltemperatures++;
860  sum_ddegC += (float)pValidatedTemperatures
861  ->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c];
862 
863  if (pValidatedTemperatures->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] <
864  min) {
865  min = pValidatedTemperatures
867  moduleNumberMinimum = m;
868  sensorNumberMinimum = c;
869  }
870  if (pValidatedTemperatures->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] >
871  max) {
872  max = pValidatedTemperatures
874  moduleNumberMaximum = m;
875  sensorNumberMaximum = c;
876  }
877  }
878  }
879  }
880  pMinMaxAverageValues->minimumTemperature_ddegC[s] = min;
881  pMinMaxAverageValues->nrSensorMinimumTemperature[s] = sensorNumberMinimum;
882  pMinMaxAverageValues->nrModuleMinimumTemperature[s] = moduleNumberMinimum;
883  pMinMaxAverageValues->maximumTemperature_ddegC[s] = max;
884  pMinMaxAverageValues->nrSensorMaximumTemperature[s] = sensorNumberMaximum;
885  pMinMaxAverageValues->nrModuleMaximumTemperature[s] = moduleNumberMaximum;
886  pMinMaxAverageValues->validMeasuredCellTemperatures[s] = nrValidCelltemperatures;
887 
888  /* Prevent division by 0, if all cell voltages are invalid */
889  if (nrValidCelltemperatures > 0u) {
890  pMinMaxAverageValues->averageTemperature_ddegC[s] = (sum_ddegC / (float)nrValidCelltemperatures);
891  } else {
892  pMinMaxAverageValues->averageTemperature_ddegC[s] = 0.0f;
893  retval = STD_NOT_OK;
894  }
895  }
896  return retval;
897 }
898 
900  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageBase,
901  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageRedundancy0,
902  DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages) {
903  /* Pointer validity check */
904  FAS_ASSERT(pCellvoltageBase != NULL_PTR);
905  FAS_ASSERT(pCellvoltageRedundancy0 != NULL_PTR);
906  FAS_ASSERT(pValidatedVoltages != NULL_PTR);
907 
908  uint16_t numberValidMeasurements = 0u;
909  STD_RETURN_TYPE_e noPlausibilityIssueDetected = STD_OK; /* Flag if implausable value detected */
910  STD_RETURN_TYPE_e retval = STD_OK;
911 
912  /* Iterate over all cell measurements */
913  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
914  int32_t sum = 0;
915  for (uint8_t m = 0; m < BS_NR_OF_MODULES; m++) {
916  for (uint8_t c = 0; c < BS_NR_OF_CELLS_PER_MODULE; c++) {
917  if (((pCellvoltageBase->invalidCellVoltage[s][m] & (1u << c)) == 0u) &&
918  ((pCellvoltageRedundancy0->invalidCellVoltage[s][m] & (1u << c)) == 0u)) {
919  /* Check if cell voltage of base AND redundant measurement is valid -> do plausibility check */
921  pCellvoltageBase->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c],
922  pCellvoltageRedundancy0->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c],
923  &pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c])) {
924  /* Clear valid flag */
925  pValidatedVoltages->invalidCellVoltage[s][m] = pValidatedVoltages->invalidCellVoltage[s][m] &
926  (~(1u << c));
927  numberValidMeasurements++;
928  sum += pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c];
929  } else {
930  /* Set invalid flag */
931  noPlausibilityIssueDetected = STD_NOT_OK;
932  pValidatedVoltages->invalidCellVoltage[s][m] |= (1u << c);
933  /* Set return value to #STD_NOT_OK as not all cell voltages have a valid measurement value */
934  retval = STD_NOT_OK;
935  }
936  } else if ((pCellvoltageBase->invalidCellVoltage[s][m] & (1u << c)) == 0u) {
937  /* Only base measurement value is valid -> use this voltage without further plausibility checks */
938  pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c] =
939  pCellvoltageBase->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c];
940  /* Reset valid flag */
941  pValidatedVoltages->invalidCellVoltage[s][m] = pValidatedVoltages->invalidCellVoltage[s][m] &
942  (~(1u << c));
943  numberValidMeasurements++;
944  sum += pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c];
945  } else if ((pCellvoltageRedundancy0->invalidCellVoltage[s][m] & (1u << c)) == 0u) {
946  /* Only redundant measurement value is valid -> use this voltage without further plausibility checks */
947  pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c] =
948  pCellvoltageRedundancy0->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c];
949  /* Reset valid flag */
950  pValidatedVoltages->invalidCellVoltage[s][m] = pValidatedVoltages->invalidCellVoltage[s][m] &
951  (~(1u << c));
952  numberValidMeasurements++;
953  sum += pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c];
954  } else {
955  /* Both, base and redundant measurement value are invalid */
956  /* Save average cell voltage value of base and redundant */
957  pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c] =
958  (pCellvoltageBase->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c] +
959  pCellvoltageRedundancy0->cellVoltage_mV[s][(m * BS_NR_OF_CELLS_PER_MODULE) + c]) /
960  2u;
961  /* Set invalid flag */
962  pValidatedVoltages->invalidCellVoltage[s][m] |= (1u << c);
963  /* Set return value to #STD_NOT_OK as not all cell voltages have a valid measurement value */
964  retval = STD_NOT_OK;
965  }
966  }
967  }
968  pValidatedVoltages->nrValidCellVoltages[s] = numberValidMeasurements;
969  pValidatedVoltages->packVoltage_mV[s] = sum;
970  numberValidMeasurements = 0u; /* Reset counter for next string */
971 
972  (void)DIAG_CheckEvent(noPlausibilityIssueDetected, DIAG_ID_PLAUSIBILITY_CELL_VOLTAGE, DIAG_STRING, s);
973  noPlausibilityIssueDetected = STD_OK; /* Reset flag for next string */
974  }
975  return retval;
976 }
977 
979  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltage,
980  DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages) {
981  /* Pointer validity check */
982  FAS_ASSERT(pCellvoltage != NULL_PTR);
983  FAS_ASSERT(pValidatedVoltages != NULL_PTR);
984 
985  /* Save header struct to copy to correct database entry */
986  DATA_BLOCK_HEADER_s tmpHeader = pValidatedVoltages->header;
987  /* Copy whole database entry */
988  *pValidatedVoltages = *pCellvoltage;
989  /* Restore previous header */
990  pValidatedVoltages->header = tmpHeader;
991 
992  return STD_OK;
993 }
994 
996  DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureBase,
997  DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureRedundancy0,
998  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures) {
999  /* Pointer validity check */
1000  FAS_ASSERT(pCelltemperatureBase != NULL_PTR);
1001  FAS_ASSERT(pCelltemperatureRedundancy0 != NULL_PTR);
1002  FAS_ASSERT(pValidatedTemperatures != NULL_PTR);
1003 
1004  uint16_t numberValidMeasurements = 0u;
1005  STD_RETURN_TYPE_e noPlausibilityIssueDetected = STD_OK; /* Flag if implausable value detected */
1006  STD_RETURN_TYPE_e retval = STD_OK;
1007 
1008  /* Iterate over all cell measurements */
1009  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
1010  for (uint8_t m = 0u; m < BS_NR_OF_MODULES; m++) {
1011  for (uint8_t c = 0u; c < BS_NR_OF_TEMP_SENSORS_PER_MODULE; c++) {
1012  if (((pCelltemperatureBase->invalidCellTemperature[s][m] & (1u << c)) == 0u) &&
1013  ((pCelltemperatureRedundancy0->invalidCellTemperature[s][m] & (1u << c)) == 0u)) {
1014  /* Check if cell voltage of base AND redundant measurement is valid -> do plausibility check */
1015  if (STD_OK ==
1017  pCelltemperatureBase->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c],
1018  pCelltemperatureRedundancy0
1020  &pValidatedTemperatures
1022  /* Clear valid flag */
1023  pValidatedTemperatures->invalidCellTemperature[s][m] =
1024  pValidatedTemperatures->invalidCellTemperature[s][m] & (~(1u << c));
1025  numberValidMeasurements++;
1026  } else {
1027  /* Set invalid flag */
1028  noPlausibilityIssueDetected = STD_NOT_OK;
1029  pValidatedTemperatures->invalidCellTemperature[s][m] |= (1u << c);
1030  /* Set return value to #STD_NOT_OK as not all cell temperatures have a valid measurement value */
1031  retval = STD_NOT_OK;
1032  }
1033  } else if ((pCelltemperatureBase->invalidCellTemperature[s][m] & (1u << c)) == 0u) {
1034  /* Only base measurement value is valid -> use this temperature without further plausibility checks */
1035  pValidatedTemperatures->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] =
1036  pCelltemperatureBase->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c];
1037  /* Reset valid flag */
1038  pValidatedTemperatures->invalidCellTemperature[s][m] =
1039  pValidatedTemperatures->invalidCellTemperature[s][m] & (~(1u << c));
1040  numberValidMeasurements++;
1041  } else if ((pCelltemperatureRedundancy0->invalidCellTemperature[s][m] & (1u << c)) == 0u) {
1042  /* Only redundant measurement value is valid -> use this temperature without further plausibility checks */
1043  pValidatedTemperatures->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] =
1044  pCelltemperatureRedundancy0
1045  ->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c];
1046  /* Reset valid flag */
1047  pValidatedTemperatures->invalidCellTemperature[s][m] =
1048  pValidatedTemperatures->invalidCellTemperature[s][m] & (~(1u << c));
1049  numberValidMeasurements++;
1050  } else {
1051  /* Both, base and redundant measurement value are invalid */
1052  /* Save average cell voltage value of base and redundant */
1053  pValidatedTemperatures->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] =
1054  (pCelltemperatureBase->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] +
1055  pCelltemperatureRedundancy0
1057  2u;
1058  /* Set invalid flag */
1059  pValidatedTemperatures->invalidCellTemperature[s][m] |= (1u << c);
1060  /* Set return value to #STD_NOT_OK as not all cell temperatures have a valid measurement value */
1061  retval = STD_NOT_OK;
1062  }
1063  }
1064  }
1065  pValidatedTemperatures->nrValidTemperatures[s] = numberValidMeasurements;
1066  numberValidMeasurements = 0u; /* Reset counter for next string */
1067 
1068  (void)DIAG_CheckEvent(noPlausibilityIssueDetected, DIAG_ID_PLAUSIBILITY_CELL_TEMP, DIAG_STRING, s);
1069  noPlausibilityIssueDetected = STD_OK; /* Reset flag for next string */
1070  }
1071 
1072  return retval;
1073 }
1074 
1076  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperature,
1077  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperature) {
1078  /* Pointer validity check */
1079  FAS_ASSERT(pCellTemperature != NULL_PTR);
1080  FAS_ASSERT(pValidatedTemperature != NULL_PTR);
1081 
1082  /* Save header struct to copy to correct database entry */
1083  DATA_BLOCK_HEADER_s tmpHeader = pValidatedTemperature->header;
1084  /* Copy whole database entry */
1085  *pValidatedTemperature = *pCellTemperature;
1086  /* Restore previous header */
1087  pValidatedTemperature->header = tmpHeader;
1088  return STD_OK;
1089 }
1090 
1091 /*========== Extern Function Implementations ================================*/
1093  STD_RETURN_TYPE_e retval = STD_NOT_OK;
1094  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
1095  for (uint8_t m = 0u; m < BS_NR_OF_MODULES; m++) {
1096  /* Invalidate cell voltage values */
1097  mrc_tableCellVoltages.invalidCellVoltage[s][m] = 0xFFFFFFFFFFFFFFFFULL;
1099  /* Invalidate cell temperature values */
1101  }
1102  /* Invalidate string values */
1106  }
1107  /* Invalidate pack values */
1108  mrc_tablePackValues.invalidPackCurrent = 0x01; /*!< bitmask if current is valid. 0->valid, 1->invalid */
1109  mrc_tablePackValues.invalidBatteryVoltage = 0x01; /*!< bitmask if voltage is valid. 0->valid, 1->invalid */
1110  mrc_tablePackValues.invalidHvBusVoltage = 0x01; /*!< bitmask if voltage is valid. 0->valid, 1->invalid */
1111  mrc_tablePackValues.invalidPackPower = 0x01; /*!< bitmask if power is valid. 0->valid, 1->invalid */
1112 
1114  return retval;
1115 }
1116 
1118  STD_RETURN_TYPE_e retval = STD_OK;
1119 
1120  /* Database entries are declared static, so that they are placed in the data segment and not on the stack */
1121  static DATA_BLOCK_CELL_VOLTAGE_s mrc_tableCellvoltageBase = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE_BASE};
1122  static DATA_BLOCK_CELL_VOLTAGE_s mrc_tableCellvoltageRedundancy0 = {
1124 
1125  static DATA_BLOCK_CELL_TEMPERATURE_s mrc_tableCelltemperatureBase = {
1127  static DATA_BLOCK_CELL_TEMPERATURE_s mrc_tableCelltemperatureRedundancy0 = {
1129 
1130  /* Get measurement values */
1132  &mrc_tableCellvoltageBase,
1133  &mrc_tableCellvoltageRedundancy0,
1134  &mrc_tableCelltemperatureBase,
1135  &mrc_tableCelltemperatureRedundancy0);
1136 
1137  /* Perform validation of cell voltage measurement */
1138  bool updateCellVoltages =
1139  MRC_ValidateCellVoltageMeasurement(&mrc_tableCellvoltageBase, &mrc_tableCellvoltageRedundancy0);
1140 
1141  /* Perform validation of cell temperature measurement */
1142  bool updateCellTemperatures =
1143  MRC_ValidateCellTemperatureMeasurement(&mrc_tableCelltemperatureBase, &mrc_tableCelltemperatureRedundancy0);
1144 
1145  /* Update database entries if necessary */
1146  if ((updateCellVoltages == true) && (updateCellTemperatures == true)) {
1148  } else if (updateCellVoltages == true) {
1150  } else if (updateCellTemperatures == true) {
1152  } else {
1153  retval = STD_NOT_OK;
1154  }
1155  return retval;
1156 }
1157 
1159  STD_RETURN_TYPE_e retval = STD_OK;
1161 
1162  DATA_READ_DATA(&tableCurrentSensor);
1163 
1164  MRC_ValidateCurrentMeasurement(&tableCurrentSensor);
1167  MRC_ValidateHighVoltageBusMeasurement(&tableCurrentSensor);
1168  MRC_ValidatePowerMeasurement(&tableCurrentSensor);
1169 
1171 
1172  return retval;
1173 }
1174 
1175 /*========== Externalized Static Function Implementations (Unit Test) =======*/
1176 #ifdef UNITY_UNIT_TEST
1177 extern bool TEST_MRC_MeasurementUpdatedAtLeastOnce(uint32_t timestamp, uint32_t previousTimestamp) {
1178  return MRC_MeasurementUpdatedAtLeastOnce(timestamp, previousTimestamp);
1179 }
1180 extern STD_RETURN_TYPE_e TEST_MRC_MeasurementUpdatedRecently(
1181  uint32_t timestamp,
1182  uint32_t previousTimestamp,
1183  uint32_t timeInterval) {
1184  return MRC_MeasurementUpdatedRecently(timestamp, previousTimestamp, timeInterval);
1185 }
1186 extern bool TEST_MRC_ValidateCellVoltageMeasurement(
1187  DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageBase,
1188  DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageRedundancy0) {
1189  return MRC_ValidateCellVoltageMeasurement(pCellVoltageBase, pCellVoltageRedundancy0);
1190 }
1191 extern bool TEST_MRC_ValidateCellTemperatureMeasurement(
1192  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureBase,
1193  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureRedundancy0) {
1194  return MRC_ValidateCellTemperatureMeasurement(pCellTemperatureBase, pCellTemperatureRedundancy0);
1195 }
1196 
1197 extern void TEST_MRC_ValidateCurrentMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor) {
1198  MRC_ValidateCurrentMeasurement(pTableCurrentSensor);
1199 }
1200 
1201 extern void TEST_MRC_ValidatePowerMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor) {
1202  MRC_ValidatePowerMeasurement(pTableCurrentSensor);
1203 }
1204 extern void TEST_MRC_ValidateStringVoltageMeasurement(
1205  DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor,
1206  DATA_BLOCK_CELL_VOLTAGE_s *pTableCellVoltage) {
1207  MRC_ValidateStringVoltageMeasurement(pTableCurrentSensor, pTableCellVoltage);
1208 }
1209 extern void TEST_MRC_ValidateBatteryVoltageMeasurement(void) {
1211 }
1212 extern void TEST_MRC_ValidateHighVoltageMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor) {
1213  MRC_ValidateHighVoltageBusMeasurement(pTableCurrentSensor);
1214 }
1215 extern STD_RETURN_TYPE_e TEST_MRC_CalculateCellVoltageMinMaxAverage(
1216  DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages,
1217  DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues) {
1218  return MRC_CalculateCellVoltageMinMaxAverage(pValidatedVoltages, pMinMaxAverageValues);
1219 }
1220 extern STD_RETURN_TYPE_e TEST_MRC_CalculateCellTemperatureMinMaxAverage(
1221  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures,
1222  DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues) {
1223  return MRC_CalculateCellTemperatureMinMaxAverage(pValidatedTemperatures, pMinMaxAverageValues);
1224 }
1225 extern STD_RETURN_TYPE_e TEST_MRC_ValidateCellVoltage(
1226  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageBase,
1227  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageRedundancy0,
1228  DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages) {
1229  return MRC_ValidateCellVoltage(pCellvoltageBase, pCellvoltageRedundancy0, pValidatedVoltages);
1230 }
1231 extern STD_RETURN_TYPE_e TEST_MRC_UpdateCellVoltageValidation(
1232  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltage,
1233  DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages) {
1234  return MRC_UpdateCellVoltageValidation(pCellvoltage, pValidatedVoltages);
1235 }
1236 extern STD_RETURN_TYPE_e TEST_MRC_ValidateCellTemperature(
1237  DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureBase,
1238  DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureRedundancy0,
1239  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures) {
1240  return MRC_ValidateCellTemperature(pCelltemperatureBase, pCelltemperatureRedundancy0, pValidatedTemperatures);
1241 }
1242 extern STD_RETURN_TYPE_e TEST_MRC_UpdateCellTemperatureValidation(
1243  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperature,
1244  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperature) {
1245  return MRC_UpdateCellTemperatureValidation(pCellTemperature, pValidatedTemperature);
1246 }
1247 #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:1297
uint8_t BMS_GetNumberOfConnectedStrings(void)
Returns number of connected strings.
Definition: bms.c:1306
bool BMS_IsStringClosed(uint8_t stringNumber)
Returns string state (closed or open)
Definition: bms.c:1288
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:102
@ 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:248
@ DIAG_STRING
Definition: diag_cfg.h:249
@ DIAG_EVENT_NOT_OK
Definition: diag_cfg.h:236
@ DIAG_EVENT_OK
Definition: diag_cfg.h:235
@ 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:239
#define FAS_TRAP
Define that evaluates to essential boolean false thus tripping an assert.
Definition: fassert.h:110
math library for often used math functions
#define UNIT_CONVERSION_FACTOR_1000_INTEGER
Definition: foxmath.h:74
@ STD_NOT_OK
Definition: fstd_types.h:82
@ STD_OK
Definition: fstd_types.h:81
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:75
enum STD_RETURN_TYPE STD_RETURN_TYPE_e
Declaration of the OS wrapper interface.
uint32_t OS_GetTickCount(void)
Returns OS based system tick value.
Definition: os_freertos.c:129
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
STD_RETURN_TYPE_e PL_CheckStringVoltage(int32_t voltageAfe_mV, int32_t voltageCurrentSensor_mV)
Pack voltage plausibility check between LTC and current sensor values.
Definition: plausibility.c:73
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:717
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:576
STD_RETURN_TYPE_e MRC_Initialize(void)
Function to initalize redundancy module.
Definition: redundancy.c:1092
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:683
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:899
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:978
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:399
static void MRC_ValidateCurrentMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor)
Function to validate results of current measurement.
Definition: redundancy.c:525
static bool MRC_MeasurementUpdatedAtLeastOnce(uint32_t timestamp, uint32_t previousTimestamp)
Check timestamp if measurement has been updated at least once.
Definition: redundancy.c:242
STD_RETURN_TYPE_e MRC_ValidateAfeMeasurement(void)
Function to validate the measurement between redundant measurement values for cell voltage and cell t...
Definition: redundancy.c:1117
STD_RETURN_TYPE_e MRC_ValidatePackMeasurement(void)
Function to validate the measurements of pack values (string values, pack values)
Definition: redundancy.c:1158
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:778
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:1075
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:995
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:836
static void MRC_ValidateBatteryVoltageMeasurement(void)
Function to validate HV battery voltage measurement.
Definition: redundancy.c:645
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:271
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:253
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_CURRENT_MEASUREMENT_PERIOD_TIMEOUT_ms
Definition: redundancy.h:73
#define MRC_CURRENT_SENSOR_MEASUREMENT_TIMEOUT_ms
Definition: redundancy.h:100
#define MRC_AFE_MEASUREMENT_PERIOD_TIMEOUT_ms
Definition: redundancy.h:87
DATA_BLOCK_ID_e uniqueId
Definition: database_cfg.h:111
uint32_t timestamp
Definition: database_cfg.h:112
int16_t cellTemperature_ddegC[BS_NR_OF_STRINGS][BS_NR_OF_TEMP_SENSORS_PER_STRING]
Definition: database_cfg.h:139
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:137
uint16_t invalidCellTemperature[BS_NR_OF_STRINGS][BS_NR_OF_MODULES]
Definition: database_cfg.h:141
uint16_t nrValidTemperatures[BS_NR_OF_STRINGS]
Definition: database_cfg.h:142
uint16_t nrValidCellVoltages[BS_NR_OF_STRINGS]
Definition: database_cfg.h:127
int16_t cellVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_BAT_CELLS]
Definition: database_cfg.h:124
uint64_t invalidCellVoltage[BS_NR_OF_STRINGS][BS_NR_OF_MODULES]
Definition: database_cfg.h:126
bool validModuleVoltage[BS_NR_OF_STRINGS][BS_NR_OF_MODULES]
Definition: database_cfg.h:129
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:121
int32_t packVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:123
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:202
uint8_t invalidCurrentMeasurement[BS_NR_OF_STRINGS]
Definition: database_cfg.h:204
uint32_t timestampCurrent[BS_NR_OF_STRINGS]
Definition: database_cfg.h:207
uint32_t timestampPower[BS_NR_OF_STRINGS]
Definition: database_cfg.h:214
int32_t power_W[BS_NR_OF_STRINGS]
Definition: database_cfg.h:210
uint8_t invalidHighVoltageMeasurement[BS_NR_OF_STRINGS][BS_NR_OF_VOLTAGES_FROM_CURRENT_SENSOR]
Definition: database_cfg.h:224
uint32_t previousTimestampPower[BS_NR_OF_STRINGS]
Definition: database_cfg.h:213
int32_t current_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:203
uint32_t timestampHighVoltage[BS_NR_OF_STRINGS][BS_NR_OF_VOLTAGES_FROM_CURRENT_SENSOR]
Definition: database_cfg.h:230
uint8_t invalidPowerMeasurement[BS_NR_OF_STRINGS]
Definition: database_cfg.h:211
uint32_t previousTimestampHighVoltage[BS_NR_OF_STRINGS][BS_NR_OF_VOLTAGES_FROM_CURRENT_SENSOR]
Definition: database_cfg.h:228
int32_t highVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_VOLTAGES_FROM_CURRENT_SENSOR]
Definition: database_cfg.h:225
uint32_t previousTimestampCurrent[BS_NR_OF_STRINGS]
Definition: database_cfg.h:206
uint16_t nrCellMinimumCellVoltage[BS_NR_OF_STRINGS]
Definition: database_cfg.h:158
uint16_t validMeasuredCellTemperatures[BS_NR_OF_STRINGS]
Definition: database_cfg.h:169
uint16_t nrSensorMinimumTemperature[BS_NR_OF_STRINGS]
Definition: database_cfg.h:165
int16_t maximumTemperature_ddegC[BS_NR_OF_STRINGS]
Definition: database_cfg.h:166
int16_t minimumTemperature_ddegC[BS_NR_OF_STRINGS]
Definition: database_cfg.h:163
float averageTemperature_ddegC[BS_NR_OF_STRINGS]
Definition: database_cfg.h:162
uint16_t nrModuleMaximumCellVoltage[BS_NR_OF_STRINGS]
Definition: database_cfg.h:159
uint16_t nrCellMaximumCellVoltage[BS_NR_OF_STRINGS]
Definition: database_cfg.h:160
uint16_t nrSensorMaximumTemperature[BS_NR_OF_STRINGS]
Definition: database_cfg.h:168
uint16_t validMeasuredCellVoltages[BS_NR_OF_STRINGS]
Definition: database_cfg.h:161
int16_t maximumCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:155
uint16_t nrModuleMinimumCellVoltage[BS_NR_OF_STRINGS]
Definition: database_cfg.h:157
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:150
uint16_t nrModuleMaximumTemperature[BS_NR_OF_STRINGS]
Definition: database_cfg.h:167
int16_t averageCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:152
uint16_t nrModuleMinimumTemperature[BS_NR_OF_STRINGS]
Definition: database_cfg.h:164
int16_t minimumCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:153
int32_t stringCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:191
int32_t stringPower_W[BS_NR_OF_STRINGS]
Definition: database_cfg.h:193
int32_t highVoltageBusVoltage_mV
Definition: database_cfg.h:185
uint8_t invalidStringCurrent[BS_NR_OF_STRINGS]
Definition: database_cfg.h:192
int32_t stringVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:189
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:178
uint8_t invalidStringPower[BS_NR_OF_STRINGS]
Definition: database_cfg.h:194
uint8_t invalidStringVoltage[BS_NR_OF_STRINGS]
Definition: database_cfg.h:190
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