foxBMS  1.4.1
The foxBMS Battery Management System API Documentation
bender_ir155_helper.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 bender_ir155_helper.c
44  * @author foxBMS Team
45  * @date 2021-09-17 (date of creation)
46  * @updated 2022-10-27 (date of last update)
47  * @version v1.4.1
48  * @ingroup DRIVERS
49  * @prefix IR155
50  *
51  * @brief Driver for the insulation monitoring
52  */
53 
54 /*========== Includes =======================================================*/
55 #include "bender_ir155_helper.h"
56 
57 #include "bender_ir155_cfg.h"
58 
59 #include "fram.h"
60 
61 /*========== Macros and Definitions =========================================*/
62 /** Maximum measurable resistance according to formula:
63  * ((90 * 1200kOhm) / (dc - 5) ) - 1200kOhm
64  * with dc ]5%,95%[ */
65 #define IR155_MAXIMUM_INSULATION_RESISTANCE_kOhm (106800u)
66 #define IR155_MINIMUM_INSULATION_RESISTANCE_kOhm (0u)
67 
68 /* Normal mode: duty cycle limits */
69 #define IR155_NORMAL_MODE_LOWER_DUTY_CYCLE_LIMIT_perc (4.0f)
70 #define IR155_NORMAL_MODE_UPPER_DUTY_CYCLE_LIMIT_perc (96.0f)
71 
72 /* Speed start mode: duty cycle limits */
73 #define IR155_SPEED_START_ESTIMATION_GOOD_LOWER_DUTY_CYCLE_LIMIT_perc (4.0f)
74 #define IR155_SPEED_START_ESTIMATION_GOOD_UPPER_DUTY_CYCLE_LIMIT_perc (11.0f)
75 
76 #define IR155_SPEED_START_ESTIMATION_BAD_LOWER_DUTY_CYCLE_LIMIT_perc (89.0f)
77 #define IR155_SPEED_START_ESTIMATION_BAD_UPPER_DUTY_CYCLE_LIMIT_perc (96.0f)
78 
79 /* Undervoltage mode: duty cycle limits */
80 #define IR155_UNDERVOLTAGE_MODE_LOWER_DUTY_CYCLE_LIMIT_perc (4.0f)
81 #define IR155_UNDERVOLTAGE_MODE_UPPER_DUTY_CYCLE_LIMIT_perc (96.0f)
82 
83 /* Device error mode: duty cycle limits */
84 #define IR155_DEVICE_ERROR_LOWER_DUTY_CYCLE_LIMIT_perc (46.5f)
85 #define IR155_DEVICE_ERROR_UPPER_DUTY_CYCLE_LIMIT_perc (53.5f)
86 
87 /* Device error mode: duty cycle limits */
88 #define IR155_GROUND_ERROR_LOWER_DUTY_CYCLE_LIMIT_perc (46.5f)
89 #define IR155_GROUND_ERROR_UPPER_DUTY_CYCLE_LIMIT_perc (53.5f)
90 
91 /*========== Static Constant and Variable Definitions =======================*/
92 
93 /*========== Extern Constant and Variable Definitions =======================*/
94 extern IR155_STATE_s ir155_state = {
95  .ir155Initialized = false,
96  .measurement.isMeasurementValid = false,
97  .measurement.isUndervoltageDetected = false,
98  .measurement.measurementState = IR155_UNINITIALIZED,
99  .measurement.measurementMode = IR155_UNKNOWN,
100  .measurement.digitalStatusPin = STD_PIN_LOW,
101  .measurement.resistance_kOhm = 0,
102  .measurement.pwmSignal.dutyCycle_perc = 0.0f,
103  .measurement.pwmSignal.frequency_Hz = 0.0f,
104  .periodTriggerTime_ms = IMD_PERIODIC_CALL_TIME_ms,
105 };
106 
107 /*========== Static Function Prototypes =====================================*/
108 /**
109  * @brief Determines frequency-dependent measurement state.
110  * @details Use of intervals because of measuring and signal inaccuracy. This
111  * interval is configurable via define #IR155_MEASUREMENT_INTERVAL_RANGE_Hz
112  * @param[in] frequency_Hz measured signal frequency in Hz
113  * @return #IR155_MEASUREMENT_MODE_e bender measurement mode
114  */
115 static IR155_MEASUREMENT_MODE_e IR155_GetMeasurementMode(float frequency_Hz);
116 
117 /**
118  * @brief Calculate insulation resistance from measured dutycycle.
119  * @details Function check, that passed duty-cycle lies within allowed range.
120  * Otherwise, the calculated resistance will be limited to the next
121  * reasonable value.
122  * @param[in] dutyCycle_perc measured signal duty-cycle in percentage
123  * @return measured insulation resistance in kOhm
124  */
125 static uint32_t IR155_CalculateResistance(float dutyCycle_perc);
126 
127 /**
128  * @brief Check if passed duty cycle is within interval limits
129  * @param[in] dutyCycle_perc measured signal duty-cycle in percentage
130  * @param[in] lowerLimit_perc lower interval limit
131  * @param[in] upperLimit_perc upper interval limit
132  * @return measured insulation resistance in kOhm
133  */
134 static bool IR155_IsDutyCycleWithinInterval(float dutyCycle_perc, float lowerLimit_perc, float upperLimit_perc);
135 
136 /*========== Static Function Implementations ================================*/
138  FAS_ASSERT(frequency_Hz >= 0.0f);
140 
141  if ((frequency_Hz >= IR155_NORMAL_CONDITION_LOWER_FREQUENCY_Hz) &&
143  retVal = IR155_NORMAL_MODE;
144  } else if (
145  (frequency_Hz >= IR155_UNDERVOLTAGE_LOWER_FREQUENCY_Hz) &&
146  (frequency_Hz < IR155_UNDERVOLTAGE_UPPER_FREQUENCY_Hz)) {
147  retVal = IR155_UNDERVOLTAGE_MODE; /* should not be detected as default threshold 0V, EOL Bender configurable! */
148  } else if (
149  (frequency_Hz >= IR155_SPEEDSTART_LOWER_FREQUENCY_Hz) && (frequency_Hz < IR155_SPEEDSTART_UPPER_FREQUENCY_Hz)) {
150  retVal = IR155_SPEEDSTART_MODE;
151  } else if (
152  (frequency_Hz >= IR155_IMD_DEVICE_ERROR_LOWER_FREQUENCY_Hz) &&
154  retVal = IR155_IMD_ERROR_MODE;
155  } else if (
156  (frequency_Hz >= IR155_GROUND_ERROR_LOWER_FREQUENCY_Hz) &&
157  (frequency_Hz < IR155_GROUND_ERROR_UPPER_FREQUENCY_Hz)) {
158  retVal = IR155_GROUNDERROR_MODE;
159  } else if (frequency_Hz <= IR155_MINIMUM_FREQUENCY_Hz) {
160  retVal = IR155_SHORT_CLAMP;
161  } else {
162  retVal = IR155_UNDEFINED_FREQUENCY;
163  }
164  return retVal;
165 }
166 
167 static uint32_t IR155_CalculateResistance(float dutyCycle_perc) {
168  FAS_ASSERT(dutyCycle_perc <= 100.0f);
169  FAS_ASSERT(dutyCycle_perc > 0.0f);
170 
171  float insulationResistance_kOhm = 0.0f;
172  if (dutyCycle_perc <= 5.0f) {
173  insulationResistance_kOhm = (float)IR155_MAXIMUM_INSULATION_RESISTANCE_kOhm;
174  } else if (dutyCycle_perc > 95.0f) {
175  insulationResistance_kOhm = (float)IR155_MINIMUM_INSULATION_RESISTANCE_kOhm;
176  } else {
177  insulationResistance_kOhm = ((90.0f * 1200.0f) / (dutyCycle_perc - 5.0f)) - 1200.0f;
178  }
179  return (uint32_t)insulationResistance_kOhm;
180 }
181 
182 static bool IR155_IsDutyCycleWithinInterval(float dutyCycle_perc, float lowerLimit_perc, float upperLimit_perc) {
183  bool retval = false;
184  if ((lowerLimit_perc < dutyCycle_perc) && (upperLimit_perc > dutyCycle_perc)) {
185  retval = true;
186  } else {
187  retval = false;
188  }
189  return retval;
190 }
191 
192 /*========== Extern Function Implementations ================================*/
193 
194 void IR155_Initialize(uint8_t triggerTime_ms) {
195  /* Timer peripheral initialization if not already done. */
196  if (false == PWM_IsEcapModuleInitialized()) {
197  PWM_Initialize(); /* TODO: split PWM_Init function in a dedicated function for ecap and etpwm module */
198  }
199 
200  /* Read non-volatile FRAM */
202 
203  /* Check grounderror flag */
205  /* GROUND ERROR occurred before shutting down */
207  } else {
208  /* Normal startup delay -> wait 2.2s until first measurement is trustworthy */
210  }
211 
212  ir155_state.periodTriggerTime_ms = triggerTime_ms;
214 }
215 
216 void IR155_Deinitialize(void) {
217  /* Reset cycle time */
219 
220  /* Reset timer duty cycle struct */
223 
225 
226  /* Set diagnosis message that measurement is not trustworthy */
227  /* TODO: do it really like this? DIAG_Handler(DIAG_CH_ISOMETER_MEAS_INVALID, DIAG_EVENT_NOK, 0); */
228 }
229 
231  /* Initialize struct */
232  IR155_MEASUREMENT_s measurementResult = {
233  .isMeasurementValid = false,
234  .isUndervoltageDetected = true,
235  .pwmSignal.dutyCycle_perc = 0.0f,
236  .pwmSignal.frequency_Hz = 0.0f,
237  .resistance_kOhm = 0u,
238  .digitalStatusPin = STD_PIN_UNDEFINED,
239  .measurementMode = IR155_UNKNOWN,
240  .measurementState = IR155_UNINITIALIZED,
241  };
242 
243  /* read value of Bender IR155 digital status pin (OHKS) */
245 
246  /* get duty-cycle and frequency from PWM input measurement */
247  measurementResult.pwmSignal = PWM_GetPwmData();
248 
249  /* TODO: How-to check valid data? */
250  bool isPwmMeasurementValid = true;
251  if (isPwmMeasurementValid == true) {
252  /* TODO: Throw error? */
253  isPwmMeasurementValid = true;
254  } else {
255  /* Invalid values measurement */
256 
257  /* Invalidate data? */
258  isPwmMeasurementValid = false;
259  }
260 
261  /* Get measurement mode */
262  if (isPwmMeasurementValid == true) {
263  measurementResult.measurementMode = IR155_GetMeasurementMode(measurementResult.pwmSignal.frequency_Hz);
264  } else {
265  measurementResult.measurementMode = IR155_UNKNOWN;
266  /* TODO: Throw what error? */
267  }
268 
269  switch (measurementResult.measurementMode) {
270  case IR155_NORMAL_MODE:
273  measurementResult.pwmSignal.dutyCycle_perc,
276  measurementResult.resistance_kOhm =
278  measurementResult.isMeasurementValid = true;
280  } else {
282  measurementResult.isMeasurementValid = false;
284  }
285  break;
286 
288  measurementResult.isUndervoltageDetected = false;
290  measurementResult.pwmSignal.dutyCycle_perc,
294  measurementResult.isMeasurementValid = true;
295  measurementResult.measurementState = IR155_RESISTANCE_ESTIMATION;
296  } else if (
298  measurementResult.pwmSignal.dutyCycle_perc,
302  measurementResult.isMeasurementValid = true;
303  measurementResult.measurementState = IR155_RESISTANCE_ESTIMATION;
304  } else {
306  measurementResult.isMeasurementValid = false;
308  }
309  break;
310 
312  measurementResult.isUndervoltageDetected = true;
314  measurementResult.pwmSignal.dutyCycle_perc,
317  measurementResult.resistance_kOhm =
319  measurementResult.isMeasurementValid = true;
321  } else {
322  measurementResult.isMeasurementValid = false;
325  }
326  break;
327 
329  measurementResult.isUndervoltageDetected = false;
332  measurementResult.pwmSignal.dutyCycle_perc,
335  /* Error detected and verified with duty cycle */
336  measurementResult.isMeasurementValid = true;
337  measurementResult.measurementState = IR155_IMD_ERROR_MEASUREMENT;
338  } else {
339  /* Error detected but invalid duty cycle */
341  measurementResult.isMeasurementValid = false;
342  }
343  break;
345  measurementResult.isUndervoltageDetected = false;
348  measurementResult.pwmSignal.dutyCycle_perc,
351  /* Error detected and verified with duty cycle */
352  measurementResult.isMeasurementValid = true;
353  measurementResult.measurementState = IR155_GROUND_ERROR_MODE;
354  } else {
355  /* Error detected but invalid duty cycle */
357  measurementResult.isMeasurementValid = false;
358  }
359  break;
360 
361  case IR155_SHORT_CLAMP:
362  measurementResult.isUndervoltageDetected = false;
364  measurementResult.measurementState = IR155_SIGNAL_SHORT;
365  measurementResult.isMeasurementValid = true;
366  break;
367 
368  default:
370  measurementResult.measurementState = IR155_MEASUREMENT_NOT_VALID;
371  measurementResult.isMeasurementValid = false;
372  break;
373  }
374 
375  return measurementResult;
376 }
377 
378 /*========== Externalized Static Function Implementations (Unit Test) =======*/
Headers for the configuration for the insulation monitoring.
#define IR155_SPEEDSTART_LOWER_FREQUENCY_Hz
#define IR155_GROUND_ERROR_UPPER_FREQUENCY_Hz
#define IR155_UNDERVOLTAGE_LOWER_FREQUENCY_Hz
#define IR155_MINIMUM_FREQUENCY_Hz
#define IR155_STARTUP_TIME_ms
#define IR155_SPEEDSTART_UPPER_FREQUENCY_Hz
#define IR155_IMD_DEVICE_ERROR_LOWER_FREQUENCY_Hz
#define IR155_UNDERVOLTAGE_UPPER_FREQUENCY_Hz
#define IR155_IMD_DEVICE_ERROR_UPPER_FREQUENCY_Hz
#define IR155_WAIT_TIME_AFTER_GROUND_ERROR_ms
#define IR155_GROUND_ERROR_LOWER_FREQUENCY_Hz
#define IR155_NORMAL_CONDITION_UPPER_FREQUENCY_Hz
#define IR155_NORMAL_CONDITION_LOWER_FREQUENCY_Hz
#define IR155_DEVICE_ERROR_LOWER_DUTY_CYCLE_LIMIT_perc
#define IR155_MAXIMUM_INSULATION_RESISTANCE_kOhm
#define IR155_SPEED_START_ESTIMATION_GOOD_UPPER_DUTY_CYCLE_LIMIT_perc
#define IR155_MINIMUM_INSULATION_RESISTANCE_kOhm
static bool IR155_IsDutyCycleWithinInterval(float dutyCycle_perc, float lowerLimit_perc, float upperLimit_perc)
Check if passed duty cycle is within interval limits.
#define IR155_GROUND_ERROR_UPPER_DUTY_CYCLE_LIMIT_perc
static uint32_t IR155_CalculateResistance(float dutyCycle_perc)
Calculate insulation resistance from measured dutycycle.
#define IR155_NORMAL_MODE_LOWER_DUTY_CYCLE_LIMIT_perc
#define IR155_SPEED_START_ESTIMATION_BAD_UPPER_DUTY_CYCLE_LIMIT_perc
#define IR155_UNDERVOLTAGE_MODE_LOWER_DUTY_CYCLE_LIMIT_perc
static IR155_MEASUREMENT_MODE_e IR155_GetMeasurementMode(float frequency_Hz)
Determines frequency-dependent measurement state.
#define IR155_SPEED_START_ESTIMATION_BAD_LOWER_DUTY_CYCLE_LIMIT_perc
#define IR155_DEVICE_ERROR_UPPER_DUTY_CYCLE_LIMIT_perc
void IR155_Initialize(uint8_t triggerTime_ms)
Software initialization of Timer-module.
void IR155_Deinitialize(void)
Software deinitialization of Timer-module.
#define IR155_GROUND_ERROR_LOWER_DUTY_CYCLE_LIMIT_perc
IR155_MEASUREMENT_s IR155_GetMeasurementValues(void)
Interface function which delivers the actual signal measurement (duty cyle) and evaluation....
#define IR155_NORMAL_MODE_UPPER_DUTY_CYCLE_LIMIT_perc
IR155_STATE_s ir155_state
#define IR155_UNDERVOLTAGE_MODE_UPPER_DUTY_CYCLE_LIMIT_perc
#define IR155_SPEED_START_ESTIMATION_GOOD_LOWER_DUTY_CYCLE_LIMIT_perc
Headers for the configuration for the insulation monitoring.
@ IR155_NORMAL_MODE
@ IR155_UNDEFINED_FREQUENCY
@ IR155_SPEEDSTART_MODE
@ IR155_SHORT_CLAMP
@ IR155_IMD_ERROR_MODE
@ IR155_UNKNOWN
@ IR155_UNDERVOLTAGE_MODE
@ IR155_GROUNDERROR_MODE
@ IR155_SIGNAL_SHORT
@ IR155_GROUND_ERROR_MODE_UNKNOWN
@ IR155_UNINITIALIZED
@ IR155_IMD_ERROR_MEASUREMENT_UNKNOWN
@ IR155_UNDERVOLTAGE_MEASUREMENT_UNKNOWN
@ IR155_IMD_ERROR_MEASUREMENT
@ IR155_RESISTANCE_MEASUREMENT
@ IR155_RESISTANCE_ESTIMATION_UNKNOWN
@ IR155_RESISTANCE_ESTIMATION
@ IR155_MEASUREMENT_NOT_VALID
@ IR155_RESISTANCE_MEASUREMENT_UNKNOWN
@ IR155_UNDERVOLTAGE_MEASUREMENT
@ IR155_GROUND_ERROR_MODE
#define IR155_GET_DIGITAL_STATUS_PIN_STATE()
enum IR155_MEASUREMENT_MODE IR155_MEASUREMENT_MODE_e
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:252
FRAM_RETURN_TYPE_e FRAM_ReadData(FRAM_BLOCK_ID_e blockId)
Reads a variable from the FRAM.
Definition: fram.c:193
Header for the driver for the FRAM module.
FRAM_INSULATION_FLAG_s fram_insulationFlags
Definition: fram_cfg.c:77
@ FRAM_BLOCK_ID_INSULATION_FLAG
Definition: fram_cfg.h:107
@ STD_PIN_UNDEFINED
Definition: fstd_types.h:90
@ STD_PIN_LOW
Definition: fstd_types.h:88
#define IMD_PERIODIC_CALL_TIME_ms
Definition: imd.h:67
void PWM_Initialize(void)
Initializes the ETPWM and the ECAP module.
Definition: pwm.c:124
PWM_SIGNAL_s PWM_GetPwmData(void)
Get dutycycle and frequency of input PWM signal.
Definition: pwm.c:201
bool PWM_IsEcapModuleInitialized(void)
Get initialization state of ecap module.
Definition: pwm.c:197
IR155_MEASUREMENT_MODE_e measurementMode
STD_PIN_STATE_e digitalStatusPin
IR155_MEASUREMENT_STATE_e measurementState
uint16_t periodTriggerTime_ms
IR155_MEASUREMENT_s measurement
uint32_t timeUntilValidMeasurement_ms
float dutyCycle_perc
Definition: pwm.h:70
float frequency_Hz
Definition: pwm.h:71