foxBMS  1.4.1
The foxBMS Battery Management System API Documentation
bms.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 bms.c
44  * @author foxBMS Team
45  * @date 2020-02-24 (date of creation)
46  * @updated 2022-10-27 (date of last update)
47  * @version v1.4.1
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 /*========== Macros and Definitions =========================================*/
71 /** default value for unset "active delay time" */
72 #define BMS_NO_ACTIVE_DELAY_TIME_ms (UINT32_MAX)
73 
74 /**
75  * Saves the last state and the last substate
76  */
77 #define BMS_SAVELASTSTATES() \
78  bms_state.laststate = bms_state.state; \
79  bms_state.lastsubstate = bms_state.substate
80 
81 /*========== Static Constant and Variable Definitions =======================*/
82 
83 /**
84  * contains the state of the bms state machine
85  */
87  .timer = 0,
88  .stateRequest = BMS_STATE_NO_REQUEST,
90  .substate = BMS_ENTRY,
91  .laststate = BMS_STATEMACH_UNINITIALIZED,
92  .lastsubstate = BMS_ENTRY,
93  .triggerentry = 0u,
94  .ErrRequestCounter = 0u,
95  .initFinished = STD_NOT_OK,
96  .counter = 0u,
97  .OscillationTimeout = 0u,
98  .PrechargeTryCounter = 0u,
99  .powerPath = BMS_POWER_PATH_OPEN,
100  .closedStrings = {0u},
101  .closedPrechargeContactors = {0u},
102  .numberOfClosedStrings = 0u,
103  .deactivatedStrings = {0},
104  .firstClosedString = 0u,
105  .stringOpenTimeout = 0u,
106  .nextstringclosedtimer = 0u,
107  .stringCloseTimeout = 0u,
108  .nextstate = BMS_STATEMACH_STANDBY,
109  .restTimer_10ms = BS_RELAXATION_PERIOD_10ms,
110  .currentFlowState = BMS_RELAXATION,
111  .remainingDelay_ms = BMS_NO_ACTIVE_DELAY_TIME_ms,
112  .minimumActiveDelay_ms = BMS_NO_ACTIVE_DELAY_TIME_ms,
113  .transitionToErrorState = false,
114  .timeAboveContactorBreakCurrent_ms = 0u,
115  .stringToBeOpened = 0u,
116  .contactorToBeOpened = CONT_UNDEFINED,
117 };
118 
119 /** local copies of database tables */
120 /**@{*/
124 /**@}*/
125 
126 /*========== Extern Constant and Variable Definitions =======================*/
127 
128 /*========== Static Function Prototypes =====================================*/
129 
130 /**
131  * @brief checks the state requests that are made.
132  * @details This function checks the validity of the state requests. The
133  * results of the checked is returned immediately.
134  * @param[in] statereq state request to be checked
135  * @return result of the state request that was made
136  */
138 
139 /**
140  * @brief transfers the current state request to the state machine.
141  * @details This function takes the current state request from #bms_state
142  * transfers it to the state machine. It resets the value from
143  * #bms_state to #BMS_STATE_NO_REQUEST
144  * @return current state request
145  */
147 
148 /**
149  * @brief re-entrance check of SYS state machine trigger function
150  * @details This function is not re-entrant and should only be called time- or
151  * event-triggered. It increments the triggerentry counter from the
152  * state variable ltc_state. It should never be called by two
153  * different processes, so if it is the case, triggerentry should
154  * never be higher than 0 when this function is called.
155  * @return retval 0 if no further instance of the function is active, 0xff
156  * else
157  */
158 static uint8_t BMS_CheckReEntrance(void);
159 
160 /**
161  * @brief Checks the state requests made to the BMS state machine.
162  * @details Checks of the state request in the database and sets this value as
163  * return value.
164  * @return requested state
165  */
166 static uint8_t BMS_CheckCanRequests(void);
167 
168 /**
169  * @brief Checks all the error flags from diagnosis module with a severity of
170  * #DIAG_FATAL_ERROR
171  * @details Checks all the error flags from diagnosis module with a severity of
172  * #DIAG_FATAL_ERROR. Furthermore, sets parameter minimumActiveDelay_ms
173  * of bms_state variable.
174  * @return true if error flag is set, otherwise false
175  */
176 static bool BMS_IsAnyFatalErrorFlagSet(void);
177 
178 /**
179  * @brief Checks if any error flag is set and handles delay until contactors
180  * need to be opened.
181  * @details Checks all the diagnosis entries with severity of #DIAG_FATAL_ERROR
182  * and handles the configured delay until the contactors need to be
183  * opened. The shortest delay is used, if multiple errors are active at
184  * once.
185  * @return #STD_NOT_OK if error detected and delay time elapsed, otherwise #STD_OK
186  */
188 
189 /**
190  * @brief Checks if the contactor feedback for a specific contactor is valid
191  * need to be opened.
192  * @details Reads error flag database entry and checks if the feedback for this
193  * specific contactor is valid or not.
194  * @return true if no error detected feedback is valid, otherwise false
195  */
196 static bool BMS_IsContactorFeedbackValid(uint8_t stringNumber, CONT_TYPE_e contactorType);
197 
198 /** Get latest database entries for static module variables */
199 static void BMS_GetMeasurementValues(void);
200 
201 /**
202  * @brief Check for any open voltage sense wire
203  */
204 static void BMS_CheckOpenSenseWire(void);
205 
206 /**
207  * @brief Checks if the current limitations are violated
208  * @param[in] stringNumber string addressed
209  * @param[in] pPackValues pointer to pack values database entry
210  * @return #STD_OK if the current limitations are NOT violated, else
211  * #STD_NOT_OK (type: #STD_RETURN_TYPE_e)
212  */
213 static STD_RETURN_TYPE_e BMS_CheckPrecharge(uint8_t stringNumber, const DATA_BLOCK_PACK_VALUES_s *pPackValues);
214 
215 /**
216  * @brief Returns ID of string with highest total voltage
217  * @details This is used to close the first string when drive-off is requested.
218  * @param[in] precharge If #BMS_DO_NOT_TAKE_PRECHARGE_INTO_ACCCOUNT,
219  * precharge availability for string is ignored.
220  * if #BMS_TAKE_PRECHARGE_INTO_ACCCOUNT, only select
221  * string that has precharge available.
222  * @param[in] pPackValues pointer to pack values database entry
223  * @return index of string with highest voltage If no string is available,
224  * returns #BMS_NO_STRING_AVAILABLE.
225  */
226 static uint8_t BMS_GetHighestString(BMS_CONSIDER_PRECHARGE_e precharge, DATA_BLOCK_PACK_VALUES_s *pPackValues);
227 
228 /**
229  * @brief Returns ID of string with voltage closest to first closed string voltage
230  * @details This is used to close further strings in drive.
231  * @param[in] precharge If #BMS_DO_NOT_TAKE_PRECHARGE_INTO_ACCCOUNT,
232  * precharge availability for string is ignored.
233  * if #BMS_TAKE_PRECHARGE_INTO_ACCCOUNT, only select
234  * string that has precharge available.
235  * @param[in] pPackValues pointer to pack values database entry
236  * @return index of string with voltage closest to the first closed string voltage.
237  * If no string is available, returns #BMS_NO_STRING_AVAILABLE.
238  */
239 static uint8_t BMS_GetClosestString(BMS_CONSIDER_PRECHARGE_e precharge, DATA_BLOCK_PACK_VALUES_s *pPackValues);
240 
241 /**
242  * @brief Returns ID of string with lowest total voltage
243  * @details This is used to close the first string when charge-off is requested.
244  *
245  * @param[in] precharge If 0, precharge availability for string is ignored.
246  * If 1, only selects a string that has precharge
247  * available.
248  * @param[in] pPackValues pointer to pack values database entry
249  * @return index of string with lowest voltage. If no string is available,
250  * returns #BMS_NO_STRING_AVAILABLE.
251  */
252 static uint8_t BMS_GetLowestString(BMS_CONSIDER_PRECHARGE_e precharge, DATA_BLOCK_PACK_VALUES_s *pPackValues);
253 
254 /**
255  * @brief Returns voltage difference between first closed string and
256  * string ID
257  * @details This function is used to check voltage when trying to close further
258  * strings.
259  * @param[in] string ID of string that must be compared with first closed
260  * string
261  * @param[in] pPackValues pointer to pack values database entry
262  * @return voltage difference in mV, will return INT32_MAX if voltages are
263  * invalid and difference can not be calculated
264  */
265 static int32_t BMS_GetStringVoltageDifference(uint8_t string, const DATA_BLOCK_PACK_VALUES_s *pPackValues);
266 
267 /**
268  * @brief Returns the average current flowing through all strings.
269  * @details This function is used when closing strings.
270  * @param[in] pPackValues pointer to pack values database entry
271  * @return average current taking all strings into account in mA. INT32_MAX if there is no valid current measurement
272  */
273 static int32_t BMS_GetAverageStringCurrent(DATA_BLOCK_PACK_VALUES_s *pPackValues);
274 
275 /**
276  * @brief Updates battery system state variable depending on measured/recent
277  * current values
278  * @param[in] pPackValues recent measured values from current sensor
279  */
280 static void BMS_UpdateBatsysState(DATA_BLOCK_PACK_VALUES_s *pPackValues);
281 
282 /**
283  * @brief Get first string contactor that should be opened depending on the
284  * actual current flow direction
285  * @details Check the mounting direction of the contactors and open the
286  * contactor that is mounted in the preferred current flow direction.
287  * Open the plus contactor first if, there is no contactor in
288  * preferred direction to the curren flow to open available. This may
289  * be either because both contactors are installed in the same
290  * direction or because the contactors are bidirectional.
291  * @param stringNumber string that will be opened
292  * @param flowDirection current flow direction (charging or discharging)
293  * @return #CONT_TYPE_e contactor that should be opened
294  */
295 static CONT_TYPE_e BMS_GetFirstContactorToBeOpened(uint8_t stringNumber, BMS_CURRENT_FLOW_STATE_e flowDirection);
296 
297 /**
298  * @brief Get second string contactor that should be opened
299  * @details Mounting direction of the contactor does not need to be checked
300  * for the second contactor as the current has already been
301  * interrupted opening the first contactor.
302  * @param stringNumber string that will be opened
303  * @param firstOpenedContactorType type of first contactor that has been opened
304  * @return #CONT_TYPE_e contactor that should be opened
305  */
306 static CONT_TYPE_e BMS_GetSecondContactorToBeOpened(uint8_t stringNumber, CONT_TYPE_e firstOpenedContactorType);
307 
308 /*========== Static Function Implementations ================================*/
309 
311  if (statereq == BMS_STATE_ERROR_REQUEST) {
312  return BMS_OK;
313  }
314 
316  /* init only allowed from the uninitialized state */
317  if (statereq == BMS_STATE_INIT_REQUEST) {
319  return BMS_OK;
320  } else {
322  }
323  } else {
324  return BMS_ILLEGAL_REQUEST;
325  }
326  } else {
327  return BMS_REQUEST_PENDING;
328  }
329 }
330 
331 static uint8_t BMS_CheckReEntrance(void) {
332  uint8_t retval = 0;
334  if (!bms_state.triggerentry) {
336  } else {
337  retval = 0xFF; /* multiple calls of function */
338  }
340  return retval;
341 }
342 
345 
347  retval = bms_state.stateRequest;
350  return retval;
351 }
352 
353 static void BMS_GetMeasurementValues(void) {
355 }
356 
357 static uint8_t BMS_CheckCanRequests(void) {
358  uint8_t retVal = BMS_REQ_ID_NOREQ;
360 
361  DATA_READ_DATA(&request);
362 
363  if (request.stateRequestViaCan == BMS_REQ_ID_STANDBY) {
364  retVal = BMS_REQ_ID_STANDBY;
365  } else if (request.stateRequestViaCan == BMS_REQ_ID_NORMAL) {
366  retVal = BMS_REQ_ID_NORMAL;
367  } else if (request.stateRequestViaCan == BMS_REQ_ID_CHARGE) {
368  retVal = BMS_REQ_ID_CHARGE;
369  } else if (request.stateRequestViaCan == BMS_REQ_ID_NOREQ) {
370  retVal = BMS_REQ_ID_NOREQ;
371  } else {
372  /* invalid or no request, default to BMS_REQ_ID_NOREQ (already set) */
373  }
374 
375  return retVal;
376 }
377 
378 static void BMS_CheckOpenSenseWire(void) {
379  uint8_t openWireDetected = 0;
380 
381  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
382  /* Iterate over all modules */
383  for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) {
384  /* Iterate over all voltage sense wires: cells per module + 1 */
385  for (uint8_t wire = 0u; wire < (BS_NR_OF_CELL_BLOCKS_PER_MODULE + 1); wire++) {
386  /* open wire detected */
387  if (bms_tableOpenWire.openwire[s][(wire + (m * (BS_NR_OF_CELL_BLOCKS_PER_MODULE + 1))) == 1] > 0u) {
388  openWireDetected++;
389 
390  /* Add additional error handling here */
391  }
392  }
393  }
394  /* Set error if open wire detected */
395  if (openWireDetected == 0u) {
397  } else {
399  }
400  }
401 }
402 
403 static STD_RETURN_TYPE_e BMS_CheckPrecharge(uint8_t stringNumber, const DATA_BLOCK_PACK_VALUES_s *pPackValues) {
404  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
405  /* make sure that we do not access the arrays in the database
406  tables out of bounds */
407  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
408  FAS_ASSERT(pPackValues != NULL_PTR);
409 
410  /* Only check precharging if current value and voltages are valid */
411  if ((pPackValues->invalidStringCurrent[stringNumber] == 0u) &&
412  (pPackValues->invalidStringVoltage[stringNumber] == 0u) && (pPackValues->invalidHvBusVoltage == 0u)) {
413  /* Only current not current direction is checked */
414  const int32_t current_mA = MATH_AbsInt32_t(pPackValues->stringCurrent_mA[stringNumber]);
415  const int64_t cont_prechargeVoltDiff_mV = MATH_AbsInt64_t(
416  (int64_t)pPackValues->stringVoltage_mV[stringNumber] - (int64_t)pPackValues->highVoltageBusVoltage_mV);
417 
418  if ((cont_prechargeVoltDiff_mV < BMS_PRECHARGE_VOLTAGE_THRESHOLD_mV) &&
419  (current_mA < BMS_PRECHARGE_CURRENT_THRESHOLD_mA)) {
420  retVal = STD_OK;
421  } else {
422  retVal = STD_NOT_OK;
423  }
424  }
425 
426  return retVal;
427 }
428 
429 static bool BMS_IsAnyFatalErrorFlagSet(void) {
430  bool fatalErrorActive = false;
431 
432  for (uint16_t entry = 0u; entry < diag_device.numberOfFatalErrors; entry++) {
433  const STD_RETURN_TYPE_e diagnosisState =
435  if (STD_NOT_OK == diagnosisState) {
436  /* Fatal error detected -> get delay of this error until contactors shall be opened */
437  const uint32_t kDelay_ms = DIAG_GetDelay(diag_device.pFatalErrorLinkTable[entry]->id);
438  /* Check if delay of detected failure is smaller than the delay of a previously detected failure */
439  if (bms_state.minimumActiveDelay_ms > kDelay_ms) {
440  bms_state.minimumActiveDelay_ms = kDelay_ms;
441  }
442  fatalErrorActive = true;
443  }
444  }
445  return fatalErrorActive;
446 }
447 
449  STD_RETURN_TYPE_e retVal = STD_OK; /* is set to STD_NOT_OK if error detected */
450  static uint32_t previousTimestamp = 0u;
451  uint32_t timestamp = OS_GetTickCount();
452 
453  /* Check if any fatal error is detected */
454  const bool isErrorActive = BMS_IsAnyFatalErrorFlagSet();
455 
456  /** Check if a fatal error has been detected previously. If yes, check delay */
457  if (bms_state.transitionToErrorState == true) {
458  /* Decrease active delay since last call */
459  const uint32_t timeSinceLastCall_ms = timestamp - previousTimestamp;
460  if (timeSinceLastCall_ms <= bms_state.remainingDelay_ms) {
461  bms_state.remainingDelay_ms -= timeSinceLastCall_ms;
462  } else {
464  }
465 
466  /* Check if delay from a new error is shorter then active delay from
467  * previously detected error in BMS statemachine */
470  }
471  } else {
472  /* Delay is not active, check if it should be activated */
473  if (isErrorActive == true) {
476  }
477  }
478 
479  /** Set previous timestamp for next call */
480  previousTimestamp = timestamp;
481 
482  /* Check if bms statemachine should switch to error state. This is the case
483  * if the delay is activated and the remaining delay is down to 0 */
484  if ((bms_state.transitionToErrorState == true) && (bms_state.remainingDelay_ms == 0u)) {
485  retVal = STD_NOT_OK;
486  }
487 
488  return retVal;
489 }
490 
491 static bool BMS_IsContactorFeedbackValid(uint8_t stringNumber, CONT_TYPE_e contactorType) {
492  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
493  FAS_ASSERT(contactorType != CONT_UNDEFINED);
494  bool feedbackValid = false;
495  /* Read latest error flags from database */
497  DATA_READ_DATA(&tableErrorFlags);
498  /* Check if contactor feedback is valid */
499  switch (contactorType) {
500  case CONT_PLUS:
501  if (tableErrorFlags.stringPlusContactor[stringNumber] == 0u) {
502  feedbackValid = true;
503  }
504  break;
505  case CONT_MINUS:
506  if (tableErrorFlags.stringMinusContactor[stringNumber] == 0u) {
507  feedbackValid = true;
508  }
509  break;
510  case CONT_PRECHARGE:
511  if (tableErrorFlags.prechargeContactor[stringNumber] == 0u) {
512  feedbackValid = true;
513  }
514  break;
515  default:
516  /* CONT_UNDEFINED already prevent via assert */
517  break;
518  }
519  return feedbackValid;
520 }
521 
523  FAS_ASSERT(pPackValues != NULL_PTR);
524  uint8_t highest_string_index = BMS_NO_STRING_AVAILABLE;
525  int32_t max_stringVoltage_mV = INT32_MIN;
526 
527  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
528  if ((pPackValues->stringVoltage_mV[s] >= max_stringVoltage_mV) &&
529  (pPackValues->invalidStringVoltage[s] == 0u)) {
530  if (bms_state.deactivatedStrings[s] == 0u) {
531  if (precharge == BMS_DO_NOT_TAKE_PRECHARGE_INTO_ACCCOUNT) {
532  max_stringVoltage_mV = pPackValues->stringVoltage_mV[s];
533  highest_string_index = s;
534  } else {
536  max_stringVoltage_mV = pPackValues->stringVoltage_mV[s];
537  highest_string_index = s;
538  }
539  }
540  }
541  }
542  }
543 
544  return highest_string_index;
545 }
546 
548  FAS_ASSERT(pPackValues != NULL_PTR);
549  uint8_t closestStringIndex = BMS_NO_STRING_AVAILABLE;
550  int32_t closedStringVoltage_mV = 0;
551  bool searchString = false;
552 
553  /* Get voltage of first closed string */
554  if (pPackValues->invalidStringVoltage[bms_state.firstClosedString] == 0u) {
555  closedStringVoltage_mV = pPackValues->stringVoltage_mV[bms_state.firstClosedString];
556  searchString = true;
557  } else if (pPackValues->invalidHvBusVoltage == 0u) {
558  /* Use high voltage bus voltage if measured string voltage is invalid */
559  closedStringVoltage_mV = pPackValues->highVoltageBusVoltage_mV;
560  searchString = true;
561  } else {
562  /* Do not search for next string if no valid voltages could be measured */
563  searchString = false;
564  }
565 
566  if (searchString == true) {
567  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
568  const bool isStringClosed = BMS_IsStringClosed(s);
569  const uint8_t isStringVoltageValid = pPackValues->invalidStringVoltage[s];
570  if ((isStringClosed == false) && (isStringVoltageValid == 0u)) {
571  /* Only check open strings with valid voltages */
572  int32_t minimumVoltageDifference_mV = INT32_MAX;
573  int32_t voltageDifference_mV = labs(closedStringVoltage_mV - pPackValues->stringVoltage_mV[s]);
574  if (voltageDifference_mV <= minimumVoltageDifference_mV) {
575  if (bms_state.deactivatedStrings[s] == 0u) {
576  if (precharge == BMS_TAKE_PRECHARGE_INTO_ACCCOUNT) {
578  minimumVoltageDifference_mV = voltageDifference_mV;
579  closestStringIndex = s;
580  }
581  } else {
582  minimumVoltageDifference_mV = voltageDifference_mV;
583  closestStringIndex = s;
584  }
585  }
586  }
587  }
588  }
589  }
590  return closestStringIndex;
591 }
592 
594  FAS_ASSERT(pPackValues != NULL_PTR);
595  uint8_t lowest_string_index = BMS_NO_STRING_AVAILABLE;
596  int32_t min_stringVoltage_mV = INT32_MAX;
597 
598  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
599  if ((pPackValues->stringVoltage_mV[s] <= min_stringVoltage_mV) &&
600  (pPackValues->invalidStringVoltage[s] == 0u)) {
601  if (bms_state.deactivatedStrings[s] == 0u) {
602  if (precharge == BMS_DO_NOT_TAKE_PRECHARGE_INTO_ACCCOUNT) {
603  min_stringVoltage_mV = pPackValues->stringVoltage_mV[s];
604  lowest_string_index = s;
605  } else {
607  min_stringVoltage_mV = pPackValues->stringVoltage_mV[s];
608  lowest_string_index = s;
609  }
610  }
611  }
612  }
613  }
614  return lowest_string_index;
615 }
616 
617 static int32_t BMS_GetStringVoltageDifference(uint8_t string, const DATA_BLOCK_PACK_VALUES_s *pPackValues) {
618  FAS_ASSERT(string < BS_NR_OF_STRINGS);
619  FAS_ASSERT(pPackValues != NULL_PTR);
620  int32_t voltageDifference_mV = INT32_MAX;
621  if ((pPackValues->invalidStringVoltage[string] == 0u) &&
622  (pPackValues->invalidStringVoltage[bms_state.firstClosedString] == 0u)) {
623  /* Calculate difference between string voltages */
624  voltageDifference_mV = MATH_AbsInt32_t(
625  pPackValues->stringVoltage_mV[string] - pPackValues->stringVoltage_mV[bms_state.firstClosedString]);
626  } else if ((pPackValues->invalidStringVoltage[string] == 0u) && (pPackValues->invalidHvBusVoltage == 0u)) {
627  /* Calculate difference between string and high voltage bus voltage */
628  voltageDifference_mV =
629  MATH_AbsInt32_t(pPackValues->stringVoltage_mV[string] - pPackValues->highVoltageBusVoltage_mV);
630  } else {
631  /* No valid voltages for comparison -> do not calculate difference and return INT32_MAX */
632  voltageDifference_mV = INT32_MAX;
633  }
634  return voltageDifference_mV;
635 }
636 
638  FAS_ASSERT(pPackValues != NULL_PTR);
639  int32_t average_current = pPackValues->packCurrent_mA / (int32_t)BS_NR_OF_STRINGS;
640  if (pPackValues->invalidPackCurrent == 1u) {
641  average_current = INT32_MAX;
642  }
643  return average_current;
644 }
645 
647  FAS_ASSERT(pPackValues != NULL_PTR);
648 
649  /* Only update system state if current value is valid */
650  if (pPackValues->invalidPackCurrent == 0u) {
651  if (POSITIVE_DISCHARGE_CURRENT == true) {
652  /* Positive current values equal a discharge of the battery system */
653  if (pPackValues->packCurrent_mA >= BS_REST_CURRENT_mA) { /* TODO: string use pack current */
656  } else if (pPackValues->packCurrent_mA <= -BS_REST_CURRENT_mA) {
659  } else {
660  /* Current below rest current: either battery system is at rest
661  * or the relaxation process is still ongoing */
662  if (bms_state.restTimer_10ms == 0u) {
663  /* Rest timer elapsed -> battery system at rest */
665  } else {
668  }
669  }
670  } else {
671  /* Negative current values equal a discharge of the battery system */
672  if (pPackValues->packCurrent_mA <= -BS_REST_CURRENT_mA) {
675  } else if (pPackValues->packCurrent_mA >= BS_REST_CURRENT_mA) {
678  } else {
679  /* Current below rest current: either battery system is at rest
680  * or the relaxation process is still ongoing */
681  if (bms_state.restTimer_10ms == 0u) {
682  /* Rest timer elapsed -> battery system at rest */
684  } else {
687  }
688  }
689  }
690  }
691 }
692 
693 static CONT_TYPE_e BMS_GetFirstContactorToBeOpened(uint8_t stringNumber, BMS_CURRENT_FLOW_STATE_e flowDirection) {
694  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
695  /* AXIVION Routine Generic-MissingParameterAssert: flowDirection: parameter accepts all defined enums */
696  CONT_TYPE_e contactorToBeOpened = CONT_UNDEFINED;
698  /* Required preferred opening direction dependent on the current direction */
699  if (flowDirection == BMS_CHARGING) {
700  breakingDirection = CONT_CHARGING_DIRECTION;
701  } else {
702  breakingDirection = CONT_DISCHARGING_DIRECTION;
703  }
704  /* Iterate over contactor array and search for wanted contactor */
705  uint8_t contactor = 0u;
706  for (; contactor < BS_NR_OF_CONTACTORS; contactor++) {
707  /* Search for:
708  * 1. contactor from requested string
709  * 2. contactor mounted in preferred opening direction or is bidirectional
710  * 3. is no precharge contactor */
711  bool correctString = (bool)(stringNumber == cont_contactorStates[contactor].stringIndex);
712  bool inPreferredDirection = (bool)(breakingDirection == cont_contactorStates[contactor].breakingDirection);
713  bool hasNoPreferredDirection = (bool)(cont_contactorStates[contactor].breakingDirection == CONT_BIDIRECTIONAL);
714  bool noPrechargeContactor = (bool)(cont_contactorStates[contactor].type != CONT_PRECHARGE);
715  if (correctString && noPrechargeContactor && (inPreferredDirection || hasNoPreferredDirection)) {
716  contactorToBeOpened = cont_contactorStates[contactor].type;
717  break;
718  }
719  }
720  if (contactor == BS_NR_OF_CONTACTORS) {
721  /* No contactor mounted in preferred current direction found. Select
722  * the PLUS contactor found in array cont_contactorStates from the
723  * passed string */
724  for (contactor = 0u; contactor < BS_NR_OF_CONTACTORS; contactor++) {
725  /* Search for:
726  * 1. contactor from requested string
727  * 2. is PLUS contactor */
728  if ((stringNumber == cont_contactorStates[contactor].stringIndex) &&
729  (cont_contactorStates[contactor].type == CONT_PLUS)) {
730  contactorToBeOpened = cont_contactorStates[contactor].type;
731  break;
732  }
733  }
734  }
735  if (contactor == BS_NR_OF_CONTACTORS) {
736  /* No PLUS contactor found. Select MINUS contactor found in array
737  * cont_contactorStates from the passed string */
738  for (contactor = 0u; contactor < BS_NR_OF_CONTACTORS; contactor++) {
739  /* Search for:
740  * 1. contactor from requested string
741  * 2. is PLUS contactor */
742  if ((stringNumber == cont_contactorStates[contactor].stringIndex) &&
743  (cont_contactorStates[contactor].type == CONT_MINUS)) {
744  contactorToBeOpened = cont_contactorStates[contactor].type;
745  break;
746  }
747  }
748  }
749  if (contactor == BS_NR_OF_CONTACTORS) {
750  /* No PLUS or MAIN_MINUS contactor found in requested string. */
752  }
753  return contactorToBeOpened;
754 }
755 
756 static CONT_TYPE_e BMS_GetSecondContactorToBeOpened(uint8_t stringNumber, CONT_TYPE_e firstOpenedContactorType) {
757  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
758  FAS_ASSERT((firstOpenedContactorType != CONT_UNDEFINED) && (firstOpenedContactorType != CONT_PRECHARGE));
759  CONT_TYPE_e contactorToBeOpened = CONT_UNDEFINED;
760  /* Check what contactor has already been opened and select the other one */
761  if (firstOpenedContactorType == CONT_PLUS) {
762  contactorToBeOpened = CONT_MINUS;
763  } else {
764  contactorToBeOpened = CONT_PLUS;
765  }
766  /* Iterate over contactor array and search for wanted contactor */
767  uint8_t contactor = 0u;
768  for (; contactor < BS_NR_OF_CONTACTORS; contactor++) {
769  /* Search for specific contactor from requested string */
770  if ((stringNumber == cont_contactorStates[contactor].stringIndex) &&
771  (contactorToBeOpened == cont_contactorStates[contactor].type)) {
772  contactorToBeOpened = cont_contactorStates[contactor].type;
773  break;
774  }
775  }
776  if (contactor == BS_NR_OF_CONTACTORS) {
777  /* No PLUS or MAIN_MINUS contactor found in requested string.
778  * Apparently, only one contactor has been defined for this string */
780  }
781  return contactorToBeOpened;
782 }
783 
784 /*========== Extern Function Implementations ================================*/
785 
787  return bms_state.initFinished;
788 }
789 
791  return bms_state.state;
792 }
793 
795  BMS_RETURN_TYPE_e retVal = BMS_OK;
796 
798  retVal = BMS_CheckStateRequest(statereq);
799 
800  if (retVal == BMS_OK) {
801  bms_state.stateRequest = statereq;
802  }
804 
805  return retVal;
806 }
807 
808 void BMS_Trigger(void) {
811  uint32_t timestamp = OS_GetTickCount();
812  static uint32_t nextOpenWireCheck = 0;
813  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
814  static uint8_t stringNumber = 0u;
815  static uint8_t nextStringNumber = 0u;
817  bool contactorFeedbackValid = false;
818  STD_RETURN_TYPE_e contRetVal = STD_NOT_OK;
819 
829  }
830  /* Check re-entrance of function */
831  if (BMS_CheckReEntrance() > 0u) {
832  return;
833  }
834 
835  if (bms_state.nextstringclosedtimer > 0u) {
837  }
838  if (bms_state.stringOpenTimeout > 0u) {
840  }
841 
842  if (bms_state.stringCloseTimeout > 0u) {
844  }
845 
846  if (bms_state.OscillationTimeout > 0u) {
848  }
849 
850  if (bms_state.timer > 0u) {
851  if ((--bms_state.timer) > 0u) {
853  return; /* handle state machine only if timer has elapsed */
854  }
855  }
856 
857  /****Happens every time the state machine is triggered**************/
858  switch (bms_state.state) {
859  /****************************UNINITIALIZED****************************/
861  /* waiting for Initialization Request */
862  statereq = BMS_TransferStateRequest();
863  if (statereq == BMS_STATE_INIT_REQUEST) {
868  } else if (statereq == BMS_STATE_NO_REQUEST) {
869  /* no actual request pending */
870  } else {
871  bms_state.ErrRequestCounter++; /* illegal request pending */
872  }
873  break;
874 
875  /****************************INITIALIZATION***************************/
878  /* Reset ALERT mode flag */
884  break;
885 
886  /****************************INITIALIZED******************************/
890  /* Initialization of IMD device not finished yet -> wait until this is finished before moving on */
892  } else {
896  }
897  break;
898 
899  /****************************IDLE*************************************/
900  case BMS_STATEMACH_IDLE:
902 
903  if (bms_state.substate == BMS_ENTRY) {
904  DATA_READ_DATA(&systemstate);
905  systemstate.bmsCanState = BMS_CANSTATE_IDLE;
906  DATA_WRITE_DATA(&systemstate);
909  break;
910  } else if (bms_state.substate == BMS_CHECK_ERROR_FLAGS) {
916  break;
917  } else {
920  break;
921  }
927  break;
928  }
929  break;
930 
931  /****************************OPEN CONTACTORS**************************/
934 
935  if (bms_state.substate == BMS_ENTRY) {
939  break;
941  /* Precharge contactors can always be opened as the precharge
942  * resistor limits the maximum current */
944 
945  /* Now go to string opening - open one string after another */
946  stringNumber = BS_NR_OF_STRINGS - 1u; /* Select last string */
950  /* Precharge contactors have been opened -> start opening first string contactor */
951  /* TODO: Check if precharge contactors have been opened? */
952 
953  if ((bms_tablePackValues.invalidStringCurrent[stringNumber] == 0u) &&
956  /* Current is below maximum break current -> open first contactor
957  * Check the mounting direction of the contactors and open the contactor that is mounted in the
958  * preferred current flow direction. Open the plus contactor first if, there is no contactor
959  * in preferred direction to the curren flow to open available. This may be either because both
960  * contactors are installed in the same direction or because the contactors are bidirectional.
961  */
962  const BMS_CURRENT_FLOW_STATE_e flowDirection =
964  bms_state.contactorToBeOpened = BMS_GetFirstContactorToBeOpened(stringNumber, flowDirection);
965  bms_state.stringToBeOpened = stringNumber;
966  /* Open first contactor */
971  } else {
972  /* Current is above maximum contactor break current -> contactor can not be opened */
975  /* Fuse should have been triggered by now but apparently has not yet. Do not wait any
976  * longer. Activate ALERT mode and nevertheless start opening the contactors */
978  const BMS_CURRENT_FLOW_STATE_e flowDirection =
980  bms_state.contactorToBeOpened = BMS_GetFirstContactorToBeOpened(stringNumber, flowDirection);
981  bms_state.stringToBeOpened = stringNumber;
982  /* Open first contactor */
986  }
987  }
988  break;
990  /* Check if first contactor has been opened correctly */
992  contactorFeedbackValid =
994  /* If we want to open the contactors because of a feedback
995  * error for this contactor, the statement will never be true.
996  * Thus, also continue if a feedback error for this contactor
997  * is detected as we are not able to get a valid feedback
998  * information at this point */
999  if ((contactorState == CONT_SWITCH_OFF) || (contactorFeedbackValid == false)) {
1000  /* First contactor opened correctly.
1001  * Open second contactor. Pass first opened contactor into function */
1004  /* Open second contactor */
1008  } else {
1009  /* String not opened, re-issue closing request */
1012  /* TODO: add timeout */
1013  }
1015  /* Check if second contactor has been opened correctly */
1017  contactorFeedbackValid =
1019  /* If we want to open the contactors because of a feedback
1020  * error for this contactor, the statement will never be true.
1021  * Thus, also continue if a feedback error for this contactor
1022  * is detected as we are not able to get a valid feedback
1023  * information at this point */
1024  if ((contactorState == CONT_SWITCH_OFF) || (contactorFeedbackValid == false)) {
1025  /* Opening for this string finished. Reset state variables used for opening */
1028  /* String opened. Decrement string counter */
1029  if (bms_state.numberOfClosedStrings > 0u) {
1031  }
1032  bms_state.closedStrings[stringNumber] = 0u;
1033  if (stringNumber > 0u) {
1034  /* Not all strings opened yet -> open next string */
1035  stringNumber--;
1038  break;
1039  } else {
1040  /* All strings opened -> prepare to leave state BMS_STATEMACH_OPEN_CONTACTORS */
1043  }
1044  break;
1045  } else if (bms_state.stringOpenTimeout == 0u) {
1046  /* String takes too long to open, go to next string */
1049  break;
1050  } else {
1051  /* String not opened, re-issue closing request */
1054  break;
1055  }
1056  } else if (bms_state.substate == BMS_OPEN_STRINGS_EXIT) {
1058  /* Opening due to STANDBY request -> switch to BMS_STATEMACH_STANDBY */
1062  break;
1063  } else {
1064  /* Opening due to detected error -> switch to BMS_STATEMACH_ERROR */
1068  }
1069  } else {
1071  }
1072  break;
1073 
1074  /****************************STANDBY**********************************/
1075  case BMS_STATEMACH_STANDBY:
1077  if (bms_state.substate == BMS_ENTRY) {
1079 #if BS_STANDBY_PERIODIC_OPEN_WIRE_CHECK == TRUE
1080  nextOpenWireCheck = timestamp + BS_STANDBY_OPEN_WIRE_PERIOD_ms;
1081 #endif /* BS_STANDBY_PERIODIC_OPEN_WIRE_CHECK == TRUE */
1084  DATA_READ_DATA(&systemstate);
1085  systemstate.bmsCanState = BMS_CANSTATE_STANDBY;
1086  DATA_WRITE_DATA(&systemstate);
1087  break;
1094  break;
1095  } else {
1098  break;
1099  }
1100  } else if (bms_state.substate == BMS_INTERLOCK_CHECKED) {
1103  break;
1104  } else if (bms_state.substate == BMS_CHECK_ERROR_FLAGS) {
1110  break;
1111  } else {
1114  break;
1115  }
1123  break;
1124  }
1131  break;
1132  } else {
1133 #if BS_STANDBY_PERIODIC_OPEN_WIRE_CHECK == TRUE
1134  if (nextOpenWireCheck <= timestamp) {
1136  nextOpenWireCheck = timestamp + BS_STANDBY_OPEN_WIRE_PERIOD_ms;
1137  }
1138 #endif /* BS_STANDBY_PERIODIC_OPEN_WIRE_CHECK == TRUE */
1141  break;
1142  }
1143  } else {
1145  }
1146  break;
1147 
1148  /****************************PRECHARGE********************************/
1151 
1152  if (bms_state.substate == BMS_ENTRY) {
1153  DATA_READ_DATA(&systemstate);
1154  systemstate.bmsCanState = BMS_CANSTATE_PRECHARGE;
1155  DATA_WRITE_DATA(&systemstate);
1158  } else {
1160  }
1161  if (stringNumber == BMS_NO_STRING_AVAILABLE) {
1166  break;
1167  }
1168  bms_state.firstClosedString = stringNumber;
1169  if (bms_state.OscillationTimeout == 0u) {
1170  /* Close MINUS string contactor */
1175  } else {
1176  /* Invalid contactor requested */
1181  }
1182  } else if (BMS_IsBatterySystemStateOkay() == STD_NOT_OK) {
1183  /* If precharge re-enter timeout not elapsed, wait (and check errors while waiting) */
1188  break;
1189  }
1190  break;
1192  /* Check if MINUS contactor has been successfully closed */
1194  if (contactorState == CONT_SWITCH_ON) {
1197  bms_state.closedPrechargeContactors[stringNumber] = 1u;
1198  if (contRetVal == STD_OK) {
1202  } else {
1207  }
1208  } else if (bms_state.stringCloseTimeout == 0u) {
1209  /* String takes too long to close */
1214  } else {
1215  /* String not closed, re-issue closing request */
1218  }
1219  break;
1226  break;
1227  } else {
1230  break;
1231  }
1238  break;
1239  } else {
1242  }
1246  /* Check if precharge contactor is closed and precharge is finished */
1247  if ((contactorState == CONT_SWITCH_ON) && (retVal == STD_OK)) {
1248  /* Successfully precharged. Close string PLUS contactor */
1253  break;
1254  } else {
1255  /* Precharging failed. Open precharge contactor. */
1257  /* Check if retry limit has been reached */
1259  bms_state.closedPrechargeContactors[stringNumber] = 0u;
1260  if (contRetVal == STD_OK) {
1264  } else {
1269  }
1270  break;
1271  } else {
1272  bms_state.closedPrechargeContactors[stringNumber] = 0u;
1277  break;
1278  }
1279  }
1282  if (contactorState == CONT_SWITCH_ON) {
1287  break;
1288  } else if (bms_state.stringCloseTimeout == 0u) {
1289  /* String takes too long to close */
1294  break;
1295  } else {
1296  /* String not closed, re-issue closing request */
1300  break;
1301  }
1308  break;
1309  } else {
1312  break;
1313  }
1315  /* Always make one error check after the first string was closed successfully */
1321  break;
1322  } else {
1325  break;
1326  }
1329  if (contRetVal == STD_OK) {
1330  bms_state.closedPrechargeContactors[stringNumber] = 0u;
1333  } else {
1338  }
1339  break;
1342  if (contactorState == CONT_SWITCH_OFF) {
1346  break;
1347  } else if (bms_state.stringCloseTimeout == 0u) {
1348  /* Precharge contactor takes too long to open */
1353  break;
1354  } else {
1355  /* Precharge contactor not opened, re-issue open request */
1359  break;
1360  }
1361  } else {
1363  }
1364  break;
1365 
1366  /****************************NORMAL**************************************/
1367  case BMS_STATEMACH_NORMAL:
1369 
1370  if (bms_state.substate == BMS_ENTRY) {
1371 #if BS_NORMAL_PERIODIC_OPEN_WIRE_CHECK == TRUE
1372  nextOpenWireCheck = timestamp + BS_NORMAL_OPEN_WIRE_PERIOD_ms;
1373 #endif /* BS_NORMAL_PERIODIC_OPEN_WIRE_CHECK == TRUE */
1374  DATA_READ_DATA(&systemstate);
1376  systemstate.bmsCanState = BMS_CANSTATE_CHARGE;
1377  } else {
1378  systemstate.bmsCanState = BMS_CANSTATE_NORMAL;
1379  }
1380  DATA_WRITE_DATA(&systemstate);
1384  break;
1385  } else if (bms_state.substate == BMS_CHECK_ERROR_FLAGS) {
1391  break;
1392  } else {
1395  break;
1396  }
1403  break;
1404  } else {
1405 #if BS_NORMAL_PERIODIC_OPEN_WIRE_CHECK == TRUE
1406  if (nextOpenWireCheck <= timestamp) {
1408  nextOpenWireCheck = timestamp + BS_NORMAL_OPEN_WIRE_PERIOD_ms;
1409  }
1410 #endif /* BS_NORMAL_PERIODIC_OPEN_WIRE_CHECK == TRUE */
1413  break;
1414  }
1416  if (bms_state.nextstringclosedtimer == 0u) {
1417  nextStringNumber =
1419  if (nextStringNumber == BMS_NO_STRING_AVAILABLE) {
1422  break;
1423  } else if (
1424  (BMS_GetStringVoltageDifference(nextStringNumber, &bms_tablePackValues) <=
1427  /* Voltage/current conditions suitable to close a further string. Close first string contactor */
1428  CONT_CloseContactor(nextStringNumber, CONT_MINUS);
1432  break;
1433  }
1434  } else {
1437  break;
1438  }
1440  contactorState = CONT_GetContactorState(nextStringNumber, CONT_MINUS);
1441  if (contactorState == CONT_SWITCH_ON) {
1442  /* First string contactor closed. Close second string contactor */
1443  CONT_CloseContactor(nextStringNumber, CONT_PLUS);
1446  } else if (bms_state.stringCloseTimeout == 0u) {
1447  /* String takes too long to close */
1452  break;
1453  } else {
1454  /* String minus contactor has not been closed successfully. Re-trigger closing */
1455  CONT_CloseContactor(nextStringNumber, CONT_MINUS);
1457  }
1458  break;
1459  } else if (bms_state.substate == BMS_CHECK_STRING_CLOSED) {
1460  contactorState = CONT_GetContactorState(nextStringNumber, CONT_PLUS);
1461  if (contactorState == CONT_SWITCH_ON) {
1463  bms_state.closedStrings[nextStringNumber] = 1u;
1465  /* Go to begin of NORMAL case to redo the full procedure with error check and request check */
1467  break;
1468  } else if (bms_state.stringCloseTimeout == 0u) {
1469  /* String takes too long to close */
1474  break;
1475  } else if (BMS_IsBatterySystemStateOkay() == STD_NOT_OK) {
1480  break;
1481  } else if (BMS_CheckCanRequests() == BMS_REQ_ID_STANDBY) {
1486  break;
1487  } else {
1488  /* String not closed, re-issue closing request */
1489  CONT_CloseContactor(nextStringNumber, CONT_PLUS);
1491  break;
1492  }
1493  } else {
1495  }
1496  break;
1497 
1498  /****************************ERROR*************************************/
1499  case BMS_STATEMACH_ERROR:
1501 
1502  if (bms_state.substate == BMS_ENTRY) {
1503  /* Set BMS System state to error */
1504  DATA_READ_DATA(&systemstate);
1505  systemstate.bmsCanState = BMS_CANSTATE_ERROR;
1506  DATA_WRITE_DATA(&systemstate);
1507  /* Deactivate balancing */
1509  /* Change LED toggle frequency to indicate an error */
1511  /* Set timer for next open wire check */
1512  nextOpenWireCheck = timestamp + AFE_ERROR_OPEN_WIRE_PERIOD_ms;
1513  /* Switch to next substate */
1516  break;
1517  } else if (bms_state.substate == BMS_CHECK_ERROR_FLAGS) {
1518  if (DIAG_IsAnyFatalErrorSet() == true) {
1519  /* we stay already in requested state */
1520  if (nextOpenWireCheck <= timestamp) {
1521  /* Perform open-wire check periodically */
1522  /* MEAS_RequestOpenWireCheck(); */ /*TODO: check with strings */
1523  nextOpenWireCheck = timestamp + AFE_ERROR_OPEN_WIRE_PERIOD_ms;
1524  }
1525  } else {
1526  /* No error detected anymore - reset fatal error related variables */
1530  /* Check for STANDBY request */
1533  break;
1534  }
1537  /* Activate balancing again */
1539  /* Set LED frequency to normal operation as we leave error
1540  state subsequently */
1542 
1543  /* Verify that all contactors are opened and switch to
1544  * STANDBY state afterwards */
1548  break;
1549  } else {
1552  break;
1553  }
1554  } else {
1555  /* invalid state -> this should never be reached */
1557  }
1558  break;
1559  default:
1560  /* invalid state */
1562  break;
1563  } /* end switch (bms_state.state) */
1564 
1566  bms_state.counter++;
1567 }
1568 
1570  return bms_state.currentFlowState;
1571 }
1572 
1574  /* AXIVION Routine Generic-MissingParameterAssert: current_mA: parameter accepts whole range */
1576 
1577  if (POSITIVE_DISCHARGE_CURRENT == true) {
1578  if (current_mA >= BS_REST_CURRENT_mA) {
1579  retVal = BMS_DISCHARGING;
1580  } else if (current_mA <= -BS_REST_CURRENT_mA) {
1581  retVal = BMS_CHARGING;
1582  } else {
1583  retVal = BMS_AT_REST;
1584  }
1585  } else {
1586  if (current_mA <= -BS_REST_CURRENT_mA) {
1587  retVal = BMS_DISCHARGING;
1588  } else if (current_mA >= BS_REST_CURRENT_mA) {
1589  retVal = BMS_CHARGING;
1590  } else {
1591  retVal = BMS_AT_REST;
1592  }
1593  }
1594  return retVal;
1595 }
1596 
1597 extern bool BMS_IsStringClosed(uint8_t stringNumber) {
1598  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
1599  bool retval = false;
1600  if (bms_state.closedStrings[stringNumber] == 1u) {
1601  retval = true;
1602  }
1603  return retval;
1604 }
1605 
1606 extern bool BMS_IsStringPrecharging(uint8_t stringNumber) {
1607  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
1608  bool retval = false;
1609  if (bms_state.closedPrechargeContactors[stringNumber] == 1u) {
1610  retval = true;
1611  }
1612  return retval;
1613 }
1614 
1615 extern uint8_t BMS_GetNumberOfConnectedStrings(void) {
1617 }
1618 
1621 }
1622 
1623 /*========== Externalized Static Function Implementations (Unit Test) =======*/
1624 #ifdef UNITY_UNIT_TEST
1625 extern BMS_RETURN_TYPE_e TEST_BMS_CheckStateRequest(BMS_STATE_REQUEST_e statereq) {
1626  return BMS_CheckStateRequest(statereq);
1627 }
1628 extern BMS_STATE_REQUEST_e TEST_BMS_TransferStateRequest(void) {
1629  return BMS_TransferStateRequest();
1630 }
1631 extern uint8_t TEST_BMS_CheckReEntrance(void) {
1632  return BMS_CheckReEntrance();
1633 }
1634 extern uint8_t TEST_BMS_CheckCanRequests(void) {
1635  return BMS_CheckCanRequests();
1636 }
1637 extern bool TEST_BMS_IsAnyFatalErrorFlagSet(void) {
1638  return BMS_IsAnyFatalErrorFlagSet();
1639 }
1640 extern STD_RETURN_TYPE_e TEST_BMS_IsBatterySystemStateOkay(void) {
1642 }
1643 extern void TEST_BMS_GetMeasurementValues(void) {
1645 }
1646 extern void TEST_BMS_CheckOpenSenseWire(void) {
1648 }
1649 extern STD_RETURN_TYPE_e TEST_BMS_CheckPrecharge(uint8_t stringNumber, DATA_BLOCK_PACK_VALUES_s *pPackValues) {
1650  return BMS_CheckPrecharge(stringNumber, pPackValues);
1651 }
1652 extern uint8_t TEST_BMS_GetHighestString(BMS_CONSIDER_PRECHARGE_e precharge, DATA_BLOCK_PACK_VALUES_s *pPackValues) {
1653  return BMS_GetHighestString(precharge, pPackValues);
1654 }
1655 extern uint8_t TEST_BMS_GetClosestString(BMS_CONSIDER_PRECHARGE_e precharge, DATA_BLOCK_PACK_VALUES_s *pPackValues) {
1656  return BMS_GetClosestString(precharge, pPackValues);
1657 }
1658 
1659 extern uint8_t TEST_BMS_GetLowestString(BMS_CONSIDER_PRECHARGE_e precharge, DATA_BLOCK_PACK_VALUES_s *pPackValues) {
1660  return BMS_GetLowestString(precharge, pPackValues);
1661 }
1662 extern int32_t TEST_BMS_GetStringVoltageDifference(uint8_t string, DATA_BLOCK_PACK_VALUES_s *pPackValues) {
1663  return BMS_GetStringVoltageDifference(string, pPackValues);
1664 }
1665 extern int32_t TEST_BMS_GetAverageStringCurrent(DATA_BLOCK_PACK_VALUES_s *pPackValues) {
1666  return BMS_GetAverageStringCurrent(pPackValues);
1667 }
1668 extern void TEST_BMS_UpdateBatsysState(DATA_BLOCK_PACK_VALUES_s *pPackValues) {
1669  BMS_UpdateBatsysState(pPackValues);
1670 }
1671 
1672 #endif
AFE driver header.
#define AFE_ERROR_OPEN_WIRE_PERIOD_ms
Definition: afe.h:65
Header for the driver for balancing.
@ BAL_STATE_ALLOWBALANCING_REQUEST
Definition: bal.h:104
@ BAL_STATE_NO_BALANCING_REQUEST
Definition: bal.h:103
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 determing rest state of battery. If absolute current is below this limit value ...
#define BS_MAIN_CONTACTORS_MAXIMUM_BREAK_CURRENT_mA
Maximum break current of main contactors.
#define 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:403
#define BMS_SAVELASTSTATES()
Definition: bms.c:77
static DATA_BLOCK_MIN_MAX_s bms_tableMinMax
Definition: bms.c:121
bool BMS_IsStringPrecharging(uint8_t stringNumber)
Returns if string is currently precharging or not.
Definition: bms.c:1606
bool BMS_IsTransitionToErrorStateActive(void)
Check if transition in to error state is active.
Definition: bms.c:1619
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:794
static bool BMS_IsAnyFatalErrorFlagSet(void)
Checks all the error flags from diagnosis module with a severity of DIAG_FATAL_ERROR.
Definition: bms.c:429
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:491
static BMS_RETURN_TYPE_e BMS_CheckStateRequest(BMS_STATE_REQUEST_e statereq)
checks the state requests that are made.
Definition: bms.c:310
static void BMS_GetMeasurementValues(void)
Definition: bms.c:353
static DATA_BLOCK_PACK_VALUES_s bms_tablePackValues
Definition: bms.c:123
static void BMS_UpdateBatsysState(DATA_BLOCK_PACK_VALUES_s *pPackValues)
Updates battery system state variable depending on measured/recent current values.
Definition: bms.c:646
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:693
#define BMS_NO_ACTIVE_DELAY_TIME_ms
Definition: bms.c:72
static int32_t BMS_GetAverageStringCurrent(DATA_BLOCK_PACK_VALUES_s *pPackValues)
Returns the average current flowing through all strings.
Definition: bms.c:637
void BMS_Trigger(void)
trigger function for the SYS driver state machine.
Definition: bms.c:808
uint8_t BMS_GetNumberOfConnectedStrings(void)
Returns number of connected strings.
Definition: bms.c:1615
bool BMS_IsStringClosed(uint8_t stringNumber)
Returns string state (closed or open)
Definition: bms.c:1597
static void BMS_CheckOpenSenseWire(void)
Check for any open voltage sense wire.
Definition: bms.c:378
BMS_CURRENT_FLOW_STATE_e BMS_GetCurrentFlowDirection(int32_t current_mA)
Get current flow direction, current value as function parameter.
Definition: bms.c:1573
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:617
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:593
BMS_CURRENT_FLOW_STATE_e BMS_GetBatterySystemState(void)
Returns current battery system state (charging/discharging, resting or in relaxation phase)
Definition: bms.c:1569
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:522
static uint8_t BMS_CheckReEntrance(void)
re-entrance check of SYS state machine trigger function
Definition: bms.c:331
static DATA_BLOCK_OPEN_WIRE_s bms_tableOpenWire
Definition: bms.c:122
static BMS_STATE_REQUEST_e BMS_TransferStateRequest(void)
transfers the current state request to the state machine.
Definition: bms.c:343
static BMS_STATE_s bms_state
Definition: bms.c:86
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:448
static CONT_TYPE_e BMS_GetSecondContactorToBeOpened(uint8_t stringNumber, CONT_TYPE_e firstOpenedContactorType)
Get second string contactor that should be opened.
Definition: bms.c:756
STD_RETURN_TYPE_e BMS_GetInitializationState(void)
Gets the initialization state.
Definition: bms.c:786
static uint8_t BMS_CheckCanRequests(void)
Checks the state requests made to the BMS state machine.
Definition: bms.c:357
BMS_STATEMACH_e BMS_GetState(void)
Returns the current state.
Definition: bms.c:790
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:547
bms driver header
@ BMS_CANSTATE_NORMAL
Definition: bms.h:116
@ BMS_CANSTATE_CHARGE
Definition: bms.h:117
@ BMS_CANSTATE_STANDBY
Definition: bms.h:114
@ BMS_CANSTATE_ERROR
Definition: bms.h:118
@ BMS_CANSTATE_IDLE
Definition: bms.h:112
@ BMS_CANSTATE_PRECHARGE
Definition: bms.h:115
BMS_CONSIDER_PRECHARGE_e
Definition: bms.h:83
@ BMS_DO_NOT_TAKE_PRECHARGE_INTO_ACCCOUNT
Definition: bms.h:84
@ BMS_TAKE_PRECHARGE_INTO_ACCCOUNT
Definition: bms.h:85
BMS_STATE_REQUEST_e
Definition: bms.h:159
@ BMS_STATE_NO_REQUEST
Definition: bms.h:162
@ BMS_STATE_INIT_REQUEST
Definition: bms.h:160
@ BMS_STATE_ERROR_REQUEST
Definition: bms.h:161
@ BMS_NORMAL_CLOSE_SECOND_STRING_CONTACTOR
Definition: bms.h:148
@ BMS_PRECHARGE_OPEN_PRECHARGE
Definition: bms.h:134
@ BMS_OPEN_SECOND_STRING_CONTACTOR
Definition: bms.h:153
@ BMS_OPEN_STRINGS_EXIT
Definition: bms.h:155
@ BMS_PRECHARGE_CLOSE_PRECHARGE
Definition: bms.h:132
@ BMS_NORMAL_CLOSE_NEXT_STRING
Definition: bms.h:147
@ BMS_CHECK_CLOSE_SECOND_STRING_CONTACTOR_PRECHARGE_STATE
Definition: bms.h:139
@ BMS_CHECK_ERROR_FLAGS_PRECHARGE_CLOSINGSTRINGS
Definition: bms.h:145
@ BMS_ENTRY
Definition: bms.h:123
@ BMS_INTERLOCK_CHECKED
Definition: bms.h:125
@ BMS_CHECK_ERROR_FLAGS_PRECHARGE_FIRST_STRING
Definition: bms.h:141
@ BMS_CHECK_ERROR_FLAGS_CLOSINGPRECHARGE
Definition: bms.h:146
@ BMS_PRECHARGE_CHECK_VOLTAGES
Definition: bms.h:133
@ BMS_CHECK_STRING_CLOSED
Definition: bms.h:144
@ BMS_PRECHARGE_CHECK_OPEN_PRECHARGE
Definition: bms.h:135
@ BMS_CHECK_ERROR_FLAGS
Definition: bms.h:128
@ BMS_OPEN_ALL_PRECHARGES
Definition: bms.h:149
@ BMS_CHECK_ERROR_FLAGS_INTERLOCK
Definition: bms.h:124
@ BMS_CHECK_STATE_REQUESTS
Definition: bms.h:126
@ BMS_OPEN_FIRST_STRING_CONTACTOR
Definition: bms.h:152
@ BMS_CHECK_SECOND_STRING_CONTACTOR
Definition: bms.h:154
@ BMS_POWER_PATH_1
Definition: bms.h:177
@ BMS_POWER_PATH_OPEN
Definition: bms.h:175
@ BMS_POWER_PATH_0
Definition: bms.h:176
BMS_STATEMACH_e
Definition: bms.h:89
@ BMS_STATEMACH_PRECHARGE
Definition: bms.h:97
@ BMS_STATEMACH_STANDBY
Definition: bms.h:96
@ BMS_STATEMACH_CHARGE
Definition: bms.h:100
@ BMS_STATEMACH_UNINITIALIZED
Definition: bms.h:91
@ BMS_STATEMACH_ERROR
Definition: bms.h:101
@ BMS_STATEMACH_NORMAL
Definition: bms.h:98
@ BMS_STATEMACH_INITIALIZATION
Definition: bms.h:92
@ BMS_STATEMACH_DISCHARGE
Definition: bms.h:99
@ BMS_STATEMACH_OPEN_CONTACTORS
Definition: bms.h:95
@ BMS_STATEMACH_INITIALIZED
Definition: bms.h:93
@ BMS_STATEMACH_IDLE
Definition: bms.h:94
BMS_CURRENT_FLOW_STATE_e
Definition: bms.h:68
@ BMS_AT_REST
Definition: bms.h:72
@ BMS_DISCHARGING
Definition: bms.h:70
@ BMS_CHARGING
Definition: bms.h:69
@ BMS_RELAXATION
Definition: bms.h:71
BMS_RETURN_TYPE_e
Definition: bms.h:166
@ BMS_OK
Definition: bms.h:167
@ BMS_REQUEST_PENDING
Definition: bms.h:168
@ BMS_ALREADY_INITIALIZED
Definition: bms.h:170
@ BMS_ILLEGAL_REQUEST
Definition: bms.h:169
#define BMS_REQ_ID_STANDBY
Definition: bms_cfg.h:68
#define BMS_AVERAGE_STRING_CURRENT_LIMIT_MA
Definition: bms_cfg.h:143
#define BMS_TIME_WAIT_AFTER_OPENING_PRECHARGE
Definition: bms_cfg.h:149
#define BMS_STATEMACH_LONGTIME
BMS state machine long time definition in BMS_Trigger() calls until next state/substate is processed.
Definition: bms_cfg.h:113
#define BMS_STATEMACHINE_TASK_CYCLE_CONTEXT_MS
TODO.
Definition: bms_cfg.h:91
#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:134
#define BMS_REQ_ID_NOREQ
Definition: bms_cfg.h:65
#define BMS_WAIT_TIME_AFTER_OPENING_STRING_CONTACTOR
Definition: bms_cfg.h:119
#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:128
#define BMS_WAIT_TIME_AFTER_CLOSING_STRING_CONTACTOR
Definition: bms_cfg.h:116
#define BMS_WAIT_TIME_BETWEEN_CLOSING_STRINGS
Definition: bms_cfg.h:122
#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:140
#define BMS_PRECHARGE_TRIES
Definition: bms_cfg.h:165
#define BMS_STATEMACH_MEDIUMTIME
BMS state machine medium time definition in BMS_Trigger() calls until next state/substate is processe...
Definition: bms_cfg.h:107
#define BMS_STATEMACH_SHORTTIME
BMS state machine short time definition in BMS_Trigger() calls until next state/substate is processed...
Definition: bms_cfg.h:101
#define BMS_REQ_ID_CHARGE
Definition: bms_cfg.h:74
#define BMS_REQ_ID_NORMAL
Definition: bms_cfg.h:71
#define BMS_NO_STRING_AVAILABLE
Functions searching for next string return this value if no further string is available.
Definition: bms_cfg.h:79
#define BMS_OSCILLATION_TIMEOUT
Timeout in 1*10ms to wait before re-entering to precharge.
Definition: bms_cfg.h:162
#define BMS_TIME_WAIT_AFTERPRECHARGEFAIL
Time to wait in BMS_Trigger() calls after precharge opened because precharge failed.
Definition: bms_cfg.h:155
#define BMS_PRECHARGE_VOLTAGE_THRESHOLD_mV
Definition: bms_cfg.h:168
#define BMS_PRECHARGE_CURRENT_THRESHOLD_mA
Definition: bms_cfg.h:171
#define BMS_TIME_WAIT_AFTER_CLOSING_PRECHARGE
Definition: bms_cfg.h:146
void CONT_CheckFeedback(void)
checks the feedback of all contactors
Definition: contactor.c:121
STD_RETURN_TYPE_e CONT_CloseContactor(uint8_t stringNumber, CONT_TYPE_e contactor)
Closes the contactor.
Definition: contactor.c:180
STD_RETURN_TYPE_e CONT_OpenPrecharge(uint8_t stringNumber)
Opens precharge.
Definition: contactor.c:209
STD_RETURN_TYPE_e CONT_OpenContactor(uint8_t stringNumber, CONT_TYPE_e contactor)
Opens the contactor.
Definition: contactor.c:161
CONT_ELECTRICAL_STATE_TYPE_e CONT_GetContactorState(uint8_t stringNumber, CONT_TYPE_e contactorType)
Returns the current contactor state.
Definition: contactor.c:232
void CONT_OpenAllPrechargeContactors(void)
Open all currently closed precharge contactors.
Definition: contactor.c:219
STD_RETURN_TYPE_e CONT_ClosePrecharge(uint8_t stringNumber)
Closes precharge.
Definition: contactor.c:199
CONT_CONTACTOR_STATE_s cont_contactorStates[BS_NR_OF_CONTACTORS]
Definition: contactor_cfg.c:65
CONT_TYPE_e
Definition: contactor_cfg.h:84
@ CONT_UNDEFINED
Definition: contactor_cfg.h:88
@ CONT_PRECHARGE
Definition: contactor_cfg.h:87
@ CONT_MINUS
Definition: contactor_cfg.h:86
@ CONT_PLUS
Definition: contactor_cfg.h:85
CONT_ELECTRICAL_STATE_TYPE_e
Definition: contactor_cfg.h:69
@ CONT_SWITCH_UNDEFINED
Definition: contactor_cfg.h:72
@ CONT_SWITCH_ON
Definition: contactor_cfg.h:71
@ CONT_SWITCH_OFF
Definition: contactor_cfg.h:70
CONT_CURRENT_BREAKING_DIRECTION_e
Definition: contactor_cfg.h:99
@ CONT_BIDIRECTIONAL
@ CONT_CHARGING_DIRECTION
@ CONT_DISCHARGING_DIRECTION
Database module header.
#define DATA_READ_DATA(...)
Definition: database.h:83
#define DATA_WRITE_DATA(...)
Definition: database.h:93
@ DATA_BLOCK_ID_MIN_MAX
Definition: database_cfg.h:78
@ DATA_BLOCK_ID_SYSTEMSTATE
Definition: database_cfg.h:90
@ DATA_BLOCK_ID_OPEN_WIRE_BASE
Definition: database_cfg.h:84
@ DATA_BLOCK_ID_ERRORSTATE
Definition: database_cfg.h:86
@ DATA_BLOCK_ID_PACK_VALUES
Definition: database_cfg.h:105
@ DATA_BLOCK_ID_STATEREQUEST
Definition: database_cfg.h:95
uint32_t DIAG_GetDelay(DIAG_ID_e diagnosisEntry)
Get configured delay of passed diagnosis entry.
Definition: diag.c:383
STD_RETURN_TYPE_e DIAG_GetDiagnosisEntryState(DIAG_ID_e diagnosisEntry)
Checks if passed diagnosis entry has been triggered or not.
Definition: diag.c:189
bool DIAG_IsAnyFatalErrorSet(void)
Check if any fatal error is set.
Definition: diag.c:388
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:243
Diagnosis driver header.
DIAG_DEV_s diag_device
Definition: diag_cfg.c:227
@ DIAG_EVENT_NOT_OK
Definition: diag_cfg.h:258
@ DIAG_EVENT_OK
Definition: diag_cfg.h:257
@ DIAG_SYSTEM
Definition: diag_cfg.h:270
@ DIAG_STRING
Definition: diag_cfg.h:271
@ DIAG_ID_AFE_OPEN_WIRE
Definition: diag_cfg.h:227
@ DIAG_ID_ALERT_MODE
Definition: diag_cfg.h:251
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:252
#define FAS_TRAP
Define that evaluates to essential boolean false thus tripping an assert.
Definition: fassert.h:126
int32_t MATH_AbsInt32_t(const int32_t value)
Returns the absolute value of passed int32_t value.
Definition: foxmath.c:154
int64_t MATH_AbsInt64_t(const int64_t value)
Returns the absolute value of passed int64_t value.
Definition: foxmath.c:162
math library for often used math functions
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
#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:513
API header for the insulation monitoring device.
@ IMD_ILLEGAL_REQUEST
Definition: imd.h:79
void LED_SetToggleTime(uint32_t onOffTime_ms)
Set debug LED with defined frequency.
Definition: led.c:110
Header file of the debug LED driver.
#define LED_NORMAL_OPERATION_ON_OFF_TIME_ms
Definition: led.h:73
#define LED_ERROR_OPERATION_ON_OFF_TIME_ms
Definition: led.h:75
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:120
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:135
void OS_EnterTaskCritical(void)
Enter Critical interface function for use in FreeRTOS-Tasks and FreeRTOS-ISR.
Definition: os_freertos.c:131
uint32_t OS_GetTickCount(void)
Returns OS based system tick value.
Definition: os_freertos.c:139
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:145
void SOA_CheckVoltages(DATA_BLOCK_MIN_MAX_s *pMinimumMaximumCellVoltages)
checks the abidance by the safe operating area
Definition: soa.c:78
void SOA_CheckSlaveTemperatures(void)
FOR FUTURE COMPATIBILITY; DUMMY FUNCTION; DO NOT USE.
Definition: soa.c:350
void SOA_CheckCurrent(DATA_BLOCK_PACK_VALUES_s *pTablePackValues)
checks the abidance by the safe operating area
Definition: soa.c:268
Header for SOA module, responsible for checking battery parameters against safety limits.
uint32_t restTimer_10ms
Definition: bms.h:197
uint8_t PrechargeTryCounter
Definition: bms.h:199
uint8_t counter
Definition: bms.h:195
bool transitionToErrorState
Definition: bms.h:214
uint16_t timer
Definition: bms.h:186
BMS_CURRENT_FLOW_STATE_e currentFlowState
Definition: bms.h:196
uint8_t triggerentry
Definition: bms.h:194
STD_RETURN_TYPE_e initFinished
Definition: bms.h:193
uint8_t closedPrechargeContactors[BS_NR_OF_STRINGS]
Definition: bms.h:215
BMS_STATEMACH_e nextstate
Definition: bms.h:205
uint8_t closedStrings[BS_NR_OF_STRINGS]
Definition: bms.h:216
uint8_t firstClosedString
Definition: bms.h:206
CONT_TYPE_e contactorToBeOpened
Definition: bms.h:213
uint8_t deactivatedStrings[BS_NR_OF_STRINGS]
Definition: bms.h:217
uint32_t nextstringclosedtimer
Definition: bms.h:203
BMS_STATE_REQUEST_e stateRequest
Definition: bms.h:187
uint8_t stringToBeOpened
Definition: bms.h:212
uint32_t ErrRequestCounter
Definition: bms.h:192
uint32_t minimumActiveDelay_ms
Definition: bms.h:210
uint8_t numberOfClosedStrings
Definition: bms.h:201
BMS_STATEMACH_e state
Definition: bms.h:188
uint16_t stringCloseTimeout
Definition: bms.h:204
BMS_STATEMACH_SUB_e substate
Definition: bms.h:189
uint16_t stringOpenTimeout
Definition: bms.h:202
uint32_t timeAboveContactorBreakCurrent_ms
Definition: bms.h:211
BMS_POWER_PATH_TYPE_e powerPath
Definition: bms.h:200
uint32_t remainingDelay_ms
Definition: bms.h:209
uint16_t OscillationTimeout
Definition: bms.h:198
const CONT_TYPE_e type
uint8_t stringPlusContactor[BS_NR_OF_STRINGS]
Definition: database_cfg.h:332
uint8_t prechargeContactor[BS_NR_OF_STRINGS]
Definition: database_cfg.h:333
uint8_t stringMinusContactor[BS_NR_OF_STRINGS]
Definition: database_cfg.h:331
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:329
DATA_BLOCK_ID_e uniqueId
Definition: database_cfg.h:119
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:159
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:302
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:307
int32_t stringVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:198
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
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:522
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:431
DIAG_ID_CFG_s * pFatalErrorLinkTable[DIAG_ID_MAX]
Definition: diag_cfg.h:347
uint16_t numberOfFatalErrors
Definition: diag_cfg.h:345
DIAG_ID_e id
Definition: diag_cfg.h:324