Hi All,
I'm currently undertaking a project that uses a thermistor and a voltage divider circuit to calculate the temperature.
I've set up a room temperature test and my circuit gives credible results against another reference thermometer and I'm satisfied with its performance in that range. However, once I place my thermistor probe into a water basin that is kept at a constant temperature by using a hot plate, my thermistor gives a reading that is 5-6 degrees more than my reference thermometer. Does any one have any ideas why there is such a degradation in performance and how can I rectify this?
The function that is used for the voltage reading:
/*
#####GET TEMP FLOAT DESCRIPTION#####
This function converts a thermistor reading into a corresponding temp in ^C
The thermistor is incorporated into a Voltage Divider Circuit:
+Vref---[Thermistor]---+--[1.8K]---GND
|
ADC @ thermPin
ADC Values were externally calculated from the calibration table using: ADC = 1023*1k8/(Rtherm+1k8)
The LUT is an array of integer constants containing the predicted ADC values for all temperatures between +7^C to +49.9^C.
The array index starts at zero, which corresponds to a temperature of +7^C.
A linear interpolation between the two closest entries is performed to give a finer output resolution.
*/
//##CONSTANTS##
/*1K8*/
const int LUT_Therm[] PROGMEM = //LUT containing ADC values - saved into program memory as running low on SRAM
{
223, 224, 225, 226, 227, 228, 229, 230, 231, 232, //7^C to 7.9^C
233, 234, 235, 236, 237, 238, 239, 240, 241, 242,
244, 245, 246, 247, 248, 249, 250, 251, 252, 253,
255, 256, 257, 258, 259, 260, 261, 263, 264, 265,
266, 267, 268, 269, 271, 272, 273, 274, 275, 277,
278, 279, 280, 281, 283, 284, 285, 286, 287, 289,
290, 291, 292, 294, 295, 296, 297, 299, 300, 301, //13^C to 13.9^C
302, 304, 305, 306, 308, 309, 310, 312, 313, 314,
315, 317, 318, 319, 321, 322, 323, 325, 326, 327,
329, 330, 332, 333, 334, 336, 337, 338, 340, 341,
343, 344, 345, 347, 348, 350, 351, 353, 354, 355,
357, 358, 360, 361, 363, 364, 366, 367, 369, 370,
371, 373, 374, 376, 377, 379, 380, 382, 383, 385,
387, 388, 390, 391, 393, 394, 396, 397, 399, 400,
402, 404, 405, 407, 408, 410, 411, 413, 415, 416,
418, 419, 421, 423, 424, 426, 428, 429, 431, 433,
434, 436, 438, 439, 441, 443, 444, 446, 448, 449,
451, 453, 454, 456, 458, 460, 461, 463, 465, 466,
468, 470, 472, 473, 475, 477, 479, 480, 482, 484,
486, 488, 489, 491, 493, 495, 497, 498, 500, 502,
504, 506, 507, 509, 511, 513, 515, 517, 519, 520,
522, 524, 526, 528, 530, 532, 534, 535, 537, 539,
541, 543, 545, 547, 549, 551, 553, 555, 557, 559,
560, 562, 564, 566, 568, 570, 572, 574, 576, 578,
580, 582, 584, 586, 588, 590, 592, 594, 596, 598,
600, 602, 604, 606, 608, 611, 613, 615, 617, 619,
621, 623, 625, 627, 629, 631, 633, 635, 638, 640,
642, 644, 646, 648, 650, 652, 655, 657, 659, 661,
663, 665, 667, 670, 672, 674, 676, 678, 680, 683,
685, 687, 689, 691, 694, 696, 698, 700, 702, 705,
707, 709, 711, 714, 716, 718, 720, 723, 725, 727,
729, 732, 734, 736, 738, 741, 743, 745, 747, 750,
752, 754, 757, 759, 761, 764, 766, 768, 771, 773,
775, 778, 780, 782, 785, 787, 789, 792, 794, 796,
799, 801, 803, 806, 808, 811, 813, 815, 818, 820,
822, 825, 827, 830, 832, 834, 837, 839, 842, 844,
847, 849, 851, 854, 856, 859, 861, 864, 866, 868,
871, 873, 876, 878, 881, 883, 886, 888, 891, 893,
896, 898, 901, 903, 906, 908, 911, 913, 916, 918,
921, 923, 926, 928, 931, 933, 936, 938, 941, 943,
946, 948, 951, 953, 956, 958, 961, 963, 966, 969,
971, 974, 976, 979, 981, 984, 987, 989, 992, 994,
997, 999, 1002, 1005, 1007, 1010, 1012, 1015, 1017, 1020, //40^C to 49.9^C
1023 //50^C
};
const int constLUTArraySize = sizeof(LUT_Therm)/sizeof(LUT_Therm[0]); //number of elements in array
float getTempFloat(int pinAnalogue)
{
//#####VARIABLE DELARATIONS#####
int i; //used as a counter / array index 'pointer'
int LUT_val; //stores the current value of the LUT eg. i
int LUT_prevVal; //stores the previous value of the LUT eg. i-1
int ADCValue; //stores value return by reading anaolgue pin
float fraction; //returns the interpolated temp
//take an analogue reading.
analogRead(pinAnalogue); //dummy reading to settle the MUX
delay(10);
ADCValue = analogRead(pinAnalogue);
/*DEBUGGING*/
/*Serial.print(F("ADC: "));
Serial.println(ADCValue);*/
//find i such that the ADC value lies between LUT[i-1] and LUT[i]
for (i = 0; i < constLUTArraySize; i++)
{
LUT_prevVal = LUT_val; //LUT value from previous loop is now previous value
LUT_val = pgm_read_word(&LUT_Therm[i]); //store current LUT val ++ since LUT is in PROGMEN - have to use pgm_read_word and array addresses to get value
/*DEBUGGING*/
/*Serial.print(F("Previous LUT Val = "));
Serial.println(LUT_prevVal);
Serial.print(F("Current LUT Val = "));
Serial.println(LUT_val);*/
if (LUT_val >= ADCValue) //this is the ADC Hi value
{
break; //break out of for
}//end if
}//end for
//special case: adc == LUT[0]
if (i == 0 && ADCValue == LUT_val)
{
/*DEBUGGING*/
/*Serial.print(F("In special case of LUT[0]"));*/
return 7.0; //return first value stored (223 = 7^C)
}//end if
// Report an error if out of range.
if (ADCValue < pgm_read_word(&LUT_Therm[0]) || ADCValue >= pgm_read_word(&LUT_Therm[constLUTArraySize-1]))
{
/*DEBUGGING*/
/*Serial.print(F("In special case of out of LUT range"));
Serial.print(F("ADCVal = "));
Serial.println(ADCValue);
Serial.print(F("LUT[0] = "));
Serial.println(pgm_read_word(&LUT_Therm[0]));
Serial.print(F("LUT[MAX] = "));
Serial.println(pgm_read_word(&LUT_Therm[constLUTArraySize-1]));*/
return NAN;
}//end if
//return interpolated temperature
fraction = float(ADCValue - LUT_prevVal) / (LUT_val - LUT_prevVal);
/*DEBUGGING*/
/*Serial.print(F("Fraction = "));
Serial.println(fraction);
Serial.print(F("getTempFloat returns = "));
Serial.println(7.0 + (i-1 + fraction) / 10.0,2);*/
return 7.0 + (i-1 + fraction) / 10.0;
}//end getTempFloat function
Any help is appreciated.
Thanks.