foxBMS  1.4.1
The foxBMS Battery Management System API Documentation
contactor.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 contactor.c
44  * @author foxBMS Team
45  * @date 2020-02-11 (date of creation)
46  * @updated 2022-10-27 (date of last update)
47  * @version v1.4.1
48  * @ingroup DRIVERS
49  * @prefix CONT
50  *
51  * @brief Driver for the contactors.
52  *
53  */
54 
55 /*========== Includes =======================================================*/
56 #include "contactor.h"
57 
58 #include "diag.h"
59 #include "mcu.h"
60 #include "sps.h"
61 
62 /*========== Macros and Definitions =========================================*/
63 
64 /*========== Static Constant and Variable Definitions =======================*/
65 
66 /*========== Extern Constant and Variable Definitions =======================*/
67 
68 /*========== Static Function Prototypes =====================================*/
69 /**
70  * @brief Reads the feedback of all contactors
71  * @details Gathers the feedback of all contactors from the configured feedback
72  * source (#CONT_FEEDBACK_TYPE_e). If #CONT_HAS_NO_FEEDBACK is
73  * configured,it is assumed that the contactor has reached the
74  * requested state.
75  */
76 static void CONT_GetFeedbackOfAllContactors(void);
77 
78 /** conducts an initialization test of the contactor registry and asserts at failure */
80 
81 /*========== Static Function Implementations ================================*/
83  /* Iterate over all contactors */
84  for (CONT_CONTACTOR_INDEX contactor = 0; contactor < BS_NR_OF_CONTACTORS; contactor++) {
85  /* Use different feedback sources depending on the individual contactor configuration */
86  if (cont_contactorStates[contactor].feedbackPinType == CONT_HAS_NO_FEEDBACK) {
87  /* no feedback: assume set value is true */
89  } else if (cont_contactorStates[contactor].feedbackPinType == CONT_FEEDBACK_THROUGH_CURRENT) {
90  /* feedback from current: ask SPS driver for feedback */
91  cont_contactorStates[contactor].feedback =
93  } else if (CONT_FEEDBACK_NORMALLY_OPEN == cont_contactorStates[contactor].feedbackPinType) {
94  cont_contactorStates[contactor].feedback =
95  SPS_GetChannelPexFeedback(cont_contactorStates[contactor].spsChannel, true);
96  } else {
97  /* CONT_FEEDBACK_NORMALLY_CLOSED */
98  cont_contactorStates[contactor].feedback =
99  SPS_GetChannelPexFeedback(cont_contactorStates[contactor].spsChannel, false);
100  }
101  }
102 }
103 
105  /* Iterate over each contactor and compare found name with resolved name (if a name is used double this would
106  always return the first entry and we would have the second entry from iterating here) */
107  for (CONT_CONTACTOR_INDEX contactor = 0u; contactor < BS_NR_OF_CONTACTORS; contactor++) {
108  /* TODO: add check that only one contactor of each type is configured for each string */
109 
110  /* Check that a configured SPS channel number is not higher than the number of available SPS channels */
112 
113  /* every contactor channel has to be affiliated with contactor */
114  const SPS_CHANNEL_AFFILIATION_e channelAffiliation =
115  SPS_GetChannelAffiliation(cont_contactorStates[contactor].spsChannel);
116  FAS_ASSERT(SPS_AFF_CONTACTOR == channelAffiliation);
117  }
118 }
119 
120 /*========== Extern Function Implementations ================================*/
121 extern void CONT_CheckFeedback(void) {
122  /* Get the feedback from all contactors from the configured feedback sources */
124  /* Check the contactor feedback */
125  for (CONT_CONTACTOR_INDEX contactor = 0u; contactor < BS_NR_OF_CONTACTORS; contactor++) {
126  /* TODO: add check that only one contactor of each type is configured for each string */
127  DIAG_EVENT_e feedbackStatus = DIAG_EVENT_NOT_OK;
128  if (cont_contactorStates[contactor].currentSet == cont_contactorStates[contactor].feedback) {
129  /* Set feedback status to okay, if expected and actual contactor state match */
130  feedbackStatus = DIAG_EVENT_OK;
131  }
132  switch (cont_contactorStates[contactor].type) {
133  case CONT_PLUS:
134  DIAG_Handler(
136  feedbackStatus,
137  DIAG_STRING,
138  (uint8_t)cont_contactorStates[contactor].stringIndex);
139  break;
140  case CONT_MINUS:
141  DIAG_Handler(
143  feedbackStatus,
144  DIAG_STRING,
145  (uint8_t)cont_contactorStates[contactor].stringIndex);
146  break;
147  case CONT_PRECHARGE:
148  DIAG_Handler(
150  feedbackStatus,
151  DIAG_STRING,
152  (uint8_t)cont_contactorStates[contactor].stringIndex);
153  break;
154  default:
155  /* Type: CONT_UNDEFINED -> trap */
157  }
158  }
159 }
160 
161 extern STD_RETURN_TYPE_e CONT_OpenContactor(uint8_t stringNumber, CONT_TYPE_e contactor) {
162  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
163  FAS_ASSERT(contactor != CONT_UNDEFINED);
164  STD_RETURN_TYPE_e retval = STD_NOT_OK;
165  /* Iterate over contactor array, find the correct one and request state change via SPS module */
166  for (uint8_t contactorIndex = 0u; contactorIndex < BS_NR_OF_CONTACTORS; contactorIndex++) {
167  if (((BS_STRING_ID_e)stringNumber == cont_contactorStates[contactorIndex].stringIndex) &&
168  (contactor == cont_contactorStates[contactorIndex].type)) {
169  /* Set set state in cont_contactorStates array */
171  /* Request contactor state via SPS module */
173  retval = STD_OK;
174  break;
175  }
176  }
177  return retval;
178 }
179 
180 extern STD_RETURN_TYPE_e CONT_CloseContactor(uint8_t stringNumber, CONT_TYPE_e contactor) {
181  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
182  FAS_ASSERT(contactor != CONT_UNDEFINED);
183  STD_RETURN_TYPE_e retval = STD_NOT_OK;
184  /* Iterate over contactor array, find the correct one and request state change via SPS module */
185  for (uint8_t contactorIndex = 0u; contactorIndex < BS_NR_OF_CONTACTORS; contactorIndex++) {
186  if (((BS_STRING_ID_e)stringNumber == cont_contactorStates[contactorIndex].stringIndex) &&
187  (contactor == cont_contactorStates[contactorIndex].type)) {
188  /* Set set state in cont_contactorStates array */
190  /* Request contactor state via SPS module */
192  retval = STD_OK;
193  break;
194  }
195  }
196  return retval;
197 }
198 
199 extern STD_RETURN_TYPE_e CONT_ClosePrecharge(uint8_t stringNumber) {
200  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
201  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
202  /* Check if passed string has configured a precharge contactor */
203  if (bs_stringsWithPrecharge[stringNumber] == BS_STRING_WITH_PRECHARGE) {
204  retVal = CONT_CloseContactor(stringNumber, CONT_PRECHARGE);
205  }
206  return retVal;
207 }
208 
209 extern STD_RETURN_TYPE_e CONT_OpenPrecharge(uint8_t stringNumber) {
210  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
211  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
212  /* Check if passed string has configured a precharge contactor */
213  if (bs_stringsWithPrecharge[stringNumber] == BS_STRING_WITH_PRECHARGE) {
214  retVal = CONT_OpenContactor(stringNumber, CONT_PRECHARGE);
215  }
216  return retVal;
217 }
218 
220  /* Iterate over all contactors and open all precharge contactors */
221  for (uint8_t contactorIndex = 0u; contactorIndex < BS_NR_OF_CONTACTORS; contactorIndex++) {
222  /* Set off a request to open all precharge contactors regardless of
223  * their current state as we want to reach a safe state */
224  if (cont_contactorStates[contactorIndex].type == CONT_PRECHARGE) {
225  /* Request opening via SPS module */
228  }
229  }
230 }
231 
232 extern CONT_ELECTRICAL_STATE_TYPE_e CONT_GetContactorState(uint8_t stringNumber, CONT_TYPE_e contactorType) {
233  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
234  FAS_ASSERT(contactorType != CONT_UNDEFINED);
236  /* Iterate over all contactors and return the requested feedback */
237  for (uint8_t contactorIndex = 0u; contactorIndex < BS_NR_OF_CONTACTORS; contactorIndex++) {
238  if ((cont_contactorStates[contactorIndex].stringIndex == (BS_STRING_ID_e)stringNumber) &&
239  (contactorType == cont_contactorStates[contactorIndex].type)) {
240  feedback = cont_contactorStates[contactorIndex].feedback;
241  break;
242  }
243  }
244  return feedback;
245 }
246 
247 extern void CONT_Initialize(void) {
249 }
250 
251 /*========== Externalized Static Function Implementations (Unit Test) =======*/
252 #ifdef UNITY_UNIT_TEST
253 extern void TEST_CONT_InitializationCheckOfContactorRegistry() {
255 }
256 #endif /* UNITY_UNIT_TEST */
BS_STRING_PRECHARGE_PRESENT_e bs_stringsWithPrecharge[BS_NR_OF_STRINGS]
#define BS_NR_OF_STRINGS
Number of parallel strings in the battery pack.
@ BS_STRING_WITH_PRECHARGE
BS_STRING_ID_e
#define BS_NR_OF_CONTACTORS
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
static void CONT_InitializationCheckOfContactorRegistry(void)
Definition: contactor.c:104
static void CONT_GetFeedbackOfAllContactors(void)
Reads the feedback of all contactors.
Definition: contactor.c:82
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
void CONT_Initialize(void)
initializes the contactor module
Definition: contactor.c:247
Headers for the driver for the contactors.
CONT_CONTACTOR_STATE_s cont_contactorStates[BS_NR_OF_CONTACTORS]
Definition: contactor_cfg.c:65
@ CONT_HAS_NO_FEEDBACK
Definition: contactor_cfg.h:80
@ CONT_FEEDBACK_THROUGH_CURRENT
Definition: contactor_cfg.h:79
@ CONT_FEEDBACK_NORMALLY_OPEN
Definition: contactor_cfg.h:77
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
uint8_t CONT_CONTACTOR_INDEX
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
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_EVENT_e
Definition: diag_cfg.h:256
@ DIAG_EVENT_NOT_OK
Definition: diag_cfg.h:258
@ DIAG_EVENT_OK
Definition: diag_cfg.h:257
@ DIAG_STRING
Definition: diag_cfg.h:271
@ DIAG_ID_STRING_PLUS_CONTACTOR_FEEDBACK
Definition: diag_cfg.h:231
@ DIAG_ID_STRING_MINUS_CONTACTOR_FEEDBACK
Definition: diag_cfg.h:230
@ DIAG_ID_PRECHARGE_CONTACTOR_FEEDBACK
Definition: diag_cfg.h:232
#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
STD_RETURN_TYPE_e
Definition: fstd_types.h:81
@ STD_NOT_OK
Definition: fstd_types.h:83
@ STD_OK
Definition: fstd_types.h:82
Headers for the driver for the MCU module.
CONT_ELECTRICAL_STATE_TYPE_e SPS_GetChannelPexFeedback(const SPS_CHANNEL_INDEX channelIndex, bool normallyOpen)
Get the feedback state of a channel.
Definition: sps.c:631
SPS_CHANNEL_AFFILIATION_e SPS_GetChannelAffiliation(SPS_CHANNEL_INDEX channelIndex)
Returns the channel affiliation.
Definition: sps.c:654
CONT_ELECTRICAL_STATE_TYPE_e SPS_GetChannelCurrentFeedback(const SPS_CHANNEL_INDEX channelIndex)
Get feedback value.
Definition: sps.c:615
void SPS_RequestContactorState(SPS_CHANNEL_INDEX channelIndex, SPS_CHANNEL_FUNCTION_e channelFunction)
Request state of a contactor.
Definition: sps.c:597
Headers for the driver for the smart power switches.
#define SPS_NR_OF_AVAILABLE_SPS_CHANNELS
Definition: sps_cfg.h:100
@ SPS_CHANNEL_ON
Definition: sps_cfg.h:186
@ SPS_CHANNEL_OFF
Definition: sps_cfg.h:185
SPS_CHANNEL_AFFILIATION_e
affiliation type of a sps channel
Definition: sps_types.h:72
@ SPS_AFF_CONTACTOR
Definition: sps_types.h:73
CONT_ELECTRICAL_STATE_TYPE_e currentSet
CONT_ELECTRICAL_STATE_TYPE_e feedback