foxBMS  1.1.1
The foxBMS Battery Management System API Documentation
bms.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2021, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice, this
12  * list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  *
18  * 3. Neither the name of the copyright holder nor the names of its
19  * contributors may be used to endorse or promote products derived from
20  * this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * We kindly request you to use one or more of the following phrases to refer to
34  * foxBMS in your hardware, software, documentation or advertising materials:
35  *
36  * - ″This product uses parts of foxBMS®″
37  * - ″This product includes parts of foxBMS®″
38  * - ″This product is derived from foxBMS®″
39  *
40  */
41 
42 /**
43  * @file bms.c
44  * @author foxBMS Team
45  * @date 2020-02-24 (date of creation)
46  * @updated 2021-07-29 (date of last update)
47  * @ingroup ENGINE
48  * @prefix BMS
49  *
50  * @brief bms driver implementation
51  */
52 
53 /*========== Includes =======================================================*/
54 #include "bms.h"
55 
56 #include "battery_cell_cfg.h"
57 
58 #include "bal.h"
59 #include "contactor.h"
60 #include "database.h"
61 #include "diag.h"
62 #include "foxmath.h"
63 #include "interlock.h"
64 #include "meas.h"
65 #include "mic.h"
66 #include "os.h"
67 #include "soa.h"
68 
69 /*========== Macros and Definitions =========================================*/
70 /** default value for unset "active delay time" */
71 #define BMS_NO_ACTIVE_DELAY_TIME_ms (UINT32_MAX)
72 
73 /**
74  * Saves the last state and the last substate
75  */
76 #define BMS_SAVELASTSTATES() \
77  bms_state.laststate = bms_state.state; \
78  bms_state.lastsubstate = bms_state.substate
79 
80 /*========== Static Constant and Variable Definitions =======================*/
81 
82 /**
83  * contains the state of the bms state machine
84  */
86  .timer = 0,
87  .stateRequest = BMS_STATE_NO_REQUEST,
89  .substate = BMS_ENTRY,
90  .laststate = BMS_STATEMACH_UNINITIALIZED,
91  .lastsubstate = BMS_ENTRY,
92  .triggerentry = 0u,
93  .ErrRequestCounter = 0u,
94  .initFinished = STD_NOT_OK,
95  .counter = 0u,
96  .OscillationTimeout = 0u,
97  .PrechargeTryCounter = 0u,
98  .powerPath = BMS_POWER_PATH_OPEN,
99  .closedStrings = {0u},
100  .closedPrechargeContactors = {0u},
101  .numberOfClosedStrings = 0u,
102  .deactivatedStrings = {0},
103  .firstClosedString = 0u,
104  .stringOpenTimeout = 0u,
105  .nextstringclosedtimer = 0u,
106  .stringCloseTimeout = 0u,
107  .nextstate = BMS_STATEMACH_STANDBY,
108  .restTimer_10ms = BS_RELAXATION_PERIOD_10ms,
109  .currentFlowState = BMS_RELAXATION,
110  .remainingDelay_ms = BMS_NO_ACTIVE_DELAY_TIME_ms,
111  .minimumActiveDelay_ms = BMS_NO_ACTIVE_DELAY_TIME_ms,
112  .transitionToErrorState = false,
113 };
114 
115 /** local copies of database tables */
116 /**@{*/
120 /**@}*/
121 
122 /*========== Extern Constant and Variable Definitions =======================*/
123 
124 /*========== Static Function Prototypes =====================================*/
125 
126 /**
127  * @brief checks the state requests that are made.
128  * @details This function checks the validity of the state requests. The
129  * results of the checked is returned immediately.
130  * @param[in] statereq state request to be checked
131  * @return result of the state request that was made
132  */
134 
135 /**
136  * @brief transfers the current state request to the state machine.
137  * @details This function takes the current state request from #bms_state
138  * transfers it to the state machine. It resets the value from
139  * #bms_state to #BMS_STATE_NO_REQUEST
140  * @return current state request
141  */
143 
144 /**
145  * @brief re-entrance check of SYS state machine trigger function
146  * @details This function is not re-entrant and should only be called time- or
147  * event-triggered. It increments the triggerentry counter from the
148  * state variable ltc_state. It should never be called by two
149  * different processes, so if it is the case, triggerentry should
150  * never be higher than 0 when this function is called.
151  * @return retval 0 if no further instance of the function is active, 0xff
152  * else
153  */
154 static uint8_t BMS_CheckReEntrance(void);
155 
156 /**
157  * @brief Checks the state requests made to the BMS state machine.
158  * @details Checks of the state request in the database and sets this value as
159  * return value.
160  * @return requested state
161  */
162 static uint8_t BMS_CheckCanRequests(void);
163 
164 /**
165  * @brief Checks all the error flags from diagnosis module with a severity of
166  * #DIAG_FATAL_ERROR
167  * @details Checks all the error flags from diagnosis module with a severity of
168  * #DIAG_FATAL_ERROR. Furthermore, sets parameter minimumActiveDelay_ms
169  * of bms_state variable.
170  * @return true if error flag is set, otherwise false
171  */
172 static bool BMS_IsAnyFatalErrorFlagSet(void);
173 
174 /**
175  * @brief Checks if any error flag is set and handles delay until contactors
176  * need to be opened.
177  * @details Checks all the diagnosis entries with severity of #DIAG_FATAL_ERROR
178  * and handles the configured delay until the contactors need to be
179  * opened. The shortest delay is used, if multiple errors are active at
180  * once.
181  * @return #STD_NOT_OK if error detected and delay time elapsed, otherwise #STD_OK
182  */
184 
185 /** Get latest database entries for static module variables */
186 static void BMS_GetMeasurementValues(void);
187 
188 /**
189  * @brief Check for any open voltage sense wire
190  */
191 static void BMS_CheckOpenSenseWire(void);
192 
193 /**
194  * @brief Checks if the current limitations are violated
195  * @param[in] stringNumber string addressed
196  * @param[in] pPackValues pointer to pack values database entry
197  * @return #STD_OK if the current limitations are NOT violated, else
198  * #STD_NOT_OK (type: #STD_RETURN_TYPE_e)
199  */
200 static STD_RETURN_TYPE_e BMS_CheckPrecharge(uint8_t stringNumber, const DATA_BLOCK_PACK_VALUES_s *pPackValues);
201 
202 /**
203  * @brief Returns ID of string with highest total voltage
204  * @details This is used to close the first string when drive-off is requested.
205  * @param[in] precharge If #BMS_DO_NOT_TAKE_PRECHARGE_INTO_ACCCOUNT,
206  * precharge availability for string is ignored.
207  * if #BMS_TAKE_PRECHARGE_INTO_ACCCOUNT, only select
208  * string that has precharge available.
209  * @param[in] pPackValues pointer to pack values database entry
210  * @return index of string with highest voltage If no string is available,
211  * returns #BMS_NO_STRING_AVAILABLE.
212  */
213 static uint8_t BMS_GetHighestString(BMS_CONSIDER_PRECHARGE_e precharge, DATA_BLOCK_PACK_VALUES_s *pPackValues);
214 
215 /**
216  * @brief Returns ID of string with voltage closest to first closed string voltage
217  * @details This is used to close further strings in drive.
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 voltage closest to the first closed string voltage.
224  * If no string is available, returns #BMS_NO_STRING_AVAILABLE.
225  */
226 static uint8_t BMS_GetClosestString(BMS_CONSIDER_PRECHARGE_e precharge, DATA_BLOCK_PACK_VALUES_s *pPackValues);
227 
228 /**
229  * @brief Returns ID of string with lowest total voltage
230  * @details This is used to close the first string when charge-off is requested.
231  *
232  * @param[in] precharge If 0, precharge availability for string is ignored.
233  * If 1, only selects a string that has precharge
234  * available.
235  * @param[in] pPackValues pointer to pack values database entry
236  * @return index of string with lowest voltage. If no string is available,
237  * returns #BMS_NO_STRING_AVAILABLE.
238  */
239 static uint8_t BMS_GetLowestString(BMS_CONSIDER_PRECHARGE_e precharge, DATA_BLOCK_PACK_VALUES_s *pPackValues);
240 
241 /**
242  * @brief Returns voltage difference between first closed string and
243  * string ID
244  * @details This function is used to check voltage when trying to close further
245  * strings.
246  * @param[in] string ID of string that must be compared with first closed
247  * string
248  * @param[in] pPackValues pointer to pack values database entry
249  * @return voltage difference in mV, will return INT32_MAX if voltages are
250  * invalid and difference can not be calculated
251  */
252 static int32_t BMS_GetStringVoltageDifference(uint8_t string, const DATA_BLOCK_PACK_VALUES_s *pPackValues);
253 
254 /**
255  * @brief Returns the average current flowing through all strings.
256  * @details This function is used when closing strings.
257  * @param[in] pPackValues pointer to pack values database entry
258  * @return average current taking all strings into account in mA. INT32_MAX if there is no valid current measurement
259  */
260 static int32_t BMS_GetAverageStringCurrent(DATA_BLOCK_PACK_VALUES_s *pPackValues);
261 
262 /**
263  * @brief Updates battery system state variable depending on measured/recent
264  * current values
265  * @param[in] pPackValues recent measured values from current sensor
266  */
267 static void BMS_UpdateBatsysState(DATA_BLOCK_PACK_VALUES_s *pPackValues);
268 
269 /*========== Static Function Implementations ================================*/
270 
272  if (statereq == BMS_STATE_ERROR_REQUEST) {
273  return BMS_OK;
274  }
275 
277  /* init only allowed from the uninitialized state */
278  if (statereq == BMS_STATE_INIT_REQUEST) {
280  return BMS_OK;
281  } else {
283  }
284  } else {
285  return BMS_ILLEGAL_REQUEST;
286  }
287  } else {
288  return BMS_REQUEST_PENDING;
289  }
290 }
291 
292 static uint8_t BMS_CheckReEntrance(void) {
293  uint8_t retval = 0;
295  if (!bms_state.triggerentry) {
297  } else {
298  retval = 0xFF; /* multiple calls of function */
299  }
301  return retval;
302 }
303 
306 
308  retval = bms_state.stateRequest;
311  return retval;
312 }
313 
314 static void BMS_GetMeasurementValues(void) {
316 }
317 
318 static uint8_t BMS_CheckCanRequests(void) {
319  uint8_t retVal = BMS_REQ_ID_NOREQ;
321 
322  DATA_READ_DATA(&request);
323 
324  if (request.stateRequestViaCan == BMS_REQ_ID_STANDBY) {
325  retVal = BMS_REQ_ID_STANDBY;
326  } else if (request.stateRequestViaCan == BMS_REQ_ID_NORMAL) {
327  retVal = BMS_REQ_ID_NORMAL;
328  }
329 
330 #if BS_SEPARATE_POWER_PATHS == 1
331  else if (request.stateRequestViaCan == BMS_REQ_ID_CHARGE) { /* NOLINT(readability/braces) */
332  retVal = BMS_REQ_ID_CHARGE;
333  }
334 #endif /* BS_SEPARATE_POWER_PATHS == 1 */
335 
336  return retVal;
337 }
338 
339 static void BMS_CheckOpenSenseWire(void) {
340  uint8_t openWireDetected = 0;
341 
342  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
343  /* Iterate over all modules */
344  for (uint8_t m = 0u; m < BS_NR_OF_MODULES; m++) {
345  /* Iterate over all voltage sense wires: cells per module + 1 */
346  for (uint8_t wire = 0u; wire < (BS_NR_OF_CELLS_PER_MODULE + 1); wire++) {
347  /* open wire detected */
348  if (bms_tableOpenWire.openwire[s][(wire + (m * (BS_NR_OF_CELLS_PER_MODULE + 1))) == 1] > 0u) {
349  openWireDetected++;
350 
351  /* Add additional error handling here */
352  }
353  }
354  }
355  /* Set error if open wire detected */
356  if (openWireDetected == 0u) {
358  } else {
360  }
361  }
362 }
363 
364 static STD_RETURN_TYPE_e BMS_CheckPrecharge(uint8_t stringNumber, const DATA_BLOCK_PACK_VALUES_s *pPackValues) {
365  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
366  /* make sure that we do not access the arrays in the database
367  tables out of bounds */
368  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
369  FAS_ASSERT(pPackValues != NULL_PTR);
370 
371  /* Only check precharging if current value and voltages are valid */
372  if ((0u == pPackValues->invalidStringCurrent[stringNumber]) &&
373  (0u == pPackValues->invalidStringVoltage[stringNumber]) && (0u == pPackValues->invalidHvBusVoltage)) {
374  /* Only current not current direction is checked */
375  const int32_t current_mA = MATH_AbsInt32(pPackValues->stringCurrent_mA[stringNumber]);
376  const int64_t cont_prechargeVoltDiff_mV = MATH_AbsInt64(
377  (int64_t)pPackValues->stringVoltage_mV[stringNumber] - (int64_t)pPackValues->highVoltageBusVoltage_mV);
378 
379  if ((cont_prechargeVoltDiff_mV < BMS_PRECHARGE_VOLTAGE_THRESHOLD_mV) &&
380  (current_mA < BMS_PRECHARGE_CURRENT_THRESHOLD_mA)) {
381  retVal = STD_OK;
382  } else {
383  retVal = STD_NOT_OK;
384  }
385  }
386 
387  return retVal;
388 }
389 
390 static bool BMS_IsAnyFatalErrorFlagSet(void) {
391  bool fatalErrorActive = false;
392 
393  for (uint16_t entry = 0u; entry < diag_device.numberOfFatalErrors; entry++) {
394  const STD_RETURN_TYPE_e diagnosisState =
396  if (STD_NOT_OK == diagnosisState) {
397  /* Fatal error detected -> get delay of this error until contactors shall be opened */
398  const uint32_t kDelay_ms = DIAG_GetDelay(diag_device.pFatalErrorLinkTable[entry]->id);
399  /* Check if delay of detected failure is smaller than the delay of a previously detected failure */
400  if (bms_state.minimumActiveDelay_ms > kDelay_ms) {
401  bms_state.minimumActiveDelay_ms = kDelay_ms;
402  }
403  fatalErrorActive = true;
404  }
405  }
406  return fatalErrorActive;
407 }
408 
410  STD_RETURN_TYPE_e retVal = STD_OK; /* is set to STD_NOT_OK if error detected */
411  static uint32_t previousTimestamp = 0u;
412  uint32_t timestamp = OS_GetTickCount();
413 
414  /* Check if any fatal error is detected */
415  const bool isErrorActive = BMS_IsAnyFatalErrorFlagSet();
416 
417  /** Check if a fatal error has been detected previously. If yes, check delay */
418  if (true == bms_state.transitionToErrorState) {
419  /* Decrease active delay since last call */
420  const uint32_t timeSinceLastCall_ms = timestamp - previousTimestamp;
421  if (timeSinceLastCall_ms <= bms_state.remainingDelay_ms) {
422  bms_state.remainingDelay_ms -= timeSinceLastCall_ms;
423  } else {
425  }
426 
427  /* Check if delay from a new error is shorter then active delay from
428  * previously detected error in BMS statemachine */
431  }
432  } else {
433  /* Delay is not active, check if it should be activated */
434  if (true == isErrorActive) {
437  }
438  }
439 
440  /** Set previous timestamp for next call */
441  previousTimestamp = timestamp;
442 
443  /* Check if bms statemachine should switch to error state. This is the case
444  * if the delay is activated and the remaining delay is down to 0 */
445  if ((true == bms_state.transitionToErrorState) && (0u == bms_state.remainingDelay_ms)) {
446  retVal = STD_NOT_OK;
447  }
448 
449  return retVal;
450 }
451 
453  FAS_ASSERT(pPackValues != NULL_PTR);
454  uint8_t highest_string_index = BMS_NO_STRING_AVAILABLE;
455  int32_t max_stringVoltage_mV = INT32_MIN;
456 
457  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
458  if ((pPackValues->stringVoltage_mV[s] >= max_stringVoltage_mV) &&
459  (0u == pPackValues->invalidStringVoltage[s])) {
460  if (bms_state.deactivatedStrings[s] == 0u) {
461  if (precharge == BMS_DO_NOT_TAKE_PRECHARGE_INTO_ACCCOUNT) {
462  max_stringVoltage_mV = pPackValues->stringVoltage_mV[s];
463  highest_string_index = s;
464  } else {
466  max_stringVoltage_mV = pPackValues->stringVoltage_mV[s];
467  highest_string_index = s;
468  }
469  }
470  }
471  }
472  }
473 
474  return highest_string_index;
475 }
476 
478  FAS_ASSERT(pPackValues != NULL_PTR);
479  uint8_t closestStringIndex = BMS_NO_STRING_AVAILABLE;
480  int32_t closedStringVoltage_mV = 0;
481  bool searchString = false;
482 
483  /* Get voltage of first closed string */
484  if (0u == pPackValues->invalidStringVoltage[bms_state.firstClosedString]) {
485  closedStringVoltage_mV = pPackValues->stringVoltage_mV[bms_state.firstClosedString];
486  searchString = true;
487  } else if (0u == pPackValues->invalidHvBusVoltage) {
488  /* Use high voltage bus voltage if measured string voltage is invalid */
489  closedStringVoltage_mV = pPackValues->highVoltageBusVoltage_mV;
490  searchString = true;
491  } else {
492  /* Do not search for next string if no valid voltages could be measured */
493  searchString = false;
494  }
495 
496  if (true == searchString) {
497  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
498  const bool isStringClosed = BMS_IsStringClosed(s);
499  const uint8_t isStringVoltageValid = pPackValues->invalidStringVoltage[s];
500  if ((false == isStringClosed) && (0u == isStringVoltageValid)) {
501  /* Only check open strings with valid voltages */
502  int32_t minimumVoltageDifference_mV = INT32_MAX;
503  int32_t voltageDifference_mV = labs(closedStringVoltage_mV - pPackValues->stringVoltage_mV[s]);
504  if (voltageDifference_mV <= minimumVoltageDifference_mV) {
505  if (bms_state.deactivatedStrings[s] == 0u) {
506  if (precharge == BMS_TAKE_PRECHARGE_INTO_ACCCOUNT) {
508  minimumVoltageDifference_mV = voltageDifference_mV;
509  closestStringIndex = s;
510  }
511  } else {
512  minimumVoltageDifference_mV = voltageDifference_mV;
513  closestStringIndex = s;
514  }
515  }
516  }
517  }
518  }
519  }
520  return closestStringIndex;
521 }
522 
524  FAS_ASSERT(pPackValues != NULL_PTR);
525  uint8_t lowest_string_index = BMS_NO_STRING_AVAILABLE;
526  int32_t min_stringVoltage_mV = INT32_MAX;
527 
528  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
529  if ((pPackValues->stringVoltage_mV[s] <= min_stringVoltage_mV) &&
530  (0u == pPackValues->invalidStringVoltage[s])) {
531  if (bms_state.deactivatedStrings[s] == 0u) {
532  if (precharge == BMS_DO_NOT_TAKE_PRECHARGE_INTO_ACCCOUNT) {
533  min_stringVoltage_mV = pPackValues->stringVoltage_mV[s];
534  lowest_string_index = s;
535  } else {
537  min_stringVoltage_mV = pPackValues->stringVoltage_mV[s];
538  lowest_string_index = s;
539  }
540  }
541  }
542  }
543  }
544  return lowest_string_index;
545 }
546 
547 static int32_t BMS_GetStringVoltageDifference(uint8_t string, const DATA_BLOCK_PACK_VALUES_s *pPackValues) {
548  FAS_ASSERT(string < BS_NR_OF_STRINGS);
549  FAS_ASSERT(pPackValues != NULL_PTR);
550  int32_t voltageDifference_mV = INT32_MAX;
551  if ((0u == pPackValues->invalidStringVoltage[string]) &&
552  (0u == pPackValues->invalidStringVoltage[bms_state.firstClosedString])) {
553  /* Calculate difference between string voltages */
554  voltageDifference_mV = MATH_AbsInt32(
555  pPackValues->stringVoltage_mV[string] - pPackValues->stringVoltage_mV[bms_state.firstClosedString]);
556  } else if ((0u == pPackValues->invalidStringVoltage[string]) && (0u == pPackValues->invalidHvBusVoltage)) {
557  /* Calculate difference between string and high voltage bus voltage */
558  voltageDifference_mV =
559  MATH_AbsInt32(pPackValues->stringVoltage_mV[string] - pPackValues->highVoltageBusVoltage_mV);
560  } else {
561  /* No valid voltages for comparison -> do not calculate difference and return INT32_MAX */
562  voltageDifference_mV = INT32_MAX;
563  }
564  return voltageDifference_mV;
565 }
566 
568  FAS_ASSERT(pPackValues != NULL_PTR);
569  int32_t average_current = pPackValues->packCurrent_mA / (int32_t)BS_NR_OF_STRINGS;
570  if (1u == pPackValues->invalidPackCurrent) {
571  average_current = INT32_MAX;
572  }
573  return average_current;
574 }
575 
577  FAS_ASSERT(pPackValues != NULL_PTR);
578 
579  /* Only update system state if current value is valid */
580  if (0u == pPackValues->invalidPackCurrent) {
581  if (POSITIVE_DISCHARGE_CURRENT == true) {
582  /* Positive current values equal a discharge of the battery system */
583  if (pPackValues->packCurrent_mA >= BS_REST_CURRENT_mA) { /* TODO: string use pack current */
586  } else if (pPackValues->packCurrent_mA <= -BS_REST_CURRENT_mA) {
589  } else {
590  /* Current below rest current: either battery system is at rest
591  * or the relaxation process is still ongoing */
592  if (bms_state.restTimer_10ms == 0u) {
593  /* Rest timer elapsed -> battery system at rest */
595  } else {
598  }
599  }
600  } else {
601  /* Negative current values equal a discharge of the battery system */
602  if (pPackValues->packCurrent_mA <= -BS_REST_CURRENT_mA) {
605  } else if (pPackValues->packCurrent_mA >= BS_REST_CURRENT_mA) {
608  } else {
609  /* Current below rest current: either battery system is at rest
610  * or the relaxation process is still ongoing */
611  if (bms_state.restTimer_10ms == 0u) {
612  /* Rest timer elapsed -> battery system at rest */
614  } else {
617  }
618  }
619  }
620  }
621 }
622 
623 /*========== Extern Function Implementations ================================*/
624 
626  return bms_state.initFinished;
627 }
628 
630  return bms_state.state;
631 }
632 
634  BMS_RETURN_TYPE_e retVal = BMS_OK;
635 
637  retVal = BMS_CheckStateRequest(statereq);
638 
639  if (retVal == BMS_OK) {
640  bms_state.stateRequest = statereq;
641  }
643 
644  return retVal;
645 }
646 
647 void BMS_Trigger(void) {
650  uint32_t timestamp = OS_GetTickCount();
651  static uint32_t nextOpenWireCheck = 0;
652  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
653  static uint8_t stringNumber = 0u;
654  static uint8_t nextStringNumber = 0u;
656  STD_RETURN_TYPE_e contRetVal = STD_NOT_OK;
657 
667  }
668  /* Check re-entrance of function */
669  if (BMS_CheckReEntrance() > 0u) {
670  return;
671  }
672 
673  if (bms_state.nextstringclosedtimer > 0u) {
675  }
676  if (bms_state.stringOpenTimeout > 0u) {
678  }
679 
680  if (bms_state.stringCloseTimeout > 0u) {
682  }
683 
684  if (bms_state.OscillationTimeout > 0u) {
686  }
687 
688  if (bms_state.timer > 0u) {
689  if ((--bms_state.timer) > 0u) {
691  return; /* handle state machine only if timer has elapsed */
692  }
693  }
694 
695  /****Happens every time the state machine is triggered**************/
696  switch (bms_state.state) {
697  /****************************UNINITIALIZED****************************/
699  /* waiting for Initialization Request */
700  statereq = BMS_TransferStateRequest();
701  if (statereq == BMS_STATE_INIT_REQUEST) {
706  } else if (statereq == BMS_STATE_NO_REQUEST) {
707  /* no actual request pending */
708  } else {
709  bms_state.ErrRequestCounter++; /* illegal request pending */
710  }
711  break;
712 
713  /****************************INITIALIZATION***************************/
716 
720  break;
721 
722  /****************************INITIALIZED******************************/
729  break;
730 
731  /****************************IDLE*************************************/
732  case BMS_STATEMACH_IDLE:
734 
735  if (bms_state.substate == BMS_ENTRY) {
736  DATA_READ_DATA(&systemstate);
737  systemstate.bmsCanState = BMS_CANSTATE_IDLE;
738  DATA_WRITE_DATA(&systemstate);
741  break;
742  } else if (bms_state.substate == BMS_CHECK_ERROR_FLAGS) {
748  break;
749  } else {
752  break;
753  }
760  break;
761  } else {
764  break;
765  }
766  }
767  break;
768 
769  /****************************OPEN CONTACTORS**************************/
772 
773  if (bms_state.substate == BMS_ENTRY) {
777  break;
779  for (stringNumber = 0u; stringNumber < BS_NR_OF_STRINGS; stringNumber++) {
780  if (bs_stringsWithPrecharge[stringNumber] == BS_STRING_WITH_PRECHARGE) {
781  CONT_OpenPrecharge(stringNumber);
782  bms_state.closedPrechargeContactors[stringNumber] = 0u;
783  }
784  }
785  /* Now go to string opening */
786  stringNumber = BS_NR_OF_STRINGS - 1u; /* Select last string */
789  } else if (bms_state.substate == BMS_OPEN_STRINGS) {
790  CONT_OpenString(stringNumber);
794  break;
795  } else if (bms_state.substate == BMS_CHECK_STRING_OPEN) {
796  contstate = CONT_GetState(stringNumber);
797  if (contstate == CONT_SWITCH_OFF) {
798  if (bms_state.numberOfClosedStrings > 0u) {
800  }
801  bms_state.closedStrings[stringNumber] = 0u;
802  if (stringNumber > 0u) {
803  stringNumber--;
806  break;
807  } else {
810  }
811  break;
812  } else if (bms_state.stringOpenTimeout == 0u) {
813  /* String takes too long to close, go to next string */
816  break;
817  } else {
818  /* String not opened, re-issue closing request */
819  CONT_OpenString(nextStringNumber);
821  break;
822  }
823  } else if (bms_state.substate == BMS_OPEN_STRINGS_EXIT) {
828  break;
829  } else {
833  }
834  }
835  break;
836 
837  /****************************STANDBY**********************************/
840  if (bms_state.substate == BMS_ENTRY) {
843 #if LTC_STANDBY_PERIODIC_OPEN_WIRE_CHECK == TRUE
844  nextOpenWireCheck = timestamp + LTC_STANDBY_OPEN_WIRE_PERIOD_ms;
845 #endif /* LTC_STANDBY_PERIODIC_OPEN_WIRE_CHECK == TRUE */
848  DATA_READ_DATA(&systemstate);
849  systemstate.bmsCanState = BMS_CANSTATE_STANDBY;
850  DATA_WRITE_DATA(&systemstate);
851  break;
858  break;
859  } else {
862  break;
863  }
864  } else if (bms_state.substate == BMS_INTERLOCK_CHECKED) {
867  break;
868  } else if (bms_state.substate == BMS_CHECK_ERROR_FLAGS) {
874  break;
875  } else {
878  break;
879  }
887  break;
888  }
895  break;
896  } else {
897 #if LTC_STANDBY_PERIODIC_OPEN_WIRE_CHECK == TRUE
898  if (nextOpenWireCheck <= timestamp) {
900  nextOpenWireCheck = timestamp + LTC_STANDBY_OPEN_WIRE_PERIOD_ms;
901  }
902 #endif /* LTC_STANDBY_PERIODIC_OPEN_WIRE_CHECK == TRUE */
905  break;
906  }
907  }
908  break;
909 
910  /****************************PRECHARGE********************************/
913 
914  if (bms_state.substate == BMS_ENTRY) {
915  DATA_READ_DATA(&systemstate);
916  systemstate.bmsCanState = BMS_CANSTATE_PRECHARGE;
917  DATA_WRITE_DATA(&systemstate);
920  } else {
922  }
923  if (stringNumber == BMS_NO_STRING_AVAILABLE) {
928  break;
929  }
930  bms_state.firstClosedString = stringNumber;
931  if (bms_state.OscillationTimeout == 0u) {
934  } else if (BMS_IsBatterySystemStateOkay() == STD_NOT_OK) {
935  /* If precharge re-enter timeout not elapsed, wait (and check errors while waiting) */
940  break;
941  }
942  break;
946  bms_state.closedPrechargeContactors[stringNumber] = 1u;
947  if (contRetVal == STD_OK) {
951  } else {
956  }
957  break;
964  break;
965  } else {
968  break;
969  }
976  break;
977  } else {
980  }
983  if (retVal == STD_OK) {
987  break;
988  } else {
991  bms_state.closedPrechargeContactors[stringNumber] = 0u;
992  if (contRetVal == STD_OK) {
996  } else {
1001  }
1002  break;
1003  } else {
1005  bms_state.closedPrechargeContactors[stringNumber] = 0u;
1010  break;
1011  }
1012  }
1020  if (contstate == CONT_SWITCH_ON) {
1025  break;
1026  } else if (bms_state.stringCloseTimeout == 0u) {
1027  /* String takes too long to close */
1032  break;
1033  } else {
1034  /* String not closed, re-issue closing request */
1038  break;
1039  }
1046  break;
1047  } else {
1050  break;
1051  }
1053  /* Always make one error check after the first string was closed successfully */
1059  break;
1060  } else {
1063  break;
1064  }
1067  if (contRetVal == STD_OK) {
1068  bms_state.closedPrechargeContactors[stringNumber] = 0u;
1072  } else {
1077  }
1078  break;
1079  }
1080  break;
1081 
1082  /****************************NORMAL**************************************/
1083  case BMS_STATEMACH_NORMAL:
1085 
1086  if (bms_state.substate == BMS_ENTRY) {
1087 #if LTC_NORMAL_PERIODIC_OPEN_WIRE_CHECK == TRUE
1088  nextOpenWireCheck = timestamp + LTC_NORMAL_OPEN_WIRE_PERIOD_ms;
1089 #endif /* LTC_NORMAL_PERIODIC_OPEN_WIRE_CHECK == TRUE */
1090  DATA_READ_DATA(&systemstate);
1092  systemstate.bmsCanState = BMS_CANSTATE_CHARGE;
1093  } else {
1094  systemstate.bmsCanState = BMS_CANSTATE_NORMAL;
1095  }
1096  DATA_WRITE_DATA(&systemstate);
1100  break;
1101  } else if (bms_state.substate == BMS_CHECK_ERROR_FLAGS) {
1106  break;
1107  } else {
1110  break;
1111  }
1118  break;
1119  } else {
1120 #if LTC_NORMAL_PERIODIC_OPEN_WIRE_CHECK == TRUE
1121  if (nextOpenWireCheck <= timestamp) {
1123  nextOpenWireCheck = timestamp + LTC_NORMAL_OPEN_WIRE_PERIOD_ms;
1124  }
1125 #endif /* LTC_NORMAL_PERIODIC_OPEN_WIRE_CHECK == TRUE */
1128  break;
1129  }
1131  if (bms_state.nextstringclosedtimer == 0u) {
1132  nextStringNumber =
1134  if (nextStringNumber == BMS_NO_STRING_AVAILABLE) {
1137  break;
1138  } else if (
1139  (BMS_GetStringVoltageDifference(nextStringNumber, &bms_tablePackValues) <=
1142  /* Voltage/current conditions suitable to close a further string */
1143  CONT_CloseString(nextStringNumber);
1147  break;
1148  }
1149  } else {
1152  break;
1153  }
1154  } else if (bms_state.substate == BMS_CHECK_STRING_CLOSED) {
1155  contstate = CONT_GetState(nextStringNumber);
1156  if (contstate == CONT_SWITCH_ON) {
1158  bms_state.closedStrings[nextStringNumber] = 1u;
1160  /* Go to begin of NORMAL case to redo the full procedure with error check and request check */
1162  break;
1163  } else if (bms_state.stringCloseTimeout == 0u) {
1164  /* String takes too long to close */
1169  break;
1170  } else if (BMS_IsBatterySystemStateOkay() == STD_NOT_OK) {
1175  break;
1176  } else if (BMS_CheckCanRequests() == BMS_REQ_ID_STANDBY) {
1181  break;
1182  } else {
1183  /* String not closed, re-issue closing request */
1184  CONT_CloseString(nextStringNumber);
1186  break;
1187  }
1188  }
1189  break;
1190 
1191  /****************************ERROR*************************************/
1192  case BMS_STATEMACH_ERROR:
1194 
1195  if (bms_state.substate == BMS_ENTRY) {
1199  DATA_READ_DATA(&systemstate);
1200  systemstate.bmsCanState = BMS_CANSTATE_ERROR;
1201  DATA_WRITE_DATA(&systemstate);
1202  break;
1203  } else if (bms_state.substate == BMS_OPEN_INTERLOCK) {
1205  nextOpenWireCheck = timestamp + MIC_ERROR_OPEN_WIRE_PERIOD_ms;
1208  break;
1209  } else if (bms_state.substate == BMS_CHECK_ERROR_FLAGS) {
1210  if (true == DIAG_IsAnyFatalErrorSet()) {
1211  /* we stay already in requested state */
1212  if (nextOpenWireCheck <= timestamp) {
1213  /* Perform open-wire check periodically */
1214  /* MEAS_RequestOpenWireCheck(); */ /*TODO: check with strings */
1215  nextOpenWireCheck = timestamp + MIC_ERROR_OPEN_WIRE_PERIOD_ms;
1216  }
1217  } else {
1218  /* Reset fatal error related variables */
1222 
1225  break;
1226  }
1232 
1233  /** Remove statements below once interlock module is working */
1237  /** Remove statements above once interlock module is working */
1238 
1239  break;
1240  } else {
1243  break;
1244  }
1247  /* TODO: check */
1250  /* Only valid as interlock module is not active */
1254  break;
1255  } else {
1258  break;
1259  }
1260  }
1261  break;
1262  default:
1263  /* invalid state */
1265  break;
1266  } /* end switch (bms_state.state) */
1267 
1269  bms_state.counter++;
1270 }
1271 
1273  return bms_state.currentFlowState;
1274 }
1275 
1278 
1279  if (POSITIVE_DISCHARGE_CURRENT == true) {
1280  if (current_mA >= BS_REST_CURRENT_mA) {
1281  retVal = BMS_DISCHARGING;
1282  } else if (current_mA <= -BS_REST_CURRENT_mA) {
1283  retVal = BMS_CHARGING;
1284  } else {
1285  retVal = BMS_AT_REST;
1286  }
1287  } else {
1288  if (current_mA <= -BS_REST_CURRENT_mA) {
1289  retVal = BMS_DISCHARGING;
1290  } else if (current_mA >= BS_REST_CURRENT_mA) {
1291  retVal = BMS_CHARGING;
1292  } else {
1293  retVal = BMS_AT_REST;
1294  }
1295  }
1296  return retVal;
1297 }
1298 
1299 extern bool BMS_IsStringClosed(uint8_t stringNumber) {
1300  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
1301  bool retval = false;
1302  if (bms_state.closedStrings[stringNumber] == 1u) {
1303  retval = true;
1304  }
1305  return retval;
1306 }
1307 
1308 extern bool BMS_IsStringPrecharging(uint8_t stringNumber) {
1309  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
1310  bool retval = false;
1311  if (bms_state.closedPrechargeContactors[stringNumber] == 1u) {
1312  retval = true;
1313  }
1314  return retval;
1315 }
1316 
1317 extern uint8_t BMS_GetNumberOfConnectedStrings(void) {
1319 }
1320 
1323 }
1324 
1325 /*========== Externalized Static Function Implementations (Unit Test) =======*/
1326 #ifdef UNITY_UNIT_TEST
1327 extern BMS_RETURN_TYPE_e TEST_BMS_CheckStateRequest(BMS_STATE_REQUEST_e statereq) {
1328  return BMS_CheckStateRequest(statereq);
1329 }
1330 extern BMS_STATE_REQUEST_e TEST_BMS_TransferStateRequest(void) {
1331  return BMS_TransferStateRequest();
1332 }
1333 extern uint8_t TEST_BMS_CheckReEntrance(void) {
1334  return BMS_CheckReEntrance();
1335 }
1336 extern uint8_t TEST_BMS_CheckCanRequests(void) {
1337  return BMS_CheckCanRequests();
1338 }
1339 extern bool TEST_BMS_IsAnyFatalErrorFlagSet(void) {
1340  return BMS_IsAnyFatalErrorFlagSet();
1341 }
1342 extern STD_RETURN_TYPE_e TEST_BMS_IsBatterySystemStateOkay(void) {
1344 }
1345 extern void TEST_BMS_GetMeasurementValues(void) {
1347 }
1348 extern void TEST_BMS_CheckOpenSenseWire(void) {
1350 }
1351 extern STD_RETURN_TYPE_e TEST_BMS_CheckPrecharge(uint8_t stringNumber, DATA_BLOCK_PACK_VALUES_s *pPackValues) {
1352  return BMS_CheckPrecharge(stringNumber, pPackValues);
1353 }
1354 extern uint8_t TEST_BMS_GetHighestString(BMS_CONSIDER_PRECHARGE_e precharge, DATA_BLOCK_PACK_VALUES_s *pPackValues) {
1355  return BMS_GetHighestString(precharge, pPackValues);
1356 }
1357 extern uint8_t TEST_BMS_GetClosestString(BMS_CONSIDER_PRECHARGE_e precharge, DATA_BLOCK_PACK_VALUES_s *pPackValues) {
1358  return BMS_GetClosestString(precharge, pPackValues);
1359 }
1360 
1361 extern uint8_t TEST_BMS_GetLowestString(BMS_CONSIDER_PRECHARGE_e precharge, DATA_BLOCK_PACK_VALUES_s *pPackValues) {
1362  return BMS_GetLowestString(precharge, pPackValues);
1363 }
1364 extern int32_t TEST_BMS_GetStringVoltageDifference(uint8_t string, DATA_BLOCK_PACK_VALUES_s *pPackValues) {
1365  return BMS_GetStringVoltageDifference(string, pPackValues);
1366 }
1367 extern int32_t TEST_BMS_GetAverageStringCurrent(DATA_BLOCK_PACK_VALUES_s *pPackValues) {
1368  return BMS_GetAverageStringCurrent(pPackValues);
1369 }
1370 extern void TEST_BMS_UpdateBatsysState(DATA_BLOCK_PACK_VALUES_s *pPackValues) {
1371  BMS_UpdateBatsysState(pPackValues);
1372 }
1373 
1374 #endif
Header for the driver for balancing.
BAL_RETURN_TYPE_e BAL_SetStateRequest(BAL_STATE_REQUEST_e stateRequest)
sets the current state request of the state variable bal_state.
@ BAL_STATE_ALLOWBALANCING_REQUEST
Definition: bal.h:103
@ BAL_STATE_NO_BALANCING_REQUEST
Definition: bal.h:102
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_STRINGS
#define BS_NR_OF_CELLS_PER_MODULE
number of battery cells per battery module (parallel cells are counted as one)
#define BS_REST_CURRENT_mA
current threshold for determing rest state of battery. If absolute current is below this limit value ...
#define BS_NR_OF_MODULES
number of modules in battery pack
#define POSITIVE_DISCHARGE_CURRENT
#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
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:364
#define BMS_SAVELASTSTATES()
Definition: bms.c:76
static DATA_BLOCK_MIN_MAX_s bms_tableMinMax
Definition: bms.c:117
bool BMS_IsStringPrecharging(uint8_t stringNumber)
Returns if string is currently precharging or not.
Definition: bms.c:1308
bool BMS_IsTransitionToErrorStateActive(void)
Check if transition in to error state is active.
Definition: bms.c:1321
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:633
static bool BMS_IsAnyFatalErrorFlagSet(void)
Checks all the error flags from diagnosis module with a severity of DIAG_FATAL_ERROR.
Definition: bms.c:390
static BMS_RETURN_TYPE_e BMS_CheckStateRequest(BMS_STATE_REQUEST_e statereq)
checks the state requests that are made.
Definition: bms.c:271
static void BMS_GetMeasurementValues(void)
Definition: bms.c:314
static DATA_BLOCK_PACK_VALUES_s bms_tablePackValues
Definition: bms.c:119
static void BMS_UpdateBatsysState(DATA_BLOCK_PACK_VALUES_s *pPackValues)
Updates battery system state variable depending on measured/recent current values.
Definition: bms.c:576
#define BMS_NO_ACTIVE_DELAY_TIME_ms
Definition: bms.c:71
static int32_t BMS_GetAverageStringCurrent(DATA_BLOCK_PACK_VALUES_s *pPackValues)
Returns the average current flowing through all strings.
Definition: bms.c:567
void BMS_Trigger(void)
trigger function for the SYS driver state machine.
Definition: bms.c:647
uint8_t BMS_GetNumberOfConnectedStrings(void)
Returns number of connected strings.
Definition: bms.c:1317
bool BMS_IsStringClosed(uint8_t stringNumber)
Returns string state (closed or open)
Definition: bms.c:1299
static void BMS_CheckOpenSenseWire(void)
Check for any open voltage sense wire.
Definition: bms.c:339
BMS_CURRENT_FLOW_STATE_e BMS_GetCurrentFlowDirection(int32_t current_mA)
Get current flow direction, current value as function parameter.
Definition: bms.c:1276
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:547
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:523
BMS_CURRENT_FLOW_STATE_e BMS_GetBatterySystemState(void)
Returns current battery system state (charging/discharging, resting or in relaxation phase)
Definition: bms.c:1272
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:452
static uint8_t BMS_CheckReEntrance(void)
re-entrance check of SYS state machine trigger function
Definition: bms.c:292
static DATA_BLOCK_OPEN_WIRE_s bms_tableOpenWire
Definition: bms.c:118
static BMS_STATE_REQUEST_e BMS_TransferStateRequest(void)
transfers the current state request to the state machine.
Definition: bms.c:304
static BMS_STATE_s bms_state
Definition: bms.c:85
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:409
STD_RETURN_TYPE_e BMS_GetInitializationState(void)
Gets the initialization state.
Definition: bms.c:625
static uint8_t BMS_CheckCanRequests(void)
Checks the state requests made to the BMS state machine.
Definition: bms.c:318
BMS_STATEMACH_e BMS_GetState(void)
Returns the current state.
Definition: bms.c:629
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:477
bms driver header
@ BMS_AT_REST
Definition: bms.h:69
@ BMS_DISCHARGING
Definition: bms.h:67
@ BMS_CHARGING
Definition: bms.h:66
@ BMS_RELAXATION
Definition: bms.h:68
@ BMS_CANSTATE_NORMAL
Definition: bms.h:113
@ BMS_CANSTATE_CHARGE
Definition: bms.h:114
@ BMS_CANSTATE_STANDBY
Definition: bms.h:111
@ BMS_CANSTATE_ERROR
Definition: bms.h:115
@ BMS_CANSTATE_IDLE
Definition: bms.h:109
@ BMS_CANSTATE_PRECHARGE
Definition: bms.h:112
enum BMS_RETURN_TYPE BMS_RETURN_TYPE_e
@ BMS_OK
Definition: bms.h:165
@ BMS_REQUEST_PENDING
Definition: bms.h:167
@ BMS_ALREADY_INITIALIZED
Definition: bms.h:169
@ BMS_ILLEGAL_REQUEST
Definition: bms.h:168
enum BMS_STATE_REQUEST BMS_STATE_REQUEST_e
enum BMS_STATEMACH BMS_STATEMACH_e
@ BMS_POWER_PATH_1
Definition: bms.h:177
@ BMS_POWER_PATH_OPEN
Definition: bms.h:175
@ BMS_POWER_PATH_0
Definition: bms.h:176
enum BMS_CURRENT_FLOW_STATE BMS_CURRENT_FLOW_STATE_e
@ BMS_STATE_NO_REQUEST
Definition: bms.h:158
@ BMS_STATE_INIT_REQUEST
Definition: bms.h:156
@ BMS_STATE_ERROR_REQUEST
Definition: bms.h:157
@ BMS_DO_NOT_TAKE_PRECHARGE_INTO_ACCCOUNT
Definition: bms.h:81
@ BMS_TAKE_PRECHARGE_INTO_ACCCOUNT
Definition: bms.h:82
@ BMS_PRECHARGE_OPEN_PRECHARGE
Definition: bms.h:133
@ BMS_CHECK_STRING_OPEN
Definition: bms.h:150
@ BMS_OPEN_STRINGS_EXIT
Definition: bms.h:151
@ BMS_PRECHARGE_CLOSE_PRECHARGE
Definition: bms.h:131
@ BMS_NORMAL_CLOSE_NEXT_STRING
Definition: bms.h:145
@ BMS_CHECK_ERROR_FLAGS_PRECHARGE_CLOSINGSTRINGS
Definition: bms.h:143
@ BMS_ENTRY
Definition: bms.h:120
@ BMS_INTERLOCK_CHECKED
Definition: bms.h:122
@ BMS_OPEN_STRINGS
Definition: bms.h:149
@ BMS_CHECK_ERROR_FLAGS_PRECHARGE_FIRST_STRING
Definition: bms.h:140
@ BMS_CHECK_ERROR_FLAGS_CLOSINGPRECHARGE
Definition: bms.h:144
@ BMS_CHECK_INTERLOCK_CLOSE_AFTER_ERROR
Definition: bms.h:129
@ BMS_PRECHARGE_CHECK_VOLTAGES
Definition: bms.h:132
@ BMS_CHECK_STRING_CLOSED
Definition: bms.h:142
@ BMS_CHECK_ERROR_FLAGS
Definition: bms.h:125
@ BMS_OPEN_ALL_PRECHARGES
Definition: bms.h:146
@ BMS_CHECK_ERROR_FLAGS_INTERLOCK
Definition: bms.h:121
@ BMS_OPEN_INTERLOCK
Definition: bms.h:128
@ BMS_CHECK_STATE_REQUESTS
Definition: bms.h:123
@ BMS_CLOSE_FIRST_STRING_PRECHARGE_STATE
Definition: bms.h:137
@ BMS_CHECK_CLOSE_FIRST_STRING_PRECHARGE_STATE
Definition: bms.h:138
enum BMS_CONSIDER_PRECHARGE BMS_CONSIDER_PRECHARGE_e
@ BMS_STATEMACH_PRECHARGE
Definition: bms.h:94
@ BMS_STATEMACH_STANDBY
Definition: bms.h:93
@ BMS_STATEMACH_CHARGE
Definition: bms.h:97
@ BMS_STATEMACH_OPENCONTACTORS
Definition: bms.h:92
@ BMS_STATEMACH_UNINITIALIZED
Definition: bms.h:88
@ BMS_STATEMACH_ERROR
Definition: bms.h:98
@ BMS_STATEMACH_NORMAL
Definition: bms.h:95
@ BMS_STATEMACH_INITIALIZATION
Definition: bms.h:89
@ BMS_STATEMACH_DISCHARGE
Definition: bms.h:96
@ BMS_STATEMACH_INITIALIZED
Definition: bms.h:90
@ BMS_STATEMACH_IDLE
Definition: bms.h:91
#define BMS_TIME_WAIT_AFTER_OPENING_STRING
Definition: bms_cfg.h:124
#define BMS_REQ_ID_STANDBY
Definition: bms_cfg.h:67
#define BMS_AVERAGE_STRING_CURRENT_LIMIT_MA
Definition: bms_cfg.h:142
#define BMS_TIME_WAIT_AFTER_OPENING_PRECHARGE
Definition: bms_cfg.h:148
#define BMS_STATEMACH_LONGTIME
BMS statemachine long time definition in BMS_Trigger() calls until next state/substate is processed.
Definition: bms_cfg.h:112
#define BMS_STRING_OPEN_TIMEOUT
Definition: bms_cfg.h:133
#define BMS_REQ_ID_NOREQ
Definition: bms_cfg.h:64
#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:130
#define BMS_STATEMACH_VERYLONGTIME
BMS statemachine very long time definition in BMS_Trigger() calls until next state/substate is proces...
Definition: bms_cfg.h:118
#define BMS_TIME_WAIT_AFTER_STRING_CLOSED
Definition: bms_cfg.h:121
#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:139
#define BMS_PRECHARGE_TRIES
Definition: bms_cfg.h:164
#define BMS_STATEMACH_MEDIUMTIME
BMS statemachine medium time definition in BMS_Trigger() calls until next state/substate is processed...
Definition: bms_cfg.h:106
#define BMS_STATEMACH_SHORTTIME
BMS statemachine short time definition in BMS_Trigger() calls until next state/substate is processed.
Definition: bms_cfg.h:100
#define BMS_REQ_ID_CHARGE
Definition: bms_cfg.h:73
#define BMS_REQ_ID_NORMAL
Definition: bms_cfg.h:70
#define BMS_NO_STRING_AVAILABLE
Functions searching for next string return this value if no further string is available.
Definition: bms_cfg.h:78
#define BMS_OSCILLATION_TIMEOUT
Timeout in 1*10ms to wait before re-entering to precharge.
Definition: bms_cfg.h:161
#define BMS_TIME_WAIT_AFTERPRECHARGEFAIL
Time to wait in BMS_Trigger() calls after precharge opened because precharge failed.
Definition: bms_cfg.h:154
#define BMS_PRECHARGE_VOLTAGE_THRESHOLD_mV
Definition: bms_cfg.h:167
#define BMS_PRECHARGE_CURRENT_THRESHOLD_mA
Definition: bms_cfg.h:170
#define BMS_TIME_WAIT_AFTER_CLOSING_PRECHARGE
Definition: bms_cfg.h:145
CONT_ELECTRICAL_STATE_TYPE_e CONT_GetState(uint8_t contactorNumber)
Gets the current state.
Definition: contactor.c:286
void CONT_CheckFeedback(void)
checks the feedback of the contactors
Definition: contactor.c:212
STD_RETURN_TYPE_e CONT_OpenPrecharge(uint8_t stringNumber)
Opens precharge.
Definition: contactor.c:260
STD_RETURN_TYPE_e CONT_CloseString(uint8_t stringNumber)
Closes the contactor of a string.
Definition: contactor.c:217
STD_RETURN_TYPE_e CONT_ClosePrecharge(uint8_t stringNumber)
Closes precharge.
Definition: contactor.c:234
STD_RETURN_TYPE_e CONT_OpenString(uint8_t stringNumber)
Opens the contactor of a string.
Definition: contactor.c:225
Headers for the driver for the contactors.
enum CONT_ELECTRICAL_STATE_TYPE CONT_ELECTRICAL_STATE_TYPE_e
@ CONT_SWITCH_ON
Definition: contactor_cfg.h:72
@ CONT_SWITCH_OFF
Definition: contactor_cfg.h:71
Database module header.
#define DATA_READ_DATA(...)
Definition: database.h:76
#define DATA_WRITE_DATA(...)
Definition: database.h:86
@ DATA_BLOCK_ID_MIN_MAX
Definition: database_cfg.h:75
@ DATA_BLOCK_ID_SYSTEMSTATE
Definition: database_cfg.h:87
@ DATA_BLOCK_ID_OPEN_WIRE_BASE
Definition: database_cfg.h:81
@ DATA_BLOCK_ID_PACK_VALUES
Definition: database_cfg.h:103
@ DATA_BLOCK_ID_STATEREQUEST
Definition: database_cfg.h:92
uint32_t DIAG_GetDelay(DIAG_ID_e diagnosisEntry)
Get configured delay of passed diagnosis entry.
Definition: diag.c:369
STD_RETURN_TYPE_e DIAG_GetDiagnosisEntryState(DIAG_ID_e diagnosisEntry)
Checks if passed diagnosis entry has been triggered or not.
Definition: diag.c:173
bool DIAG_IsAnyFatalErrorSet(void)
Check if any fatal error is set.
Definition: diag.c:374
DIAG_RETURNTYPE_e DIAG_Handler(DIAG_ID_e diag_id, DIAG_EVENT_e event, DIAG_IMPACT_LEVEL_e impact, uint32_t data)
DIAG_Handler provides generic error handling, based on diagnosis group.
Definition: diag.c:226
Diagnosis driver header.
DIAG_DEV_s diag_device
Definition: diag_cfg.c:212
@ DIAG_STRING
Definition: diag_cfg.h:248
@ DIAG_EVENT_NOT_OK
Definition: diag_cfg.h:235
@ DIAG_EVENT_OK
Definition: diag_cfg.h:234
@ DIAG_ID_OPEN_WIRE
Definition: diag_cfg.h:209
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:237
#define FAS_TRAP
Define that evaluates to essential boolean false thus tripping an assert.
Definition: fassert.h:108
int32_t MATH_AbsInt32(int32_t value)
Returns the absolute value of passed int32_t value.
Definition: foxmath.c:117
int64_t MATH_AbsInt64(int64_t value)
Returns the absolute value of passed int64_t value.
Definition: foxmath.c:125
math library for often used math functions
@ STD_NOT_OK
Definition: fstd_types.h:73
@ STD_OK
Definition: fstd_types.h:72
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:66
enum STD_RETURN_TYPE STD_RETURN_TYPE_e
ILCK_RETURN_TYPE_e ILCK_SetStateRequest(ILCK_STATE_REQUEST_e statereq)
sets the current state request of the state variable ilck_state.
Definition: interlock.c:306
ILCK_ELECTRICAL_STATE_TYPE_e ILCK_GetInterlockFeedback(void)
Reads the feedback pin of the interlock and returns its current value (ILCK_SWITCH_OFF/ILCK_SWITCH_ON...
Definition: interlock.c:287
Headers for the driver for the interlock.
@ ILCK_STATE_OPEN_REQUEST
Definition: interlock.h:89
@ ILCK_STATE_CLOSE_REQUEST
Definition: interlock.h:90
@ ILCK_SWITCH_ON
Definition: interlock_cfg.h:97
#define LTC_STANDBY_OPEN_WIRE_PERIOD_ms
Definition: ltc_6806_cfg.h:258
#define LTC_NORMAL_OPEN_WIRE_PERIOD_ms
Definition: ltc_6806_cfg.h:264
STD_RETURN_TYPE_e MEAS_RequestOpenWireCheck(uint8_t string)
Makes the request to the MIC state machine to perform open-wire check.
Definition: meas.c:119
Headers for the driver for the measurements needed by the BMS (e.g., I,V,T).
Measurement IC driver header.
#define MIC_ERROR_OPEN_WIRE_PERIOD_ms
Definition: mic.h:64
void OS_ExitTaskCritical(void)
Exit Critical interface function for use in FreeRTOS-Tasks and FreeRTOS-ISR.
Definition: os.c:178
void OS_EnterTaskCritical(void)
Enter Critical interface function for use in FreeRTOS-Tasks and FreeRTOS-ISR.
Definition: os.c:174
uint32_t OS_GetTickCount(void)
Returns OS based system tick value.
Definition: os.c:182
Implementation of the tasks used by the system, headers.
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:143
void SOA_CheckVoltages(DATA_BLOCK_MIN_MAX_s *pMinimumMaximumCellVoltages)
checks the abidance by the safe operating area
Definition: soa.c:77
void SOA_CheckSlaveTemperatures(void)
FOR FUTURE COMPATIBILITY; DUMMY FUNCTION; DO NOT USE.
Definition: soa.c:357
void SOA_CheckCurrent(DATA_BLOCK_PACK_VALUES_s *pTablePackValues)
checks the abidance by the safe operating area
Definition: soa.c:275
Header for SOA module, responsible for checking battery parameters against safety limits.
Definition: bms.h:185
uint8_t deactivatedStrings[BS_NR_OF_STRINGS]
Definition: bms.h:214
BMS_STATEMACH_e nextstate
Definition: bms.h:205
BMS_STATEMACH_e state
Definition: bms.h:188
uint8_t numberOfClosedStrings
Definition: bms.h:201
uint16_t stringCloseTimeout
Definition: bms.h:204
BMS_STATE_REQUEST_e stateRequest
Definition: bms.h:187
uint8_t firstClosedString
Definition: bms.h:206
uint32_t minimumActiveDelay_ms
Definition: bms.h:210
BMS_POWER_PATH_TYPE_e powerPath
Definition: bms.h:200
uint8_t PrechargeTryCounter
Definition: bms.h:199
uint16_t OscillationTimeout
Definition: bms.h:198
uint8_t counter
Definition: bms.h:195
BMS_STATEMACH_SUB_e substate
Definition: bms.h:189
uint8_t triggerentry
Definition: bms.h:194
STD_RETURN_TYPE_e initFinished
Definition: bms.h:193
uint16_t timer
Definition: bms.h:186
uint32_t ErrRequestCounter
Definition: bms.h:192
uint32_t nextstringclosedtimer
Definition: bms.h:203
uint8_t closedStrings[BS_NR_OF_STRINGS]
Definition: bms.h:213
uint16_t stringOpenTimeout
Definition: bms.h:202
uint32_t restTimer_10ms
Definition: bms.h:197
bool transitionToErrorState
Definition: bms.h:211
uint32_t remainingDelay_ms
Definition: bms.h:209
uint8_t closedPrechargeContactors[BS_NR_OF_STRINGS]
Definition: bms.h:212
BMS_CURRENT_FLOW_STATE_e currentFlowState
Definition: bms.h:196
DATA_BLOCK_ID_e uniqueId
Definition: database_cfg.h:110
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:163
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:303
uint8_t openwire[BS_NR_OF_STRINGS][BS_NR_OF_MODULES *(BS_NR_OF_CELLS_PER_MODULE+1)]
Definition: database_cfg.h:307
int32_t stringCurrent_mA[BS_NR_OF_STRINGS]
Definition: database_cfg.h:204
int32_t highVoltageBusVoltage_mV
Definition: database_cfg.h:198
uint8_t invalidStringCurrent[BS_NR_OF_STRINGS]
Definition: database_cfg.h:205
int32_t stringVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:202
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:191
uint8_t invalidStringVoltage[BS_NR_OF_STRINGS]
Definition: database_cfg.h:203
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:510
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:422
DIAG_ID_e id
Definition: diag_cfg.h:301
DIAG_ID_CFG_s * pFatalErrorLinkTable[DIAG_ID_MAX]
Definition: diag_cfg.h:324
uint16_t numberOfFatalErrors
Definition: diag_cfg.h:322