# Trying to get (more) accurate readings from thermistor (electronics, math, and code inside)

So I'm trying to get accurate temperature readings off this TDK B57164K472J thermistor...

It's connected in series with a 1 K resistor, and connected to an ESP8266's onboard ADC.

The thermistor has a Beta of 3950, and the datasheet includes a table for resistances between -55 and 150 C.

In my attempt to increase accuracy, I calculate the Beta myself for the interval the thermistor's resistance is in using the following equation:

B = 1 / ( 1 / T1 - 1 / T2 ) log ( R1 / RR2 )


Then I try to determine the temperature using this equation:

T = T1 * B / log ( R1 / R2 ) / ( B / log ( R1 / R2 ) - T1 )


The full code can be viewed here: https://pastebin.com/ECQHruKN

Factors that are possibly affecting accuracy: The ESP's interval voltage reference reads 3.56 V, it's supposed to be 3.3 V, and my multimeter reads 3.26.

I'm not sure about signage, that is whether my terms should be positive or negative, or when they should be the other.

I'm not sure about my circuit... it's simple for me to learn, but I've seen more complex thermistor circuits, I wasn't just sure how to implement them, and even less confident that I was going to be able to troubleshoot them.

Help would be greatly appreciated. Thank you.

Schematic

simulate this circuit – Schematic created using CircuitLab

• What is your intended temperature range? How are you reading the ADC reference voltage? Jun 9 '19 at 4:57
• Please provide a schematic diagram that shows how you've designed your circuit. Show the power supply voltage for the resistor + thermistor circuit. How are the resistor and thermistor connected?--i.e., VCC->resistor->thermistor->GND, or VCC->thermistor->resistor->GND, or other? I'm guessing the midpoint of the series-connected thermistor + resistor pair is connected directly to the ADC input? Jun 9 '19 at 7:05
• @MadHatter : Normal outdoor ranges, +/- 40 C for here in Canada... Jun 10 '19 at 0:36
• A resistor pair doesn't need (and your ADC doesn't have) an absolute voltage reference. Probably the ten-bit vaue from the converter is a ratio reading, 1023 means 'equal to Vcc' and 0 means 'equal to ground'. Jun 10 '19 at 4:28
• If the ADC's reference is the supply rail, or proportional to it, then the output of a voltage divider between the supply rail and ground will also be proportional to the supply rail, and so any changes in the supply rail voltage won't affect the reading from the ADC (assuming the ratio of the voltage divider stays constant). However Spehro's answer implies that's not how the ESP8266's ADC works, and it instead has an internal but not very accurate reference voltage. Jun 10 '19 at 22:43

The ESP8266 ADC is not really a very good one for instrumentation purposes. I believe it's not very linear (especially for voltages near 0V) and the internal reference voltage might be +/-10% or worse tolerance- loosely specified (with no accuracy limits that I can see, kind of a "bonus" functionality that you shouldn't depend on too much for serious applications).

You also have a pretty crummy NTC and are putting a lot of current through it at high temperatures due to the small 1K resistance (meaning self-heating).

Preferred method for thermistor measurement is ratiometric so the reference voltage cancels out, however the Espressif chip does not bring out the reference voltage, also many boards (I infer that yours is one) include a divider on the input that will load your input at least somewhat, perhaps 220K/100K for a nominal ~3.52V for 1024 counts +/- whatever. 10 bits is none too many for such a wide range of resistance.

There are other ways of measuring a thermistor resistance but they generally require more circuitry, for example to convert resistance to frequency, and switch between a reference resistor or resistors and the thermistor.

Given the huge memory in the ESP8266 you can forget all the fancy math and just build a simple lookup table with 1024 entries, but you'd probably have to build a calibration rig to do that (at least a programmable voltage) to cancel out the errors and the chip is not really specified for any particular accuracy or stability, so most of us would use an external ADC or other circuit so that the accuracy and stability is baked in at the beginning.

• I have this ADS1115/1015 module (I2C ADC, 12 or 16 bit, not sure)... I guess I'll try that... I mostly wanted to familiarize myself with the electronic side of things, but then wanted to gain on accuracy... Also I got these thermistors from Arrow thinking they were good... What's not good about them? I just saw it had a more complete datasheet than most, and went with those... I'm kinda disappointed to learn they're not at least "okay"... 🙁 Jun 10 '19 at 0:45
• If you do a parametric search at, say, Digikey you'll find you get 1% (beta and resistance tolerance) thermistors for 60 or 70 cents and +/-0.1°C ones for a few dollars. The ADS1115 is a nice part but the internal reference is not available outside the chip, so not ideal. Thermistors are best suited for a narrow range of temperatures, otherwise you need a lot of dynamic range in the measurement. You might have a temperature range of -40 to 125°C and the resistance ratio is 1000:1 so it's hard to get much resolution at the extremes. Jun 10 '19 at 2:12
• It's not that they are bad, it's just for absolute temperature measurments you want the best you can get. In my experience NTCs are better used for relative things like PID control etc. Jun 10 '19 at 11:56
• @SpehroPefhany : Ah, you mean that way... When I got them I was mostly looking at the datasheet, to see if it was complete... When I found THT thermistors that weren't too expensive and that had a datasheet with a beta value, I got the first ones... Didn't even think of variance and accuracy, I didn't think the resistance itself would vary in intervals, so I forgot about manufacturing and materials... I guess I'm still learning from the experience, though, so I guess it still can be viewed as positive... 😊 Jun 10 '19 at 20:07

Unless you have a better than 1C temperature reference, I would not bother trying to get a higher absolute accuracy than what you get using nominal data sheet info. If you need a true high accuracy temperature reference, use a thermal couple or Platinum temperature sensor (RTD).

If you want to try this anyways:

1. The reference voltage, if your info is correct will cause way more error then the 3% Beta error and 5% resistance error.
2. First line of calibration would be to verify the resistance at the specified 25C, since the manufacture specs 5%.
3. Then work on the 3% Beta drift... Assuming you need accuracy over a large range beyond near room temperature.

Also consider purchasing a better spec'ed NTC to save your self some time. You can find 2% Beta, 2% Resistance or better for not much more than yours.

• Yes, I'm disappointed to learn that people think my thermistors aren't very good... : \ I got these from Arrow during their free shipping week, and thought they'd be perfect to learn with, and useful for future applications, but you're the second to say they're kinda crummy, and I'm a bit disappointed now, but that's mostly an emotional problem 😋 Jun 10 '19 at 0:47
• If you want true high accuracy, use a high quality platinum RTD. Reading a thermocouple accurately involves measuring a very small voltage difference and in any case the accuracy will only ever be as good as your cold junction reference, so now you have two sensors to worry about. Jun 10 '19 at 9:03
• @nekomatic : Well the exercise still seemed sound, plus I figured I could use them to check temperature inside enclosures, or near components, to warn me of possible malfunction, or to ensure consistent performance if, say, I have a box with sensors somewhere with a solar cell, batteries, and sensors in it... Making sure it doesn't get too hot could be important... Are thermistors suited for that kind of purpose? What's a good use for thermistors? Jun 10 '19 at 20:03
• Thermistors are cheap and are a perfectly good choice where you need low to moderate accuracy - your suggested applications sound ideal. You clearly are learning from beginning to work with them! It sounds like the crummy part of your setup is not your thermistors but the ESP8266's ADC. Jun 10 '19 at 22:36

How accurate do you want your readings to be? 0.1 of a degree? 0.01 of a degree?

You have a couple of problems. Firstly your ADC is not very accurate to begin with. You also should be looking at reducing any noise your ADC is currently subject to. MCUs produce noise, if you have done nothing about that then your ADC is probably subject to enough noise to give you inconsistent results.

Then there is the thermistor, they aren't really super accurate devices to begin with. They suffer from self heating for a start and then there is how stable your input is.

You also need accurate calibration data on your thermistor, since there can be 5% difference to the data sheet values in some cases. But getting a reading at 25 degrees isn't easy, how do you keep the sensor at 25 degrees while you measure it? Getting a reading at 100 degrees is much easier, boiling water has to be at 100 degrees (at sea level, the hotter parts become steam). So you can just stick it in some boiling water.

Once you have all your circuit issues squared away you can start thinking about your programming. Thermistors have a logarithmic relation with temperature to resistance. Generally they have better accuracy in some temperature range. The usual approach is to select the specific temperature range you're interested in (smaller range means greater accuracy) and then use your log functions over that range. Either generating a look-up table or if you have a fast enough chip that isn't terribly busy you can do the actual math on the fly.

But then this comes back to the accuracy of your ADC. If it can only produce 1024 discrete values, then you can only measure 1024 discrete temperatures.

Now if you only care that temperature is definitely between say 35.0 and 35.5 and you're only interested in temperatures between -20 and 50. Then this would entirely achievable with what you have. But if you wanted a larger range or a higher precision, it's not really going to be possible with what you're using.

To get more precision you would have use a smaller range and conversely for a larger range you have to reduce precision. Then at some point your ADC wont be able to tell the difference between two values or the noise will make it impossible to get a stable reading.

I highly recommend using this spreadsheet. You can play with the values and see what the error margins will be along with it providing recommended resistor values for measuring in a given temperature range.

• Well, others recommended using another ADC, which I have a ADS1115/1015 module that I can try, just got to solder pins to it, but your comment allowed the fact that I could limit the effective range of my thermistor with resistors, so that the 0 - Vref interval matches my desired temperature range for my thermistor, thereby increasing the effective resolution, the 1024 values covering a smaller range of actual voltages... I'm not sure if this is right, or makes sense, but I think it's sound, if not implied... As such, thank you 😊 Jun 10 '19 at 0:52
• boiling water has to be at 100 degrees Only at sea level. I have measured at my home at 97C
– GPS
Jun 10 '19 at 6:56
• @poorandunlucky Your thermistor is paired with another resistor to create a voltage divider. By selecting the appropriate value for that resistor based on the temperate range you're interested in you can improve the accuracy. And of course the smaller the range you are interested in, the greater you can improve it. I highly recommend you play around with this spreadsheet. You can enter the temperate range and it will give you a recommended resistance as well as expected error margins. Jun 10 '19 at 7:01
• You make a good point though, one should verify what temperature their water is boiling at. It still makes a good stable temperature reference that is easy to generate though. Jun 10 '19 at 7:08
• Measuring temperature accurate to 0.01 degrees (rather than just to 0.01 degrees resolution) is actually really hard. Fortunately you probably don't need to unless you're doing some sort of science experiment. Jun 10 '19 at 9:06

In addition to the other comments/answers you've received to date, the figure you've added to your original post shows a design flaw that must be addressed. By my calculations, if VCC's nominal voltage is 3.3 V, then for thermistor temperature values of

T = [-40 0 25 40]  (°C)


the corresponding nominal output voltages V_OUT from your circuit are

V_OUT = [ 3.2667    3.0633    2.7211    2.4198 ]  (VDC)


(n.b. V_OUT is the voltage that's connected to the ADC input pin.) According to Espressif's data sheet for the ESP8266EX (p. 16):

The [ADC] input voltage range is 0 to 1.0V when TOUT is connected to external circuit.

So these V_OUT voltages are too high and could possibly damage the ADC input.

FWIW, if you swap the resistor and thermistor positions so that the circuit topology becomes

VCC -- thermistor --(V_OUT)-- resistor -- GND


the resulting nominal V_OUT voltages applied to the ADC for the aforementioned thermistor temperatures are

V_OUT = [ 0.0333    0.2367    0.5789    0.8802 ]  (VDC)


which would be okay. This topology also ensures that V_OUT increases with increasing thermistor temperature, AND the worst-case resolution (not taking into consideration other error sources--e.g., component tolerances) would be about 0.5 °C/bit at the -40°C end, which isn't too terrible.

In Espressif's FAQ for the ESP8266 (scroll down to the "Peripherals" section), the item titled "What should I use the internal ADC for?" states (emphasis added).

The internal ADC can be used for temperature sensing or sensing approximate current drawn by external devices. Note that because the ADC readings are prone to noise, it should only be used for applications where high accuracy is not required. For example, thermal cut-off mechanisms, etc.

Additional considerations related to this ^^^ topic regarding ways to reduce the errors in your measurements are addressed by the other respondents to your post--e.g., tightening the component tolerances, using a ratiometric measurement method (which would likely require an external ADC chip with at least two inputs to measure VCC and V_OUT), etc.

The FAQ topic titled "How accurate is the internal ADC?" states (emphasis added):

If a high accuracy is required, please use system_adc_fast_read API. But RF circuitry should be shut down before measuring and Wi-Fi will be disconnected. For an relatively lower accuracy when readings’ difference of 1 or 2 can be tolerated, we recommend users to configure Wi-Fi to non-sleep mode wifi_set_sleep_type(NONE_SLEEP_T).

For lower accuracy, the user may enter sleep mode. Power consumption is lower in this case.

When the Wi-Fi transmitter is howling RF energy, the power that's drawn from the power supply by the RF transmitter, and the electromagnetic radiation emitted by the RF transmitter+antenna adds (possibly substantial) electrical noise to a) the board's power buses (e.g., VCC voltage droop), and b) your nearby resistor + thermistor + connecting wires circuit. Note that your component leads and hookup wires will act as antennas and will receive some of the RF energy that's emitted by the Wi-Fi transmitter. IOW, power bus voltage droops and unwanted absorption of RF energy in the power bus and in your components are other significant noise sources that must be managed if you want your temperature measurements to exhibit reproducibility, precision, and accuracy.

If you have an extra analog input resistor divide the supply voltage and measure it with the analog input. This will allow you to compensate for voltage error and drift.

• @JimFischer : That's extremely considerate of you to address my predicament in such a comprehensive manner, I am very thankful for your effort! Indeed, it would appear that the ESP8266's ADC, on top of having a recommended input limit of 1 V, isn't the most accurate in the world... A few other contributors to this thread, three (I think), have mentioned a large power variance, and sensitivity to noise, but I thought electrical noise, not RF noise... Your input and response is much valued, thank you again! 😊 Jun 10 '19 at 20:24
• I'm not sure I understand what you mean..? Jun 10 '19 at 20:25

You already have several answers covering different aspects of the problem. In this answer, I will try to cover only a very specific part of the question: how to get an accurate mathematical model from calibration data. In other words, how to fit a model to the data.

You expect the resistance–temperature relation to be of the form:

1/T = a0 + a1 log(R)

where T is the absolute temperature and R is the resistance in ohms. The first thing I would do is plot 1/T as a function of log(R) to see whether the relationship is indeed linear. I did that using the array of data from your Lua code. I could see that it is almost linear, but there is a slight visible curvature.

In order to account for this curvature, I fitted a second degree polynomial, and got an almost perfect fit with:

1/T = a0 + a1 log(R) + a2 log(R)2
a0 = 1.35715e-3 ± 2.464e-6 (0.1816%)
a1 = 2.11435e-4 ± 5.886e-7 (0.2784%)
a2 = 2.93419e-6 ± 3.324e-8 (1.133%)

I say the fit is “almost perfect” because there is not obvious trend in the residues, which look like rounding noise. Then you could use the formula above instead of the table if this is more convenient to you. Alternatively, you could redo the fit over a smaller temperature range that better reflects your intended use of the thermistor.

• I thank you for your elegant addition, however I'm afraid my problem is largely rooted in the physical layer... I don't think I'm able to appreciate your contribution at this time, with all those wires, instruments, and loose parts in front of me, but once I've comprehended what there is to comprehend, and managed to reach reasonable numbers, or at least a good enough indication that my own understanding of the forces at work in this system won't be a problem in itself going forward, I'll be sure to revisit your equations. 😊 Jun 10 '19 at 23:17

Well I would like to thank all those who tried to help me with my problem. Even if your input did not pinpoint the exact problem, it allowed me to take upon myself to look at the breadboard, and also regain confidence in myself towards mathematics. Special mention to the kind man who looked-up the ESP8266's ADC's specs, where it should only be subjected to < 1 VDC.

As for my TDK 472-Series thermistor, it's apparently a good one... Some people thought it wasn't a good part, but it's surprisingly responsive... My only gripe is that the legs easily oxidize, but that's something covered in the spec sheet... It's meant to be soldered, not played with, anyway... I think it's a quality part, but maybe there's, indeed, better out there... I'm just satisfied with it so far.

The (main) problem was the Steinhart-Hart equation.

Indeed my circuit wasn't wired properly for the ADC's 1 V limit, indeed my circuit could've been better constructed in regard to the range of temperatures it should be subjected to, but my Beta and Temperature equations I had taken from a calculator page, and hadn't double-checked... When checking those, they didn't resemble the actual Steinhart-Hart equations at all... In fact, my Beta was way off the Beta provided by the manufacturer, but I had no idea how much it should fluctuate, or even what it represented, so I didn't really consider that when looking at my variables during debugging. The equation returned somewhat reasonable, maybe plausible temperatures, though, and maybe it's "some" thermistor equation, but it's not the Steinhart-Hart equation...

Now my Beta value is close to what the manufacturer provides, but I found that those results were kind of inaccurate... I coded the math for the A, B, C coefficients, and am now using those to find temperature...

My TDK thermistor is very responsive, due to its thermal transfer capabilities, it loses heat very fast to the ambient air, if anyone ever wonders... I like it, anyway... I feel it was a good Arrow purchase 😊

Again, thank you all for trying to help me, and help me you did, even if not for what I had asked 🙂

If you'd like to see my updated code, please feel free to ask, and I'll post an updated copy.

Again: Thank you all

• WRT posting source code. The preferred way to do this, IMHO, is to get yourself a GitHub account (or something similar), post the latest-and-greatest version of your source code there, and then provide herein a link to that GitHub page. With this approach, as you continue to make improvements to the source code you simply upload the source code to your GitHub account. Persons reading this message in the future can simply click on the link (herein) that takes them to your GitHub page where they can then find and download the latest-and-greatest version of your source code. Jun 14 '19 at 15:03