foxBMS - Unit Tests  1.3.0
The foxBMS Unit Tests API Documentation
redundancy.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2022, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice, this
12  * list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  *
18  * 3. Neither the name of the copyright holder nor the names of its
19  * contributors may be used to endorse or promote products derived from
20  * this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * We kindly request you to use one or more of the following phrases to refer to
34  * foxBMS in your hardware, software, documentation or advertising materials:
35  *
36  * - ″This product uses parts of foxBMS®″
37  * - ″This product includes parts of foxBMS®″
38  * - ″This product is derived from foxBMS®″
39  *
40  */
41 
42 /**
43  * @file redundancy.c
44  * @author foxBMS Team
45  * @date 2020-07-31 (date of creation)
46  * @updated 2022-05-30 (date of last update)
47  * @version v1.3.0
48  * @ingroup APPLICATION
49  * @prefix MRC
50  *
51  * @brief Source file for handling redundancy between redundant cell voltage
52  * and cell temperature measurements
53  *
54  */
55 
56 /*========== Includes =======================================================*/
57 #include "redundancy.h"
58 
59 #include "bms.h"
60 #include "database.h"
61 #include "diag.h"
62 #include "foxmath.h"
63 #include "os.h"
64 #include "plausibility.h"
65 
66 /*========== Macros and Definitions =========================================*/
67 
68 /*========== Static Constant and Variable Definitions =======================*/
69 /** local copies of database tables */
70 /**@{*/
75 /**@}*/
76 
77 /** state of the redundancy module */
80  .lastRedundancy0CellvoltageTimestamp = 0u,
81  .lastBaseCelltemperatureTimestamp = 0u,
82  .lastRedundancy0CelltemperatureTimestamp = 0u,
83  .lastStringCurrentTimestamp = {0u},
84 };
85 
86 /*========== Extern Constant and Variable Definitions =======================*/
87 
88 /*========== Static Function Prototypes =====================================*/
89 /**
90  * @brief Check timestamp if measurement has been updated at least once.
91  * @param[in] timestamp timestamp of last measurement update
92  * @param[in] previousTimestamp timestamp of previously updated measurement
93  * @return true if measurement has been updated at least once, otherwise false
94  */
95 static bool MRC_MeasurementUpdatedAtLeastOnce(uint32_t timestamp, uint32_t previousTimestamp);
96 
97 /**
98  * @brief Check timestamp if measurement has been updated recently.
99  * @param[in] timestamp timestamp of last measurement update
100  * @param[in] previousTimestamp timestamp of previously updated measurement
101  * @param[in] timeInterval in systicks (type: uint32_t)
102  * @return true if measurement has recently been updated, otherwise false
103  */
105  uint32_t timestamp,
106  uint32_t previousTimestamp,
107  uint32_t timeInterval);
108 
109 /**
110  * @brief Function to validate results of cell voltage measurement
111  * @param[in] pCellVoltageBase base cell voltage measurement
112  * @param[in] pCellVoltageRedundancy0 redundant cell voltage measurement
113  * @return bool true, if measurement has been validated successfully and
114  * database entry needs to be updated, otherwise false.
115  */
117  DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageBase,
118  DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageRedundancy0);
119 
120 /**
121  * @brief Function to validate results of cell temperature measurement
122  * @param[in] pCellTemperatureBase base cell temperature measurement
123  * @param[in] pCellTemperatureRedundancy0 redundant cell temperature measurement
124  * @return bool true, if measurement has been validated successfully and
125  * database entry needs to be updated, otherwise false.
126  */
128  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureBase,
129  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureRedundancy0);
130 
131 /**
132  * @brief Function to validate results of current measurement
133  * @param[in] pTableCurrentSensor pointer to current measurements
134  */
135 static void MRC_ValidateCurrentMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor);
136 
137 /**
138  * @brief Function to validate results of string voltage measurement
139  * @param[in] pTableCurrentSensor pointer current sensor high voltage measurements
140  * @param[in] pTableCellVoltage pointer to cell voltage measurements
141  */
143  DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor,
144  DATA_BLOCK_CELL_VOLTAGE_s *pTableCellVoltage);
145 
146 /**
147  * @brief Function to validate HV battery voltage measurement
148  */
149 static void MRC_ValidateBatteryVoltageMeasurement(void);
150 
151 /**
152  * @brief Function to validate results of high voltage measurement and calculate
153  * battery voltage and high voltage bus voltage.
154  * @param[in] pTableCurrentSensor pointer current sensor high voltage measurements
155  */
157 
158 /**
159  * @brief Function to validate results of power measurement
160  * @param[in] pTableCurrentSensor pointer to power/current measurements
161  */
162 static void MRC_ValidatePowerMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor);
163 
164 /**
165  * @brief Function calculates minimum, maximum and average cell voltages.
166  * @param[in] pValidatedVoltages validated voltages from base and/or redundant measurements
167  * @param[out] pMinMaxAverageValues calculated cell voltage min/max/average values
168  * @return #STD_NOT_OK if all cell voltage are invalid and no minimum, maximum
169  * and average cell voltage values could be calculated, otherwise #STD_OK
170  */
172  const DATA_BLOCK_CELL_VOLTAGE_s *const pValidatedVoltages,
173  DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues);
174 
175 /**
176  * @brief Function calculates minimum, maximum and average cell temperatures.
177  * @param[in] pValidatedTemperatures validated temperatures from base and/or redundant measurements
178  * @param[out] pMinMaxAverageValues calculated cell temperature min/max/average values
179  * @return #STD_NOT_OK if all cell temperatures are invalid and no minimum, maximum
180  * and average cell temperature values could be calculated, otherwise #STD_OK
181  */
183  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures,
184  DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues);
185 
186 /**
187  * @brief Function compares cell voltage measurements from base measurement with
188  * one redundant measurement and writes result in pValidatedVoltages.
189  * @param[in] pCellvoltageBase base cell voltage measurement
190  * @param[in] pCellvoltageRedundancy0 redundant cell voltage measurement
191  * @param[out] pValidatedVoltages validated voltages from redundant measurement values
192  * @return #STD_NOT_OK if not all cell voltages could be validated, otherwise
193  * #STD_OK
194  */
196  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageBase,
197  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageRedundancy0,
198  DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages);
199 
200 /**
201  * @brief Function updates validated cell voltage measurement with data from a
202  * single measurement source. This can be the case if no redundancy is
203  * used at all or if one or more of the redundant measurements are not
204  * working properly.
205  * @param[in] pCellvoltage cell voltage measurement
206  * @param[out] pValidatedVoltages validated voltage values
207  * @return #STD_NOT_OK if not all cell voltages could be validated, otherwise
208  * #STD_OK
209  */
211  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltage,
212  DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages);
213 
214 /**
215  * @brief Function compares cell temperature measurements from base measurement
216  * with one redundant measurement and writes result in pValidatedTemperatures.
217  * @param[in] pCelltemperatureBase base cell temperature measurement
218  * @param[in] pCelltemperatureRedundancy0 redundant cell temperature measurement
219  * @param[out] pValidatedTemperatures validated temperatures from redundant measurement values
220  * @return #STD_NOT_OK if not all cell voltages could be validated, otherwise
221  * #STD_OK
222  */
224  DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureBase,
225  DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureRedundancy0,
226  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures);
227 
228 /**
229  * @brief Function updates validated cell temperature measurement with data from a
230  * single measurement source. This can be the case if no redundancy is
231  * used at all or if one or more of the redundant measurements are not
232  * working properly.
233  * @param[in] pCellTemperature cell temperature measurement
234  * @param[out] pValidatedTemperature validated temperature values
235  * @return #STD_NOT_OK if not all cell voltages could be validated, otherwise
236  * #STD_OK
237  */
239  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperature,
240  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperature);
241 
242 /*========== Static Function Implementations ================================*/
243 static bool MRC_MeasurementUpdatedAtLeastOnce(uint32_t timestamp, uint32_t previousTimestamp) {
244  bool retval = false;
245  if (!((timestamp == 0u) && (previousTimestamp == 0u))) {
246  /* Only possibility for timestamp AND previous timestamp to be 0 is, if
247  the measurement has never been updated. Thus, if this is not the case
248  the measurement must have been updated */
249  retval = true;
250  }
251  return retval;
252 }
253 
255  uint32_t timestamp,
256  uint32_t previousTimestamp,
257  uint32_t timeInterval) {
258  STD_RETURN_TYPE_e retval = STD_NOT_OK;
259  uint32_t currentTimestamp = OS_GetTickCount();
260 
261  /* Unsigned integer arithmetic also works correctly if currentTimestap is
262  larger than pHeader->timestamp (timer overflow), thus no need to use abs() */
263  if (((currentTimestamp - timestamp) <= timeInterval) &&
264  (MRC_MeasurementUpdatedAtLeastOnce(timestamp, previousTimestamp) == true)) {
265  /* Difference between current timestamp and last update timestamp is
266  smaller than passed time interval */
267  retval = STD_OK;
268  }
269  return retval;
270 }
271 
273  DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageBase,
274  DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageRedundancy0) {
275  FAS_ASSERT(pCellVoltageBase != NULL_PTR);
276  FAS_ASSERT(pCellVoltageRedundancy0 != NULL_PTR);
277 
278  bool updatedValidatedVoltageDatbaseEntry = false;
279 
280  bool baseCellvoltageUpdated = false;
281 
282  bool useCellvoltageRedundancy = false;
283  bool baseCellvoltageMeasurementTimeoutReached = true;
284  bool redundancy0CellvoltageMeasurementTimeoutReached = true;
285 
286  /* Following decision will be undertaken:
287  *
288  * - Use redundancy only if timestamp of redundant database entry != 0
289  * - Perform redundant check if both timestamps have been updated
290  * - Add timeout and trigger error if timestamps have not been updated in the last XXXXms
291  * - If timeout reached and only one of the two redundant measurements has been updated use this measurement value
292  * but throw an error that one measurement has not been updated recently.
293  */
294 
295  /* -------------- Check if cell voltage redundant measurement is used -- */
296  /* Use redundant cell voltage measurements if measurement values have been acquired once */
297  useCellvoltageRedundancy = DATA_DatabaseEntryUpdatedAtLeastOnce(pCellVoltageRedundancy0->header);
298 
299  /* ----------------- Check timestamp of base measurements--------------- */
301  baseCellvoltageMeasurementTimeoutReached = false;
303  } else {
304  baseCellvoltageMeasurementTimeoutReached = true;
305  /* Set error flag */
307  }
308 
309  /* Check if base measurement values have been updated since last MRC */
310  if (mrc_state.lastBaseCellvoltageTimestamp != pCellVoltageBase->header.timestamp) {
311  baseCellvoltageUpdated = true;
312  } else {
313  baseCellvoltageUpdated = false;
314  }
315 
316  /* ----------------- Check timestamp of redundant measurements --------- */
318  false) &&
319  (useCellvoltageRedundancy == true)) {
320  redundancy0CellvoltageMeasurementTimeoutReached = true;
321  /* Set error flag */
323  } else {
324  redundancy0CellvoltageMeasurementTimeoutReached = false;
326  }
327 
328  /* ----------------- Validate cell voltages ---------------------------- */
329  if (useCellvoltageRedundancy == true) {
330  bool redundany0CellvoltageUpdated = false;
331  /* Check if redundant measurement values have been updated since last MRC */
332  if (mrc_state.lastRedundancy0CellvoltageTimestamp != pCellVoltageRedundancy0->header.timestamp) {
333  redundany0CellvoltageUpdated = true;
334  } else {
335  redundany0CellvoltageUpdated = false;
336  }
337  /* Make sure cell voltage timestamps have been updated since last call */
338  if ((baseCellvoltageUpdated == true) && (redundany0CellvoltageUpdated == true)) {
339  /* Update timestamp */
342 
343  /* Validate cell voltages */
344  MRC_ValidateCellVoltage(pCellVoltageBase, pCellVoltageRedundancy0, &mrc_tableCellVoltages);
345  /* Set to true for following minimum, maximum and average calculation */
346  updatedValidatedVoltageDatbaseEntry = true;
347 
348  } else if ((baseCellvoltageUpdated == true) || (redundany0CellvoltageUpdated == true)) {
349  /* At least one measurement has been updated */
350  if (baseCellvoltageUpdated == true) {
351  /* Has redundant measurement timeout been reached? If yes, update. */
352  if (redundancy0CellvoltageMeasurementTimeoutReached == true) {
353  /* Copy cell voltage base measurement values into validated database struct */
355  /* Set to true for following minimum, maximum and average calculation */
356  updatedValidatedVoltageDatbaseEntry = true;
357  }
358  } else if (redundany0CellvoltageUpdated == true) {
359  /* Has base measurement timeout been reached? If yes, update. */
360  if (baseCellvoltageMeasurementTimeoutReached == true) {
361  /* Copy cell voltage base measurement values into validated database struct */
362  MRC_UpdateCellVoltageValidation(pCellVoltageRedundancy0, &mrc_tableCellVoltages);
363  /* Set to true for following minimum, maximum and average calculation */
364  updatedValidatedVoltageDatbaseEntry = true;
365  }
366  } else {
368  }
369  } else {
370  /* No cell voltage measurement has been updated -> do nothing */
371  }
372  } else {
373  if (baseCellvoltageUpdated == true) {
374  /* Only update database entries if new raw data has been acquired */
375  /* Update timestamp */
377 
378  /* Copy cell voltage base measurement values into validated database struct */
380 
381  /* Set to true for following minimum, maximum and average calculation */
382  updatedValidatedVoltageDatbaseEntry = true;
383  }
384  }
385 
386  if (updatedValidatedVoltageDatbaseEntry == true) {
387  /* Calculate min/max/average cell voltages */
389 
390  /* Individual cell voltages validated and min/max/average calculated -> check voltage spread */
392  /* Recalculate min/max/average cell voltages as at least one cell voltage has been detected as invalid */
394  }
395  }
396 
397  return updatedValidatedVoltageDatbaseEntry;
398 }
399 
401  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureBase,
402  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureRedundancy0) {
403  FAS_ASSERT(pCellTemperatureBase != NULL_PTR);
404  FAS_ASSERT(pCellTemperatureRedundancy0 != NULL_PTR);
405 
406  bool baseCelltemperatureUpdated = false;
407  bool useCelltemperatureRedundancy = false;
408  bool updatedValidatedTemperatureDatbaseEntry = false;
409 
410  bool baseCellTemperatureMeasurementTimeoutReached = true;
411  bool redundancy0CellTemperatureMeasurementTimeoutReached = true;
412 
413  /* Following decision will be undertaken:
414  *
415  * - Use redundancy only if timestamp of redundant database entry != 0
416  * - Perform redundant check if both timestamps have been updated
417  * - Add timeout and trigger error if timestamps have not been updated in the last XXXXms
418  * - If timeout reached and only one of the two redundant measurements has been updated use this measurement value
419  * but throw an error that one measurement has not been updated recently.
420  */
421 
422  /* -------------- Check if cell cell temperature redundant measurement is used ---------- */
423  /* Use redundant cell voltage measurements if measurement values have been acquired once */
424  useCelltemperatureRedundancy = DATA_DatabaseEntryUpdatedAtLeastOnce(pCellTemperatureRedundancy0->header);
425 
426  /* ----------------- Check timestamp of base measurements--------------- */
428  baseCellTemperatureMeasurementTimeoutReached = false;
430  } else {
431  baseCellTemperatureMeasurementTimeoutReached = true;
432  /* Set error flag */
434  }
435  /* Check if base measurement values have been updated since last MRC */
436  if (mrc_state.lastBaseCelltemperatureTimestamp != pCellTemperatureBase->header.timestamp) {
437  baseCelltemperatureUpdated = true;
438  } else {
439  baseCelltemperatureUpdated = false;
440  }
441 
442  /* ----------------- Check timestamp of redundant measurements --------- */
444  false) &&
445  (useCelltemperatureRedundancy == true)) {
446  redundancy0CellTemperatureMeasurementTimeoutReached = true;
447  /* Set error flag */
449  } else {
450  redundancy0CellTemperatureMeasurementTimeoutReached = false;
452  }
453 
454  /* ----------------- Validate cell temperatures ------------------------ */
455  if (useCelltemperatureRedundancy == true) {
456  bool redundancy0CelltemperatureUpdated = false;
457  /* Check if redundant measurement values have been updated since last MRC */
458  if (mrc_state.lastRedundancy0CelltemperatureTimestamp != pCellTemperatureRedundancy0->header.timestamp) {
459  redundancy0CelltemperatureUpdated = true;
460  } else {
461  redundancy0CelltemperatureUpdated = false;
462  }
463  /* Make sure cell voltage timestamps have been updated since last call */
464  if ((baseCelltemperatureUpdated == true) && (redundancy0CelltemperatureUpdated == true)) {
465  /* Update timestamp */
467  mrc_state.lastRedundancy0CelltemperatureTimestamp = pCellTemperatureRedundancy0->header.timestamp;
468 
469  /* Validate cell temperatures */
470  MRC_ValidateCellTemperature(pCellTemperatureBase, pCellTemperatureRedundancy0, &mrc_tableCellTemperatures);
471  /* Set to true for following minimum, maximum and average calculation */
472  updatedValidatedTemperatureDatbaseEntry = true;
473 
474  } else if ((baseCelltemperatureUpdated == true) || (redundancy0CelltemperatureUpdated == true)) {
475  /* At least one measurement has been updated */
476  if (baseCelltemperatureUpdated == true) {
477  /* Has redundant measurement timeout been reached? If yes, update. */
478  if (redundancy0CellTemperatureMeasurementTimeoutReached == true) {
479  /* Copy cell temperature base measurement values into validated database struct */
481  /* Set to true for following minimum, maximum and average calculation */
482  updatedValidatedTemperatureDatbaseEntry = true;
483  }
484  } else if (redundancy0CelltemperatureUpdated == true) {
485  /* Has base measurement timeout been reached? If yes, update. */
486  if (baseCellTemperatureMeasurementTimeoutReached == true) {
487  /* Copy cell temperature redundant measurement values into validated database struct */
488  MRC_UpdateCellTemperatureValidation(pCellTemperatureRedundancy0, &mrc_tableCellTemperatures);
489  /* Set to true for following minimum, maximum and average calculation */
490  updatedValidatedTemperatureDatbaseEntry = true;
491  }
492  } else {
494  }
495  } else {
496  /* No cell temperature measurement has been updated -> do nothing */
497  }
498  } else { /* useCelltemperatureRedundancy == true */
499  if (baseCelltemperatureUpdated == true) {
500  /* Only update database entries if new raw data has been acquired */
501  /* Update timestamp */
503 
504  /* Copy cell temperature base measurement values into validated database struct */
506 
507  /* Set to true for following minimum, maximum and average calculation */
508  updatedValidatedTemperatureDatbaseEntry = true;
509  }
510  }
511 
512  if (updatedValidatedTemperatureDatbaseEntry == true) {
513  /* Calculate min/max/average cell temperatures */
515 
516  /* Individual cell temperatures validated and min/max/average calculated -> check temperature spread */
518  /* Recalculate min/max/average temperatures as at least one temperature has been detected as invalid */
520  }
521  }
522 
523  return updatedValidatedTemperatureDatbaseEntry;
524 }
525 
527  FAS_ASSERT(pTableCurrentSensor != NULL_PTR);
528  int32_t packCurrent_mA = 0;
529 
530  /* Validate pack current. Will be invalidated if not all current measurement values are valid */
532 
533  /* Iterate over all strings to calculate pack current */
534  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
535  /* Check timestamp of measurement */
537  pTableCurrentSensor->timestampCurrent[s],
538  pTableCurrentSensor->previousTimestampCurrent[s],
541 
542  if (noTimeout == STD_OK) {
543  /* Check if current entry has been updated since last call */
544  if (mrc_state.lastStringCurrentTimestamp[s] != pTableCurrentSensor->timestampCurrent[s]) {
545  mrc_state.lastStringCurrentTimestamp[s] = pTableCurrentSensor->timestampCurrent[s];
546  mrc_tablePackValues.stringCurrent_mA[s] = pTableCurrentSensor->current_mA[s];
547  if (pTableCurrentSensor->invalidCurrentMeasurement[s] == 0u) {
548  /* String current measurement valid -> set valid flag */
551  } else {
552  /* String current measurement invalid -> set invalid flag */
555  }
556  } else {
557  /* Nothing to do. Measurement has not been updated but still within timeout */
558  }
559  } else {
560  /* Measurement timeout reached -> set string current invalid */
562  }
563 
565  packCurrent_mA += mrc_tablePackValues.stringCurrent_mA[s];
566  } else {
567  /* One string current is invalid -> pack current cannot be correct.
568  * Set pack current invalid */
570  }
571  }
572  mrc_tablePackValues.packCurrent_mA = packCurrent_mA;
573 }
574 
576  DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor,
577  DATA_BLOCK_CELL_VOLTAGE_s *pTableCellVoltage) {
578  /* Pointer validity check */
579  FAS_ASSERT(pTableCurrentSensor != NULL_PTR);
580  FAS_ASSERT(pTableCellVoltage != NULL_PTR);
581 
582  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
583  /* Check timeout of current sensor measurement */
585  pTableCurrentSensor->timestampHighVoltage[s][0u],
586  pTableCurrentSensor->previousTimestampHighVoltage[s][0u],
589 
590  /* Perform plausibility check if AFE and new current sensor measurement is valid */
591  if ((updatedMeasurement == STD_OK) && (pTableCurrentSensor->invalidHighVoltageMeasurement[s][0u] == 0u) &&
592  (pTableCellVoltage->nrValidCellVoltages[s] == BS_NR_OF_CELL_BLOCKS_PER_STRING)) {
593  STD_RETURN_TYPE_e voltagePlausible =
594  PL_CheckStringVoltage(pTableCellVoltage->packVoltage_mV[s], pTableCurrentSensor->highVoltage_mV[s][0u]);
596 
597  /* Use current sensor measurement */ /* TODO: use really current sensor? Average of both? AFE measurement? */
598  mrc_tablePackValues.stringVoltage_mV[s] = pTableCurrentSensor->highVoltage_mV[s][0u];
599 
600  if (voltagePlausible == STD_OK) {
602  } else {
604  }
605  } else {
606  /* Plausibility check cannot be performed if we do not have valid
607  * values from AFE and current sensor measurement */
609 
610  if ((updatedMeasurement == STD_OK) && (pTableCurrentSensor->invalidHighVoltageMeasurement[s][0u] == 0u)) {
611  /* Current sensor measurement valid -> use this measurement */
612  mrc_tablePackValues.stringVoltage_mV[s] = pTableCurrentSensor->highVoltage_mV[s][0u];
614  } else if (pTableCellVoltage->nrValidCellVoltages[s] == BS_NR_OF_CELL_BLOCKS_PER_STRING) {
615  /* AFE measurement valid -> use this measurement */
616  mrc_tablePackValues.stringVoltage_mV[s] = pTableCellVoltage->packVoltage_mV[s];
618  } else {
619  /* AFE and current sensor measurement invalid -> try to construct
620  * a valid from the number of valid cell voltages and substitute
621  * invalid cell voltages with the average cell voltage. */
622  uint16_t numberInvalidCellVoltages =
623  (BS_NR_OF_CELL_BLOCKS_PER_STRING - pTableCellVoltage->nrValidCellVoltages[s]);
624 
626  pTableCellVoltage->packVoltage_mV[s] +
627  (mrc_tableMinimumMaximumValues.averageCellVoltage_mV[s] * (int16_t)numberInvalidCellVoltages);
628 
629  /* Only use this as valid value if not more than five cell voltages are invalid */
630  if (numberInvalidCellVoltages > MRC_ALLOWED_NUMBER_OF_INVALID_CELL_VOLTAGES) {
632  } else {
634  }
635  }
636  }
637  }
638 }
639 
641  int64_t sumOfStringValues_mV = 0;
642  int8_t numberOfValidStringVoltages = 0;
643  uint8_t numberOfConnectedStrings = BMS_GetNumberOfConnectedStrings();
644 
645  if (0u != numberOfConnectedStrings) {
646  /* Iterate over all strings to see which strings are connected */
647  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
648  bool isStringConnected = BMS_IsStringClosed(s);
649  if ((mrc_tablePackValues.invalidStringVoltage[s] == 0u) && (isStringConnected == true)) {
650  /* AXIVION Disable Style MisraC2012Directive-4.1: Values start with 0, iteration is less than UINT8_MAX; overflow impossible */
651  sumOfStringValues_mV += mrc_tablePackValues.stringVoltage_mV[s];
652  numberOfValidStringVoltages++;
653  /* AXIVION Enable Style MisraC2012Directive-4.1: */
654  }
655  }
656  } else {
657  /* Take average of all strings if no strings are connected */
658  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
660  /* AXIVION Disable Style MisraC2012Directive-4.1: Values start with 0, iteration is less than UINT8_MAX; overflow impossible */
661  sumOfStringValues_mV += mrc_tablePackValues.stringVoltage_mV[s];
662  numberOfValidStringVoltages++;
663  /* AXIVION Enable Style MisraC2012Directive-4.1: */
664  }
665  }
666  }
667 
668  /* Only calculate average if at least one string voltage is valid */
669  if (0 != numberOfValidStringVoltages) {
670  /* AXIVION Disable Style MisraC2012Directive-4.1: truncation impossible; we sum INT32 values x times and divide by x, resulting in INT32 */
671  mrc_tablePackValues.batteryVoltage_mV = (int32_t)(sumOfStringValues_mV / numberOfValidStringVoltages);
672  /* AXIVION Enable Style MisraC2012Directive-4.1: */
673  } else {
675  }
676 }
677 
679  FAS_ASSERT(pTableCurrentSensor != NULL_PTR);
680 
681  int32_t sum_mV = 0;
682  uint8_t validVoltages = 0u;
683  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
684  /* Check timeout of current sensor measurement */
686  pTableCurrentSensor->timestampHighVoltage[s][2u],
687  pTableCurrentSensor->previousTimestampHighVoltage[s][2u],
690 
691  const bool stringClosed = BMS_IsStringClosed(s);
692  const bool stringPrecharging = BMS_IsStringPrecharging(s);
693  if (((stringPrecharging == true) || (stringClosed == true)) && (updatedMeasurement == STD_OK)) {
694  /* Only voltages of connected strings can be used */
695  if (pTableCurrentSensor->invalidHighVoltageMeasurement[s][2] == 0u) {
696  /* Measured high voltage is valid */
697  validVoltages++;
698  sum_mV += pTableCurrentSensor->highVoltage_mV[s][2];
699  }
700  }
701  }
702 
703  if (validVoltages > 0u) {
704  mrc_tablePackValues.highVoltageBusVoltage_mV = (sum_mV / (int32_t)validVoltages);
706  } else {
707  /* TODO: do we want to write special data if no valid values can be read? */
709  }
710 }
711 
713  FAS_ASSERT(pTableCurrentSensor != NULL_PTR);
714  bool calculatePower = false;
715  int32_t packPower_W = 0;
716 
717  /* Validate pack power. Will be invalidated if not all power measurement values are valid */
719 
720  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
721  /* Check timeout of current sensor measurement */
723  pTableCurrentSensor->timestampPower[s],
724  pTableCurrentSensor->previousTimestampPower[s],
727 
728  if (noTimeout == STD_OK) {
729  /* Check if current sensor measurement has been updated */
730  if (pTableCurrentSensor->timestampPower[s] != mrc_state.lastStringPowerTimestamp[s]) {
731  mrc_state.lastStringPowerTimestamp[s] = pTableCurrentSensor->timestampPower[s];
732  /* Check if measurement is valid */
733  if (pTableCurrentSensor->invalidPowerMeasurement[s] == 0u) {
734  mrc_tablePackValues.stringPower_W[s] = pTableCurrentSensor->power_W[s];
736  } else {
737  /* Measurement has been updated but value is invalid -> calculate from current and string voltage */
738  calculatePower = true;
739  /* TODO: do we want to calculate values by hand if we are within time limit but value is invalid? */
740  }
741  } else {
742  /* Nothing to do. Measurement has not been updated but still within timeout */
743  }
744  } else {
745  /* Timeout reached. Set invalid flag */
746  calculatePower = true;
748  }
749  if ((calculatePower == true) && (mrc_tablePackValues.invalidStringCurrent[s] == 0u) &&
751  /* Power measurement is invalid, but current and string voltage measurement are valid */
752  int64_t stringPower_W =
754  (UNIT_CONVERSION_FACTOR_1000_INTEGER * /* convert: mV -> V */
755  UNIT_CONVERSION_FACTOR_1000_INTEGER)); /* convert: mA -> A */
756  mrc_tablePackValues.stringPower_W[s] = (int32_t)stringPower_W;
758  }
760  packPower_W += mrc_tablePackValues.stringPower_W[s];
762  } else {
763  /* One string power is invalid -> pack power cannot be correct.
764  * Set pack power invalid */
767  }
768  }
769  mrc_tablePackValues.packPower_W = packPower_W;
770 }
771 
773  const DATA_BLOCK_CELL_VOLTAGE_s *const pValidatedVoltages,
774  DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues) {
775  /* Pointer validity check */
776  FAS_ASSERT(pValidatedVoltages != NULL_PTR);
777  FAS_ASSERT(pMinMaxAverageValues != NULL_PTR);
778 
779  STD_RETURN_TYPE_e retval = STD_OK;
780 
781  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
782  uint16_t nrValidCellvoltages = 0u;
783  int16_t min = INT16_MAX;
784  int16_t max = INT16_MIN;
785  int32_t sum = 0;
786  uint16_t moduleNumberMinimum = 0u;
787  uint16_t cellNumberMinimum = 0u;
788  uint16_t moduleNumberMaximum = 0u;
789  uint16_t cellNumberMaximum = 0u;
790  /* Iterate over all cells in each string */
791  for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) {
792  for (uint8_t c = 0u; c < BS_NR_OF_CELL_BLOCKS_PER_MODULE; c++) {
793  if ((pValidatedVoltages->invalidCellVoltage[s][m] & (0x01u << c)) == 0u) {
794  /* Cell voltage is valid -> use this voltage for subsequent calculations */
795  nrValidCellvoltages++;
796  sum += pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c];
797 
798  if (pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c] < min) {
799  min = pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c];
800  moduleNumberMinimum = m;
801  cellNumberMinimum = c;
802  }
803  if (pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c] > max) {
804  max = pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c];
805  moduleNumberMaximum = m;
806  cellNumberMaximum = c;
807  }
808  }
809  }
810  }
811  pMinMaxAverageValues->minimumCellVoltage_mV[s] = min;
812  pMinMaxAverageValues->nrCellMinimumCellVoltage[s] = cellNumberMinimum;
813  pMinMaxAverageValues->nrModuleMinimumCellVoltage[s] = moduleNumberMinimum;
814  pMinMaxAverageValues->maximumCellVoltage_mV[s] = max;
815  pMinMaxAverageValues->nrCellMaximumCellVoltage[s] = cellNumberMaximum;
816  pMinMaxAverageValues->nrModuleMaximumCellVoltage[s] = moduleNumberMaximum;
817  pMinMaxAverageValues->validMeasuredCellVoltages[s] = nrValidCellvoltages;
818 
819  /* Prevent division by 0, if all cell voltages are invalid */
820  if (nrValidCellvoltages > 0u) {
821  pMinMaxAverageValues->averageCellVoltage_mV[s] = (int16_t)(sum / (int32_t)nrValidCellvoltages);
822  } else {
823  pMinMaxAverageValues->averageCellVoltage_mV[s] = 0;
824  retval = STD_NOT_OK;
825  }
826  }
827  return retval;
828 }
829 
831  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures,
832  DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues) {
833  /* Pointer validity check */
834  FAS_ASSERT(pValidatedTemperatures != NULL_PTR);
835  FAS_ASSERT(pMinMaxAverageValues != NULL_PTR);
836 
837  STD_RETURN_TYPE_e retval = STD_OK;
838 
839  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
840  uint16_t moduleNumberMinimum = 0u;
841  uint16_t sensorNumberMinimum = 0u;
842  uint16_t moduleNumberMaximum = 0u;
843  uint16_t sensorNumberMaximum = 0u;
844  uint16_t nrValidCelltemperatures = 0u;
845  int16_t min = INT16_MAX;
846  int16_t max = INT16_MIN;
847  float sum_ddegC = 0.0f;
848 
849  for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) {
850  for (uint8_t c = 0u; c < BS_NR_OF_TEMP_SENSORS_PER_MODULE; c++) {
851  if ((pValidatedTemperatures->invalidCellTemperature[s][m] & (0x01u << c)) == 0u) {
852  /* Cell temperature is valid -> use this voltage for subsequent calculations */
853  nrValidCelltemperatures++;
854  sum_ddegC += (float)pValidatedTemperatures
855  ->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c];
856 
857  if (pValidatedTemperatures->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] <
858  min) {
859  min = pValidatedTemperatures
861  moduleNumberMinimum = m;
862  sensorNumberMinimum = c;
863  }
864  if (pValidatedTemperatures->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] >
865  max) {
866  max = pValidatedTemperatures
868  moduleNumberMaximum = m;
869  sensorNumberMaximum = c;
870  }
871  }
872  }
873  }
874  pMinMaxAverageValues->minimumTemperature_ddegC[s] = min;
875  pMinMaxAverageValues->nrSensorMinimumTemperature[s] = sensorNumberMinimum;
876  pMinMaxAverageValues->nrModuleMinimumTemperature[s] = moduleNumberMinimum;
877  pMinMaxAverageValues->maximumTemperature_ddegC[s] = max;
878  pMinMaxAverageValues->nrSensorMaximumTemperature[s] = sensorNumberMaximum;
879  pMinMaxAverageValues->nrModuleMaximumTemperature[s] = moduleNumberMaximum;
880  pMinMaxAverageValues->validMeasuredCellTemperatures[s] = nrValidCelltemperatures;
881 
882  /* Prevent division by 0, if all cell voltages are invalid */
883  if (nrValidCelltemperatures > 0u) {
884  pMinMaxAverageValues->averageTemperature_ddegC[s] = (sum_ddegC / (float)nrValidCelltemperatures);
885  } else {
886  pMinMaxAverageValues->averageTemperature_ddegC[s] = 0.0f;
887  retval = STD_NOT_OK;
888  }
889  }
890  return retval;
891 }
892 
894  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageBase,
895  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageRedundancy0,
896  DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages) {
897  /* Pointer validity check */
898  FAS_ASSERT(pCellvoltageBase != NULL_PTR);
899  FAS_ASSERT(pCellvoltageRedundancy0 != NULL_PTR);
900  FAS_ASSERT(pValidatedVoltages != NULL_PTR);
901 
902  uint16_t numberValidMeasurements = 0u;
903  STD_RETURN_TYPE_e noPlausibilityIssueDetected = STD_OK; /* Flag if implausable value detected */
904  STD_RETURN_TYPE_e retval = STD_OK;
905 
906  /* Iterate over all cell measurements */
907  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
908  int32_t sum = 0;
909  for (uint8_t m = 0; m < BS_NR_OF_MODULES_PER_STRING; m++) {
910  for (uint8_t c = 0; c < BS_NR_OF_CELL_BLOCKS_PER_MODULE; c++) {
911  if (((pCellvoltageBase->invalidCellVoltage[s][m] & (1u << c)) == 0u) &&
912  ((pCellvoltageRedundancy0->invalidCellVoltage[s][m] & (1u << c)) == 0u)) {
913  /* Check if cell voltage of base AND redundant measurement is valid -> do plausibility check */
914  if (STD_OK ==
916  pCellvoltageBase->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c],
917  pCellvoltageRedundancy0->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c],
918  &pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c])) {
919  /* Clear valid flag */
920  pValidatedVoltages->invalidCellVoltage[s][m] = pValidatedVoltages->invalidCellVoltage[s][m] &
921  (~(1u << c));
922  numberValidMeasurements++;
923  sum += pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c];
924  } else {
925  /* Set invalid flag */
926  noPlausibilityIssueDetected = STD_NOT_OK;
927  pValidatedVoltages->invalidCellVoltage[s][m] |= (1u << c);
928  /* Set return value to #STD_NOT_OK as not all cell voltages have a valid measurement value */
929  retval = STD_NOT_OK;
930  }
931  } else if ((pCellvoltageBase->invalidCellVoltage[s][m] & (1u << c)) == 0u) {
932  /* Only base measurement value is valid -> use this voltage without further plausibility checks */
933  pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c] =
934  pCellvoltageBase->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c];
935  /* Reset valid flag */
936  pValidatedVoltages->invalidCellVoltage[s][m] = pValidatedVoltages->invalidCellVoltage[s][m] &
937  (~(1u << c));
938  numberValidMeasurements++;
939  sum += pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c];
940  } else if ((pCellvoltageRedundancy0->invalidCellVoltage[s][m] & (1u << c)) == 0u) {
941  /* Only redundant measurement value is valid -> use this voltage without further plausibility checks */
942  pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c] =
943  pCellvoltageRedundancy0->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c];
944  /* Reset valid flag */
945  pValidatedVoltages->invalidCellVoltage[s][m] = pValidatedVoltages->invalidCellVoltage[s][m] &
946  (~(1u << c));
947  numberValidMeasurements++;
948  sum += pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c];
949  } else {
950  /* Both, base and redundant measurement value are invalid */
951  /* Save average cell voltage value of base and redundant */
952  pValidatedVoltages->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c] =
953  (pCellvoltageBase->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c] +
954  pCellvoltageRedundancy0->cellVoltage_mV[s][(m * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c]) /
955  2u;
956  /* Set invalid flag */
957  pValidatedVoltages->invalidCellVoltage[s][m] |= (1u << c);
958  /* Set return value to #STD_NOT_OK as not all cell voltages have a valid measurement value */
959  retval = STD_NOT_OK;
960  }
961  }
962  }
963  pValidatedVoltages->nrValidCellVoltages[s] = numberValidMeasurements;
964  pValidatedVoltages->packVoltage_mV[s] = sum;
965  numberValidMeasurements = 0u; /* Reset counter for next string */
966 
967  (void)DIAG_CheckEvent(noPlausibilityIssueDetected, DIAG_ID_PLAUSIBILITY_CELL_VOLTAGE, DIAG_STRING, s);
968  noPlausibilityIssueDetected = STD_OK; /* Reset flag for next string */
969  }
970  return retval;
971 }
972 
974  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltage,
975  DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages) {
976  /* Pointer validity check */
977  FAS_ASSERT(pCellvoltage != NULL_PTR);
978  FAS_ASSERT(pValidatedVoltages != NULL_PTR);
979 
980  /* Save header struct to copy to correct database entry */
981  DATA_BLOCK_HEADER_s tmpHeader = pValidatedVoltages->header;
982  /* Copy whole database entry */
983  *pValidatedVoltages = *pCellvoltage;
984  /* Restore previous header */
985  pValidatedVoltages->header = tmpHeader;
986 
987  return STD_OK;
988 }
989 
991  DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureBase,
992  DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureRedundancy0,
993  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures) {
994  /* Pointer validity check */
995  FAS_ASSERT(pCelltemperatureBase != NULL_PTR);
996  FAS_ASSERT(pCelltemperatureRedundancy0 != NULL_PTR);
997  FAS_ASSERT(pValidatedTemperatures != NULL_PTR);
998 
999  uint16_t numberValidMeasurements = 0u;
1000  STD_RETURN_TYPE_e noPlausibilityIssueDetected = STD_OK; /* Flag if implausable value detected */
1001  STD_RETURN_TYPE_e retval = STD_OK;
1002 
1003  /* Iterate over all cell measurements */
1004  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
1005  for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) {
1006  for (uint8_t c = 0u; c < BS_NR_OF_TEMP_SENSORS_PER_MODULE; c++) {
1007  if (((pCelltemperatureBase->invalidCellTemperature[s][m] & (1u << c)) == 0u) &&
1008  ((pCelltemperatureRedundancy0->invalidCellTemperature[s][m] & (1u << c)) == 0u)) {
1009  /* Check if cell voltage of base AND redundant measurement is valid -> do plausibility check */
1010  if (STD_OK ==
1012  pCelltemperatureBase->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c],
1013  pCelltemperatureRedundancy0
1015  &pValidatedTemperatures
1017  /* Clear valid flag */
1018  pValidatedTemperatures->invalidCellTemperature[s][m] =
1019  pValidatedTemperatures->invalidCellTemperature[s][m] & (~(1u << c));
1020  numberValidMeasurements++;
1021  } else {
1022  /* Set invalid flag */
1023  noPlausibilityIssueDetected = STD_NOT_OK;
1024  pValidatedTemperatures->invalidCellTemperature[s][m] |= (1u << c);
1025  /* Set return value to #STD_NOT_OK as not all cell temperatures have a valid measurement value */
1026  retval = STD_NOT_OK;
1027  }
1028  } else if ((pCelltemperatureBase->invalidCellTemperature[s][m] & (1u << c)) == 0u) {
1029  /* Only base measurement value is valid -> use this temperature without further plausibility checks */
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  /* Reset valid flag */
1033  pValidatedTemperatures->invalidCellTemperature[s][m] =
1034  pValidatedTemperatures->invalidCellTemperature[s][m] & (~(1u << c));
1035  numberValidMeasurements++;
1036  } else if ((pCelltemperatureRedundancy0->invalidCellTemperature[s][m] & (1u << c)) == 0u) {
1037  /* Only redundant measurement value is valid -> use this temperature without further plausibility checks */
1038  pValidatedTemperatures->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] =
1039  pCelltemperatureRedundancy0
1040  ->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c];
1041  /* Reset valid flag */
1042  pValidatedTemperatures->invalidCellTemperature[s][m] =
1043  pValidatedTemperatures->invalidCellTemperature[s][m] & (~(1u << c));
1044  numberValidMeasurements++;
1045  } else {
1046  /* Both, base and redundant measurement value are invalid */
1047  /* Save average cell voltage value of base and redundant */
1048  pValidatedTemperatures->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] =
1049  (pCelltemperatureBase->cellTemperature_ddegC[s][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c] +
1050  pCelltemperatureRedundancy0
1052  2u;
1053  /* Set invalid flag */
1054  pValidatedTemperatures->invalidCellTemperature[s][m] |= (1u << c);
1055  /* Set return value to #STD_NOT_OK as not all cell temperatures have a valid measurement value */
1056  retval = STD_NOT_OK;
1057  }
1058  }
1059  }
1060  pValidatedTemperatures->nrValidTemperatures[s] = numberValidMeasurements;
1061  numberValidMeasurements = 0u; /* Reset counter for next string */
1062 
1063  (void)DIAG_CheckEvent(noPlausibilityIssueDetected, DIAG_ID_PLAUSIBILITY_CELL_TEMP, DIAG_STRING, s);
1064  noPlausibilityIssueDetected = STD_OK; /* Reset flag for next string */
1065  }
1066 
1067  return retval;
1068 }
1069 
1071  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperature,
1072  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperature) {
1073  /* Pointer validity check */
1074  FAS_ASSERT(pCellTemperature != NULL_PTR);
1075  FAS_ASSERT(pValidatedTemperature != NULL_PTR);
1076 
1077  /* Save header struct to copy to correct database entry */
1078  DATA_BLOCK_HEADER_s tmpHeader = pValidatedTemperature->header;
1079  /* Copy whole database entry */
1080  *pValidatedTemperature = *pCellTemperature;
1081  /* Restore previous header */
1082  pValidatedTemperature->header = tmpHeader;
1083  return STD_OK;
1084 }
1085 
1086 /*========== Extern Function Implementations ================================*/
1088  STD_RETURN_TYPE_e retval = STD_NOT_OK;
1089  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
1090  for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) {
1091  /* Invalidate cell voltage values */
1092  mrc_tableCellVoltages.invalidCellVoltage[s][m] = 0xFFFFFFFFFFFFFFFFULL;
1094  /* Invalidate cell temperature values */
1096  }
1097  /* Invalidate string values */
1101  }
1102  /* Invalidate pack values */
1103  mrc_tablePackValues.invalidPackCurrent = 0x01; /*!< bitmask if current is valid. 0->valid, 1->invalid */
1104  mrc_tablePackValues.invalidBatteryVoltage = 0x01; /*!< bitmask if voltage is valid. 0->valid, 1->invalid */
1105  mrc_tablePackValues.invalidHvBusVoltage = 0x01; /*!< bitmask if voltage is valid. 0->valid, 1->invalid */
1106  mrc_tablePackValues.invalidPackPower = 0x01; /*!< bitmask if power is valid. 0->valid, 1->invalid */
1107 
1109  return retval;
1110 }
1111 
1113  STD_RETURN_TYPE_e retval = STD_OK;
1114 
1115  /* Database entries are declared static, so that they are placed in the data segment and not on the stack */
1116  static DATA_BLOCK_CELL_VOLTAGE_s mrc_tableCellvoltageBase = {.header.uniqueId = DATA_BLOCK_ID_CELL_VOLTAGE_BASE};
1117  static DATA_BLOCK_CELL_VOLTAGE_s mrc_tableCellvoltageRedundancy0 = {
1119 
1120  static DATA_BLOCK_CELL_TEMPERATURE_s mrc_tableCelltemperatureBase = {
1122  static DATA_BLOCK_CELL_TEMPERATURE_s mrc_tableCelltemperatureRedundancy0 = {
1124 
1125  /* Get measurement values */
1127  &mrc_tableCellvoltageBase,
1128  &mrc_tableCellvoltageRedundancy0,
1129  &mrc_tableCelltemperatureBase,
1130  &mrc_tableCelltemperatureRedundancy0);
1131 
1132  /* Perform validation of cell voltage measurement */
1133  bool updateCellVoltages =
1134  MRC_ValidateCellVoltageMeasurement(&mrc_tableCellvoltageBase, &mrc_tableCellvoltageRedundancy0);
1135 
1136  /* Perform validation of cell temperature measurement */
1137  bool updateCellTemperatures =
1138  MRC_ValidateCellTemperatureMeasurement(&mrc_tableCelltemperatureBase, &mrc_tableCelltemperatureRedundancy0);
1139 
1140  /* Update database entries if necessary */
1141  if ((updateCellVoltages == true) && (updateCellTemperatures == true)) {
1143  } else if (updateCellVoltages == true) {
1145  } else if (updateCellTemperatures == true) {
1147  } else {
1148  retval = STD_NOT_OK;
1149  }
1150  return retval;
1151 }
1152 
1154  STD_RETURN_TYPE_e retval = STD_OK;
1156 
1157  DATA_READ_DATA(&tableCurrentSensor);
1158 
1159  MRC_ValidateCurrentMeasurement(&tableCurrentSensor);
1162  MRC_ValidateHighVoltageBusMeasurement(&tableCurrentSensor);
1163  MRC_ValidatePowerMeasurement(&tableCurrentSensor);
1164 
1166 
1167  return retval;
1168 }
1169 
1170 /*========== Externalized Static Function Implementations (Unit Test) =======*/
1171 #ifdef UNITY_UNIT_TEST
1172 extern bool TEST_MRC_MeasurementUpdatedAtLeastOnce(uint32_t timestamp, uint32_t previousTimestamp) {
1173  return MRC_MeasurementUpdatedAtLeastOnce(timestamp, previousTimestamp);
1174 }
1176  uint32_t timestamp,
1177  uint32_t previousTimestamp,
1178  uint32_t timeInterval) {
1179  return MRC_MeasurementUpdatedRecently(timestamp, previousTimestamp, timeInterval);
1180 }
1182  DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageBase,
1183  DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageRedundancy0) {
1184  return MRC_ValidateCellVoltageMeasurement(pCellVoltageBase, pCellVoltageRedundancy0);
1185 }
1187  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureBase,
1188  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureRedundancy0) {
1189  return MRC_ValidateCellTemperatureMeasurement(pCellTemperatureBase, pCellTemperatureRedundancy0);
1190 }
1191 
1193  MRC_ValidateCurrentMeasurement(pTableCurrentSensor);
1194 }
1195 
1197  MRC_ValidatePowerMeasurement(pTableCurrentSensor);
1198 }
1200  DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor,
1201  DATA_BLOCK_CELL_VOLTAGE_s *pTableCellVoltage) {
1202  MRC_ValidateStringVoltageMeasurement(pTableCurrentSensor, pTableCellVoltage);
1203 }
1206 }
1208  MRC_ValidateHighVoltageBusMeasurement(pTableCurrentSensor);
1209 }
1211  DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages,
1212  DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues) {
1213  return MRC_CalculateCellVoltageMinMaxAverage(pValidatedVoltages, pMinMaxAverageValues);
1214 }
1216  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures,
1217  DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues) {
1218  return MRC_CalculateCellTemperatureMinMaxAverage(pValidatedTemperatures, pMinMaxAverageValues);
1219 }
1221  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageBase,
1222  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageRedundancy0,
1223  DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages) {
1224  return MRC_ValidateCellVoltage(pCellvoltageBase, pCellvoltageRedundancy0, pValidatedVoltages);
1225 }
1227  DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltage,
1228  DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages) {
1229  return MRC_UpdateCellVoltageValidation(pCellvoltage, pValidatedVoltages);
1230 }
1232  DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureBase,
1233  DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureRedundancy0,
1234  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures) {
1235  return MRC_ValidateCellTemperature(pCelltemperatureBase, pCelltemperatureRedundancy0, pValidatedTemperatures);
1236 }
1238  DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperature,
1239  DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperature) {
1240  return MRC_UpdateCellTemperatureValidation(pCellTemperature, pValidatedTemperature);
1241 }
1242 #endif
#define BS_NR_OF_CELL_BLOCKS_PER_MODULE
number of cells per module
#define BS_NR_OF_STRINGS
Number of parallel strings in the battery pack.
#define BS_NR_OF_TEMP_SENSORS_PER_MODULE
number of temperature sensors per battery module
#define BS_NR_OF_CELL_BLOCKS_PER_STRING
#define BS_NR_OF_MODULES_PER_STRING
number of modules in a string
bool BMS_IsStringPrecharging(uint8_t stringNumber)
Returns if string is currently precharging or not.
Definition: bms.c:1311
uint8_t BMS_GetNumberOfConnectedStrings(void)
Returns number of connected strings.
Definition: bms.c:1320
bool BMS_IsStringClosed(uint8_t stringNumber)
Returns string state (closed or open)
Definition: bms.c:1302
bms driver header
Database module header.
#define DATA_READ_DATA(...)
Definition: database.h:83
#define DATA_WRITE_DATA(...)
Definition: database.h:93
@ DATA_BLOCK_ID_CELL_VOLTAGE_REDUNDANCY0
Definition: database_cfg.h:99
@ DATA_BLOCK_ID_MIN_MAX
Definition: database_cfg.h:78
@ DATA_BLOCK_ID_CELL_VOLTAGE
Definition: database_cfg.h:76
@ DATA_BLOCK_ID_CELL_TEMPERATURE_REDUNDANCY0
Definition: database_cfg.h:100
@ DATA_BLOCK_ID_CELL_TEMPERATURE_BASE
Definition: database_cfg.h:98
@ DATA_BLOCK_ID_CURRENT_SENSOR
Definition: database_cfg.h:79
@ DATA_BLOCK_ID_CELL_VOLTAGE_BASE
Definition: database_cfg.h:97
@ DATA_BLOCK_ID_PACK_VALUES
Definition: database_cfg.h:105
@ DATA_BLOCK_ID_CELL_TEMPERATURE
Definition: database_cfg.h:77
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:229
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:356
Diagnosis driver header.
@ DIAG_EVENT_NOT_OK
Definition: diag_cfg.h:239
@ DIAG_EVENT_OK
Definition: diag_cfg.h:238
@ DIAG_SYSTEM
Definition: diag_cfg.h:251
@ DIAG_STRING
Definition: diag_cfg.h:252
@ DIAG_ID_POWER_MEASUREMENT_ERROR
Definition: diag_cfg.h:226
@ DIAG_ID_CURRENT_MEASUREMENT_TIMEOUT
Definition: diag_cfg.h:221
@ DIAG_ID_BASE_CELL_TEMPERATURE_MESUREMENT_TIMEOUT
Definition: diag_cfg.h:219
@ DIAG_ID_PLAUSIBILITY_PACK_VOLTAGE
Definition: diag_cfg.h:211
@ DIAG_ID_REDUNDANCY0_CELL_TEMPERATURE_MESUREMENT_TIMEOUT
Definition: diag_cfg.h:220
@ DIAG_ID_PLAUSIBILITY_CELL_VOLTAGE
Definition: diag_cfg.h:170
@ DIAG_ID_PLAUSIBILITY_CELL_TEMP
Definition: diag_cfg.h:173
@ DIAG_ID_CURRENT_SENSOR_POWER_MEASUREMENT_TIMEOUT
Definition: diag_cfg.h:225
@ DIAG_ID_REDUNDANCY0_CELL_VOLTAGE_MESUREMENT_TIMEOUT
Definition: diag_cfg.h:218
@ DIAG_ID_CURRENT_SENSOR_V1_MEASUREMENT_TIMEOUT
Definition: diag_cfg.h:223
@ DIAG_ID_CURRENT_SENSOR_V3_MEASUREMENT_TIMEOUT
Definition: diag_cfg.h:224
@ DIAG_ID_BASE_CELL_VOLTAGE_MESUREMENT_TIMEOUT
Definition: diag_cfg.h:217
@ DIAG_ID_CURRENT_MEASUREMENT_ERROR
Definition: diag_cfg.h:222
#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:115
math library for often used math functions
#define UNIT_CONVERSION_FACTOR_1000_INTEGER
Definition: foxmath.h:75
STD_RETURN_TYPE_e
Definition: fstd_types.h:81
@ STD_NOT_OK
Definition: fstd_types.h:83
@ STD_OK
Definition: fstd_types.h:82
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:76
Declaration of the OS wrapper interface.
uint32_t OS_GetTickCount(void)
Returns OS based system tick value.
Definition: os_freertos.c:139
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:155
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:86
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:104
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:123
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:74
plausibility checks for cell voltage and cell temperatures
static DATA_BLOCK_CELL_TEMPERATURE_s mrc_tableCellTemperatures
Definition: redundancy.c:73
static DATA_BLOCK_CELL_VOLTAGE_s mrc_tableCellVoltages
Definition: redundancy.c:72
bool TEST_MRC_ValidateCellVoltageMeasurement(DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageBase, DATA_BLOCK_CELL_VOLTAGE_s *pCellVoltageRedundancy0)
Definition: redundancy.c:1181
static DATA_BLOCK_MIN_MAX_s mrc_tableMinimumMaximumValues
Definition: redundancy.c:71
static void MRC_ValidatePowerMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor)
Function to validate results of power measurement.
Definition: redundancy.c:712
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:575
STD_RETURN_TYPE_e TEST_MRC_CalculateCellTemperatureMinMaxAverage(DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures, DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues)
Definition: redundancy.c:1215
STD_RETURN_TYPE_e MRC_Initialize(void)
Function to initalize redundancy module.
Definition: redundancy.c:1087
bool TEST_MRC_ValidateCellTemperatureMeasurement(DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureBase, DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperatureRedundancy0)
Definition: redundancy.c:1186
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:678
STD_RETURN_TYPE_e TEST_MRC_CalculateCellVoltageMinMaxAverage(DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages, DATA_BLOCK_MIN_MAX_s *pMinMaxAverageValues)
Definition: redundancy.c:1210
void TEST_MRC_ValidateBatteryVoltageMeasurement(void)
Definition: redundancy.c:1204
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:893
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:973
static DATA_BLOCK_PACK_VALUES_s mrc_tablePackValues
Definition: redundancy.c:74
void TEST_MRC_ValidatePowerMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor)
Definition: redundancy.c:1196
STD_RETURN_TYPE_e TEST_MRC_UpdateCellTemperatureValidation(DATA_BLOCK_CELL_TEMPERATURE_s *pCellTemperature, DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperature)
Definition: redundancy.c:1237
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:400
bool TEST_MRC_MeasurementUpdatedAtLeastOnce(uint32_t timestamp, uint32_t previousTimestamp)
Definition: redundancy.c:1172
static void MRC_ValidateCurrentMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor)
Function to validate results of current measurement.
Definition: redundancy.c:526
void TEST_MRC_ValidateStringVoltageMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor, DATA_BLOCK_CELL_VOLTAGE_s *pTableCellVoltage)
Definition: redundancy.c:1199
static bool MRC_MeasurementUpdatedAtLeastOnce(uint32_t timestamp, uint32_t previousTimestamp)
Check timestamp if measurement has been updated at least once.
Definition: redundancy.c:243
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:1112
STD_RETURN_TYPE_e TEST_MRC_UpdateCellVoltageValidation(DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltage, DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages)
Definition: redundancy.c:1226
STD_RETURN_TYPE_e TEST_MRC_ValidateCellTemperature(DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureBase, DATA_BLOCK_CELL_TEMPERATURE_s *pCelltemperatureRedundancy0, DATA_BLOCK_CELL_TEMPERATURE_s *pValidatedTemperatures)
Definition: redundancy.c:1231
void TEST_MRC_ValidateCurrentMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor)
Definition: redundancy.c:1192
STD_RETURN_TYPE_e MRC_ValidatePackMeasurement(void)
Function to validate the measurements of pack values (string values, pack values)
Definition: redundancy.c:1153
STD_RETURN_TYPE_e TEST_MRC_ValidateCellVoltage(DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageBase, DATA_BLOCK_CELL_VOLTAGE_s *pCellvoltageRedundancy0, DATA_BLOCK_CELL_VOLTAGE_s *pValidatedVoltages)
Definition: redundancy.c:1220
STD_RETURN_TYPE_e TEST_MRC_MeasurementUpdatedRecently(uint32_t timestamp, uint32_t previousTimestamp, uint32_t timeInterval)
Definition: redundancy.c:1175
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:772
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:1070
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:990
static MRC_STATE_s mrc_state
Definition: redundancy.c:78
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:830
static void MRC_ValidateBatteryVoltageMeasurement(void)
Function to validate HV battery voltage measurement.
Definition: redundancy.c:640
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:272
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:254
void TEST_MRC_ValidateHighVoltageMeasurement(DATA_BLOCK_CURRENT_SENSOR_s *pTableCurrentSensor)
Definition: redundancy.c:1207
Header fileS for handling redundancy between redundant cell voltage and cell temperature measurements...
#define MRC_ALLOWED_NUMBER_OF_INVALID_CELL_VOLTAGES
Definition: redundancy.h:111
#define MRC_CURRENT_MEASUREMENT_PERIOD_TIMEOUT_ms
Definition: redundancy.h:74
#define MRC_CURRENT_SENSOR_MEASUREMENT_TIMEOUT_ms
Definition: redundancy.h:101
#define MRC_AFE_MEASUREMENT_PERIOD_TIMEOUT_ms
Definition: redundancy.h:88
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:146
int16_t cellTemperature_ddegC[BS_NR_OF_STRINGS][BS_NR_OF_TEMP_SENSORS_PER_STRING]
Definition: database_cfg.h:148
uint16_t nrValidTemperatures[BS_NR_OF_STRINGS]
Definition: database_cfg.h:151
uint16_t invalidCellTemperature[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]
Definition: database_cfg.h:150
int32_t packVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:131
bool validModuleVoltage[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]
Definition: database_cfg.h:138
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:129
uint64_t invalidCellVoltage[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]
Definition: database_cfg.h:135
uint16_t nrValidCellVoltages[BS_NR_OF_STRINGS]
Definition: database_cfg.h:136
int16_t cellVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_CELL_BLOCKS_PER_STRING]
Definition: database_cfg.h:132
uint32_t previousTimestampCurrent[BS_NR_OF_STRINGS]
Definition: database_cfg.h:215
uint32_t timestampCurrent[BS_NR_OF_STRINGS]
Definition: database_cfg.h:216
uint32_t previousTimestampHighVoltage[BS_NR_OF_STRINGS][BS_NR_OF_VOLTAGES_FROM_CURRENT_SENSOR]
Definition: database_cfg.h:237
int32_t current_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:212
uint32_t timestampHighVoltage[BS_NR_OF_STRINGS][BS_NR_OF_VOLTAGES_FROM_CURRENT_SENSOR]
Definition: database_cfg.h:239
uint32_t previousTimestampPower[BS_NR_OF_STRINGS]
Definition: database_cfg.h:222
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:211
uint32_t timestampPower[BS_NR_OF_STRINGS]
Definition: database_cfg.h:223
int32_t highVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_VOLTAGES_FROM_CURRENT_SENSOR]
Definition: database_cfg.h:234
uint8_t invalidCurrentMeasurement[BS_NR_OF_STRINGS]
Definition: database_cfg.h:213
uint8_t invalidHighVoltageMeasurement[BS_NR_OF_STRINGS][BS_NR_OF_VOLTAGES_FROM_CURRENT_SENSOR]
Definition: database_cfg.h:233
int32_t power_W[BS_NR_OF_STRINGS]
Definition: database_cfg.h:219
uint8_t invalidPowerMeasurement[BS_NR_OF_STRINGS]
Definition: database_cfg.h:220
DATA_BLOCK_ID_e uniqueId
Definition: database_cfg.h:119
int16_t minimumTemperature_ddegC[BS_NR_OF_STRINGS]
Definition: database_cfg.h:172
uint16_t nrSensorMinimumTemperature[BS_NR_OF_STRINGS]
Definition: database_cfg.h:174
uint16_t nrModuleMinimumTemperature[BS_NR_OF_STRINGS]
Definition: database_cfg.h:173
uint16_t nrModuleMaximumTemperature[BS_NR_OF_STRINGS]
Definition: database_cfg.h:176
int16_t maximumTemperature_ddegC[BS_NR_OF_STRINGS]
Definition: database_cfg.h:175
int16_t averageCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:161
uint16_t nrSensorMaximumTemperature[BS_NR_OF_STRINGS]
Definition: database_cfg.h:177
uint16_t validMeasuredCellVoltages[BS_NR_OF_STRINGS]
Definition: database_cfg.h:170
float averageTemperature_ddegC[BS_NR_OF_STRINGS]
Definition: database_cfg.h:171
uint16_t validMeasuredCellTemperatures[BS_NR_OF_STRINGS]
Definition: database_cfg.h:178
uint16_t nrCellMaximumCellVoltage[BS_NR_OF_STRINGS]
Definition: database_cfg.h:169
uint16_t nrCellMinimumCellVoltage[BS_NR_OF_STRINGS]
Definition: database_cfg.h:167
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:159
uint16_t nrModuleMinimumCellVoltage[BS_NR_OF_STRINGS]
Definition: database_cfg.h:166
uint16_t nrModuleMaximumCellVoltage[BS_NR_OF_STRINGS]
Definition: database_cfg.h:168
int16_t maximumCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:164
int16_t minimumCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:162
int32_t stringVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:198
int32_t stringPower_W[BS_NR_OF_STRINGS]
Definition: database_cfg.h:202
uint8_t invalidStringPower[BS_NR_OF_STRINGS]
Definition: database_cfg.h:203
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:187
int32_t stringCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:200
uint8_t invalidStringCurrent[BS_NR_OF_STRINGS]
Definition: database_cfg.h:201
uint8_t invalidStringVoltage[BS_NR_OF_STRINGS]
Definition: database_cfg.h:199
uint32_t lastBaseCellvoltageTimestamp
Definition: redundancy.h:118
uint32_t lastBaseCelltemperatureTimestamp
Definition: redundancy.h:120
uint32_t lastStringCurrentTimestamp[BS_NR_OF_STRINGS]
Definition: redundancy.h:122
uint32_t lastRedundancy0CelltemperatureTimestamp
Definition: redundancy.h:121
uint32_t lastStringPowerTimestamp[BS_NR_OF_STRINGS]
Definition: redundancy.h:123
uint32_t lastRedundancy0CellvoltageTimestamp
Definition: redundancy.h:119