Introduction
Often we have a requirement to measure the temperature of
the board, the environment or some process.
Here’s a quick and easy guide to simple temperature measurement using a
simple, cheap thermistor.
There are numerous silicon devices on the market which seem
to simplify temperature measurement, but it’s difficult to beat a good quality
NTC thermistor. I’ve used them to measure
the temperature of things as diverse as engine manifolds to LEDs, and in medical applications have
measured patient internal temperatures to accuracies far better than 0.1°C.
Selecting the Thermistor
There are two types of thermistor, defined by whether their
resistance increases or decreases as temperature rises. Temperature is best measured using NTC
(negative temperature coefficient) thermistors, whose resistance decreases as
temperature rises.
There are two parameters of importance in defining the
characteristic: A reference resistance and the Beta value. The reference resistance is usually specified
as the resistance at a temperature of 25°C.
The most common types have a 10k resistance at 25°C. The Beta value specifies how the resistance
varies as temperature deviates from the reference temperature. The most common types have values in the
region of 4000 and have units of Kelvin.
For this example, we will use a Vishay NTCLE100E3103JB0,
(Farnell/Newark part 1187031, Digikey part BC2301-ND). This is a cheap and simple leaded part with a
2.54mm (0.1”) lead spacing, has a 10k resistance at 25°C and a Beta value
B=3977K.
There are many, many types of NTC thermistor, some with
different case styles including surface mount parts, different reference
resistances for nominal temperature ranges other than room temperature, and
different tolerances for accuracy. This
one is good for general purpose air temperature measurement.
The Measurement Circuit
The thermistor is connected to the ADC 0V and in series with
a reference resistor, forming a potential divider from the ADC reference. A filter capacitor across the thermistor will
reduce any thermal noise, or other pickup.
Now, we can easily calculate the ADC value at 25°C. And we’ll see that as the temperature
increases, the thermistor resistance decreases and the voltage measured at the
ADC falls.
Calculating Temperature
We could approximate the thermistor response as a linear
function, but beyond a very small range around 25°C, the errors would quickly
become unacceptable. A better
approximation is made by using the Beta-curve function:
R = exp[(Beta/Tk) + LN(A)]
Where Tk is the thermistor temperature in Kelvin, not
degrees centigrade, and LN(A) is a constant value for the thermistor. (Kelvin
is an absolute temperature scale, where Tk = Tc + 273.15).
Solving the above equation for temperature gives
Tk = Beta/(LN(R)-LN(A))
Or
Tc = Beta/(LN(R)-LN(A)) – 273.15
Where
LN(A) = LN(R25)-(Beta/298.15)
But now we need to know the thermistor resistance R. The ADC value depends of the resistance R as
follows:
ADC = ADC_TOP * R / (R + Rref)
Where ADC_TOP is the highest value given by the ADC, (e.g.
4095 for a 12-bit ADC), and Rref is the reference resistor value.
Solving for R gives
R = Rref * ADC / ((ADC_ TOP * Kadc) – ADC)
Implementing in C-code
The following is representative of code which calculates
temperature measured using the above method.
The detailed code will need to be adapted depending on your processor, your
board and your thermistor.
// Include math library for calculations
#include <math.h>
// Define ADC parameters
#define ADC_TOP 1023
// Define thermistor parameters
#define R_NTC 10000
#define BETA 3977
#define LNA (-4.12858298874828)
// Define Reference Resistor
#define R_REF 15000
float read_temperature(void)
{
float x = 0;
// Calculate thermistor resistance from ADC
x = (R_REF * adc[0]) / (ADC_TOP – adc[0];
// Calculate Kelvin temperature from resistance
x = BETA / (log(x) - LNA);
// Convert temperature to Celsius
x = x – 273.15;
// Return result
return(x);
}
Have you had any issues with low temperatures? I also had issues with your formula for calculating the T.
ReplyDeleteAccording to the data sheet the formula should be:
(A+B*log(R/R_REF)+C*log(R/R_REF)^2+D*log(R/R_REF)^3))^(-1)
This gives good results for temperatures around the ref temp but when I attempt to use it in my freezer (~-8F) it displays temperatures around 29F.
Im not sure what is going on. might be an issue with my selected resistor?
Hi Tyler, Thanks for the comment. The international standard for temperature measurement, and the one used to characterise these thermistors, is the Kelvin scale. This has the same slope as the Celsius scale, just with an offset of -273.15. This method, and indeed the data sheet values usually given, are completely unsuitable for Fahrenheit. If you want a Fahrenheit result, for quaint colloquial American usage (smile), then you first need to calculate the Celsius temperature using the above, then convert to Fahrenheit using Tf = (Tc * 9/5) + 32. Good luck!
ReplyDeleteIf you want better approximations, over a wider range, then the Steinhart-Hart method is better, and may be what your formula is based on. Be sure to use the natural log, (ln) not the decimal log (log) function. I'll think about posting on using that method, which I've used in precision medical applications, but for now, you may find what you need by Googling Steinhart-Hart.
ReplyDelete"We could approximate the thermistor response as a linear function, but beyond a very small range around 25°C, the errors would quickly become unacceptable."
ReplyDeleteTrue, but a very useful, cheap (as in CPU resource / code size)and as accurate as required implementation, is to calculate the temperature for a few (how many depends on how accurate you need it to be) evenly spaced ADC values and interpolate between them.
Look-up and interpolation can be very fast operations if implemented correctly. Minimal code and CPU usage.