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