I built a digital thermometer last night:
There are a lot of wires there but most of them are for communicating with the LCD display. The thermometer itself is just two parts, a thermistor and a fixed resistor:
They form a voltage divider, and the voltage from Arduino (analog input) pin 0 to ground depends on the thermistor resistance, and so on temperature. Easy.
That dependence on temperature isn’t so easy. The thermistor I’m using is a Vishay NTCLE100E3103JB0 and according to the datasheet, the temperature (in Kelvins) as a function of the resistance is given by
1/T = A + B ln(R/Rnom) + C (ln(R/Rnom))2 + D (ln(R/Rnom))2
where Rnom = 10000 ohms and A, B, C, and D are empirically determined constants. This isn’t at all linear, and the sensitivity — the rate at which R varies with T — is largest at low temperatures and much smaller at high temperatures. Notice that as the temperature goes down, R goes up — this is a negative temperature coefficient thermistor.
So, OK, the Arduino code can calculate T from this formula; so what? Well, suppose we wanted to use this thermistor to measure air temperature as a function of altitude up to 100,000 feet. The temperature will vary from roughly –70°C to +25°C, and the sensitivity of the resistance to the temperature will vary considerably over that range.
(Be careful here; the resistance is most sensitive at low temperature, but what we measure is the voltage from the divider, which doesn’t depend linearly on the resistance:
vout = Vin(R2/(R1+R2))
So for example, if at high temperature the thermistor resistance R1 is much smaller than the fixed resistance R2 then the voltage we measure will be close to Vin=5V and it won’t vary much even if R1 does.)
What we read on the Arduino of course isn’t the voltage, but a value from an ADC (analog to digital converter). Analog levels from 0 to 5V are read as integers in the range 0 to 1023 ADC channels. If the sensitivity is low, then a change of 1 ADC channel (the minimum change we can see) might correspond to a large temperature change.
For this thermistor (using the nominal calibration constants from the data sheet) and a fixed resistor R2=10 Kohm (which is what I used in the photo above), the ADC values and the resolution — the number of degrees producing a change of 1 ADC channel — are as shown here. ADC values (in blue, read off the left vertical axis) range from 1 to 512 channels. The resolution (in red, read off the logarithmic right axis) is 0.09 degrees per channel at 25°C, but only 5 degrees per channel at –80°C!
That’s pretty pathetic. Clearly the thermistor resistance at low temperature is way too large compared to the fixed resistor.
So here are two other cases:
The darker colored points are for R2 = 33 Kohm, and the lighter ones are R3 = 1 Mohm. The ADC values are larger, and in fact for 1 Mohm they saturate near 1023 channels above about 0°C, but they do not saturate near 0 channels at the bottom of the temperature range. In fact they start at 124 channels, giving a very comfortable margin of safety. At the low end the resolution is better than 0.1 deg/chan. For 33 Kohm the resolution at high temperature is just slightly worse than befor, still around 0.1 deg/chan. The two resolutions cross at around –25°C.
What I take away from this is, if I haven’t overlooked some other problem (which is very possible!), a good way to operate would be to use two thermometers, one with a 33 Kohm resistor for temperatures above about –25°C and one with 1 Mohm for lower temperatures. The uLog can read three inputs, so we could in fact have three thermometers — two measuring the outside air, optimized for low and high temperatures, and the third measuring the temperature near the uLog as a check on how much (if at all) the insulation helps the electronics stay near its spec range. That one would be optimized for low temperatures too, of course.
Now, all of that assumes I’d be using the Vishay NTCLE100E3103JB0, and I don’t want to do that. It’s not specced for such low temperatures. I’d have to do a similar analysis for the thermistor I do end up using, but I haven’t yet found nominal calibration constants for the one I’m considering.