Preferable Thermistor Configuration

I'm considering trying to put together a accurate thermistor sensor system. The Thermistor would likely be the 10k kind, and the circuit a wheatstone bridge with the two top legs (including the thermistor) being the 10k while the lower leg would be two 4.7k. Some of the literature I have reviewed suggests that adding a unit-gain buffer would further enhance stability and accuracy, I'm hoping that a wheatstone bridge and the MCP3424 would do it.

To help offset and gain issues, I'll set aside one channel to just measure those so that they can be compensated for. Thus, four channel inputs became 3...

Any thoughts regarding the above or should I be looking at different circuits?

I have some experience in this area. What temperature range do you need to cover, and what accuracy are you looking for? Are you prepared to calibrate the system at 2 or more temperatures to achieve this accuracy? Many thermistors have a resistance tolerance of 5% or so, and this (along with tolerances in the other characteristics) limits the accuracy you can achieve without calibration.

A Wheatstone bridge is a good arrangement for an analog measuring device but not necessarily helpful for digital temperature measurement unless the temperature range is very small and you use an ADC with differential inputs. A unity gain buffer is probably unnecessary and may even degrade accuracy, depending on the conditions. Whether 2 x 4k7 is the right value for the lower leg depends on the temperature range you want to cover.

In short, the best arrangement depends on precisely what you want to achieve.

Hi DC42,

I'm only looking to cover about 10-50*C, though a better specification range might be 0-100*C just to be safe. I was thinking the following probe from US Sensor looked tasty. It has a range of resistances from about 7k4 Ohm at 0*C to 150 Ohm at 100*C and at $4.6 a piece, the price is not bad for its accuracy/resolution.

I played around with the Wheatstone bridge simulator over at Daycounter and it would seem that a pair of 4k7 and a 2k2 (opposite the the thermistor) would yield a wheatstone output voltage range of -0.96 to 0.95 if I used a precision Voltage source VCC = 3.3V. A MCP 3424 would then measure that voltage on a differential basis with a gain of 2, so I'd lose no virtually bits in the process vs. a full bit if I hooked the unit up as suggested in the datasheet.

Calibration would occur occasionally, as described in this article. That means one less channel to sample with but better auto-calibration. If I can just sample the VCC every other MUX channel cycle, then the rig can enjoy its auto calibration with 18 bit resolution and yet sample all four inputs.

Thanks again for your insights and any thoughts you might have re: the above.


You still haven't said what resolution and accuracy you are looking to achieve. If you only want 10 to 50C with 0.25C resolution for example, you can achieve that using just an Arduino, thermistor and resistor. If you want to cover 0 to 100 with similar resolution, then you probably need a dual range approach, using a small mosfet to switch in a different resistor as shown in that article. It's a little easier to swap the resistor and thermistor (i.e. resistor to ground, thermistor to Vref) and use an n-channel mosfet (e.g. 2N7000).

What's the point in sampling Vcc? ADCs are ratiometric devices, so as long as Vref for the ADC is the same supply you are using to feed the thermistor and resistor (e.g. the 3.3v Arduino pin), then the reading is independent of Vcc anyway, provided Vcc remains steady and ignoring self-heating in the thermistor.

Apologies, it was late.

The thermistor from US Sensor is allegedly good for 0.1*C readings. I was trying to put a ADC on the backside that can take advantage of that, i.e. make the sensor the single limiting factor re: temperature resolution and accuracy. I’d prefer 10x resolution but accuracy is important too. I didn’t want to go the whole hog to RTDs either since I’d need a much bigger PCB for all the terminals that would ensue…

As I understand it, (and please correct me if I am wrong) the theoretical vs. practical resolution and accuracy of a ADC are two very different things. IIRC, Atmel only specifies the AVR ADC to be accurate down to 2LSBs, so there can be significant offset errors. Hence the folk at openenergymonitor use a software-based filter suggested by Atmel to filter out the offset error.

The sampling of VCC on one channel allegedly can help address that, i.e. help improve accuracy by taking care of some of the inherent wanderings in ADC readings and / or voltage sources. Such sampling may not be necessary as you point out since the ADC has a much higher resolution than what the sensor can theoretically deliver.

But since I wanted an ADC that was better than the thermistor in terms of resolution despite loosing a LSB here and there due to noise and other factors, I was drawn to this 18 bit ADC. Even if I take off 4LSBs due to noise, drift, or other factors, I still get a ADC resolution down to 0.006C from 0-100C. That seems more than adequate to support that thermistor.

What I liked about the Wheatstone bridge arrangement was how I could take advantage of it to use the whole input range on the ADC. But a non-Wheatstone arrangement with a carefully designed voltage divider may be able achieve more than adequate resolution. I’ll have to look into that.

So I took a look at the outputs out of a Wheatstone bridge vs. a Unipolar design in Excel. The conclusion I come to is that either design can work, it really depends on whether the ADC is of the unipolar bipolar type. The latter definitely benefits from a Wheatstone bridge - otherwise you're throwing away a bit of resolution for no good reason.

The resolution at low temperatures for the resistor values I chose (4k7x2 and 2k2 on the Wheatstone and 11k for the Unipolar design) and the 2k2 precision thermistor from US Sensors is gargantuan when it comes to 0-50*C measurements which are the mainstay of our expected temperature measurements. (I never expect measurements below zero *C, that would require a different kind of sensor.)

The differences are more pronounced at the high end of the temperature scale, however, where the linearization of the Wheatstone tends to decompress the steps a bit. To cite an extreme, the number of bit 'steps' from 110*C to 120*C for the Bipolar/Wheatstone approach is 542 while the Unipolar design makes it to 392.

So, you gain a bit of resolution at the high end of the temperature scale with the Bipolar design while enjoying fewer steps at the low end of the temperature scale. To put that in perspective, the 0-10*C range enjoys 17k steps in the unipolar design and 'only' 12k steps in the bipolar design. But either approach is offering up 10x the theoretical resolution of the Arduino. And 10k+ steps should allow me to characterize the temperature rather well.

To properly get to temperature measurements in between stated data points, I decided to create a lookup table that uses a ln(x) function between each published data point for interpolation. The results match up to beyond 3 digits after the dot, which is good enough for me. I plan on dumping these floats into ProgMem as an array and using them in a ln approximation function as a function of the integer that the ADC is reporting.

I derived the offset and multiplier through an iterative approach in Excel. The nice thing about all that work is knowing that I can now convert directly from the long integer values reported by the ADC into a temperature. See below:

| Temp (*C) | ADC Integer Value | ln(x) multiplier | ln(x) Offset constant | | - | - | - | - | | 120 | 1045 | -22.27923662 | 274.880177 | | 110 | 1637 | -24.95192121 | 294.6597015 | | 100 | 2444 | -26.56710287 | 307.2603658 | | 90 | 3561 | -27.61393547 | 315.8211499 | | 80 | 5115 | -28.17896062 | 320.6464267 | | 70 | 7294 | -28.51382449 | 323.6249762 | | 60 | 10358 | -28.86768587 | 326.8966067 | | 50 | 14646 | -29.47440202 | 332.716181 | | 40 | 20562 | -30.6152316 | 344.0459878 | | 30 | 28505 | -32.1216923 | 359.4990127 | | 25 | 33306 | -33.62930719 | 375.1985497 | | 20 | 38645 | -36.90097385 | 409.7544579 | | 10 | 50674 | -44.05057072 | 487.2072436 | | 0 | 63588 | -56.60933954 | 626.1094879 |

To get at the offset and gain issues inside the ADC, I am considering the following: Use a 8 channel multiplexer with 3 precision resistors to create a linear offset. Every time the MUX inputs are cycled for all the channels, these resistors are sampled also. Then, the offset is calculated and added as function of the integer that the ADC is responding with on later measurements. So that takes care of offset and hopefully gain errors also.

At the 15 samples per second rate that this ADC supports in 16 bit mode, I may even elect to do two measurements of the other analog input channels (i.e. 10 samples altogether) and average them for ever second time-slice I am interested in.

Last but not least, I expect that no matter how well the thermistors are calibrated up front that they will need to be calibrated once they're on the ADC. The test with least damage potential is ice water, as thermistors apparently do not like prolonged exposure to temperatures above 90*C. But I might try both an ice water and a boiling pot of water, just to 'bound' the ADC range.

Hi all, I am back.

Turns out that addressing the offset and gain error works - to a point. The issue is that offset and gain calculations require the use of quadratic equations to come up with the best line fit compensation. That in turn then leads you straight into a brick wall, aka the limits of a 8-bit microprocessor. Since the Arduino does not support anything larger than uint64's, you pretty quickly approach the limits imposed by the microprocessor when it comes to calculating factors like sum of x^4 times sum x^2.

In the end, it meant that it made more sense to calculate a generalized offset and gain compensation curve in excel and then transfer the factors to the Arduino. Then, it's possible to use the offset and gain compensators to verify the proper performance of the ADC, i.e. one can flag if there is a problem or not by seeing how many LSBs one is off by due to temperature swings by the ADC, etc.

One unexpected twist was how much memory the ln(x) and offset factors take up in flash memory. As a result, I have resorted to not doing the temperature conversion on the actual temp DAQ module, I'm doing it on the main module instead where I have 128kB of memory instead of just 32. Thus, the daughter module will just transfer the raw integer data from the DAQ to the main module and conversions, checks, etc. will happen there.

This also gives me the opportunity to modify the data set being stored on the flash drive to include offset and gain data from the reference resistors. The curves can thus be calculated offline if need be. I also reverted to a unipolar design because it is easier to set up and if the PGA stages are used correctly can produce some very good results also. My intention is to scan all channels quickly at 12bit resolution (i.e. allowing 240SPS) and then following up with a 16 bit sample for each channel that has the "perfect" PGA setting also.