Author Topic: [AVR] reading thermistors  (Read 3416 times)

0 Members and 1 Guest are viewing this topic.

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
[AVR] reading thermistors
« on: July 05, 2018, 01:03:31 pm »
For a long time my method of dealing with thermistors has been to use a series resistor that sort of gets me a linear response in the area i am interested in. This of course has severe limitations.

So I am looking to just use the thermistor formula to calculate the temperature based on the resistance. I have come across the attached, would this all work in GCC/AVR land? seem's I just need to add the relevant *.C file to my project and call the function when I want the temperature from the calculated resistance.
 

Offline darrylp

  • Regular Contributor
  • *
  • Posts: 127
  • Country: gb
Re: [AVR] reading thermistors
« Reply #1 on: July 05, 2018, 01:09:15 pm »
To use on an avr processor ? That's a huge lib. Many avr are very limited on program space. Surely a better quick 8 bit based lib would be better, or do you need high accuracy ? In which case use a proper temp device that can talk i2c or give a linear output might be better ?

Sent from my HTC One using Tapatalk 2

 

Offline firewalker

  • Super Contributor
  • ***
  • Posts: 2450
  • Country: gr
Re: [AVR] reading thermistors
« Reply #2 on: July 05, 2018, 01:21:29 pm »
No need for a library. Just solve the Steinhart-Hart equation for temperature.




Code: [Select]
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>




// R2 exact value.
#define R2 9988.0
// NTC value at 25 degrees C.
#define Rn 10000.0

/*
    Vcc
     |
     |
     /
     \
     /  NTC_Res
     \
     /
     |
     |--------ADC_in
     |
     /
     \
     /  R2
     \
     /
     |
     |
    GND

    NTC_Res = (1024*R2)/ADC - R2

*/


// A, B, C and D are NTC coefficient.
#define A 0.003354016
#define B 0.000256985
#define C 0.000002620131
#define D 0.00000006383091

double adc2temp(int RawADC) {

    double NTC_Res, celsius;
    double tmp;                 // temporary variable.

    NTC_Res=((1024 * R2 / RawADC) - R2);

    tmp = log(NTC_Res/Rn);

    tmp = (A+(B*tmp)+(C*tmp*tmp)+(D*tmp*tmp*tmp));

    celsius = (1.0/tmp)-273;    // Celsius to Kelvin.


    return celsius;
}

Alexander.
Become a realist, stay a dreamer.

 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [AVR] reading thermistors
« Reply #3 on: July 05, 2018, 01:33:04 pm »
ok but i normally only ever get the beta value. I found this that makes short work of it: https://learn.adafruit.com/thermistor/using-a-thermistor
 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 3240
  • Country: gb
Re: [AVR] reading thermistors
« Reply #4 on: July 05, 2018, 01:47:21 pm »
You still need to put some current through the thermistor to measure it's resistance, and you might as well carry on doing this with a fixed resistor since this provides a decent amount of linearisation.  After that, just use a pre-calculated lookup table to convert your ADC value to a temperature - the linearisation provided by the resistor means you can get away with a fairly small table and use interpolation, which will be massively faster than trying to calculate temperature in real time via either the Beta equation or Steinhart-Hart.
 

Offline C

  • Super Contributor
  • ***
  • Posts: 1346
  • Country: us
Re: [AVR] reading thermistors
« Reply #5 on: July 05, 2018, 03:22:56 pm »

You could do a calibration run against a know good sensor and collect a lot of data.
then use a program to built a correction table.

Then between values of table you could possibility do a Least Squares fit

 

Offline Kalvin

  • Super Contributor
  • ***
  • Posts: 2145
  • Country: fi
  • Embedded SW/HW.
Re: [AVR] reading thermistors
« Reply #6 on: July 05, 2018, 04:01:40 pm »
Precomputed piece-wise linear lookup table might do the job with very little Flash/RAM without the floats.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [AVR] reading thermistors
« Reply #7 on: July 05, 2018, 04:25:58 pm »
You still need to put some current through the thermistor to measure it's resistance, and you might as well carry on doing this with a fixed resistor since this provides a decent amount of linearisation.  After that, just use a pre-calculated lookup table to convert your ADC value to a temperature - the linearisation provided by the resistor means you can get away with a fairly small table and use interpolation, which will be massively faster than trying to calculate temperature in real time via either the Beta equation or Steinhart-Hart.

So when did anyone say a series resistor was not being used. I do get some linearity with a resistor but I'd like a less adhoc method.

I could break it down into small sections and use a straight line every 10C. Code speed is not a problem.
 

Offline C

  • Super Contributor
  • ***
  • Posts: 1346
  • Country: us
Re: [AVR] reading thermistors
« Reply #8 on: July 05, 2018, 07:06:37 pm »

So when did anyone say a series resistor was not being used. I do get some linearity with a resistor but I'd like a less adhoc method.

I could break it down into small sections and use a straight line every 10C. Code speed is not a problem.

With some math you can replace the straight line fit with a curved line fit and possibility get a better answer with a smaller table.

As stated before if you have an ADC value that you can match to actual temperature the fit can get better.

Instead of sitting an taking a bunch of reading, the easy way is to use a CPU to compare actual temperature from a good calibrated temperature sensor to your ADC value and use this data to build table.
Not that hard to create a slow heat/slow cool chamber. This constant slow change even if not linear lets you get better comparison of values.
C
 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 3240
  • Country: gb
Re: [AVR] reading thermistors
« Reply #9 on: July 06, 2018, 11:45:44 am »
You still need to put some current through the thermistor to measure it's resistance, and you might as well carry on doing this with a fixed resistor since this provides a decent amount of linearisation.  After that, just use a pre-calculated lookup table to convert your ADC value to a temperature - the linearisation provided by the resistor means you can get away with a fairly small table and use interpolation, which will be massively faster than trying to calculate temperature in real time via either the Beta equation or Steinhart-Hart.

So when did anyone say a series resistor was not being used. I do get some linearity with a resistor but I'd like a less adhoc method.

I could break it down into small sections and use a straight line every 10C. Code speed is not a problem.

It's not an "adhoc" method, it's an absolutely standard way of using thermistors.  Code speed is not the only downside; drag in floating point libraries and the code size also bloats up significantly.  There is really no good reason to do this on an 8bit micro when a basic piece-wise linear interpolation will give you all the performance you need at a fraction of the code size and execution time, especially if you are using the on-board ADC.

Stick the thermistor parameters (Beta or Steinhart) into Excel and make yourself a table.  You can do some basic analysis to determine the error introduced for the number of points in your table.  FWIW I used this method on a Mega128 to control the temperature of a tunable laser to a resolution better than 0.01 Celsius (with a 16bit SPI ADC). IIRC the linearisation function took around 150 cycles without any special optimisations.

If you make the table hold temperatures in equal, power-of-two ADC intervals rather than equal temperature intervals then it makes the maths very easy and very fast.  The initial table lookup just requires the ADC value to be shifted right by the number of bits of your intervals size (e.g. 6 bits for an interval of 64LSBs) and used as the index into the table.  The power of two interval then makes the interpolation calculations fast and simple with only a single multiply required.
« Last Edit: July 06, 2018, 11:51:17 am by mikerj »
 

Offline firewalker

  • Super Contributor
  • ***
  • Posts: 2450
  • Country: gr
Re: [AVR] reading thermistors
« Reply #10 on: July 06, 2018, 12:07:28 pm »
Manufactures like Vishay have Excel files available to build the tables really quickly.

Alexander.
Become a realist, stay a dreamer.

 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [AVR] reading thermistors
« Reply #11 on: July 06, 2018, 01:06:50 pm »


It's not an "adhoc" method, it's an absolutely standard way of using thermistors.  Code speed is not the only downside; drag in floating point libraries and the code size also bloats up significantly.  There is really no good reason to do this on an 8bit micro when a basic piece-wise linear interpolation will give you all the performance you need at a fraction of the code size and execution time, especially if you are using the on-board ADC.

Stick the thermistor parameters (Beta or Steinhart) into Excel and make yourself a table.  You can do some basic analysis to determine the error introduced for the number of points in your table.  FWIW I used this method on a Mega128 to control the temperature of a tunable laser to a resolution better than 0.01 Celsius (with a 16bit SPI ADC). IIRC the linearisation function took around 150 cycles without any special optimisations.

If you make the table hold temperatures in equal, power-of-two ADC intervals rather than equal temperature intervals then it makes the maths very easy and very fast.  The initial table lookup just requires the ADC value to be shifted right by the number of bits of your intervals size (e.g. 6 bits for an interval of 64LSBs) and used as the index into the table.  The power of two interval then makes the interpolation calculations fast and simple with only a single multiply required.

Yes that is indeed what I think i will do, the change is R/C is not much over a few C so it would be fairly easy to do and like you say so much less resource hungry.
 

Online T3sl4co1l

  • Super Contributor
  • ***
  • Posts: 21677
  • Country: us
  • Expert, Analog Electronics, PCB Layout, EMC
    • Seven Transistor Labs
Re: [AVR] reading thermistors
« Reply #12 on: July 06, 2018, 01:07:31 pm »
Seven Transistor Labs, LLC
Electronic design, from concept to prototype.
Bringing a project to life?  Send me a message!
 
The following users thanked this post: firewalker

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [AVR] reading thermistors
« Reply #13 on: July 06, 2018, 01:12:51 pm »
Thanks Tim
 

Offline Gibson486

  • Frequent Contributor
  • **
  • Posts: 324
  • Country: us
Re: [AVR] reading thermistors
« Reply #14 on: July 12, 2018, 01:13:35 am »
Steinhart is fine on an AVR....until you start using an ADC greater than 12 bits. We used piece wise equations instead.  It worked well until we realized that we were talking to a computer, so why not just have the computer take care of the conversion.
 

Offline sleemanj

  • Super Contributor
  • ***
  • Posts: 3024
  • Country: nz
  • Professional tightwad.
    • The electronics hobby components I sell.
Re: [AVR] reading thermistors
« Reply #15 on: July 12, 2018, 01:34:48 am »
Some years ago I made a whole spreadsheet thing for generating NTC code including various different approximations charts so you can pick suitable ranges and so forth...

https://sparks.gogo.co.nz/ntc_thermistor.html

At the core it is Steinhart Beta equation (which is a derivation from Steinhart) and derivations or further linear approximation based on that including integer-math only approximations if you don't have room for floating point.

There is a lot of information there, but in essence, open the spreadsheet (make a copy), in the thermistor charcateristics change the Beta Value and nominal resistance as appropriate (if you don't know beta you can calculate it see the info in the green boxes), then set connection to either Vcc of Gnd (where the thermistor is connected) and choose the other resistor (other half of the divider), then you can right click the code in cell A45 and copy-paste it.  For the cheaper approximations set a range of temperatures you are most interested in in the Low and High C fields, and change fiddle about with the Multiplier and "Other Resistor" while watching the charts.
« Last Edit: July 12, 2018, 01:46:36 am by sleemanj »
~~~
EEVBlog Members - get yourself 10% discount off all my electronic components for sale just use the Buy Direct links and use Coupon Code "eevblog" during checkout.  Shipping from New Zealand, international orders welcome :-)
 

Offline sleemanj

  • Super Contributor
  • ***
  • Posts: 3024
  • Country: nz
  • Professional tightwad.
    • The electronics hobby components I sell.
Re: [AVR] reading thermistors
« Reply #16 on: July 12, 2018, 01:50:00 am »
For sake of simple example, for a 10k thermistor of beta 3950 with a 10k "other" resistor with the NTC on the low side (connected to Gnd), and a 10 bit ADC, my spreadsheet will poop out the following code (from which I have stripped comments for legibility)...

Code: [Select]
float  convertAnalogToTemperature(unsigned int analogReadValue)
{
  // If analogReadValue is 1023, we would otherwise cause a Divide-By-Zero,
  // Treat as crazy out-of-range temperature.
  if(analogReadValue == 1023) return 1000.0;
                                               
  return (1/((log(((10000.0 * analogReadValue) / (1023.0 - analogReadValue))/10000.0)/3950.0) + (1 / (273.15 + 25.000)))) - 273.15;
}


float  approximateTemperatureFloat(unsigned int analogReadValue)
{
  return -0.0917300598433493*analogReadValue+72.3197381920379;
}

int approximateTemperatureInt(unsigned int analogReadValue)
{
  return ((((((long)analogReadValue*64) / -698) * 64) + 4628) / 64) - 0;
}

~~~
EEVBlog Members - get yourself 10% discount off all my electronic components for sale just use the Buy Direct links and use Coupon Code "eevblog" during checkout.  Shipping from New Zealand, international orders welcome :-)
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [AVR] reading thermistors
« Reply #17 on: July 12, 2018, 07:21:54 am »
https://www.seventransistorlabs.com/Calc/Thermistor.html
/thread ;D

Tim

You lost me there as i don't have the practical understanding of the math. But peicewise linearization will do fine for my application.
 

Online T3sl4co1l

  • Super Contributor
  • ***
  • Posts: 21677
  • Country: us
  • Expert, Analog Electronics, PCB Layout, EMC
    • Seven Transistor Labs
Re: [AVR] reading thermistors
« Reply #18 on: July 12, 2018, 03:12:07 pm »
The article is lengthy, but example code appears at the bottom. :)

Piecewise interpolation is worse in all respects: it requires much more memory (lookup table), code and execution time (a division is required).  A polynomial fit is best suited to the AVR, because it has hardware multiply.

I suppose I should port the code to C some time, and also compare GCC's performance on the task.

Tim
« Last Edit: July 12, 2018, 03:13:43 pm by T3sl4co1l »
Seven Transistor Labs, LLC
Electronic design, from concept to prototype.
Bringing a project to life?  Send me a message!
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [AVR] reading thermistors
« Reply #19 on: July 12, 2018, 03:25:36 pm »
Basically I can have power of two intervals so I can have an array with the linear slope of a range of values, bit shifting the reading will give the index of the applicable slope value, multiply by it.
 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 3240
  • Country: gb
Re: [AVR] reading thermistors
« Reply #20 on: July 13, 2018, 06:26:29 am »
The article is lengthy, but example code appears at the bottom. :)

Piecewise interpolation is worse in all respects: it requires much more memory (lookup table), code and execution time (a division is required). 

Arrange the table with 2^x ADC intervals and the division can be performed by shifts.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf