foxBMS - Unit Tests  1.2.1
The foxBMS Unit Tests 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-10-01 (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 if (CONT_FEEDBACK_NORMALLY_OPEN == cont_contactorStates[contactor].feedbackPinType) {
178  cont_contactorStates[contactor].feedback =
180  } else {
181  /* CONT_FEEDBACK_NORMALLY_CLOSED */
182  cont_contactorStates[contactor].feedback =
184  }
185  }
186 }
187 
189  const CONT_NAMES_e name,
190  CONT_ELECTRICAL_STATE_TYPE_e requestedContactorState) {
192  FAS_ASSERT(contactor < BS_NR_OF_CONTACTORS);
193  FAS_ASSERT(
194  (CONT_SWITCH_OFF == requestedContactorState) || (CONT_SWITCH_ON == requestedContactorState) ||
195  (CONT_SWITCH_UNDEF == requestedContactorState));
196 
197  STD_RETURN_TYPE_e retVal = STD_OK;
198 
199  if (requestedContactorState == CONT_SWITCH_ON) {
201  } else if (requestedContactorState == CONT_SWITCH_OFF) {
203  } else {
204  retVal = STD_NOT_OK;
205  }
206 
208 
209  return retVal;
210 }
211 
212 /**
213  * @brief checks the feedback of the contactors
214  *
215  * @details makes a DIAG entry for each contactor when the feedback does not match the set value
216  */
217 extern void CONT_CheckFeedback(void) {
219  /* TODO implement when contactor feedback is available */
220 }
221 
222 extern STD_RETURN_TYPE_e CONT_CloseString(uint8_t stringNumber) {
223  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
224  /* String contactors in the list start at index 0
225  * so string number corresponds to contactor index
226  */
228 }
229 
230 extern STD_RETURN_TYPE_e CONT_OpenString(uint8_t stringNumber) {
231  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
232  /* String contactors in the list start at index 0
233  * so string number corresponds to contactor index
234  */
235  /* TODO: implement current check and similar when opening */
237 }
238 
239 extern STD_RETURN_TYPE_e CONT_ClosePrecharge(uint8_t stringNumber) {
240  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
241  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
242  uint8_t prechargeContactorNumber = 0u;
243  static_assert((BS_NR_OF_STRINGS <= (uint8_t)UINT8_MAX), "This code assumes BS_NR_OF_STRINGS fits into uint8_t");
244 
245  /* Precharge contactors in the list stay after string contactors
246  * so it has index (number of contactors)-1
247  */
248  if (bs_stringsWithPrecharge[stringNumber] == BS_STRING_WITH_PRECHARGE) {
249  /* Find contactor number corresponding to precharge of the requested string */
250  for (uint8_t stringPrechargeNumber = 0u; stringPrechargeNumber < BS_NR_OF_STRINGS; stringPrechargeNumber++) {
251  if (bs_stringsWithPrecharge[stringPrechargeNumber] == BS_STRING_WITH_PRECHARGE) {
252  if (stringPrechargeNumber == stringNumber) {
253  break;
254  }
255  prechargeContactorNumber++;
256  }
257  }
258  if ((BS_NR_OF_STRINGS + prechargeContactorNumber) < BS_NR_OF_CONTACTORS) {
259  retVal = CONT_SetContactorState(
260  CONT_GetContactorName(BS_NR_OF_STRINGS + prechargeContactorNumber), CONT_SWITCH_ON);
261  }
262  }
263  return retVal;
264 }
265 
266 extern STD_RETURN_TYPE_e CONT_OpenPrecharge(uint8_t stringNumber) {
267  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
268  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
269  uint8_t prechargeContactorNumber = 0u;
270 
271  /* Precharge contactors in the list stay after string contactors
272  * so it has index (number of contactors)-1
273  */
274  if (bs_stringsWithPrecharge[stringNumber] == BS_STRING_WITH_PRECHARGE) {
275  /* Find contactor number corresponding to precharge of the requested string */
276  for (uint8_t stringPrechargeNumber = 0u; stringPrechargeNumber < BS_NR_OF_STRINGS; stringPrechargeNumber++) {
277  if (bs_stringsWithPrecharge[stringPrechargeNumber] == BS_STRING_WITH_PRECHARGE) {
278  if (stringPrechargeNumber == stringNumber) {
279  break;
280  }
281  prechargeContactorNumber++;
282  }
283  }
284  if ((BS_NR_OF_STRINGS + prechargeContactorNumber) < BS_NR_OF_CONTACTORS) {
285  retVal = CONT_SetContactorState(
286  CONT_GetContactorName(BS_NR_OF_STRINGS + prechargeContactorNumber), CONT_SWITCH_OFF);
287  }
288  }
289  return retVal;
290 }
291 
292 extern CONT_ELECTRICAL_STATE_TYPE_e CONT_GetState(uint8_t contactorNumber) {
293  FAS_ASSERT(contactorNumber < BS_NR_OF_CONTACTORS);
294  return (cont_contactorStates[contactorNumber].feedback);
295 }
296 
297 extern void CONT_Initialize(void) {
299 }
300 
301 /*========== Externalized Static Function Implementations (Unit Test) =======*/
302 #ifdef UNITY_UNIT_TEST
305 }
307  return CONT_ResolveContactorName(name);
308 }
309 #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:292
CONT_CONTACTOR_INDEX TEST_CONT_ResolveContactorName(const CONT_NAMES_e name)
Definition: contactor.c:306
void CONT_CheckFeedback(void)
checks the feedback of the contactors
Definition: contactor.c:217
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
void TEST_CONT_InitializationCheckOfContactorRegistry()
Definition: contactor.c:303
STD_RETURN_TYPE_e CONT_OpenPrecharge(uint8_t stringNumber)
Opens precharge.
Definition: contactor.c:266
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:188
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:222
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:239
void CONT_Initialize(void)
initializes the contactor module
Definition: contactor.c:297
STD_RETURN_TYPE_e CONT_OpenString(uint8_t stringNumber)
Opens the contactor of a string.
Definition: contactor.c:230
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
@ CONT_FEEDBACK_NORMALLY_OPEN
Definition: contactor_cfg.h:89
enum CONT_NAMES CONT_NAMES_e
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:235
#define static_assert(cond, msg)
static assertion macro
Definition: fassert.h:254
#define FAS_TRAP
Define that evaluates to essential boolean false thus tripping an assert.
Definition: fassert.h:110
@ STD_NOT_OK
Definition: fstd_types.h:82
@ STD_OK
Definition: fstd_types.h:81
enum STD_RETURN_TYPE STD_RETURN_TYPE_e
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:622
SPS_CHANNEL_AFFILIATION_e SPS_GetChannelAffiliation(SPS_CHANNEL_INDEX channelIndex)
Returns the channel affiliation.
Definition: sps.c:645
CONT_ELECTRICAL_STATE_TYPE_e SPS_GetChannelCurrentFeedback(const SPS_CHANNEL_INDEX channelIndex)
Get feedback value.
Definition: sps.c:606
void SPS_RequestContactorState(SPS_CHANNEL_INDEX channelIndex, SPS_CHANNEL_FUNCTION_e channelFunction)
Request state of a contactor.
Definition: sps.c:596
Headers for the driver for the smart power switches.
@ SPS_CHANNEL_ON
Definition: sps_cfg.h:174
@ SPS_CHANNEL_OFF
Definition: sps_cfg.h:173
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