foxBMS  1.6.0
The foxBMS Battery Management System API Documentation
bms.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice, this
12  * list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  *
18  * 3. Neither the name of the copyright holder nor the names of its
19  * contributors may be used to endorse or promote products derived from
20  * this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * We kindly request you to use one or more of the following phrases to refer to
34  * foxBMS in your hardware, software, documentation or advertising materials:
35  *
36  * - ″This product uses parts of foxBMS®″
37  * - ″This product includes parts of foxBMS®″
38  * - ″This product is derived from foxBMS®″
39  *
40  */
41 
42 /**
43  * @file bms.c
44  * @author foxBMS Team
45  * @date 2020-02-24 (date of creation)
46  * @updated 2023-10-12 (date of last update)
47  * @version v1.6.0
48  * @ingroup ENGINE
49  * @prefix BMS
50  *
51  * @brief bms driver implementation
52  */
53 
54 /*========== Includes =======================================================*/
55 #include "bms.h"
56 
57 #include "battery_cell_cfg.h"
58 
59 #include "afe.h"
60 #include "bal.h"
61 #include "database.h"
62 #include "diag.h"
63 #include "foxmath.h"
64 #include "imd.h"
65 #include "led.h"
66 #include "meas.h"
67 #include "os.h"
68 #include "soa.h"
69 
70 #include <stdbool.h>
71 #include <stdint.h>
72 
73 /*========== Macros and Definitions =========================================*/
74 /** default value for unset "active delay time" */
75 #define BMS_NO_ACTIVE_DELAY_TIME_ms (UINT32_MAX)
76 
77 /**
78  * Saves the last state and the last substate
79  */
80 #define BMS_SAVELASTSTATES() \
81  bms_state.laststate = bms_state.state; \
82  bms_state.lastsubstate = bms_state.substate
83 
84 /*========== Static Constant and Variable Definitions =======================*/
85 
86 /**
87  * contains the state of the bms state machine
88  */
90  .timer = 0,
91  .stateRequest = BMS_STATE_NO_REQUEST,
93  .substate = BMS_ENTRY,
94  .laststate = BMS_STATEMACH_UNINITIALIZED,
95  .lastsubstate = BMS_ENTRY,
96  .triggerentry = 0u,
97  .ErrRequestCounter = 0u,
98  .initFinished = STD_NOT_OK,
99  .counter = 0u,
100  .OscillationTimeout = 0u,
101  .prechargeTryCounter = 0u,
102  .powerPath = BMS_POWER_PATH_OPEN,
103  .closedStrings = {0u},
104  .closedPrechargeContactors = {0u},
105  .numberOfClosedStrings = 0u,
106  .deactivatedStrings = {0},
107  .firstClosedString = 0u,
108  .stringOpenTimeout = 0u,
109  .nextstringclosedtimer = 0u,
110  .stringCloseTimeout = 0u,
111  .nextstate = BMS_STATEMACH_STANDBY,
112  .restTimer_10ms = BS_RELAXATION_PERIOD_10ms,
113  .currentFlowState = BMS_RELAXATION,
114  .remainingDelay_ms = BMS_NO_ACTIVE_DELAY_TIME_ms,
115  .minimumActiveDelay_ms = BMS_NO_ACTIVE_DELAY_TIME_ms,
116  .transitionToErrorState = false,
117  .timeAboveContactorBreakCurrent_ms = 0u,
118  .stringToBeOpened = 0u,
119  .contactorToBeOpened = CONT_UNDEFINED,
120 };
121 
122 /** local copies of database tables */
123 /**@{*/
127 /**@}*/
128 
129 /*========== Extern Constant and Variable Definitions =======================*/
130 
131 /*========== Static Function Prototypes =====================================*/
132 
133 /**
134  * @brief checks the state requests that are made.
135  * @details This function checks the validity of the state requests. The
136  * results of the checked is returned immediately.
137  * @param[in] statereq state request to be checked
138  * @return result of the state request that was made
139  */
141 
142 /**
143  * @brief transfers the current state request to the state machine.
144  * @details This function takes the current state request from #bms_state
145  * transfers it to the state machine. It resets the value from
146  * #bms_state to #BMS_STATE_NO_REQUEST
147  * @return current state request
148  */
150 
151 /**
152  * @brief re-entrance check of SYS state machine trigger function
153  * @details This function is not re-entrant and should only be called time- or
154  * event-triggered. It increments the triggerentry counter from the
155  * state variable ltc_state. It should never be called by two
156  * different processes, so if it is the case, triggerentry should
157  * never be higher than 0 when this function is called.
158  * @return retval 0 if no further instance of the function is active, 0xff
159  * else
160  */
161 static uint8_t BMS_CheckReEntrance(void);
162 
163 /**
164  * @brief Checks the state requests made to the BMS state machine.
165  * @details Checks of the state request in the database and sets this value as
166  * return value.
167  * @return requested state
168  */
169 static uint8_t BMS_CheckCanRequests(void);
170 
171 /**
172  * @brief Checks all the error flags from diagnosis module with a severity of
173  * #DIAG_FATAL_ERROR
174  * @details Checks all the error flags from diagnosis module with a severity of
175  * #DIAG_FATAL_ERROR. Furthermore, sets parameter minimumActiveDelay_ms
176  * of bms_state variable.
177  * @return true if error flag is set, otherwise false
178  */
179 static bool BMS_IsAnyFatalErrorFlagSet(void);
180 
181 /**
182  * @brief Checks if any error flag is set and handles delay until contactors
183  * need to be opened.
184  * @details Checks all the diagnosis entries with severity of #DIAG_FATAL_ERROR
185  * and handles the configured delay until the contactors need to be
186  * opened. The shortest delay is used, if multiple errors are active at
187  * once.
188  * @return #STD_NOT_OK if error detected and delay time elapsed, otherwise #STD_OK
189  */
191 
192 /**
193  * @brief Checks if the contactor feedback for a specific contactor is valid
194  * need to be opened.
195  * @details Reads error flag database entry and checks if the feedback for this
196  * specific contactor is valid or not.
197  * @return true if no error detected feedback is valid, otherwise false
198  */
199 static bool BMS_IsContactorFeedbackValid(uint8_t stringNumber, CONT_TYPE_e contactorType);
200 
201 /** Get latest database entries for static module variables */
202 static void BMS_GetMeasurementValues(void);
203 
204 /**
205  * @brief Check for any open voltage sense wire
206  */
207 static void BMS_CheckOpenSenseWire(void);
208 
209 /**
210  * @brief Checks if the current limitations are violated
211  * @param[in] stringNumber string addressed
212  * @param[in] pPackValues pointer to pack values database entry
213  * @return #STD_OK if the current limitations are NOT violated, else
214  * #STD_NOT_OK (type: #STD_RETURN_TYPE_e)
215  */
216 static STD_RETURN_TYPE_e BMS_CheckPrecharge(uint8_t stringNumber, const DATA_BLOCK_PACK_VALUES_s *pPackValues);
217 
218 /**
219  * @brief Returns ID of string with highest total voltage
220  * @details This is used to close the first string when drive-off is requested.
221  * @param[in] precharge If #BMS_DO_NOT_TAKE_PRECHARGE_INTO_ACCCOUNT,
222  * precharge availability for string is ignored.
223  * if #BMS_TAKE_PRECHARGE_INTO_ACCCOUNT, only select
224  * string that has precharge available.
225  * @param[in] pPackValues pointer to pack values database entry
226  * @return index of string with highest voltage If no string is available,
227  * returns #BMS_NO_STRING_AVAILABLE.
228  */
229 static uint8_t BMS_GetHighestString(BMS_CONSIDER_PRECHARGE_e precharge, DATA_BLOCK_PACK_VALUES_s *pPackValues);
230 
231 /**
232  * @brief Returns ID of string with voltage closest to first closed string voltage
233  * @details This is used to close further strings in drive.
234  * @param[in] precharge If #BMS_DO_NOT_TAKE_PRECHARGE_INTO_ACCCOUNT,
235  * precharge availability for string is ignored.
236  * if #BMS_TAKE_PRECHARGE_INTO_ACCCOUNT, only select
237  * string that has precharge available.
238  * @param[in] pPackValues pointer to pack values database entry
239  * @return index of string with voltage closest to the first closed string voltage.
240  * If no string is available, returns #BMS_NO_STRING_AVAILABLE.
241  */
242 static uint8_t BMS_GetClosestString(BMS_CONSIDER_PRECHARGE_e precharge, DATA_BLOCK_PACK_VALUES_s *pPackValues);
243 
244 /**
245  * @brief Returns ID of string with lowest total voltage
246  * @details This is used to close the first string when charge-off is requested.
247  *
248  * @param[in] precharge If 0, precharge availability for string is ignored.
249  * If 1, only selects a string that has precharge
250  * available.
251  * @param[in] pPackValues pointer to pack values database entry
252  * @return index of string with lowest voltage. If no string is available,
253  * returns #BMS_NO_STRING_AVAILABLE.
254  */
255 static uint8_t BMS_GetLowestString(BMS_CONSIDER_PRECHARGE_e precharge, DATA_BLOCK_PACK_VALUES_s *pPackValues);
256 
257 /**
258  * @brief Returns voltage difference between first closed string and
259  * string ID
260  * @details This function is used to check voltage when trying to close further
261  * strings.
262  * @param[in] string ID of string that must be compared with first closed
263  * string
264  * @param[in] pPackValues pointer to pack values database entry
265  * @return voltage difference in mV, will return INT32_MAX if voltages are
266  * invalid and difference can not be calculated
267  */
268 static int32_t BMS_GetStringVoltageDifference(uint8_t string, const DATA_BLOCK_PACK_VALUES_s *pPackValues);
269 
270 /**
271  * @brief Returns the average current flowing through all strings.
272  * @details This function is used when closing strings.
273  * @param[in] pPackValues pointer to pack values database entry
274  * @return average current taking all strings into account in mA. INT32_MAX if there is no valid current measurement
275  */
276 static int32_t BMS_GetAverageStringCurrent(DATA_BLOCK_PACK_VALUES_s *pPackValues);
277 
278 /**
279  * @brief Updates battery system state variable depending on measured/recent
280  * current values
281  * @param[in] pPackValues recent measured values from current sensor
282  */
283 static void BMS_UpdateBatsysState(DATA_BLOCK_PACK_VALUES_s *pPackValues);
284 
285 /**
286  * @brief Get first string contactor that should be opened depending on the
287  * actual current flow direction
288  * @details Check the mounting direction of the contactors and open the
289  * contactor that is mounted in the preferred current flow direction.
290  * Open the plus contactor first if, there is no contactor in
291  * preferred direction to the curren flow to open available. This may
292  * be either because both contactors are installed in the same
293  * direction or because the contactors are bidirectional.
294  * @param stringNumber string that will be opened
295  * @param flowDirection current flow direction (charging or discharging)
296  * @return #CONT_TYPE_e contactor that should be opened
297  */
298 static CONT_TYPE_e BMS_GetFirstContactorToBeOpened(uint8_t stringNumber, BMS_CURRENT_FLOW_STATE_e flowDirection);
299 
300 /**
301  * @brief Get second string contactor that should be opened
302  * @details Mounting direction of the contactor does not need to be checked
303  * for the second contactor as the current has already been
304  * interrupted opening the first contactor.
305  * @param stringNumber string that will be opened
306  * @param firstOpenedContactorType type of first contactor that has been opened
307  * @return #CONT_TYPE_e contactor that should be opened
308  */
309 static CONT_TYPE_e BMS_GetSecondContactorToBeOpened(uint8_t stringNumber, CONT_TYPE_e firstOpenedContactorType);
310 
311 /*========== Static Function Implementations ================================*/
312 
314  if (statereq == BMS_STATE_ERROR_REQUEST) {
315  return BMS_OK;
316  }
317 
319  /* init only allowed from the uninitialized state */
320  if (statereq == BMS_STATE_INIT_REQUEST) {
322  return BMS_OK;
323  } else {
325  }
326  } else {
327  return BMS_ILLEGAL_REQUEST;
328  }
329  } else {
330  return BMS_REQUEST_PENDING;
331  }
332 }
333 
334 static uint8_t BMS_CheckReEntrance(void) {
335  uint8_t retval = 0;
337  if (!bms_state.triggerentry) {
339  } else {
340  retval = 0xFF; /* multiple calls of function */
341  }
343  return retval;
344 }
345 
348 
350  retval = bms_state.stateRequest;
353  return retval;
354 }
355 
356 static void BMS_GetMeasurementValues(void) {
358 }
359 
360 static uint8_t BMS_CheckCanRequests(void) {
361  uint8_t retVal = BMS_REQ_ID_NOREQ;
363 
364  DATA_READ_DATA(&request);
365 
366  if (request.stateRequestViaCan == BMS_REQ_ID_STANDBY) {
367  retVal = BMS_REQ_ID_STANDBY;
368  } else if (request.stateRequestViaCan == BMS_REQ_ID_NORMAL) {
369  retVal = BMS_REQ_ID_NORMAL;
370  } else if (request.stateRequestViaCan == BMS_REQ_ID_CHARGE) {
371  retVal = BMS_REQ_ID_CHARGE;
372  } else if (request.stateRequestViaCan == BMS_REQ_ID_NOREQ) {
373  retVal = BMS_REQ_ID_NOREQ;
374  } else {
375  /* invalid or no request, default to BMS_REQ_ID_NOREQ (already set) */
376  }
377 
378  return retVal;
379 }
380 
381 static void BMS_CheckOpenSenseWire(void) {
382  uint8_t openWireDetected = 0;
383 
384  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
385  /* Iterate over all modules */
386  for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) {
387  /* Iterate over all voltage sense wires: cells per module + 1 */
388  for (uint8_t wire = 0u; wire < (BS_NR_OF_CELL_BLOCKS_PER_MODULE + 1); wire++) {
389  /* open wire detected */
390  if (bms_tableOpenWire.openWire[s][(wire + (m * (BS_NR_OF_CELL_BLOCKS_PER_MODULE + 1))) == 1] > 0u) {
391  openWireDetected++;
392 
393  /* Add additional error handling here */
394  }
395  }
396  }
397  /* Set error if open wire detected */
398  if (openWireDetected == 0u) {
400  } else {
402  }
403  }
404 }
405 
406 static STD_RETURN_TYPE_e BMS_CheckPrecharge(uint8_t stringNumber, const DATA_BLOCK_PACK_VALUES_s *pPackValues) {
407  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
408  /* make sure that we do not access the arrays in the database
409  tables out of bounds */
410  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
411  FAS_ASSERT(pPackValues != NULL_PTR);
412 
413  /* Only check precharging if current value and voltages are valid */
414  if ((pPackValues->invalidStringCurrent[stringNumber] == 0u) &&
415  (pPackValues->invalidStringVoltage[stringNumber] == 0u) && (pPackValues->invalidHvBusVoltage == 0u)) {
416  /* Only current not current direction is checked */
417  const int32_t current_mA = MATH_AbsInt32_t(pPackValues->stringCurrent_mA[stringNumber]);
418  const int64_t cont_prechargeVoltDiff_mV = MATH_AbsInt64_t(
419  (int64_t)pPackValues->stringVoltage_mV[stringNumber] - (int64_t)pPackValues->highVoltageBusVoltage_mV);
420 
421  /* Check if precharging has been successful */
422  if ((cont_prechargeVoltDiff_mV < BMS_PRECHARGE_VOLTAGE_THRESHOLD_mV) &&
423  (current_mA < BMS_PRECHARGE_CURRENT_THRESHOLD_mA)) {
424  retVal = STD_OK;
427  } else {
428  if (cont_prechargeVoltDiff_mV >= BMS_PRECHARGE_VOLTAGE_THRESHOLD_mV) {
429  /* Voltage difference too large */
430  (void)DIAG_Handler(
433  }
434  if (current_mA >= BMS_PRECHARGE_CURRENT_THRESHOLD_mA) {
435  /* Current flow too high */
436  (void)DIAG_Handler(
439  }
440  retVal = STD_NOT_OK;
441  }
442  }
443  return retVal;
444 }
445 
446 static bool BMS_IsAnyFatalErrorFlagSet(void) {
447  bool fatalErrorActive = false;
448 
449  for (uint16_t entry = 0u; entry < diag_device.numberOfFatalErrors; entry++) {
450  const STD_RETURN_TYPE_e diagnosisState =
452  if (STD_NOT_OK == diagnosisState) {
453  /* Fatal error detected -> get delay of this error until contactors shall be opened */
454  const uint32_t kDelay_ms = DIAG_GetDelay(diag_device.pFatalErrorLinkTable[entry]->id);
455  /* Check if delay of detected failure is smaller than the delay of a previously detected failure */
456  if (bms_state.minimumActiveDelay_ms > kDelay_ms) {
457  bms_state.minimumActiveDelay_ms = kDelay_ms;
458  }
459  fatalErrorActive = true;
460  }
461  }
462  return fatalErrorActive;
463 }
464 
466  STD_RETURN_TYPE_e retVal = STD_OK; /* is set to STD_NOT_OK if error detected */
467  static uint32_t previousTimestamp = 0u;
468  uint32_t timestamp = OS_GetTickCount();
469 
470  /* Check if any fatal error is detected */
471  const bool isErrorActive = BMS_IsAnyFatalErrorFlagSet();
472 
473  /** Check if a fatal error has been detected previously. If yes, check delay */
474  if (bms_state.transitionToErrorState == true) {
475  /* Decrease active delay since last call */
476  const uint32_t timeSinceLastCall_ms = timestamp - previousTimestamp;
477  if (timeSinceLastCall_ms <= bms_state.remainingDelay_ms) {
478  bms_state.remainingDelay_ms -= timeSinceLastCall_ms;
479  } else {
481  }
482 
483  /* Check if delay from a new error is shorter then active delay from
484  * previously detected error in BMS state machine */
487  }
488  } else {
489  /* Delay is not active, check if it should be activated */
490  if (isErrorActive == true) {
493  }
494  }
495 
496  /** Set previous timestamp for next call */
497  previousTimestamp = timestamp;
498 
499  /* Check if bms state machine should switch to error state. This is the case
500  * if the delay is activated and the remaining delay is down to 0 */
501  if ((bms_state.transitionToErrorState == true) && (bms_state.remainingDelay_ms == 0u)) {
502  retVal = STD_NOT_OK;
503  }
504 
505  return retVal;
506 }
507 
508 static bool BMS_IsContactorFeedbackValid(uint8_t stringNumber, CONT_TYPE_e contactorType) {
509  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
510  FAS_ASSERT(contactorType != CONT_UNDEFINED);
511  bool feedbackValid = false;
512  /* Read latest error flags from database */
514  DATA_READ_DATA(&tableErrorFlags);
515  /* Check if contactor feedback is valid */
516  switch (contactorType) {
517  case CONT_PLUS:
518  if (tableErrorFlags.contactorInPositivePathOfStringFeedbackError[stringNumber] == false) {
519  feedbackValid = true;
520  }
521  break;
522  case CONT_MINUS:
523  if (tableErrorFlags.contactorInNegativePathOfStringFeedbackError[stringNumber] == false) {
524  feedbackValid = true;
525  }
526  break;
527  case CONT_PRECHARGE:
528  if (tableErrorFlags.prechargeContactorFeedbackError[stringNumber] == false) {
529  feedbackValid = true;
530  }
531  break;
532  default:
533  /* CONT_UNDEFINED already prevent via assert */
534  break;
535  }
536  return feedbackValid;
537 }
538 
540  FAS_ASSERT(pPackValues != NULL_PTR);
541  uint8_t highest_string_index = BMS_NO_STRING_AVAILABLE;
542  int32_t max_stringVoltage_mV = INT32_MIN;
543 
544  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
545  if ((pPackValues->stringVoltage_mV[s] >= max_stringVoltage_mV) &&
546  (pPackValues->invalidStringVoltage[s] == 0u)) {
547  if (bms_state.deactivatedStrings[s] == 0u) {
548  if (precharge == BMS_DO_NOT_TAKE_PRECHARGE_INTO_ACCCOUNT) {
549  max_stringVoltage_mV = pPackValues->stringVoltage_mV[s];
550  highest_string_index = s;
551  } else {
553  max_stringVoltage_mV = pPackValues->stringVoltage_mV[s];
554  highest_string_index = s;
555  }
556  }
557  }
558  }
559  }
560 
561  return highest_string_index;
562 }
563 
565  FAS_ASSERT(pPackValues != NULL_PTR);
566  uint8_t closestStringIndex = BMS_NO_STRING_AVAILABLE;
567  int32_t closedStringVoltage_mV = 0;
568  bool searchString = false;
569 
570  /* Get voltage of first closed string */
571  if (pPackValues->invalidStringVoltage[bms_state.firstClosedString] == 0u) {
572  closedStringVoltage_mV = pPackValues->stringVoltage_mV[bms_state.firstClosedString];
573  searchString = true;
574  } else if (pPackValues->invalidHvBusVoltage == 0u) {
575  /* Use high voltage bus voltage if measured string voltage is invalid */
576  closedStringVoltage_mV = pPackValues->highVoltageBusVoltage_mV;
577  searchString = true;
578  } else {
579  /* Do not search for next string if no valid voltages could be measured */
580  searchString = false;
581  }
582 
583  if (searchString == true) {
584  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
585  const bool isStringClosed = BMS_IsStringClosed(s);
586  const uint8_t isStringVoltageValid = pPackValues->invalidStringVoltage[s];
587  if ((isStringClosed == false) && (isStringVoltageValid == 0u)) {
588  /* Only check open strings with valid voltages */
589  int32_t minimumVoltageDifference_mV = INT32_MAX;
590  int32_t voltageDifference_mV = labs(closedStringVoltage_mV - pPackValues->stringVoltage_mV[s]);
591  if (voltageDifference_mV <= minimumVoltageDifference_mV) {
592  if (bms_state.deactivatedStrings[s] == 0u) {
593  if (precharge == BMS_TAKE_PRECHARGE_INTO_ACCCOUNT) {
595  minimumVoltageDifference_mV = voltageDifference_mV;
596  closestStringIndex = s;
597  }
598  } else {
599  minimumVoltageDifference_mV = voltageDifference_mV;
600  closestStringIndex = s;
601  }
602  }
603  }
604  }
605  }
606  }
607  return closestStringIndex;
608 }
609 
611  FAS_ASSERT(pPackValues != NULL_PTR);
612  uint8_t lowest_string_index = BMS_NO_STRING_AVAILABLE;
613  int32_t min_stringVoltage_mV = INT32_MAX;
614 
615  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
616  if ((pPackValues->stringVoltage_mV[s] <= min_stringVoltage_mV) &&
617  (pPackValues->invalidStringVoltage[s] == 0u)) {
618  if (bms_state.deactivatedStrings[s] == 0u) {
619  if (precharge == BMS_DO_NOT_TAKE_PRECHARGE_INTO_ACCCOUNT) {
620  min_stringVoltage_mV = pPackValues->stringVoltage_mV[s];
621  lowest_string_index = s;
622  } else {
624  min_stringVoltage_mV = pPackValues->stringVoltage_mV[s];
625  lowest_string_index = s;
626  }
627  }
628  }
629  }
630  }
631  return lowest_string_index;
632 }
633 
634 static int32_t BMS_GetStringVoltageDifference(uint8_t string, const DATA_BLOCK_PACK_VALUES_s *pPackValues) {
635  FAS_ASSERT(string < BS_NR_OF_STRINGS);
636  FAS_ASSERT(pPackValues != NULL_PTR);
637  int32_t voltageDifference_mV = INT32_MAX;
638  if ((pPackValues->invalidStringVoltage[string] == 0u) &&
639  (pPackValues->invalidStringVoltage[bms_state.firstClosedString] == 0u)) {
640  /* Calculate difference between string voltages */
641  voltageDifference_mV = MATH_AbsInt32_t(
642  pPackValues->stringVoltage_mV[string] - pPackValues->stringVoltage_mV[bms_state.firstClosedString]);
643  } else if ((pPackValues->invalidStringVoltage[string] == 0u) && (pPackValues->invalidHvBusVoltage == 0u)) {
644  /* Calculate difference between string and high voltage bus voltage */
645  voltageDifference_mV =
646  MATH_AbsInt32_t(pPackValues->stringVoltage_mV[string] - pPackValues->highVoltageBusVoltage_mV);
647  } else {
648  /* No valid voltages for comparison -> do not calculate difference and return INT32_MAX */
649  voltageDifference_mV = INT32_MAX;
650  }
651  return voltageDifference_mV;
652 }
653 
655  FAS_ASSERT(pPackValues != NULL_PTR);
656  int32_t average_current = pPackValues->packCurrent_mA / (int32_t)BS_NR_OF_STRINGS;
657  if (pPackValues->invalidPackCurrent == 1u) {
658  average_current = INT32_MAX;
659  }
660  return average_current;
661 }
662 
664  FAS_ASSERT(pPackValues != NULL_PTR);
665 
666  /* Only update system state if current value is valid */
667  if (pPackValues->invalidPackCurrent == 0u) {
668  if (BS_POSITIVE_DISCHARGE_CURRENT == true) {
669  /* Positive current values equal a discharge of the battery system */
670  if (pPackValues->packCurrent_mA >= BS_REST_CURRENT_mA) { /* TODO: string use pack current */
673  } else if (pPackValues->packCurrent_mA <= -BS_REST_CURRENT_mA) {
676  } else {
677  /* Current below rest current: either battery system is at rest
678  * or the relaxation process is still ongoing */
679  if (bms_state.restTimer_10ms == 0u) {
680  /* Rest timer elapsed -> battery system at rest */
682  } else {
685  }
686  }
687  } else {
688  /* Negative current values equal a discharge of the battery system */
689  if (pPackValues->packCurrent_mA <= -BS_REST_CURRENT_mA) {
692  } else if (pPackValues->packCurrent_mA >= BS_REST_CURRENT_mA) {
695  } else {
696  /* Current below rest current: either battery system is at rest
697  * or the relaxation process is still ongoing */
698  if (bms_state.restTimer_10ms == 0u) {
699  /* Rest timer elapsed -> battery system at rest */
701  } else {
704  }
705  }
706  }
707  }
708 }
709 
710 static CONT_TYPE_e BMS_GetFirstContactorToBeOpened(uint8_t stringNumber, BMS_CURRENT_FLOW_STATE_e flowDirection) {
711  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
712  /* AXIVION Routine Generic-MissingParameterAssert: flowDirection: parameter accepts all defined enums */
713  CONT_TYPE_e contactorToBeOpened = CONT_UNDEFINED;
715  /* Required preferred opening direction dependent on the current direction */
716  if (flowDirection == BMS_CHARGING) {
717  breakingDirection = CONT_CHARGING_DIRECTION;
718  } else {
719  breakingDirection = CONT_DISCHARGING_DIRECTION;
720  }
721  /* Iterate over contactor array and search for wanted contactor */
722  uint8_t contactor = 0u;
723  for (; contactor < BS_NR_OF_CONTACTORS; contactor++) {
724  /* Search for:
725  * 1. contactor from requested string
726  * 2. contactor mounted in preferred opening direction or is bidirectional
727  * 3. is no precharge contactor */
728  bool correctString = (bool)(stringNumber == cont_contactorStates[contactor].stringIndex);
729  bool inPreferredDirection = (bool)(breakingDirection == cont_contactorStates[contactor].breakingDirection);
730  bool hasNoPreferredDirection = (bool)(cont_contactorStates[contactor].breakingDirection == CONT_BIDIRECTIONAL);
731  bool noPrechargeContactor = (bool)(cont_contactorStates[contactor].type != CONT_PRECHARGE);
732  if (correctString && noPrechargeContactor && (inPreferredDirection || hasNoPreferredDirection)) {
733  contactorToBeOpened = cont_contactorStates[contactor].type;
734  break;
735  }
736  }
737  if (contactor == BS_NR_OF_CONTACTORS) {
738  /* No contactor mounted in preferred current direction found. Select
739  * the PLUS contactor found in array cont_contactorStates from the
740  * passed string */
741  for (contactor = 0u; contactor < BS_NR_OF_CONTACTORS; contactor++) {
742  /* Search for:
743  * 1. contactor from requested string
744  * 2. is PLUS contactor */
745  if ((stringNumber == cont_contactorStates[contactor].stringIndex) &&
746  (cont_contactorStates[contactor].type == CONT_PLUS)) {
747  contactorToBeOpened = cont_contactorStates[contactor].type;
748  break;
749  }
750  }
751  }
752  if (contactor == BS_NR_OF_CONTACTORS) {
753  /* No PLUS contactor found. Select MINUS contactor found in array
754  * cont_contactorStates from the passed string */
755  for (contactor = 0u; contactor < BS_NR_OF_CONTACTORS; contactor++) {
756  /* Search for:
757  * 1. contactor from requested string
758  * 2. is PLUS contactor */
759  if ((stringNumber == cont_contactorStates[contactor].stringIndex) &&
760  (cont_contactorStates[contactor].type == CONT_MINUS)) {
761  contactorToBeOpened = cont_contactorStates[contactor].type;
762  break;
763  }
764  }
765  }
766  if (contactor == BS_NR_OF_CONTACTORS) {
767  /* No PLUS or MAIN_MINUS contactor found in requested string. */
769  }
770  return contactorToBeOpened;
771 }
772 
773 static CONT_TYPE_e BMS_GetSecondContactorToBeOpened(uint8_t stringNumber, CONT_TYPE_e firstOpenedContactorType) {
774  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
775  FAS_ASSERT((firstOpenedContactorType != CONT_UNDEFINED) && (firstOpenedContactorType != CONT_PRECHARGE));
776  CONT_TYPE_e contactorToBeOpened = CONT_UNDEFINED;
777  /* Check what contactor has already been opened and select the other one */
778  if (firstOpenedContactorType == CONT_PLUS) {
779  contactorToBeOpened = CONT_MINUS;
780  } else {
781  contactorToBeOpened = CONT_PLUS;
782  }
783  /* Iterate over contactor array and search for wanted contactor */
784  uint8_t contactor = 0u;
785  for (; contactor < BS_NR_OF_CONTACTORS; contactor++) {
786  /* Search for specific contactor from requested string */
787  if ((stringNumber == cont_contactorStates[contactor].stringIndex) &&
788  (contactorToBeOpened == cont_contactorStates[contactor].type)) {
789  contactorToBeOpened = cont_contactorStates[contactor].type;
790  break;
791  }
792  }
793  if (contactor == BS_NR_OF_CONTACTORS) {
794  /* No PLUS or MAIN_MINUS contactor found in requested string.
795  * Apparently, only one contactor has been defined for this string */
797  }
798  return contactorToBeOpened;
799 }
800 
801 /*========== Extern Function Implementations ================================*/
802 
804  return bms_state.initFinished;
805 }
806 
808  return bms_state.state;
809 }
810 
812  BMS_RETURN_TYPE_e retVal = BMS_OK;
813 
815  retVal = BMS_CheckStateRequest(statereq);
816 
817  if (retVal == BMS_OK) {
818  bms_state.stateRequest = statereq;
819  }
821 
822  return retVal;
823 }
824 
825 void BMS_Trigger(void) {
828  uint32_t timestamp = OS_GetTickCount();
829  static uint32_t nextOpenWireCheck = 0;
830  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
831  static uint8_t stringNumber = 0u;
832  static uint8_t nextStringNumber = 0u;
834  bool contactorFeedbackValid = false;
835  STD_RETURN_TYPE_e contRetVal = STD_NOT_OK;
836 
846  }
847  /* Check re-entrance of function */
848  if (BMS_CheckReEntrance() > 0u) {
849  return;
850  }
851 
852  if (bms_state.nextstringclosedtimer > 0u) {
854  }
855  if (bms_state.stringOpenTimeout > 0u) {
857  }
858 
859  if (bms_state.stringCloseTimeout > 0u) {
861  }
862 
863  if (bms_state.OscillationTimeout > 0u) {
865  }
866 
867  if (bms_state.timer > 0u) {
868  if ((--bms_state.timer) > 0u) {
870  return; /* handle state machine only if timer has elapsed */
871  }
872  }
873 
874  /****Happens every time the state machine is triggered**************/
875  switch (bms_state.state) {
876  /****************************UNINITIALIZED****************************/
878  /* waiting for Initialization Request */
879  statereq = BMS_TransferStateRequest();
880  if (statereq == BMS_STATE_INIT_REQUEST) {
885  } else if (statereq == BMS_STATE_NO_REQUEST) {
886  /* no actual request pending */
887  } else {
888  bms_state.ErrRequestCounter++; /* illegal request pending */
889  }
890  break;
891 
892  /****************************INITIALIZATION***************************/
895  /* Reset ALERT mode flag */
901  break;
902 
903  /****************************INITIALIZED******************************/
907  /* Initialization of IMD device not finished yet -> wait until this is finished before moving on */
909  } else {
913  }
914  break;
915 
916  /****************************IDLE*************************************/
917  case BMS_STATEMACH_IDLE:
919 
920  if (bms_state.substate == BMS_ENTRY) {
921  DATA_READ_DATA(&systemstate);
922  systemstate.bmsCanState = BMS_CANSTATE_IDLE;
923  DATA_WRITE_DATA(&systemstate);
926  break;
927  } else if (bms_state.substate == BMS_CHECK_ERROR_FLAGS) {
933  break;
934  } else {
937  break;
938  }
944  break;
945  }
946  break;
947 
948  /****************************OPEN CONTACTORS**************************/
951 
952  if (bms_state.substate == BMS_ENTRY) {
956  break;
958  /* Precharge contactors can always be opened as the precharge
959  * resistor limits the maximum current */
961 
962  /* Now go to string opening - open one string after another */
963  stringNumber = BS_NR_OF_STRINGS - 1u; /* Select last string */
967  /* Precharge contactors have been opened -> start opening first string contactor */
968  /* TODO: Check if precharge contactors have been opened? */
969 
970  if ((bms_tablePackValues.invalidStringCurrent[stringNumber] == 0u) &&
973  /* Current is below maximum break current -> open first contactor
974  * Check the mounting direction of the contactors and open the contactor that is mounted in the
975  * preferred current flow direction. Open the plus contactor first if, there is no contactor
976  * in preferred direction to the curren flow to open available. This may be either because both
977  * contactors are installed in the same direction or because the contactors are bidirectional.
978  */
979  const BMS_CURRENT_FLOW_STATE_e flowDirection =
981  bms_state.contactorToBeOpened = BMS_GetFirstContactorToBeOpened(stringNumber, flowDirection);
982  bms_state.stringToBeOpened = stringNumber;
983  /* Open first contactor */
988  } else {
989  /* Current is above maximum contactor break current -> contactor can not be opened */
992  /* Fuse should have been triggered by now but apparently has not yet. Do not wait any
993  * longer. Activate ALERT mode and nevertheless start opening the contactors */
995  const BMS_CURRENT_FLOW_STATE_e flowDirection =
997  bms_state.contactorToBeOpened = BMS_GetFirstContactorToBeOpened(stringNumber, flowDirection);
998  bms_state.stringToBeOpened = stringNumber;
999  /* Open first contactor */
1003  }
1004  }
1005  break;
1007  /* Check if first contactor has been opened correctly */
1009  contactorFeedbackValid =
1011  /* If we want to open the contactors because of a feedback
1012  * error for this contactor, the statement will never be true.
1013  * Thus, also continue if a feedback error for this contactor
1014  * is detected as we are not able to get a valid feedback
1015  * information at this point */
1016  if ((contactorState == CONT_SWITCH_OFF) || (contactorFeedbackValid == false)) {
1017  /* First contactor opened correctly.
1018  * Open second contactor. Pass first opened contactor into function */
1021  /* Open second contactor */
1025  } else {
1026  /* String not opened, re-issue closing request */
1029  /* TODO: add timeout */
1030  }
1032  /* Check if second contactor has been opened correctly */
1034  contactorFeedbackValid =
1036  /* If we want to open the contactors because of a feedback
1037  * error for this contactor, the statement will never be true.
1038  * Thus, also continue if a feedback error for this contactor
1039  * is detected as we are not able to get a valid feedback
1040  * information at this point */
1041  if ((contactorState == CONT_SWITCH_OFF) || (contactorFeedbackValid == false)) {
1042  /* Opening for this string finished. Reset state variables used for opening */
1045  /* String opened. Decrement string counter */
1046  if (bms_state.numberOfClosedStrings > 0u) {
1048  }
1049  bms_state.closedStrings[stringNumber] = 0u;
1050  if (stringNumber > 0u) {
1051  /* Not all strings opened yet -> open next string */
1052  stringNumber--;
1055  break;
1056  } else {
1057  /* All strings opened -> prepare to leave state BMS_STATEMACH_OPEN_CONTACTORS */
1060  }
1061  break;
1062  } else if (bms_state.stringOpenTimeout == 0u) {
1063  /* String takes too long to open, go to next string */
1066  break;
1067  } else {
1068  /* String not opened, re-issue closing request */
1071  break;
1072  }
1073  } else if (bms_state.substate == BMS_OPEN_STRINGS_EXIT) {
1075  /* Opening due to STANDBY request -> switch to BMS_STATEMACH_STANDBY */
1079  break;
1080  } else {
1081  /* Opening due to detected error -> switch to BMS_STATEMACH_ERROR */
1085  }
1086  } else {
1088  }
1089  break;
1090 
1091  /****************************STANDBY**********************************/
1092  case BMS_STATEMACH_STANDBY:
1094  if (bms_state.substate == BMS_ENTRY) {
1096 #if BS_STANDBY_PERIODIC_OPEN_WIRE_CHECK == TRUE
1097  nextOpenWireCheck = timestamp + BS_STANDBY_OPEN_WIRE_PERIOD_ms;
1098 #endif /* BS_STANDBY_PERIODIC_OPEN_WIRE_CHECK == TRUE */
1101  DATA_READ_DATA(&systemstate);
1102  systemstate.bmsCanState = BMS_CANSTATE_STANDBY;
1103  DATA_WRITE_DATA(&systemstate);
1104  break;
1111  break;
1112  } else {
1115  break;
1116  }
1117  } else if (bms_state.substate == BMS_INTERLOCK_CHECKED) {
1120  break;
1121  } else if (bms_state.substate == BMS_CHECK_ERROR_FLAGS) {
1127  break;
1128  } else {
1131  break;
1132  }
1140  break;
1141  }
1148  break;
1149  } else {
1150 #if BS_STANDBY_PERIODIC_OPEN_WIRE_CHECK == TRUE
1151  if (nextOpenWireCheck <= timestamp) {
1153  nextOpenWireCheck = timestamp + BS_STANDBY_OPEN_WIRE_PERIOD_ms;
1154  }
1155 #endif /* BS_STANDBY_PERIODIC_OPEN_WIRE_CHECK == TRUE */
1158  break;
1159  }
1160  } else {
1162  }
1163  break;
1164 
1165  /****************************PRECHARGE********************************/
1168 
1169  if (bms_state.substate == BMS_ENTRY) {
1170  DATA_READ_DATA(&systemstate);
1171  systemstate.bmsCanState = BMS_CANSTATE_PRECHARGE;
1172  DATA_WRITE_DATA(&systemstate);
1175  } else {
1177  }
1178  if (stringNumber == BMS_NO_STRING_AVAILABLE) {
1183  break;
1184  }
1186  bms_state.firstClosedString = stringNumber;
1187  if (bms_state.OscillationTimeout == 0u) {
1188  /* Close MINUS string contactor */
1193  } else {
1194  /* Invalid contactor requested */
1199  }
1200  } else if (BMS_IsBatterySystemStateOkay() == STD_NOT_OK) {
1201  /* If precharge re-enter timeout not elapsed, wait (and check errors while waiting) */
1206  break;
1207  }
1208  break;
1210  /* Check if MINUS contactor has been successfully closed */
1212  if (contactorState == CONT_SWITCH_ON) {
1215  bms_state.closedPrechargeContactors[stringNumber] = 1u;
1216  if (contRetVal == STD_OK) {
1219  } else {
1224  }
1225  } else if (bms_state.stringCloseTimeout == 0u) {
1226  /* String takes too long to close */
1231  } else {
1232  /* String not closed, re-issue closing request */
1235  }
1236  break;
1243  break;
1244  } else {
1247  break;
1248  }
1255  break;
1256  } else {
1259  }
1263  /* Check if precharge contactor is closed and precharge is finished */
1264  if ((contactorState == CONT_SWITCH_ON) && (retVal == STD_OK)) {
1265  /* Successfully precharged. Close string PLUS contactor */
1270  break;
1271  } else {
1272  /* Precharging failed. Open precharge contactor. */
1274  /* Check if retry limit has been reached */
1276  bms_state.closedPrechargeContactors[stringNumber] = 0u;
1277  if (contRetVal == STD_OK) {
1281  } else {
1286  }
1287  break;
1288  } else {
1289  bms_state.closedPrechargeContactors[stringNumber] = 0u;
1294  break;
1295  }
1296  }
1299  if (contactorState == CONT_SWITCH_ON) {
1304  break;
1305  } else if (bms_state.stringCloseTimeout == 0u) {
1306  /* String takes too long to close */
1311  break;
1312  } else {
1313  /* String not closed, re-issue closing request */
1317  break;
1318  }
1325  break;
1326  } else {
1329  break;
1330  }
1332  /* Always make one error check after the first string was closed successfully */
1338  break;
1339  } else {
1342  break;
1343  }
1346  if (contRetVal == STD_OK) {
1347  bms_state.closedPrechargeContactors[stringNumber] = 0u;
1350  } else {
1355  }
1356  break;
1359  if (contactorState == CONT_SWITCH_OFF) {
1363  break;
1364  } else if (bms_state.stringCloseTimeout == 0u) {
1365  /* Precharge contactor takes too long to open */
1370  break;
1371  } else {
1372  /* Precharge contactor not opened, re-issue open request */
1376  break;
1377  }
1378  } else {
1380  }
1381  break;
1382 
1383  /****************************NORMAL**************************************/
1384  case BMS_STATEMACH_NORMAL:
1386 
1387  if (bms_state.substate == BMS_ENTRY) {
1388 #if BS_NORMAL_PERIODIC_OPEN_WIRE_CHECK == TRUE
1389  nextOpenWireCheck = timestamp + BS_NORMAL_OPEN_WIRE_PERIOD_ms;
1390 #endif /* BS_NORMAL_PERIODIC_OPEN_WIRE_CHECK == TRUE */
1391  DATA_READ_DATA(&systemstate);
1393  systemstate.bmsCanState = BMS_CANSTATE_CHARGE;
1394  } else {
1395  systemstate.bmsCanState = BMS_CANSTATE_NORMAL;
1396  }
1397  DATA_WRITE_DATA(&systemstate);
1401  break;
1402  } else if (bms_state.substate == BMS_CHECK_ERROR_FLAGS) {
1408  break;
1409  } else {
1412  break;
1413  }
1420  break;
1421  } else {
1422 #if BS_NORMAL_PERIODIC_OPEN_WIRE_CHECK == TRUE
1423  if (nextOpenWireCheck <= timestamp) {
1425  nextOpenWireCheck = timestamp + BS_NORMAL_OPEN_WIRE_PERIOD_ms;
1426  }
1427 #endif /* BS_NORMAL_PERIODIC_OPEN_WIRE_CHECK == TRUE */
1430  break;
1431  }
1433  if (bms_state.nextstringclosedtimer == 0u) {
1434  nextStringNumber =
1436  if (nextStringNumber == BMS_NO_STRING_AVAILABLE) {
1439  break;
1440  } else if (
1441  (BMS_GetStringVoltageDifference(nextStringNumber, &bms_tablePackValues) <=
1444  /* Voltage/current conditions suitable to close a further string. Close first string contactor */
1445  CONT_CloseContactor(nextStringNumber, CONT_MINUS);
1449  break;
1450  }
1451  } else {
1454  break;
1455  }
1457  contactorState = CONT_GetContactorState(nextStringNumber, CONT_MINUS);
1458  if (contactorState == CONT_SWITCH_ON) {
1459  /* First string contactor closed. Close second string contactor */
1460  CONT_CloseContactor(nextStringNumber, CONT_PLUS);
1463  } else if (bms_state.stringCloseTimeout == 0u) {
1464  /* String takes too long to close */
1469  break;
1470  } else {
1471  /* String minus contactor has not been closed successfully. Re-trigger closing */
1472  CONT_CloseContactor(nextStringNumber, CONT_MINUS);
1474  }
1475  break;
1476  } else if (bms_state.substate == BMS_CHECK_STRING_CLOSED) {
1477  contactorState = CONT_GetContactorState(nextStringNumber, CONT_PLUS);
1478  if (contactorState == CONT_SWITCH_ON) {
1480  bms_state.closedStrings[nextStringNumber] = 1u;
1482  /* Go to begin of NORMAL case to redo the full procedure with error check and request check */
1484  break;
1485  } else if (bms_state.stringCloseTimeout == 0u) {
1486  /* String takes too long to close */
1491  break;
1492  } else if (BMS_IsBatterySystemStateOkay() == STD_NOT_OK) {
1497  break;
1498  } else if (BMS_CheckCanRequests() == BMS_REQ_ID_STANDBY) {
1503  break;
1504  } else {
1505  /* String not closed, re-issue closing request */
1506  CONT_CloseContactor(nextStringNumber, CONT_PLUS);
1508  break;
1509  }
1510  } else {
1512  }
1513  break;
1514 
1515  /****************************ERROR*************************************/
1516  case BMS_STATEMACH_ERROR:
1518 
1519  if (bms_state.substate == BMS_ENTRY) {
1520  /* Set BMS System state to error */
1521  DATA_READ_DATA(&systemstate);
1522  systemstate.bmsCanState = BMS_CANSTATE_ERROR;
1523  DATA_WRITE_DATA(&systemstate);
1524  /* Deactivate balancing */
1526  /* Change LED toggle frequency to indicate an error */
1528  /* Set timer for next open wire check */
1529  nextOpenWireCheck = timestamp + AFE_ERROR_OPEN_WIRE_PERIOD_ms;
1530  /* Switch to next substate */
1533  break;
1534  } else if (bms_state.substate == BMS_CHECK_ERROR_FLAGS) {
1535  if (DIAG_IsAnyFatalErrorSet() == true) {
1536  /* we stay already in requested state */
1537  if (nextOpenWireCheck <= timestamp) {
1538  /* Perform open-wire check periodically */
1539  /* MEAS_RequestOpenWireCheck(); */ /*TODO: check with strings */
1540  nextOpenWireCheck = timestamp + AFE_ERROR_OPEN_WIRE_PERIOD_ms;
1541  }
1542  } else {
1543  /* No error detected anymore - reset fatal error related variables */
1547  /* Check for STANDBY request */
1550  break;
1551  }
1554  /* Activate balancing again */
1556  /* Set LED frequency to normal operation as we leave error
1557  state subsequently */
1559 
1560  /* Verify that all contactors are opened and switch to
1561  * STANDBY state afterwards */
1565  break;
1566  } else {
1569  break;
1570  }
1571  } else {
1572  /* invalid state -> this should never be reached */
1574  }
1575  break;
1576  default:
1577  /* invalid state */
1579  break;
1580  } /* end switch (bms_state.state) */
1581 
1583  bms_state.counter++;
1584 }
1585 
1587  return bms_state.currentFlowState;
1588 }
1589 
1591  /* AXIVION Routine Generic-MissingParameterAssert: current_mA: parameter accepts whole range */
1593 
1594  if (BS_POSITIVE_DISCHARGE_CURRENT == true) {
1595  if (current_mA >= BS_REST_CURRENT_mA) {
1596  retVal = BMS_DISCHARGING;
1597  } else if (current_mA <= -BS_REST_CURRENT_mA) {
1598  retVal = BMS_CHARGING;
1599  } else {
1600  retVal = BMS_AT_REST;
1601  }
1602  } else {
1603  if (current_mA <= -BS_REST_CURRENT_mA) {
1604  retVal = BMS_DISCHARGING;
1605  } else if (current_mA >= BS_REST_CURRENT_mA) {
1606  retVal = BMS_CHARGING;
1607  } else {
1608  retVal = BMS_AT_REST;
1609  }
1610  }
1611  return retVal;
1612 }
1613 
1614 extern bool BMS_IsStringClosed(uint8_t stringNumber) {
1615  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
1616  bool retval = false;
1617  if (bms_state.closedStrings[stringNumber] == 1u) {
1618  retval = true;
1619  }
1620  return retval;
1621 }
1622 
1623 extern bool BMS_IsStringPrecharging(uint8_t stringNumber) {
1624  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
1625  bool retval = false;
1626  if (bms_state.closedPrechargeContactors[stringNumber] == 1u) {
1627  retval = true;
1628  }
1629  return retval;
1630 }
1631 
1632 extern uint8_t BMS_GetNumberOfConnectedStrings(void) {
1634 }
1635 
1638 }
1639 
1640 /*========== Externalized Static Function Implementations (Unit Test) =======*/
1641 #ifdef UNITY_UNIT_TEST
1642 extern BMS_RETURN_TYPE_e TEST_BMS_CheckStateRequest(BMS_STATE_REQUEST_e statereq) {
1643  return BMS_CheckStateRequest(statereq);
1644 }
1645 extern BMS_STATE_REQUEST_e TEST_BMS_TransferStateRequest(void) {
1646  return BMS_TransferStateRequest();
1647 }
1648 extern uint8_t TEST_BMS_CheckReEntrance(void) {
1649  return BMS_CheckReEntrance();
1650 }
1651 extern uint8_t TEST_BMS_CheckCanRequests(void) {
1652  return BMS_CheckCanRequests();
1653 }
1654 extern bool TEST_BMS_IsAnyFatalErrorFlagSet(void) {
1655  return BMS_IsAnyFatalErrorFlagSet();
1656 }
1657 extern STD_RETURN_TYPE_e TEST_BMS_IsBatterySystemStateOkay(void) {
1659 }
1660 extern void TEST_BMS_GetMeasurementValues(void) {
1662 }
1663 extern void TEST_BMS_CheckOpenSenseWire(void) {
1665 }
1666 extern STD_RETURN_TYPE_e TEST_BMS_CheckPrecharge(uint8_t stringNumber, DATA_BLOCK_PACK_VALUES_s *pPackValues) {
1667  return BMS_CheckPrecharge(stringNumber, pPackValues);
1668 }
1669 extern uint8_t TEST_BMS_GetHighestString(BMS_CONSIDER_PRECHARGE_e precharge, DATA_BLOCK_PACK_VALUES_s *pPackValues) {
1670  return BMS_GetHighestString(precharge, pPackValues);
1671 }
1672 extern uint8_t TEST_BMS_GetClosestString(BMS_CONSIDER_PRECHARGE_e precharge, DATA_BLOCK_PACK_VALUES_s *pPackValues) {
1673  return BMS_GetClosestString(precharge, pPackValues);
1674 }
1675 
1676 extern uint8_t TEST_BMS_GetLowestString(BMS_CONSIDER_PRECHARGE_e precharge, DATA_BLOCK_PACK_VALUES_s *pPackValues) {
1677  return BMS_GetLowestString(precharge, pPackValues);
1678 }
1679 extern int32_t TEST_BMS_GetStringVoltageDifference(uint8_t string, DATA_BLOCK_PACK_VALUES_s *pPackValues) {
1680  return BMS_GetStringVoltageDifference(string, pPackValues);
1681 }
1682 extern int32_t TEST_BMS_GetAverageStringCurrent(DATA_BLOCK_PACK_VALUES_s *pPackValues) {
1683  return BMS_GetAverageStringCurrent(pPackValues);
1684 }
1685 extern void TEST_BMS_UpdateBatsysState(DATA_BLOCK_PACK_VALUES_s *pPackValues) {
1686  BMS_UpdateBatsysState(pPackValues);
1687 }
1688 
1689 #endif
AFE driver header.
#define AFE_ERROR_OPEN_WIRE_PERIOD_ms
Definition: afe.h:100
Header for the driver for balancing.
@ BAL_STATE_ALLOWBALANCING_REQUEST
Definition: bal.h:106
@ BAL_STATE_NO_BALANCING_REQUEST
Definition: bal.h:105
BAL_RETURN_TYPE_e BAL_SetStateRequest(BAL_STATE_REQUEST_e stateRequest)
sets the current state request of the state variable bal_state.
Configuration of the battery cell (e.g., minimum and maximum cell voltage)
BS_STRING_PRECHARGE_PRESENT_e bs_stringsWithPrecharge[BS_NR_OF_STRINGS]
#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_REST_CURRENT_mA
current threshold for determining rest state of battery. If absolute current is below this limit valu...
#define BS_MAIN_CONTACTORS_MAXIMUM_BREAK_CURRENT_mA
Maximum break current of main contactors.
#define BS_POSITIVE_DISCHARGE_CURRENT
#define BS_NR_OF_MODULES_PER_STRING
number of modules in a string
#define BS_RELAXATION_PERIOD_10ms
Wait time in 10ms before battery system is at rest. Balancing for example only starts if battery syst...
@ BS_STRING_WITH_PRECHARGE
#define BS_NR_OF_CONTACTORS
#define BS_MAIN_FUSE_MAXIMUM_TRIGGER_DURATION_ms
Maximum fuse trigger duration.
static STD_RETURN_TYPE_e BMS_CheckPrecharge(uint8_t stringNumber, const DATA_BLOCK_PACK_VALUES_s *pPackValues)
Checks if the current limitations are violated.
Definition: bms.c:406
#define BMS_SAVELASTSTATES()
Definition: bms.c:80
static DATA_BLOCK_MIN_MAX_s bms_tableMinMax
Definition: bms.c:124
bool BMS_IsStringPrecharging(uint8_t stringNumber)
Returns if string is currently precharging or not.
Definition: bms.c:1623
bool BMS_IsTransitionToErrorStateActive(void)
Check if transition in to error state is active.
Definition: bms.c:1636
BMS_RETURN_TYPE_e BMS_SetStateRequest(BMS_STATE_REQUEST_e statereq)
sets the current state request of the state variable bms_state.
Definition: bms.c:811
static bool BMS_IsAnyFatalErrorFlagSet(void)
Checks all the error flags from diagnosis module with a severity of DIAG_FATAL_ERROR.
Definition: bms.c:446
static bool BMS_IsContactorFeedbackValid(uint8_t stringNumber, CONT_TYPE_e contactorType)
Checks if the contactor feedback for a specific contactor is valid need to be opened.
Definition: bms.c:508
static BMS_RETURN_TYPE_e BMS_CheckStateRequest(BMS_STATE_REQUEST_e statereq)
checks the state requests that are made.
Definition: bms.c:313
static void BMS_GetMeasurementValues(void)
Definition: bms.c:356
static DATA_BLOCK_PACK_VALUES_s bms_tablePackValues
Definition: bms.c:126
static void BMS_UpdateBatsysState(DATA_BLOCK_PACK_VALUES_s *pPackValues)
Updates battery system state variable depending on measured/recent current values.
Definition: bms.c:663
static CONT_TYPE_e BMS_GetFirstContactorToBeOpened(uint8_t stringNumber, BMS_CURRENT_FLOW_STATE_e flowDirection)
Get first string contactor that should be opened depending on the actual current flow direction.
Definition: bms.c:710
#define BMS_NO_ACTIVE_DELAY_TIME_ms
Definition: bms.c:75
static int32_t BMS_GetAverageStringCurrent(DATA_BLOCK_PACK_VALUES_s *pPackValues)
Returns the average current flowing through all strings.
Definition: bms.c:654
void BMS_Trigger(void)
trigger function for the BMS driver state machine.
Definition: bms.c:825
uint8_t BMS_GetNumberOfConnectedStrings(void)
Returns number of connected strings.
Definition: bms.c:1632
bool BMS_IsStringClosed(uint8_t stringNumber)
Returns string state (closed or open)
Definition: bms.c:1614
static void BMS_CheckOpenSenseWire(void)
Check for any open voltage sense wire.
Definition: bms.c:381
BMS_CURRENT_FLOW_STATE_e BMS_GetCurrentFlowDirection(int32_t current_mA)
Get current flow direction, current value as function parameter.
Definition: bms.c:1590
static int32_t BMS_GetStringVoltageDifference(uint8_t string, const DATA_BLOCK_PACK_VALUES_s *pPackValues)
Returns voltage difference between first closed string and string ID.
Definition: bms.c:634
static uint8_t BMS_GetLowestString(BMS_CONSIDER_PRECHARGE_e precharge, DATA_BLOCK_PACK_VALUES_s *pPackValues)
Returns ID of string with lowest total voltage.
Definition: bms.c:610
BMS_CURRENT_FLOW_STATE_e BMS_GetBatterySystemState(void)
Returns current battery system state (charging/discharging, resting or in relaxation phase)
Definition: bms.c:1586
static uint8_t BMS_GetHighestString(BMS_CONSIDER_PRECHARGE_e precharge, DATA_BLOCK_PACK_VALUES_s *pPackValues)
Returns ID of string with highest total voltage.
Definition: bms.c:539
static uint8_t BMS_CheckReEntrance(void)
re-entrance check of SYS state machine trigger function
Definition: bms.c:334
static DATA_BLOCK_OPEN_WIRE_s bms_tableOpenWire
Definition: bms.c:125
static BMS_STATE_REQUEST_e BMS_TransferStateRequest(void)
transfers the current state request to the state machine.
Definition: bms.c:346
static BMS_STATE_s bms_state
Definition: bms.c:89
static STD_RETURN_TYPE_e BMS_IsBatterySystemStateOkay(void)
Checks if any error flag is set and handles delay until contactors need to be opened.
Definition: bms.c:465
static CONT_TYPE_e BMS_GetSecondContactorToBeOpened(uint8_t stringNumber, CONT_TYPE_e firstOpenedContactorType)
Get second string contactor that should be opened.
Definition: bms.c:773
STD_RETURN_TYPE_e BMS_GetInitializationState(void)
Gets the initialization state.
Definition: bms.c:803
static uint8_t BMS_CheckCanRequests(void)
Checks the state requests made to the BMS state machine.
Definition: bms.c:360
BMS_STATEMACH_e BMS_GetState(void)
Returns the current state.
Definition: bms.c:807
static uint8_t BMS_GetClosestString(BMS_CONSIDER_PRECHARGE_e precharge, DATA_BLOCK_PACK_VALUES_s *pPackValues)
Returns ID of string with voltage closest to first closed string voltage.
Definition: bms.c:564
bms driver header
@ BMS_CANSTATE_NORMAL
Definition: bms.h:120
@ BMS_CANSTATE_CHARGE
Definition: bms.h:121
@ BMS_CANSTATE_STANDBY
Definition: bms.h:118
@ BMS_CANSTATE_ERROR
Definition: bms.h:122
@ BMS_CANSTATE_IDLE
Definition: bms.h:116
@ BMS_CANSTATE_PRECHARGE
Definition: bms.h:119
BMS_CONSIDER_PRECHARGE_e
Definition: bms.h:87
@ BMS_DO_NOT_TAKE_PRECHARGE_INTO_ACCCOUNT
Definition: bms.h:88
@ BMS_TAKE_PRECHARGE_INTO_ACCCOUNT
Definition: bms.h:89
BMS_STATE_REQUEST_e
Definition: bms.h:163
@ BMS_STATE_NO_REQUEST
Definition: bms.h:166
@ BMS_STATE_INIT_REQUEST
Definition: bms.h:164
@ BMS_STATE_ERROR_REQUEST
Definition: bms.h:165
@ BMS_NORMAL_CLOSE_SECOND_STRING_CONTACTOR
Definition: bms.h:152
@ BMS_PRECHARGE_OPEN_PRECHARGE
Definition: bms.h:138
@ BMS_OPEN_SECOND_STRING_CONTACTOR
Definition: bms.h:157
@ BMS_OPEN_STRINGS_EXIT
Definition: bms.h:159
@ BMS_PRECHARGE_CLOSE_PRECHARGE
Definition: bms.h:136
@ BMS_NORMAL_CLOSE_NEXT_STRING
Definition: bms.h:151
@ BMS_CHECK_CLOSE_SECOND_STRING_CONTACTOR_PRECHARGE_STATE
Definition: bms.h:143
@ BMS_CHECK_ERROR_FLAGS_PRECHARGE_CLOSINGSTRINGS
Definition: bms.h:149
@ BMS_ENTRY
Definition: bms.h:127
@ BMS_INTERLOCK_CHECKED
Definition: bms.h:129
@ BMS_CHECK_ERROR_FLAGS_PRECHARGE_FIRST_STRING
Definition: bms.h:145
@ BMS_CHECK_ERROR_FLAGS_CLOSINGPRECHARGE
Definition: bms.h:150
@ BMS_PRECHARGE_CHECK_VOLTAGES
Definition: bms.h:137
@ BMS_CHECK_STRING_CLOSED
Definition: bms.h:148
@ BMS_PRECHARGE_CHECK_OPEN_PRECHARGE
Definition: bms.h:139
@ BMS_CHECK_ERROR_FLAGS
Definition: bms.h:132
@ BMS_OPEN_ALL_PRECHARGES
Definition: bms.h:153
@ BMS_CHECK_ERROR_FLAGS_INTERLOCK
Definition: bms.h:128
@ BMS_CHECK_STATE_REQUESTS
Definition: bms.h:130
@ BMS_OPEN_FIRST_STRING_CONTACTOR
Definition: bms.h:156
@ BMS_CHECK_SECOND_STRING_CONTACTOR
Definition: bms.h:158
@ BMS_POWER_PATH_1
Definition: bms.h:181
@ BMS_POWER_PATH_OPEN
Definition: bms.h:179
@ BMS_POWER_PATH_0
Definition: bms.h:180
BMS_STATEMACH_e
Definition: bms.h:93
@ BMS_STATEMACH_PRECHARGE
Definition: bms.h:101
@ BMS_STATEMACH_STANDBY
Definition: bms.h:100
@ BMS_STATEMACH_CHARGE
Definition: bms.h:104
@ BMS_STATEMACH_UNINITIALIZED
Definition: bms.h:95
@ BMS_STATEMACH_ERROR
Definition: bms.h:105
@ BMS_STATEMACH_NORMAL
Definition: bms.h:102
@ BMS_STATEMACH_INITIALIZATION
Definition: bms.h:96
@ BMS_STATEMACH_DISCHARGE
Definition: bms.h:103
@ BMS_STATEMACH_OPEN_CONTACTORS
Definition: bms.h:99
@ BMS_STATEMACH_INITIALIZED
Definition: bms.h:97
@ BMS_STATEMACH_IDLE
Definition: bms.h:98
BMS_CURRENT_FLOW_STATE_e
Definition: bms.h:72
@ BMS_AT_REST
Definition: bms.h:76
@ BMS_DISCHARGING
Definition: bms.h:74
@ BMS_CHARGING
Definition: bms.h:73
@ BMS_RELAXATION
Definition: bms.h:75
BMS_RETURN_TYPE_e
Definition: bms.h:170
@ BMS_OK
Definition: bms.h:171
@ BMS_REQUEST_PENDING
Definition: bms.h:172
@ BMS_ALREADY_INITIALIZED
Definition: bms.h:174
@ BMS_ILLEGAL_REQUEST
Definition: bms.h:173
#define BMS_REQ_ID_STANDBY
Definition: bms_cfg.h:69
#define BMS_AVERAGE_STRING_CURRENT_LIMIT_MA
Definition: bms_cfg.h:144
#define BMS_TIME_WAIT_AFTER_OPENING_PRECHARGE
Definition: bms_cfg.h:150
#define BMS_STATEMACH_LONGTIME
BMS state machine long time definition in BMS_Trigger() calls until next state/substate is processed.
Definition: bms_cfg.h:114
#define BMS_STATEMACHINE_TASK_CYCLE_CONTEXT_MS
TODO.
Definition: bms_cfg.h:92
#define BMS_STRING_OPEN_TIMEOUT
Timeout in BMS_Trigger() calls when opening a string after which the state machines goes to error if ...
Definition: bms_cfg.h:135
#define BMS_REQ_ID_NOREQ
Definition: bms_cfg.h:66
#define BMS_WAIT_TIME_AFTER_OPENING_STRING_CONTACTOR
Definition: bms_cfg.h:120
#define BMS_STRING_CLOSE_TIMEOUT
Timeout in BMS_Trigger() calls when closing a string after which the state machines goes to error if ...
Definition: bms_cfg.h:129
#define BMS_WAIT_TIME_AFTER_CLOSING_STRING_CONTACTOR
Definition: bms_cfg.h:117
#define BMS_WAIT_TIME_BETWEEN_CLOSING_STRINGS
Definition: bms_cfg.h:123
#define BMS_NEXT_STRING_VOLTAGE_LIMIT_MV
Max voltage difference in mV between two strings to allow closing the next string.
Definition: bms_cfg.h:141
#define BMS_PRECHARGE_TRIES
Definition: bms_cfg.h:166
#define BMS_STATEMACH_MEDIUMTIME
BMS state machine medium time definition in BMS_Trigger() calls until next state/substate is processe...
Definition: bms_cfg.h:108
#define BMS_STATEMACH_SHORTTIME
BMS state machine short time definition in BMS_Trigger() calls until next state/substate is processed...
Definition: bms_cfg.h:102
#define BMS_REQ_ID_CHARGE
Definition: bms_cfg.h:75
#define BMS_REQ_ID_NORMAL
Definition: bms_cfg.h:72
#define BMS_NO_STRING_AVAILABLE
Functions searching for next string return this value if no further string is available.
Definition: bms_cfg.h:80
#define BMS_OSCILLATION_TIMEOUT
Timeout in 1*10ms to wait before re-entering to precharge.
Definition: bms_cfg.h:163
#define BMS_TIME_WAIT_AFTERPRECHARGEFAIL
Time to wait in BMS_Trigger() calls after precharge opened because precharge failed.
Definition: bms_cfg.h:156
#define BMS_PRECHARGE_VOLTAGE_THRESHOLD_mV
Definition: bms_cfg.h:169
#define BMS_PRECHARGE_CURRENT_THRESHOLD_mA
Definition: bms_cfg.h:172
#define BMS_TIME_WAIT_AFTER_CLOSING_PRECHARGE
Definition: bms_cfg.h:147
void CONT_CheckFeedback(void)
checks the feedback of all contactors
Definition: contactor.c:125
STD_RETURN_TYPE_e CONT_CloseContactor(uint8_t stringNumber, CONT_TYPE_e contactor)
Closes the contactor.
Definition: contactor.c:184
STD_RETURN_TYPE_e CONT_OpenPrecharge(uint8_t stringNumber)
Opens precharge.
Definition: contactor.c:213
STD_RETURN_TYPE_e CONT_OpenContactor(uint8_t stringNumber, CONT_TYPE_e contactor)
Opens the contactor.
Definition: contactor.c:165
CONT_ELECTRICAL_STATE_TYPE_e CONT_GetContactorState(uint8_t stringNumber, CONT_TYPE_e contactorType)
Returns the current contactor state.
Definition: contactor.c:236
void CONT_OpenAllPrechargeContactors(void)
Open all currently closed precharge contactors.
Definition: contactor.c:223
STD_RETURN_TYPE_e CONT_ClosePrecharge(uint8_t stringNumber)
Closes precharge.
Definition: contactor.c:203
CONT_CONTACTOR_STATE_s cont_contactorStates[BS_NR_OF_CONTACTORS]
Definition: contactor_cfg.c:67
CONT_TYPE_e
Definition: contactor_cfg.h:85
@ CONT_UNDEFINED
Definition: contactor_cfg.h:89
@ CONT_PRECHARGE
Definition: contactor_cfg.h:88
@ CONT_MINUS
Definition: contactor_cfg.h:87
@ CONT_PLUS
Definition: contactor_cfg.h:86
CONT_ELECTRICAL_STATE_TYPE_e
Definition: contactor_cfg.h:70
@ CONT_SWITCH_UNDEFINED
Definition: contactor_cfg.h:73
@ CONT_SWITCH_ON
Definition: contactor_cfg.h:72
@ CONT_SWITCH_OFF
Definition: contactor_cfg.h:71
CONT_CURRENT_BREAKING_DIRECTION_e
@ CONT_BIDIRECTIONAL
@ CONT_CHARGING_DIRECTION
@ CONT_DISCHARGING_DIRECTION
Database module header.
#define DATA_READ_DATA(...)
Definition: database.h:86
#define DATA_WRITE_DATA(...)
Definition: database.h:96
@ DATA_BLOCK_ID_MIN_MAX
Definition: database_cfg.h:99
@ DATA_BLOCK_ID_ERROR_STATE
Definition: database_cfg.h:95
@ DATA_BLOCK_ID_SYSTEM_STATE
Definition: database_cfg.h:113
@ DATA_BLOCK_ID_STATE_REQUEST
Definition: database_cfg.h:112
@ DATA_BLOCK_ID_OPEN_WIRE_BASE
Definition: database_cfg.h:103
@ DATA_BLOCK_ID_PACK_VALUES
Definition: database_cfg.h:105
uint32_t DIAG_GetDelay(DIAG_ID_e diagnosisEntry)
Get configured delay of passed diagnosis entry.
Definition: diag.c:386
STD_RETURN_TYPE_e DIAG_GetDiagnosisEntryState(DIAG_ID_e diagnosisEntry)
Checks if passed diagnosis entry has been triggered or not.
Definition: diag.c:192
bool DIAG_IsAnyFatalErrorSet(void)
Check if any fatal error is set.
Definition: diag.c:391
DIAG_RETURNTYPE_e DIAG_Handler(DIAG_ID_e diagId, 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:246
Diagnosis driver header.
DIAG_DEV_s diag_device
Definition: diag_cfg.c:240
@ DIAG_EVENT_NOT_OK
Definition: diag_cfg.h:268
@ DIAG_EVENT_OK
Definition: diag_cfg.h:267
@ DIAG_SYSTEM
Definition: diag_cfg.h:280
@ DIAG_STRING
Definition: diag_cfg.h:281
@ DIAG_ID_AFE_OPEN_WIRE
Definition: diag_cfg.h:230
@ DIAG_ID_PRECHARGE_ABORT_REASON_CURRENT
Definition: diag_cfg.h:243
@ DIAG_ID_PRECHARGE_ABORT_REASON_VOLTAGE
Definition: diag_cfg.h:242
@ DIAG_ID_ALERT_MODE
Definition: diag_cfg.h:260
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:255
#define FAS_TRAP
Define that evaluates to essential boolean false thus tripping an assert.
Definition: fassert.h:129
int32_t MATH_AbsInt32_t(const int32_t value)
Returns the absolute value of passed int32_t value.
Definition: foxmath.c:152
int64_t MATH_AbsInt64_t(const int64_t value)
Returns the absolute value of passed int64_t value.
Definition: foxmath.c:160
math library for often used math functions
STD_RETURN_TYPE_e
Definition: fstd_types.h:82
@ STD_NOT_OK
Definition: fstd_types.h:84
@ STD_OK
Definition: fstd_types.h:83
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:77
#define BS_NORMAL_OPEN_WIRE_PERIOD_ms
#define BS_STANDBY_OPEN_WIRE_PERIOD_ms
IMD_RETURN_TYPE_e IMD_RequestInsulationMeasurement(void)
Request to activate the actual IMD measurement.
Definition: imd.c:516
API header for the insulation monitoring device.
@ IMD_ILLEGAL_REQUEST
Definition: imd.h:80
void LED_SetToggleTime(uint32_t onOffTime_ms)
Set debug LED with defined frequency.
Definition: led.c:114
Header file of the debug LED driver.
#define LED_NORMAL_OPERATION_ON_OFF_TIME_ms
Definition: led.h:74
#define LED_ERROR_OPERATION_ON_OFF_TIME_ms
Definition: led.h:76
STD_RETURN_TYPE_e MEAS_RequestOpenWireCheck(uint8_t string)
Makes the request to the AFE state machine to perform open-wire check.
Definition: meas.c:125
Headers for the driver for the measurements needed by the BMS (e.g., I,V,T).
Declaration of the OS wrapper interface.
void OS_ExitTaskCritical(void)
Exit Critical interface function for use in FreeRTOS-Tasks and FreeRTOS-ISR.
Definition: os_freertos.c:154
void OS_EnterTaskCritical(void)
Enter Critical interface function for use in FreeRTOS-Tasks and FreeRTOS-ISR.
Definition: os_freertos.c:150
uint32_t OS_GetTickCount(void)
Returns OS based system tick value.
Definition: os_freertos.c:158
void SOA_CheckTemperatures(DATA_BLOCK_MIN_MAX_s *pMinimumMaximumCellTemperatures, DATA_BLOCK_PACK_VALUES_s *pCurrent)
checks the abidance by the safe operating area
Definition: soa.c:148
void SOA_CheckVoltages(DATA_BLOCK_MIN_MAX_s *pMinimumMaximumCellVoltages)
checks the abidance by the safe operating area
Definition: soa.c:81
void SOA_CheckSlaveTemperatures(void)
FOR FUTURE COMPATIBILITY; DUMMY FUNCTION; DO NOT USE.
Definition: soa.c:353
void SOA_CheckCurrent(DATA_BLOCK_PACK_VALUES_s *pTablePackValues)
checks the abidance by the safe operating area
Definition: soa.c:271
Header for SOA module, responsible for checking battery parameters against safety limits.
uint32_t restTimer_10ms
Definition: bms.h:201
uint8_t prechargeTryCounter
Definition: bms.h:203
uint8_t counter
Definition: bms.h:199
bool transitionToErrorState
Definition: bms.h:218
uint16_t timer
Definition: bms.h:190
BMS_CURRENT_FLOW_STATE_e currentFlowState
Definition: bms.h:200
uint8_t triggerentry
Definition: bms.h:198
STD_RETURN_TYPE_e initFinished
Definition: bms.h:197
uint8_t closedPrechargeContactors[BS_NR_OF_STRINGS]
Definition: bms.h:219
BMS_STATEMACH_e nextstate
Definition: bms.h:209
uint8_t closedStrings[BS_NR_OF_STRINGS]
Definition: bms.h:220
uint8_t firstClosedString
Definition: bms.h:210
CONT_TYPE_e contactorToBeOpened
Definition: bms.h:217
uint8_t deactivatedStrings[BS_NR_OF_STRINGS]
Definition: bms.h:221
uint32_t nextstringclosedtimer
Definition: bms.h:207
BMS_STATE_REQUEST_e stateRequest
Definition: bms.h:191
uint8_t stringToBeOpened
Definition: bms.h:216
uint32_t ErrRequestCounter
Definition: bms.h:196
uint32_t minimumActiveDelay_ms
Definition: bms.h:214
uint8_t numberOfClosedStrings
Definition: bms.h:205
BMS_STATEMACH_e state
Definition: bms.h:192
uint16_t stringCloseTimeout
Definition: bms.h:208
BMS_STATEMACH_SUB_e substate
Definition: bms.h:193
uint16_t stringOpenTimeout
Definition: bms.h:206
uint32_t timeAboveContactorBreakCurrent_ms
Definition: bms.h:215
BMS_POWER_PATH_TYPE_e powerPath
Definition: bms.h:204
uint32_t remainingDelay_ms
Definition: bms.h:213
uint16_t OscillationTimeout
Definition: bms.h:202
const CONT_TYPE_e type
bool contactorInNegativePathOfStringFeedbackError[BS_NR_OF_STRINGS]
Definition: database_cfg.h:370
bool contactorInPositivePathOfStringFeedbackError[BS_NR_OF_STRINGS]
Definition: database_cfg.h:371
bool prechargeContactorFeedbackError[BS_NR_OF_STRINGS]
Definition: database_cfg.h:372
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:337
DATA_BLOCK_ID_e uniqueId
Definition: database_cfg.h:125
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:167
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:310
uint8_t openWire[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING *(BS_NR_OF_CELL_BLOCKS_PER_MODULE+1u)]
Definition: database_cfg.h:315
int32_t stringVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:206
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:195
int32_t stringCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:208
uint8_t invalidStringCurrent[BS_NR_OF_STRINGS]
Definition: database_cfg.h:209
uint8_t invalidStringVoltage[BS_NR_OF_STRINGS]
Definition: database_cfg.h:207
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:553
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:446
DIAG_ID_CFG_s * pFatalErrorLinkTable[DIAG_ID_MAX]
Definition: diag_cfg.h:357
uint16_t numberOfFatalErrors
Definition: diag_cfg.h:355
DIAG_ID_e id
Definition: diag_cfg.h:334