foxBMS  1.5.1
The foxBMS Battery Management System API Documentation
vishay_ntcalug01a103g.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2023, 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 vishay_ntcalug01a103g.c
44  * @author foxBMS Team
45  * @date 2018-10-30 (date of creation)
46  * @updated 2023-02-23 (date of last update)
47  * @version v1.5.1
48  * @ingroup TEMPERATURE_SENSORS
49  * @prefix TS
50  *
51  * @brief Resistive divider used for measuring temperature
52  *
53  */
54 
55 /*========== Includes =======================================================*/
56 #include "vishay_ntcalug01a103g.h"
57 
58 #include "fassert.h"
59 #include "foxmath.h"
61 
62 #include <math.h>
63 #include <stdbool.h>
64 #include <stdint.h>
65 
66 /*========== Macros and Definitions =========================================*/
67 
68 /*========== Static Constant and Variable Definitions =======================*/
69 
70 /* clang-format off */
71 /** LUT filled from higher resistance to lower resistance */
73  { -400, 334274.4f},
74  { -390, 312904.4f},
75  { -380, 293033.6f},
76  { -370, 274548.0f},
77  { -360, 257343.1f},
78  { -350, 241322.9f},
79  { -340, 226398.8f},
80  { -330, 212489.7f},
81  { -320, 199520.6f},
82  { -310, 187422.7f},
83  { -300, 176132.5f},
84  { -290, 165591.5f},
85  { -280, 155745.6f},
86  { -270, 146545.1f},
87  { -260, 137944.1f},
88  { -250, 129900.0f},
89  { -240, 122373.7f},
90  { -230, 115329.0f},
91  { -220, 108732.2f},
92  { -210, 102552.5f},
93  { -200, 96761.1f },
94  { -190, 91331.5f },
95  { -180, 86239.0f },
96  { -170, 81460.9f },
97  { -160, 76976.0f },
98  { -150, 72764.6f },
99  { -140, 68808.6f },
100  { -130, 65091.1f },
101  { -120, 61596.4f },
102  { -110, 58309.9f },
103  { -100, 55218.1f },
104  { -90, 52308.4f },
105  { -80, 49569.0f },
106  { -70, 46989.1f },
107  { -60, 44558.56f},
108  { -50, 42267.85f},
109  { -40, 40108.20f},
110  { -30, 38071.41f},
111  { -20, 36149.83f},
112  { -10, 34336.32f},
113  { 0, 32624.23f},
114  { 10, 31007.34f},
115  { 20, 29479.85f},
116  { 30, 28036.35f},
117  { 40, 26671.76f},
118  { 50, 25381.36f},
119  { 60, 24160.73f},
120  { 70, 23005.71f},
121  { 80, 21912.45f},
122  { 90, 20877.31f},
123  { 100, 19896.90f},
124  { 110, 18968.04f},
125  { 120, 18087.75f},
126  { 130, 17253.25f},
127  { 140, 16461.90f},
128  { 150, 15711.26f},
129  { 160, 14999.01f},
130  { 170, 14323.01f},
131  { 180, 13681.22f},
132  { 190, 13071.73f},
133  { 200, 12492.75f},
134  { 210, 11942.59f},
135  { 220, 11419.69f},
136  { 230, 10922.54f},
137  { 240, 10449.75f},
138  { 250, 10000.00f},
139  { 260, 9572.05f },
140  { 270, 9164.74f },
141  { 280, 8776.97f },
142  { 290, 8407.70f },
143  { 300, 8055.96f },
144  { 310, 7720.82f },
145  { 320, 7401.43f },
146  { 330, 7096.96f },
147  { 340, 6806.64f },
148  { 350, 6529.74f },
149  { 360, 6265.58f },
150  { 370, 6013.51f },
151  { 380, 5772.92f },
152  { 390, 5543.22f },
153  { 400, 5323.88f },
154  { 410, 5114.37f },
155  { 420, 4914.20f },
156  { 430, 4722.92f },
157  { 440, 4540.08f },
158  { 450, 4365.27f },
159  { 460, 4198.11f },
160  { 470, 4038.21f },
161  { 480, 3885.23f },
162  { 490, 3738.84f },
163  { 500, 3598.72f },
164  { 510, 3464.58f },
165  { 520, 3336.12f },
166  { 530, 3213.08f },
167  { 540, 3095.22f },
168  { 550, 2982.27f },
169  { 560, 2874.02f },
170  { 570, 2770.26f },
171  { 580, 2670.76f },
172  { 590, 2575.34f },
173  { 600, 2483.82f },
174  { 610, 2396.00f },
175  { 620, 2311.74f },
176  { 630, 2230.85f },
177  { 640, 2153.21f },
178  { 650, 2078.65f },
179  { 660, 2007.05f },
180  { 670, 1938.27f },
181  { 680, 1872.19f },
182  { 690, 1808.69f },
183  { 700, 1747.65f },
184  { 710, 1688.98f },
185  { 720, 1632.56f },
186  { 730, 1578.31f },
187  { 740, 1526.13f },
188  { 750, 1475.92f },
189  { 760, 1427.62f },
190  { 770, 1381.12f },
191  { 780, 1336.37f },
192  { 790, 1293.29f },
193  { 800, 1251.80f },
194  { 810, 1211.85f },
195  { 820, 1173.36f },
196  { 830, 1136.28f },
197  { 840, 1100.55f },
198  { 850, 1066.11f },
199  { 860, 1032.91f },
200  { 870, 1000.91f },
201  { 880, 970.05f },
202  { 890, 940.29f },
203  { 900, 911.59f },
204  { 910, 883.89f },
205  { 920, 857.17f },
206  { 930, 831.38f },
207  { 940, 806.49f },
208  { 950, 782.46f },
209  { 960, 759.26f },
210  { 970, 736.85f },
211  { 980, 715.21f },
212  { 990, 694.31f },
213  { 1000, 674.11f },
214  { 1010, 654.60f },
215  { 1020, 635.74f },
216  { 1030, 617.51f },
217  { 1040, 599.88f },
218  { 1050, 582.84f }
219 };
220 /* clang-format on */
221 
222 /** size of the #ts_ntcalug01a103gLut LUT */
224 
225 /*========== Extern Constant and Variable Definitions =======================*/
226 /**
227  * Defines for calculating the ADC voltage on the ends of the operating range.
228  * The ADC voltage is calculated with the following formula:
229  *
230  * V_adc = ( ( V_supply * R_ntc ) / ( R + R_ntc ) )
231  *
232  * Depending on the position of the NTC in the voltage resistor (R_1/R_2),
233  * different R_ntc values are used for the calculation.
234  * @{
235  */
236 #if defined(TS_VISHAY_NTCALUG01A103G_POSITION_IN_RESISTOR_DIVIDER_IS_R_1) && \
237  (TS_VISHAY_NTCALUG01A103G_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 == true)
238 #define TS_VISHAY_NTCALUG01A103G_ADC_VOLTAGE_V_MAX_V \
239  (float_t)( \
240  (TS_VISHAY_NTCALUG01A103G_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V * \
241  ts_ntcalug01a103gLut[ts_ntcalug01a103gLutSize - 1].resistance_Ohm) / \
242  (ts_ntcalug01a103gLut[ts_ntcalug01a103gLutSize - 1].resistance_Ohm + \
243  TS_VISHAY_NTCALUG01A103G_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm))
244 #define TS_VISHAY_NTCALUG01A103G_ADC_VOLTAGE_V_MIN_V \
245  (float_t)( \
246  (TS_VISHAY_NTCALUG01A103G_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V * ts_ntcalug01a103gLut[0].resistance_Ohm) / \
247  (ts_ntcalug01a103gLut[0].resistance_Ohm + TS_VISHAY_NTCALUG01A103G_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm))
248 #else /* TS_VISHAY_NTCALUG01A103G_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 == false */
249 #define TS_VISHAY_NTCALUG01A103G_ADC_VOLTAGE_V_MIN_V \
250  ((float_t)((TS_VISHAY_NTCALUG01A103G_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V * ts_ntcalug01a103gLut[ts_ntcalug01a103gLutSize-1].resistance_Ohm) / (ts_ntcalug01a103gLut[ts_ntcalug01a103gLutSize-1].resistance_Ohm+TS_VISHAY_NTCALUG01A103G_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm)))
251 #define TS_VISHAY_NTCALUG01A103G_ADC_VOLTAGE_V_MAX_V \
252  ((float_t)((TS_VISHAY_NTCALUG01A103G_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V * ts_ntcalug01a103gLut[0].resistance_Ohm) / (ts_ntcalug01a103gLut[0].resistance_Ohm+TS_VISHAY_NTCALUG01A103G_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm)))
253 #endif
254 /**@}*/
255 
256 /*========== Static Function Prototypes =====================================*/
257 
258 /*========== Static Function Implementations ================================*/
259 
260 /*========== Extern Function Implementations ================================*/
261 
262 extern int16_t TS_Vis00GetTemperatureFromLut(uint16_t adcVoltage_mV) {
263  int16_t temperature_ddegC = 0;
264  float_t resistance_Ohm = 0.0f;
265  float_t adcVoltage_V = adcVoltage_mV / 1000.0f; /* Convert mV to V */
266 
267  /* Check for valid ADC measurements to prevent undefined behavior */
269  /* Invalid measured ADC voltage -> sensor out of operating range or disconnected/shorted */
270  temperature_ddegC = INT16_MIN;
271  } else if (adcVoltage_V < TS_VISHAY_NTCALUG01A103G_ADC_VOLTAGE_V_MIN_V) {
272  /* Invalid measured ADC voltage -> sensor out of operating range or shorted/disconnected */
273  temperature_ddegC = INT16_MAX;
274  } else {
275  /* Calculate NTC resistance based on measured ADC voltage */
276 #if defined(TS_VISHAY_NTCALUG01A103G_POSITION_IN_RESISTOR_DIVIDER_IS_R_1) && \
277  (TS_VISHAY_NTCALUG01A103G_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 == true)
278  /* R_1 = R_2 * ( ( V_supply / V_adc ) - 1 ) */
281 #else /* TS_VISHAY_NTCALUG01A103G_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 == false */
282  /* R_2 = R_1 * ( V_2 / ( V_supply - V_adc ) ) */
284  (adcVoltage_V / (TS_VISHAY_NTCALUG01A103G_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V - adcVoltage_V));
285 #endif /* TS_VISHAY_NTCALUG01A103G_POSITION_IN_RESISTOR_DIVIDER_IS_R_1 */
286 
287  /* Variables for interpolating LUT value */
288  uint16_t between_high = 0;
289  uint16_t between_low = 0;
290  for (uint16_t i = 1u; i < ts_ntcalug01a103gLutSize; i++) {
291  if (resistance_Ohm < ts_ntcalug01a103gLut[i].resistance_Ohm) {
292  between_low = i + 1u;
293  between_high = i;
294  }
295  }
296 
297  /* Interpolate between LUT values, but do not extrapolate LUT! */
298  if (!(((between_high == 0u) && (between_low == 0u)) || /* measured resistance > maximum LUT resistance */
299  (between_low >= ts_ntcalug01a103gLutSize))) { /* measured resistance < minimum LUT resistance */
300  temperature_ddegC = (int16_t)MATH_LinearInterpolation(
301  ts_ntcalug01a103gLut[between_low].resistance_Ohm,
302  ts_ntcalug01a103gLut[between_low].temperature_ddegC,
303  ts_ntcalug01a103gLut[between_high].resistance_Ohm,
304  ts_ntcalug01a103gLut[between_high].temperature_ddegC,
305  resistance_Ohm);
306  }
307  }
308 
309  /* Return temperature based on measured NTC resistance */
310  return temperature_ddegC;
311 }
312 
313 extern int16_t TS_Vis00GetTemperatureFromPolynomial(uint16_t adcVoltage_mV) {
314  (void)adcVoltage_mV;
316  int16_t temperature_ddegC = 0;
317  /* TODO this is not implemented */
318  return temperature_ddegC;
319 }
320 
321 /*========== Externalized Static Function Implementations (Unit Test) =======*/
322 #ifdef UNITY_UNIT_TEST
323 #endif
Assert macro implementation.
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:254
#define FAS_TRAP
Define that evaluates to essential boolean false thus tripping an assert.
Definition: fassert.h:129
float_t MATH_LinearInterpolation(const float_t x1, const float_t y1, const float_t x2, const float_t y2, const float_t x_interpolate)
Linear inter-/extrapolates a third point according to two given points.
Definition: foxmath.c:84
math library for often used math functions
#define TS_VISHAY_NTCALUG01A103G_ADC_VOLTAGE_V_MIN_V
int16_t TS_Vis00GetTemperatureFromPolynomial(uint16_t adcVoltage_mV)
returns temperature based on measured ADC voltage
#define TS_VISHAY_NTCALUG01A103G_ADC_VOLTAGE_V_MAX_V
static const uint16_t ts_ntcalug01a103gLutSize
int16_t TS_Vis00GetTemperatureFromLut(uint16_t adcVoltage_mV)
returns temperature based on measured ADC voltage.
static const TS_TEMPERATURE_SENSOR_LUT_s ts_ntcalug01a103gLut[]
Resistive divider used for measuring temperature.
#define TS_VISHAY_NTCALUG01A103G_RESISTOR_DIVIDER_SUPPLY_VOLTAGE_V
#define TS_VISHAY_NTCALUG01A103G_RESISTOR_DIVIDER_RESISTANCE_R_1_R_2_Ohm