foxBMS  1.1.2
The foxBMS Battery Management System API Documentation
contactor.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 contactor.c
44  * @author foxBMS Team
45  * @date 2020-02-11 (date of creation)
46  * @updated 2021-03-24 (date of last update)
47  * @ingroup DRIVERS
48  * @prefix CONT
49  *
50  * @brief Driver for the contactors.
51  *
52  */
53 
54 /*========== Includes =======================================================*/
55 #include "contactor.h"
56 
57 #include "mcu.h"
58 #include "sps.h"
59 
60 /*========== Macros and Definitions =========================================*/
61 
62 /*========== Static Constant and Variable Definitions =======================*/
63 
64 /*========== Extern Constant and Variable Definitions =======================*/
65 
66 /*========== Static Function Prototypes =====================================*/
67 /**
68  * @brief Resolves the contactor index from a contactor name
69  * @details Searches in the contactor index by iteration from front to back for
70  * the contactor name and returns the first hit.
71  * @param[in] name Name of the contactor
72  * @returns index number of the entry in the contactor array
73  */
75 
76 /**
77  * @brief Gets the contactor name from a contactor index
78  * @param[in] index index number of the contactor
79  * @returns Returns the name of the contactor
80  */
82 
83 /**
84  * @brief Returns the sps channel index from a contactor index
85  * @details Currently this implementation maps simply in ascending order
86  */
88 
89 /**
90  * @brief Sets SPS channels according to contactors
91  * @details Currently this implementation assumes simple ascending order.
92  * @param[in] contactor index of the contactor that should be set
93  */
94 static void CONT_SetSpsChannelFromContactor(const CONT_CONTACTOR_INDEX contactor);
95 
96 /** conducts an initialization test of the contactor registry and asserts at failure */
98 
99 /*========== Static Function Implementations ================================*/
101  CONT_CONTACTOR_INDEX contactor = 0u;
102  bool hit = false;
103  do {
104  if (name == cont_contactorStates[contactor].name) {
105  /* contactor found, therefore abort */
106  hit = true;
107  } else {
108  /* continue and increase contactor counter */
109  contactor++;
110  }
111  } while ((contactor < BS_NR_OF_CONTACTORS) && (true != hit));
112 
113  /* an unknown contactor may not exist */
114  FAS_ASSERT(true == hit);
115 
116  return contactor;
117 }
118 
121  return cont_contactorStates[index].name;
122 }
123 
125  FAS_ASSERT(contactor < BS_NR_OF_CONTACTORS);
126  return cont_contactorStates[contactor].spsChannel;
127 }
128 
130  FAS_ASSERT(contactor < BS_NR_OF_CONTACTORS);
131  switch (cont_contactorStates[contactor].currentSet) {
132  case CONT_SWITCH_UNDEF:
133  case CONT_SWITCH_OFF:
135  break;
136  case CONT_SWITCH_ON:
138  break;
139  default:
141  break;
142  }
143 }
144 
146  /* iterate over each contactor and compare found name with resolved name (if a name is used double this would
147  always return the first entry and we would have the second entry from iterating here) */
148  for (CONT_CONTACTOR_INDEX contactor = 0u; contactor < BS_NR_OF_CONTACTORS; contactor++) {
149  FAS_ASSERT(contactor == CONT_ResolveContactorName(cont_contactorStates[contactor].name));
150  FAS_ASSERT(cont_contactorStates[contactor].name == CONT_GetContactorName(contactor));
151 
152  /* convention at the moment: sps channel index has to be the same as contactor index; this may change in
153  future implementations */
154  FAS_ASSERT(contactor == cont_contactorStates[contactor].spsChannel);
155 
156  /* every contactor channel has to be affiliated with contactor */
158  }
159 }
160 
161 /*========== Extern Function Implementations ================================*/
163  CONT_CONTACTOR_INDEX contactorNumber = CONT_ResolveContactorName(name);
164  CONT_ELECTRICAL_STATE_TYPE_e contactorSetInformation = cont_contactorStates[contactorNumber].currentSet;
165  return contactorSetInformation;
166 }
167 
168 extern void CONT_GetContactorFeedback(void) {
169  for (CONT_CONTACTOR_INDEX contactor = 0; contactor < BS_NR_OF_CONTACTORS; contactor++) {
170  if (CONT_HAS_NO_FEEDBACK == cont_contactorStates[contactor].feedbackPinType) {
171  /* no feedback: assume set value is true */
173  } else if (CONT_FEEDBACK_THROUGH_CURRENT == cont_contactorStates[contactor].feedbackPinType) {
174  /* feedback from current: ask SPS driver for feedback */
175  cont_contactorStates[contactor].feedback =
177  } else {
178  /* TODO: get feedback through I2C port expander */
179  }
180  }
181 }
182 
184  const CONT_NAMES_e name,
185  CONT_ELECTRICAL_STATE_TYPE_e requestedContactorState) {
187  FAS_ASSERT(contactor < BS_NR_OF_CONTACTORS);
188  FAS_ASSERT(
189  (CONT_SWITCH_OFF == requestedContactorState) || (CONT_SWITCH_ON == requestedContactorState) ||
190  (CONT_SWITCH_UNDEF == requestedContactorState));
191 
192  STD_RETURN_TYPE_e retVal = STD_OK;
193 
194  if (requestedContactorState == CONT_SWITCH_ON) {
196  } else if (requestedContactorState == CONT_SWITCH_OFF) {
198  } else {
199  retVal = STD_NOT_OK;
200  }
201 
203 
204  return retVal;
205 }
206 
207 /**
208  * @brief checks the feedback of the contactors
209  *
210  * @details makes a DIAG entry for each contactor when the feedback does not match the set value
211  */
212 extern void CONT_CheckFeedback(void) {
214  /* TODO implement when contactor feedback is available */
215 }
216 
217 extern STD_RETURN_TYPE_e CONT_CloseString(uint8_t stringNumber) {
218  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
219  /* String contactors in the list start at index 0
220  * so string number corresponds to contactor index
221  */
223 }
224 
225 extern STD_RETURN_TYPE_e CONT_OpenString(uint8_t stringNumber) {
226  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
227  /* String contactors in the list start at index 0
228  * so string number corresponds to contactor index
229  */
230  /* TODO: implement current check and similar when opening */
232 }
233 
234 extern STD_RETURN_TYPE_e CONT_ClosePrecharge(uint8_t stringNumber) {
235  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
236  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
237  uint8_t prechargeContactorNumber = 0u;
238 
239  /* Precharge contactors in the list stay after string contactors
240  * so it has index (number of contactors)-1
241  */
242  if (bs_stringsWithPrecharge[stringNumber] == BS_STRING_WITH_PRECHARGE) {
243  /* Find contactor number corresponding to precharge of the requested string */
244  for (uint8_t stringPrechargeNumber = 0u; stringPrechargeNumber < BS_NR_OF_STRINGS; stringPrechargeNumber++) {
245  if (bs_stringsWithPrecharge[stringPrechargeNumber] == BS_STRING_WITH_PRECHARGE) {
246  if (stringPrechargeNumber == stringNumber) {
247  break;
248  }
249  prechargeContactorNumber++;
250  }
251  }
252  if ((BS_NR_OF_STRINGS + prechargeContactorNumber) < BS_NR_OF_CONTACTORS) {
253  retVal = CONT_SetContactorState(
254  CONT_GetContactorName(BS_NR_OF_STRINGS + prechargeContactorNumber), CONT_SWITCH_ON);
255  }
256  }
257  return retVal;
258 }
259 
260 extern STD_RETURN_TYPE_e CONT_OpenPrecharge(uint8_t stringNumber) {
261  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
262  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
263  uint8_t prechargeContactorNumber = 0u;
264 
265  /* Precharge contactors in the list stay after string contactors
266  * so it has index (number of contactors)-1
267  */
268  if (bs_stringsWithPrecharge[stringNumber] == BS_STRING_WITH_PRECHARGE) {
269  /* Find contactor number corresponding to precharge of the requested string */
270  for (uint8_t stringPrechargeNumber = 0u; stringPrechargeNumber < BS_NR_OF_STRINGS; stringPrechargeNumber++) {
271  if (bs_stringsWithPrecharge[stringPrechargeNumber] == BS_STRING_WITH_PRECHARGE) {
272  if (stringPrechargeNumber == stringNumber) {
273  break;
274  }
275  prechargeContactorNumber++;
276  }
277  }
278  if ((BS_NR_OF_STRINGS + prechargeContactorNumber) < BS_NR_OF_CONTACTORS) {
279  retVal = CONT_SetContactorState(
280  CONT_GetContactorName(BS_NR_OF_STRINGS + prechargeContactorNumber), CONT_SWITCH_OFF);
281  }
282  }
283  return retVal;
284 }
285 
286 extern CONT_ELECTRICAL_STATE_TYPE_e CONT_GetState(uint8_t contactorNumber) {
287  FAS_ASSERT(contactorNumber < BS_NR_OF_CONTACTORS);
288  return (cont_contactorStates[contactorNumber].feedback);
289 }
290 
291 extern void CONT_Initialize(void) {
293 }
294 
295 /*========== Externalized Static Function Implementations (Unit Test) =======*/
296 #ifdef UNITY_UNIT_TEST
297 extern void TEST_CONT_InitializationCheckOfContactorRegistry() {
299 }
300 extern CONT_CONTACTOR_INDEX TEST_CONT_ResolveContactorName(const CONT_NAMES_e name) {
301  return CONT_ResolveContactorName(name);
302 }
303 #endif /* UNITY_UNIT_TEST */
BS_STRING_PRECHARGE_PRESENT_e bs_stringsWithPrecharge[BS_NR_OF_STRINGS]
#define BS_NR_OF_STRINGS
@ BS_STRING_WITH_PRECHARGE
#define BS_NR_OF_CONTACTORS
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
static void CONT_SetSpsChannelFromContactor(const CONT_CONTACTOR_INDEX contactor)
Sets SPS channels according to contactors.
Definition: contactor.c:129
static CONT_NAMES_e CONT_GetContactorName(const CONT_CONTACTOR_INDEX index)
Gets the contactor name from a contactor index.
Definition: contactor.c:119
static void CONT_InitializationCheckOfContactorRegistry(void)
Definition: contactor.c:145
STD_RETURN_TYPE_e CONT_OpenPrecharge(uint8_t stringNumber)
Opens precharge.
Definition: contactor.c:260
static SPS_CHANNEL_INDEX CONT_GetSpsChannelIndexFromContactor(const CONT_CONTACTOR_INDEX contactor)
Returns the sps channel index from a contactor index.
Definition: contactor.c:124
CONT_ELECTRICAL_STATE_TYPE_e CONT_GetContactorSetValue(const CONT_NAMES_e name)
Gets the latest value the contactors were set to.
Definition: contactor.c:162
STD_RETURN_TYPE_e CONT_SetContactorState(const CONT_NAMES_e name, CONT_ELECTRICAL_STATE_TYPE_e requestedContactorState)
Sets the contactor state to its requested state, if the contactor is at that time not in the requeste...
Definition: contactor.c:183
static CONT_CONTACTOR_INDEX CONT_ResolveContactorName(const CONT_NAMES_e name)
Resolves the contactor index from a contactor name.
Definition: contactor.c:100
STD_RETURN_TYPE_e CONT_CloseString(uint8_t stringNumber)
Closes the contactor of a string.
Definition: contactor.c:217
void CONT_GetContactorFeedback(void)
Reads the feedback pin of every contactor and returns its current value (CONT_SWITCH_OFF/CONT_SWITCH_...
Definition: contactor.c:168
STD_RETURN_TYPE_e CONT_ClosePrecharge(uint8_t stringNumber)
Closes precharge.
Definition: contactor.c:234
void CONT_Initialize(void)
initializes the contactor module
Definition: contactor.c:291
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.
CONT_CONTACTOR_STATE_s cont_contactorStates[BS_NR_OF_CONTACTORS]
Definition: contactor_cfg.c:62
uint8_t CONT_CONTACTOR_INDEX
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
@ CONT_SWITCH_UNDEF
Definition: contactor_cfg.h:73
@ CONT_HAS_NO_FEEDBACK
Definition: contactor_cfg.h:92
@ CONT_FEEDBACK_THROUGH_CURRENT
Definition: contactor_cfg.h:91
enum CONT_NAMES CONT_NAMES_e
#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
@ STD_NOT_OK
Definition: fstd_types.h:73
@ STD_OK
Definition: fstd_types.h:72
enum STD_RETURN_TYPE STD_RETURN_TYPE_e
Headers for the driver for the MCU module.
SPS_CHANNEL_AFFILIATION_e SPS_GetChannelAffiliation(SPS_CHANNEL_INDEX channelIndex)
Returns the channel affiliation.
Definition: sps.c:613
void SPS_RequestContactorState(SPS_CHANNEL_INDEX channelIndex, SPS_CHANNEL_FUNCTION_e channelFunction)
Request state of a contactor.
Definition: sps.c:587
CONT_ELECTRICAL_STATE_TYPE_e SPS_GetChannelFeedback(SPS_CHANNEL_INDEX channelIndex)
Get feedback value.
Definition: sps.c:597
Headers for the driver for the smart power switches.
@ SPS_CHANNEL_ON
Definition: sps_cfg.h:168
@ SPS_CHANNEL_OFF
Definition: sps_cfg.h:167
uint8_t SPS_CHANNEL_INDEX
Definition: sps_types.h:63
@ SPS_AFF_CONTACTOR
Definition: sps_types.h:72
CONT_ELECTRICAL_STATE_TYPE_e currentSet
Definition: contactor_cfg.h:97
const CONT_NAMES_e name
const SPS_CHANNEL_INDEX spsChannel
CONT_ELECTRICAL_STATE_TYPE_e feedback
Definition: contactor_cfg.h:98