Innacuracy in converting thermistor resistance to temperature.

Hello to all,

I just build a potential divider circuit using a thermistor, i have read several tutorials whereby they are using a 10 K thermistor ana a 10 K resistor in series.

I purchased the Ultimate microcontroller pack, havinf 2 qty of thermistor written 503 on that, with a range of 20k ohm - 1M ohm with power of 50mW and having its beta value 4300.

Through much research i could deduce that it was a 50 K thermistor due to the 503 code.

When i measured the resitance through a meter at room temperature which at that time was approx. 26 to 27, i could get around 35.2 K ohms.

My first puzzle, i should have a reading near 50 K right ??

I combine 2 100K resistors in parallel, to be used in the divider circuit, where the actual reading was 46 K ohm.

I used an external power supply, providing with 4.98 V as input on the UNO board R3.

Using the equation :

R(therm) = R(Series)/((1023/ADC) - 1);

and

V(out) = ( R(therm)/R(series) + R(therm) ) *V(in)

My resistance values were coherent, almost the same reading through measurement and calculation as well as from the program code on the arduino giving therm resistance.

However, when i convert the resistance reading through stainhart-hart equation, my values are innacurate on my UNO, above +2.8 C when compared to digital thermometer used to measure the ambient temperature.

At the time of measurement RT = 27 C with digital thermometer and arduino temperature display showing 31.58 C.

See the code i used:

Please note the stainhart equation used was for the beta value only.

// which analog pin to connect
#define THERMISTORPIN A0
// resistance at 25 degrees C
#define THERMISTORNOMINAL 50000
// temp. for nominal resistance (almost always 25 C)
#define TEMPERATURENOMINAL 25
// how many samples to take and average, more takes longer
// but is more 'smooth'
#define NUMSAMPLES 5
// The beta coefficient of the thermistor (usually 3000-4000)
#define BCOEFFICIENT 4300
// the value of the 'other' resistor
#define SERIESRESISTOR 46000
int samples[NUMSAMPLES];
void setup(void) {
Serial.begin(9600);
//analogReference(EXTERNAL);
}
void loop(void) {
uint8_t i;
float average;
// take N samples in a row, with a slight delay
for (i=0; i< NUMSAMPLES; i++) {
samples* = analogRead(THERMISTORPIN);*
delay(10);
}
// average all the samples out
average = 0;
for (i=0; i< NUMSAMPLES; i++) {
average += samples*;*
}
average /= NUMSAMPLES;
Serial.print("Average analog reading ");
Serial.println(average);
// convert the value to resistance
average = 1023 / average - 1;
average = SERIESRESISTOR / average;
Serial.print("Thermistor resistance ");
Serial.println(average);
float steinhart;
steinhart = average / THERMISTORNOMINAL; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= BCOEFFICIENT; // 1/B * ln(R/Ro)
steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // Invert
steinhart -= 273.15; // convert to C
Serial.print("Temperature ");
Serial.print(steinhart);
Serial.println(" *C");
delay(1000);
}
[/quote]
I tried to work with the full stainhart equation, using the a,b,c values constant to see if things get better, i tried the code below:
Note that the a,b,c values are constant for a 10K thermistor, i used values for a 50K therm i.e. a = 9.657154 e -4 , b= 2.106840 e -4 ,
c= 8.585481 e -8, but unfortunately my temperature reading was above 300 C instead of near room temperature.
So i stick the same values in the program code.
> #include <LiquidCrystal.h>
> #include <math.h>
>
> LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);
> int backLight = 13; // pin 13 will control the backlight
> void setup(void) {
> pinMode(backLight, OUTPUT);
> digitalWrite(backLight, HIGH); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
> lcd.begin(16,2); // rows, columns. use 16,2 for a 16x2 LCD, etc.
> lcd.clear(); // start with a blank screen
> lcd.setCursor(0,0); // set cursor to column 0, row 0
> }
> double Thermister(int RawADC) {
> double Temp;
>
> Temp = log(((10230000/RawADC) - 10000));
> Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp *
> Temp));
> Temp = Temp - 273.15; // Convert Kelvin to Celcius
> return Temp;
> }
> void printTemp(void) {
> double fTemp;
> double temp = Thermister(analogRead(0)); // Read sensor
> lcd.clear();
> lcd.setCursor(0,0);
> lcd.print("Temperature is:");
> lcd.setCursor(0,1);
> lcd.print(temp);
> lcd.print(" C / ");
> fTemp = (temp * 1.8) + 32.0; // Convert to USA
> lcd.print(fTemp);
> lcd.print(" F");
> //if (fTemp > 68 && fTemp < 78) {
> //lcd.setCursor(0,3);
> //lcd.print("Very comfortable");
> //}
> }
> void loop(void) {
> printTemp();
> delay(1000);
Again i had a drift of temperature reading, LCD displaying 32.20 C while digi thermometer showing 30.6 C
Any suggestion please.
Thanks
Taz . . .

taz3m:
When i measured the resitance through a meter at room temperature which at that time was approx. 26 to 27, i could get around 35.2 K ohms.

My first puzzle, i should have a reading near 50 K right ??

It should be near 50K at 25C and about 40K at 30C. However, it may have a tolerance as high as +/- 10%

taz3m:
I combine 2 100K resistors in parallel, to be used in the divider circuit, where the actual reading was 46 K ohm.

That's an 8% error. Resistors are usually 5% or 2% or 1% tolerance these days. Perhaps your meter is under-reading?

taz3m:
Using the equation :

R(therm) = R(Series)/((1023/ADC) - 1);

Not quite right, the 1023 should be 1024.

taz3m:
However, when i convert the resistance reading through stainhart-hart equation, my values are innacurate on my UNO, above +2.8 C when compared to digital thermometer used to measure the ambient temperature.

At the time of measurement RT = 27 C with digital thermometer and arduino temperature display showing 31.58 C.

Unless you use a very close-tolerance thermistor, you need to calibrate it at at least one temperature. We've already established that your thermistor has a resistance lower than its nominal value. Adjust the value of THERMISTORNOMINAL downwards until you get agreement with the digital thermometer around the middle of the temperature range you wish to measure.

Of course, we are assuming that your digital thermometer is accurate.

At the time of measurement RT = 27 C with digital thermometer and arduino temperature display showing 31.58 C.

To me, that seems pretty good for something that's not calibrated.... :wink:

You can do the calibration in software. Typically when calibrating a "straight line", there is an offset adjustment at zero (or at the bottom of your range). The offset is a constant correction-value added/subtracted from each reading. In other words, the offset adjustmet shifts the curve (or line) up or down without affecting the slope.

Then the top of the range there is usually calibrated with a gain adjustment. i.e. A constant correction-value multiplied by each reading. In other words, the gain adjustment adjusts the slope of the curve/line.

If you want the most accuracy at room temperature (or somewhere in the middle of the range), you may want to make that one of your calibration-points, instead of using the high-low end-points.

Sometimes, there are different corrections (calibrations) for different segments of the curve/line. But, you have to be careful not to introduce a discontinuity, where your correction value suddenly jumps and the reading could jump down, when the temperature goes up, etc.

I would take what dc42 said seriously about making sure you have a correct temp standard to calibrate against..I have been playing around with thermocouples for quite some time and have found that the difference in readings from one to another can vary quite a bit more than specs.
If I want to do a calibration, I use a very accurate mercury thermometer. I usually take an ice point ( 0c) and a boiling point ( which will vary with external pressure but can be calculated) and they do not drift or pick up noise like some of the electronic devices I have tried.

RPCoyle:
I would take what dc42 said seriously about making sure you have a correct temp standard to calibrate against..I have been playing around with thermocouples for quite some time and have found that the difference in readings from one to another can vary quite a bit more than specs.
If I want to do a calibration, I use a very accurate mercury thermometer. I usually take an ice point ( 0c) and a boiling point ( which will vary with external pressure but can be calculated) and they do not drift or pick up noise like some of the electronic devices I have tried.

So taking both the reply posted by dc42 and RPCoyle:

I should take callibration point with Ice point and Boiling point and try to adjust the nominal resistance till i get the correct value, is that correct??

DVDdoug:

You can do the calibration in software. Typically when calibrating a "straight line", there is an offset adjustment at zero (or at the bottom of your range). The offset is a constant correction-value added/subtracted from each reading. In other words, the offset adjustmet shifts the curve (or line) up or down without affecting the slope.

Then the top of the range there is usually calibrated with a gain adjustment. i.e. A constant correction-value multiplied by each reading. In other words, the gain adjustment adjusts the slope of the curve/line.

If you want the most accuracy at room temperature (or somewhere in the middle of the range), you may want to make that one of your calibration-points, instead of using the high-low end-points.

Sometimes, there are different corrections (calibrations) for different segments of the curve/line. But, you have to be careful not to introduce a discontinuity, where your correction value suddenly jumps and the reading could jump down, when the temperature goes up, etc.

That seems quite interesting, introducing a gain value and calculating the offset directly from the software.

To DVDdoug:
Can you please kindly guide me where to start, atleast with an equation and how will i be able to calculate the offset and find the proper gain value.

Where do i need to integrate the gain value in my actual equation?

Thanks

Taz ...

in theory, an accurate three point calibration of T verses R should allow you to solve for the a,b,c coefficients of the Steinhart–Hart equation. You need to bracket the temperature range you are interested in.

I have never done this because it requires solving three simultaneous equations, and I never had requirements for that kind accuracy. I could usually get away with introducing a linear "fudge factor"

The only point I was trying to make is to be careful that the tool you are using as a standard of measure of temperature is accurate.

taz3m:
Again i had a drift of temperature reading, LCD displaying 32.20 C while digi thermometer showing 30.6 C

Any suggestion please.

Thanks

Taz . . .

Thermistors are terrible things to use for temperature measurement. They are non-linear, they are fragile and their characteristics change over time.

But if you want to use one, I suggest taking THE thermistor you want to use and take several data points (against a known good thermometer) and then do at least a third or fourth order polynomial curve fit of the calibration data, then either make a lookup table (fast but uses lots of memory) or run the equation realtime on each incoming value (slower, but uses much less memory).

Be sure to take data points near each end of your expected operating range as well as several more evenly spaced in between.

Or better yet... use an LM-35..... :slight_smile:

Krupski:
Or better yet... use an LM-35..... :slight_smile:

Or LM34, which has more than double the sensitivity of the LM35 and can read temperatures below 2C without a negative supply. Or DS18B20.

taz3m:
So taking both the reply posted by dc42 and RPCoyle:

I should take callibration point with Ice point and Boiling point and try to adjust the nominal resistance till i get the correct value, is that correct??

Taz ...

Thermistors are non-linear. A simple 2 point calibration will not work. The ice and boiling points will be right, but it will be wrong in between. You need a polynomial to correct a thermistor. Or, if you don't know how to do that, at least use a piece-wise linear approximation to correct the thermistor.

Depending on what accuracy you are looking for, a 1-point calibration in the middle of the temperature range (as I suggested) may be good enough, in which case you have to use the B-value from the datasheet in your calculation. If that isn't accurate enough, use a 2-point or even 3-point calibration, or a different sort of temperature sensor.

dc42:

Krupski:
Or better yet... use an LM-35..... :slight_smile:

Or LM34, which has more than double the sensitivity of the LM35 and can read temperatures below 2C without a negative supply. Or DS18B20.

All depends on the application. For example, if I use an LM-35 (10 mV/degree C) and an Arduino with the A/D reference set to 1.1 volt internal, I can get a range of temperature readings from close to 0 deg.C to 110 deg.C (quite a useful range).

If I use an LM-34 (10 mV/degree F) then my range is from close to 0 deg.F to 110 deg. F (also quite a useful range). (fixed typo)

I just tossed out "LM-35" because that's what I'm used to using. In other cases, the LM-34 would be a better choice.

Really, the point of my comment was "don't use a crappy non-linear thermistor, use a nice linear solid state device"! :slight_smile:

dc42:
Depending on what accuracy you are looking for, a 1-point calibration in the middle of the temperature range (as I suggested) may be good enough, in which case you have to use the B-value from the datasheet in your calculation. If that isn't accurate enough, use a 2-point or even 3-point calibration, or a different sort of temperature sensor.

That's the best option. Something other than a thermistor.

If I use an LM-34 (10 mV/degree F) then my range is from close to 0 deg.F to 110 deg. C (also quite a useful range).

That's a neat trick. :wink:

Lefty

retrolefty:

If I use an LM-34 (10 mV/degree F) then my range is from close to 0 deg.F to 110 deg. C (also quite a useful range).

That's a neat trick. :wink:

Lefty

Oops... what a big difference one letter makes. I corrected my typo! :slight_smile: