Thermistor lookup table
TC
Posts: 1,019
in Propeller 1
Hello all,
I an using a 12-bit ADC to read the voltage from a thermistor voltage divider. I used a Vishay spreadsheet to calculate the min and max resistance value for each degree. I then took those values and made a spreadsheet that does the voltage divider calculations, and outputs a min ADC, and max ADC value for each degree.
My question is, how do i take a list of min ADC values, and max ADC values and have the prop know that if the ADC value it just read correlates to a temperature value?
I have included a couple values from my spreadsheet.
Thanks TC
I an using a 12-bit ADC to read the voltage from a thermistor voltage divider. I used a Vishay spreadsheet to calculate the min and max resistance value for each degree. I then took those values and made a spreadsheet that does the voltage divider calculations, and outputs a min ADC, and max ADC value for each degree.
My question is, how do i take a list of min ADC values, and max ADC values and have the prop know that if the ADC value it just read correlates to a temperature value?
I have included a couple values from my spreadsheet.
DAT ' min max tempList byte $03D8, $03AD '0deg byte $03FE, $03D2 '1deg byte $0425, $03F9 '2deg byte $044D, $0420 '3deg byte $0475, $0448 '4deg byte $049E, $0470 '5deg byte $04C7, $0499 '6deg byte $04F1, $04C3 '7deg byte $051C, $04EE '8deg byte $0547, $0518 '9deg byte $0572, $0544 '10deg byte $059E, $0570 '11deg byte $05CA, $059C '12deg byte $05F7, $05C9 '13deg byte $0624, $05F6 '14deg byte $0651, $0623 '15deg byte $067E, $0650 '16deg byte $06AB, $067E '17deg byte $06D8, $06AC '18deg byte $0706, $06D9 '19deg byte $0733, $0707 '20deg byte $0760, $0735 '21deg byte $078E, $0763 '22deg byte $07BB, $0790 '23deg byte $07E8, $07BE '24deg byte $0814, $07EB '25deg byte $0841, $0818 '26deg byte $086E, $0844 '27deg byte $089A, $086F '28deg byte $08C6, $089B '29deg byte $08F2, $08C6 '30deg byte $091D, $08F0 '31deg byte $0947, $091B '32deg byte $0971, $0944 '33deg byte $099B, $096D '34deg byte $09C4, $0996 '35deg byte $09EC, $09BE '36deg byte $0A14, $09E6 '37deg byte $0A3B, $0A0D '38deg byte $0A61, $0A33 '39deg byte $0A87, $0A58 '40deg byte $0AAC, $0A7D '41deg byte $0AD0, $0AA2 '42deg byte $0AF4, $0AC6 '43deg byte $0B16, $0AE9 '44deg byte $0B39, $0B0B '45deg byte $0B5A, $0B2C '46deg byte $0B7B, $0B4D '47deg byte $0B9B, $0B6E '48deg byte $0BBA, $0B8D '49deg byte $0BD9, $0BAC '50deg
Thanks TC
Comments
Otherwise you need to do it the hard way as you are doing and normalize and interpolate from your table to make it fit the table the way you have done it or you could just substitute a multi-turn trim pot to dial up these "temperatures" and build up your table with the actual ADC values and simply interpolate unless you aren't worried about precision. Too much hard work this way though.
Unfortunately I have to use thermistors. They have the package I need.
The table I made is the minimum ADC, and the maximum ADC value for each temperature degree. For example, say the prop got a reading of $0712, it would use the lookup table and find $0712 is greater than $0707, and less than $0733, the prop would then know those values correspond to 20 degrees.
Is there a better way to make a lookup table? I only need 1 degree(ish) precision.
Others may disagree, but I would not list min and max readings, instead I would list min and corresponding temp. After obtaining a reading, iterate through the min list and compare. If the reading is above the current min value, then compare to the next min value, otherwise you have found your temp.
I have some good code for this written in C, if you are interested.
first I notice is that your max and min seem to be swapped.
Second is - the ranges overlap.
So I would change the spreadsheet to give the border values between 2 neighboering degree values and thus reduce the values you have to store in a table by 50%.
So gives you just a simple list of values to compare your reading against to find the position which is the °C result then.
Or you can run a little plotting / regression in EXCEL and see if a simple linear or low order approximation is good enough. Giving you a formula instead of the table.
That was one option I was thinking of since I am not looking for perfect accuracy, close enough is good enough.
You are correct, I did not notice I had the labels backwards. I got the values from Vishay's spreadsheet. Then I took the "Rmin" and "Rmax" values and inputted them into the voltage divider formula (~ Vout=(4.096V*(10KΩ/"termsistor resistance"+10KΩ)) ~). I then took that value multiply it by 100, then made it an integer. That value would repersent the ADC equivalent for the termistor resistant value.
I hope that makes sense.
If you do not mind me asking, why are you using an external ADC? For a thermistor (something I am also working with now on the Propeller) using a simple cap and second resistor to make a simple RC-Time circuit is quite enough, especially considering the high resistance of a thermistor until you get to extremely high temperatures. I am only working in the temperature range of -10C to +280C so it is fairly simple, though the range excludes the use of a chip thermometer.
I am reading 7 thermistors, but I cant tie up a lot of pins. I am using a MCP3208 to read the voltages from the thermistor voltage divider.
I changed the values from HEX to decimal, and I can see there is a lot of cross over of the values. So what I have decided to do is, only calculate for the actual temperature, and not the temperature plus the tolerance. The prop would just start at the first value, compare the ADC value to the list, the ADC value is larger that the list value, the prop would go to the next value. The prop would keep doing that untill it came across a value that is less than the ADC value. And every time the prop went to the next value in the lookup table, it would add 1 to a counter.
Here it is in C, perhaps this will give you some ideas.
The code was originally written by Adafruit for the ADS1015, but it has been highly altered by yours truly to permit to different thermistor readings.
You should be able to open it up in any text editor.
If you store the low-point for a given temperature, you iterate through the list of numbers until you find one higher than your sample reading, or you reach the end of the table. When you find a reading, you can even figure out where you are between readings, and use that as a fractional measure of the degree value to improve precision.
For example, if your sample is $A4F, and your table is:
Low = $A31 = 2609
High = $A5C = 2652
Sample = $A4F = 2639
Range = (High - Low) = 43 (distance between your table entries)
Pos = (Sample - Low) = 30 (where your sample falls in the above range)
Fraction = (Pos / Range) = 30 / 43 = 0.7
So your temperature is (roughly) 39.7 degrees
For my application, I stored the temperatures in 5 degree increments and use interpolation to get degrees.
https://learn.adafruit.com/thermistor/using-a-thermistor
Done this with arduino and get 2-3 degrees error. It's simple to translate to spin.
Hah - Good catch. I copied from the original post and didn't even notice he'd be overflowing the 8-bit limit. That would very certainly cause you issues. A byte won't hold a value higher than $FF, and it'll most likely truncate, keeping the lower 8 bits of your original value.
-Phil
Thank you.
I can see that. 7 Thermistors would take 14 pins, and that would be a problem for most any project. I am doing only 3 thermistors, so only 6 pins.
What is wrong with using fixed point for that application?
This also is the right track. You do need to use those MAX and MIN values to give you some error indications, but you should not use them for lookups.
Instead, you want the most likely curve as your decision basis.
That works, but more compact is to store a difference in the ADC table, which can now fit in a byte, making a smaller table.
The table scan now adds the differences, and increments the Degrees by 1 each time.
( A slight speed hit, has decreased the table size.)
You pick the nearest table Sum, to your ADC reading. (not a < test)
The points you store to make the decisions, should be (nominally) 0.5 degrees offset, so you have a +/- 0.5 degree sawtooth error
result.
The ADC deltas you have look to vary from 31~38/1 deg increment, so you will be quite precise on the 0.5 offset , and have enough spare resolution you could add a 0.1 degree interpolate if you wanted to.
The Adafruit article linked above by JDat used floating point. Be that as it may, I'm all for fixed point. However, you'll have to formulate the natural log function as well as tricky scaling. It's not that easy. There is a log table in the Prop Rom, however you have to really understand how to use it. Most of the Prop floating point libraries use that table, so it comes back to a table lookup with lots of overhead.
The table lookup I posted earlier has parameters stored in DAT for the increment between temperature values, set at 5 degrees, but it could just as well be 1 or 2 degrees to cover the desired range with greater accuracy, also with interpolation. There are parameters in DAT for the lowest value (-40) and the highest value (+125) in the table, and the lookup/interpolation algorithm adjusts for the high, low, and the increment.
I did notice the "byte" should of been "word" when I took a good long look. I will reply to everyone a little later when my brain starts getting better.
Thanks
TC
Massimo