Interpreting non-linear temperature thermistor value

Scott4Scott4 Posts: 45
edited 2011-03-23 - 19:35:14 in Accessories
1. I'm using an analog to digital converter to read the voltage across a thermistor used to measure engine water temperature. (see attached)

2. The thermistor temperature vs resistance curve is non-linear. (see attached)

3. I was thinking about using LOOKDOWN / LOOKUP but the steps would be in 10 degree increments.

4. I was also thinking about using linear interpolation but maybe there is a better way.

Can anyone suggest a good way of getting a one degree resolution?


  • Tracy AllenTracy Allen Posts: 6,417
    edited 2010-01-07 - 17:56:46
    Linear interpolation is the way to go. If you want examples, I can dig out one I've done.

    Tracy Allen
  • kf4ixmkf4ixm Posts: 529
    edited 2010-01-07 - 18:34:54
    I for one would be interested in seeing an example.
  • Scott4Scott4 Posts: 45
    edited 2010-01-07 - 19:40:01
    An example would be greatly appreciated. -Scott
  • ZootZoot Posts: 2,227
    edited 2010-01-07 - 20:07:16
    Here's an Excel (.xls) file zipped that lets you calculate the K constants for the formula:

    linearVal = ( Kslope / ( nonLinearVal + Kyintercept ) ) - Koffset

    You can check the curves in the Excel graphs to see if you are getting the interpolation you like. This saves on table reading/parsing, but may or may not give you the linearity you are looking for. The file was written for a Sharp IR detector, but can be used for any non-linear to linear conversion.

    When the going gets weird, the weird turn pro. -- HST
  • Tracy AllenTracy Allen Posts: 6,417
    edited 2010-01-07 - 20:27:07
    I'm attaching two files, one a BS2pe program (which can run in other Stamps too), and an Excel spreadsheet.

    This particular program is for the thermistor that is in the Apogee environmental oxygen probe, and has a nominal resistance of 10kOhms at 25 degC. It is in series with a 25.5 kOhm precision resistor (included in the probe body). In the data logger (OWL2pe) the thermistor is connected to a 4.096 V reference, and the bottom of the 25.5 k resistor is connected to ground, and the junction goes to an input of a TLC2543 ADC. Voltage increases as temperature increases. The DATA in the table is the milliVolts is expected at -40, -35, ... and so on up to +85 degC. The program locates the present voltage in the table and then interpolates back to temperature. The program is set up to run in one slot of a BS2pe. If it runs in slot 0 (of any stamp), or if it is called with a cross-slot index of zero, it runs a test routine that shows current readings on the DEBUG screen. If it is called from some other slot, a slot index of 1 causes it to return Celsius (in units of 0.1 degree) in a word variable using an ADC channel stored in eeprom. If the calling slot index is 2, it uses a value passed in with the call to specify the ADC channel number (This project had to read several probes).

    The spreadsheet generates the DATA statements for the program. The DATA in this example is entered at 5 degree Celsius increments. At the top are cells to enter the fixed resistance (25.5k in this case), and the reference voltage (4.096 V in this case). The spreadsheet is also useful for exploratory purposes to check for how much error you can expect, against a Steinhart-Hart or polynomial fit.

    Tracy Allen
  • sylvie369sylvie369 Posts: 1,618
    edited 2010-01-07 - 21:34:14
    (Just thinking aloud from a non-expert)

    Depending on the way things are set up, isn't this the kind of thing for which it would make sense to simply have the BS2 report the raw data to PLX-DAQ, and have Excel do all the conversion? If I'm understanding it, that's what Zoot is suggesting. It must be easier to do that than to have the Stamp do the math.
  • ZootZoot Posts: 2,227
    edited 2010-01-07 - 21:46:54
    No, that is not what I was suggesting, and neither was Dr. Allen.

    My method (a space saver) uses the formula given to linearize a non-linear value (say from an IR ranger, thermistor, RCTIME value on a light sensor, etc). The thing is you need the three constants to plug in -- the Excel file lets you pre-calculate desired output value ranges, actual input readings, to generate the constants. These constants are used in the formula in Stamp Pbasic code.

    For example, on two of my IR rangers, I took very accurate ADC readings at 10cm intervals, plugged the values into the Excel file, and calculated my three constants.

    The table-based interpolation actually does the same thing, in a way, by going through a table of pre-defined data points, finding the closest match, then interpolating between those two points to get the closest value. Again, Dr. Allen's Excel file is used to *create* the original table of "ready-to-go" data points; those data statements are copied to the Stamp application to be read by the main program.

    But, yes, if the data is being sent to a PC, doing it there would be fast.

    When the going gets weird, the weird turn pro. -- HST

    Post Edited (Zoot) : 1/7/2010 9:52:38 PM GMT
  • pmrobertpmrobert Posts: 576
    edited 2010-01-07 - 21:47:03
    The Steinhart-Hart equation works well for characterizing engine temp sensors. See for several approaches and examples. 3 measurements at known temps on the curve and a lookup table can easily be generated, your choice of resolution.


    Edit: Oops, sorry! It looks like the Excel solution does the job.
  • sylvie369sylvie369 Posts: 1,618
    edited 2010-01-07 - 22:21:43
    I see. Very interesting thread, and that was a nice explanation.
  • kf4ixmkf4ixm Posts: 529
    edited 2010-01-07 - 22:48:42
    is there any gain of using an a/d converter instead of RCTIME with a thermistor? does the a/d make readings more linear?
  • ZootZoot Posts: 2,227
    edited 2010-01-07 - 23:42:25
    An ADC will be linear ONLY IF the voltage/current/etc it is reading is linear. So if the sensor is linear, the ADC values will be linear. Generally RCTIME will be non-linear, regardless of whether or not the input is linear.

    In the end it may not matter -- I might argue that it is always beneficial to linearize sensitive input values in code, so that the app can *always* be tuned regardless of what sensors, circuitry or methods are used to acquire the input at the beginning.

    When the going gets weird, the weird turn pro. -- HST
  • Tracy AllenTracy Allen Posts: 6,417
    edited 2010-01-08 - 06:10:02
    In principle, using RCtime should be the same as using an ADC. Instead of a table of voltages at a number of temperature points, you construct a table of RCtime values at the temperature points, then in operation do a table lookup and interpolation. As a practical matter though, RCtime does not have very good accuracy or stability, due to uncertainties in the Stamp threshold and the capacitor value, so it becomes necessary to do individual calibration and to live with calibration drift. The method using an ADC can pretty much rely on the simple math and the accuracy of the ADC and the fixed resistor. So which do you want, the rock bottom price of RCtime, with complications, or a few bucks and board area with minimal headaches? I think RCtime is great for low resolution measurements without stringent accuracy requirements. {An aside, the sigma-delta converter on a Prop pin could do it without a dedicated ADC.}

    It might be possible to implement the Steinhart-Hart equations on the Stamp, but I wouldn't want to tackle it. It involves the natural log and the natural log cubed of the resistance of the thermistor, added up with the specific coefficients to give the inverse of temperature. Not an easy thing to do on the Stamp. And PBASIC still has to calculate the resistance given a voltage divider, so there is more chance for cumulative error. I'd much rather do it as a direct table lookup with interpolation, and let Excel do the heavy lifting in advance.

    Tracy Allen
  • kf4ixmkf4ixm Posts: 529
    edited 2010-01-08 - 15:19:16
    Makes perfect sense! thanks! i was thinking of using a thermistor in a cabinet enclosure A/C controller using just rctime, acurracy would only need to be within 2-5 deg f. i think im gonna use an a/d converter now after some thought, probably a dual channel because i want to add a humidity sensor also.
  • Tracy AllenTracy Allen Posts: 6,417
    edited 2010-01-08 - 17:12:59
    If you want humidity also, the SHT11 is a good way to go. The temperature and humidity and ADC are al built into the one chip with digital interface.

    Tracy Allen
  • Beau SchwabeBeau Schwabe Posts: 6,417
    edited 2010-01-09 - 00:13:44
    A "decent" linear interpolation can also be achieved by placing a 10K resistor in parallel to the Thermistor and taking resistive measurements that way.

    Consequently you can also place a "virtual" 10K resistor in parallel with the Thermistor and mathematically calculate it in software.

    R = 1 / [noparse][[/noparse] (1/Rt) + (1/10K) ]

    Rt is the Thermistor resistance value
    R is the linear resistance value

    In the Attached Image, Rt is the 'top' resistance graph, while R is the 'bottom' resistance graph with a 10K resistor in parallel to the Thermistor.

    []Beau Schwabe[/url]

    IC Layout Engineer
    Parallax, Inc.

    Post Edited (Beau Schwabe (Parallax)) : 1/9/2010 7:30:18 AM GMT
    904 x 832 - 155K
  • kf4ixmkf4ixm Posts: 529
    edited 2010-01-13 - 22:03:14
    Thanks for the info Beau! and i will have to get me one of those SHT11's to test out, they seem to be exactly what i need, thanks Tracy.
  • SleetSleet Posts: 1
    edited 2011-03-23 - 17:01:22
    I'm attaching two files, one a BS2pe program (which can run in other Stamps too), and an Excel spreadsheet.


    Thanks for the spreadsheet you provided. I've been taking a look at it but was wondering what would be needed if I wanted to modify this to an different thermistor.

    I have the was looking at using the the 2904 epcos (link) which is 10k Ohms @ 25 Deg C. I wonder if I just changed the given data points, source voltage and the resister in series with the Thermistor if I would be good to use your excel sheet. Or is there something else I would need to consider like insert the B 25 / 100 or anything like that?

    thanks in advance

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 22,524
    edited 2011-03-23 - 17:17:47
    'Just came across this thread. Here's some additional info -- especially the part about linearization -- that could be useful:

  • Tracy AllenTracy Allen Posts: 6,417
    edited 2011-03-23 - 19:35:14
    Hi J,

    You should be able to use that spreadsheet. Alter the column of resistance to match your thermistor found in the table under type 2904. E.g, next to 25 degrees Celsius enter 10000 Ohms, next to 30 °C enter 7942 Ω and so on. And enter your reference resistor and excitation voltage. The program creates the DATA table that is used by the Stamp program to interpolate temperature in units of 0.1 °C. The program is set up to start at -40 °C.

    That thermistor has tolerance of +/-5% or +/-10%. If you measure your thermistor at 25°C and find that it is 9500Ω instead of 10000Ω, then put 9500 next to 25 Celsius in the spreadsheet, and adjust all the resistance values in the spreadsheet by the same proportion. Note that 500Ω amounts to about 1 °C error if you don't bother to correct that. The table method can also be used in conjunction with one of the linearization techniques.

    The B parameter is the basis of a math approximation to the thermistor curve. The B formula for a Excel would be:
    Resistance =10000*EXP(4300*(1/(degC+273) - 1/(25+273)))
    That gives resistance vs temperature, but remember that it is in fact an approximation (worse than the Steinhart-Hart formula) and the values you read from the table will be a better fit to the true performance. For fun you can enter the formula and compare with the values from the table.
  • kociejskokociejsko Posts: 1
    edited 2019-11-20 - 10:52:01
    For PTC thermistor connected to ground my code looks like below :
    #define RBIAS_OHM           20000
    #define ADCRES_BITS         12
    #define PTC_ADC(r)          ( (r << ADCRES_BITS) / (r + RBIAS_OHM) )
    #define ARRAY_ELEMENTS(a)   ( sizeof(a)/sizeof(a[0]) )
    typedef struct
        uint16_t adc;
        int16_t temp;
    } PtcArrayType;
    static const PtcArrayType ptcArray[] =
        { PTC_ADC(6508),  -40 },
        { PTC_ADC(6717),  -35 },
        { PTC_ADC(6937),  -30 },
        { PTC_ADC(7165),  -25 },
        { PTC_ADC(7404),  -20 },
        { PTC_ADC(7651),  -15 },
        { PTC_ADC(7906),  -10 },
        { PTC_ADC(8170),   -5 },
        { PTC_ADC(8442),    0 },
        { PTC_ADC(8722),    5 },
        { PTC_ADC(9010),   10 },
        { PTC_ADC(9305),   15 },
        { PTC_ADC(9607),   20 },
        { PTC_ADC(9916),   25 },
        { PTC_ADC(10233),  30 },
        { PTC_ADC(10557),  35 },
        { PTC_ADC(10888),  40 },
        { PTC_ADC(11226),  45 },
        { PTC_ADC(11571),  50 },
        { PTC_ADC(11923),  55 },
        { PTC_ADC(12283),  60 },
        { PTC_ADC(12651),  65 },
        { PTC_ADC(13026),  70 },
        { PTC_ADC(13409),  75 },
        { PTC_ADC(13800),  80 },
        { PTC_ADC(14200),  85 },
        { PTC_ADC(14609),  90 },
        { PTC_ADC(15026),  95 },
        { PTC_ADC(15453), 100 },
        { PTC_ADC(15890), 105 },
        { PTC_ADC(16338), 110 },
        { PTC_ADC(16796), 115 },
        { PTC_ADC(17265), 120 },
        { PTC_ADC(17746), 125 }
    static int16_t GetTemperatureFromAdc(uint16_t adc)
        uint8_t i;
        if(adc <= ptcArray[0].adc)
            return ptcArray[0].temp;
        for(i=1; i < ARRAY_ELEMENTS(ptcArray); i++)
          if(adc < ptcArray[i].adc)
              return ((ptcArray[i].temp - ptcArray[i-1].temp)*(adc - ptcArray[i-1].adc)) / (ptcArray[i].adc - ptcArray[i-1].adc) + ptcArray[i-1].temp;
        return ptcArray[i-1].temp;

    For NTC it will require modification of array or function.
    It depends if it is NTC or PTC and if it is connected to + or - .
    The simplest way is to reverse array order with entries to keep ascending trend of .adc value ( then .temp values will go descending )
    Second solution is to connect NTC to + and modify PTC_ADC(r) macro.
    PTC_ADC(r) - macro assuming that ADC reference voltage is the for R + PTC circuit supply.
    Preprocessor will calculate correct values of ADC for given resistance value from PTC datasheet.
  • @kociejsko let me be the first to welcome you the forum!

    As an aside, this is an 8 year old thread. This isnt to say your code contribution is unlikely to help someone, someday, but the immediate need has passed. Come join us in a current thread!
Sign In or Register to comment.