Playground.arduino.cc will be read-only starting December 31st, 2018. For more info pleae look at this Forum Post

This is a function I wrote to convert the value from an analogRead call of a pin with a thermistor connected to it to a temperature. Unlike most other programs that use a look-up table, this function utilizes the Steinhart-Hart Thermistor Equation to convert "Thermistor Resistance" to "Temperature in Degrees Kelvin." I found the equation here, but it can also be found at Wikipedia.

The more simple program shows how little code is necessary to do the conversion, and how much memory and program space can be saved when compared to a large look-up table.

The more elaborate program shows the power of the function. It displays lots of data including the ADC (from 0 to 1023), the voltage on the analog pin (note: ideally, the arduino would be running at 5.0 volts, but my power supply gives it 4.86 volts, so I divide by 4.86. Look at the code to change that to whatever your power supply is giving), the resistance of the Thermistor, and the temperature in Celsius and Fahrenheit. It uses the printDouble routine which I found in a forum post here.

I hope this comes in handy for everyone. Like most of my code, it's freely usable and modifiable, and no credit is needed. Free, like arduino should be.

# Thermistor Test Schematic

``` (Ground) ---- (10k-Resistor) -------|------- (Thermistor) ---- (+5v)
|
Analog Pin 0
```

# The Simple Code

%box%[@
#include <math.h>

double Temp;
//         =log(10000.0/(1024.0/RawADC-1)) // for pull-up configuration
Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp ))* Temp );
Temp = Temp - 273.15;            // Convert Kelvin to Celcius
Temp = (Temp * 9.0)/ 5.0 + 32.0; // Convert Celcius to Fahrenheit
return Temp;
}

void setup() {
Serial.begin(115200);
}

void loop() {
delay(100);
}

# The Elaborate Code

#include <math.h>
//Schematic:
// [Ground] ---- [10k-Resistor] -------|------- [Thermistor] ---- [+5v]
//                                                             |
//                                                     Analog Pin 0

// Inputs ADC Value from Thermistor and outputs Temperature in Celsius
//  requires: include <math.h>
// Utilizes the Steinhart-Hart Thermistor Equation:
//    Temperature in Kelvin = 1 / {A + B[ln(R)] + C[ln(R)]^3}
//    where A = 0.001129148, B = 0.000234125 and C = 8.76741E-08
long Resistance;  double Temp;  // Dual-Purpose variable to save space.
Resistance=10000.0*((1024.0/RawADC) - 1);  // Assuming a 10k Thermistor.  Calculation is actually: Resistance = (1024 /ADC -1) * BalanceResistor
// For a GND-Thermistor-PullUp--Varef circuit it would be Rtherm=Rpullup/(1024.0/ADC-1)
Temp = log(Resistance); // Saving the Log(resistance) so not to calculate it 4 times later. // "Temp" means "Temporary" on this line.
Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp * Temp));   // Now it means both "Temporary" and "Temperature"
Temp = Temp - 273.15;  // Convert Kelvin to Celsius                                         // Now it only means "Temperature"

// BEGIN- Remove these lines for the function not to display anything
Serial.print(", Volts: "); printDouble(((RawADC*4.860)/1024.0),3);   // 4.860 volts is what my USB Port outputs.
Serial.print(", Resistance: "); Serial.print(Resistance); Serial.print("ohms");
// END- Remove these lines for the function not to display anything

// Uncomment this line for the function to return Fahrenheit instead.
//Temp = (Temp * 9.0)/ 5.0 + 32.0; // Convert to Fahrenheit
return Temp;  // Return the Temperature
}

void printDouble(double val, byte precision) {
// prints val with number of decimal places determine by precision
// precision is a number from 0 to 6 indicating the desired decimal places
// example: printDouble(3.1415, 2); // prints 3.14 (two decimal places)
Serial.print (int(val));  //prints the int part
if( precision > 0) {
Serial.print("."); // print the decimal point
unsigned long frac, mult = 1;
while(precision--) mult *=10;
if(val >= 0) frac = (val - int(val)) * mult; else frac = (int(val) - val) * mult;
unsigned long frac1 = frac;
Serial.print(frac,DEC) ;
}
}

void setup() {
Serial.begin(115200);
}

#define ThermistorPIN 0   // Analog Pin 0
double temp;
void loop() {
Serial.print(", Celsius: "); printDouble(temp,3);     // display Celsius
temp = (temp * 9.0)/ 5.0 + 32.0;                      // converts to Fahrenheit
Serial.print(", Fahrenheit: "); printDouble(temp,3);  // display Fahrenheit
Serial.println("");                                   // End of Line
delay(100);                                           // Delay a bit... for fun, and to not Serial.print faster than the serial connection can output
}
@]%%

# The Elaborate Code (cleaned up a bit)

I have taken the liberty of cleaning the code up a bit for more modern versions of the arduino core - printDouble() is not necessary. I have also converted all the doubles to floats because the core only works in floats, but honours the completely useless casts to and from doubles. Altogether this saves ~400 bytes and makes it run a bit faster. I hope the comments make it slightly clearer what is going on.

/*
* Inputs ADC Value from Thermistor and outputs Temperature in Celsius
*  requires: include <math.h>
* Utilizes the Steinhart-Hart Thermistor Equation:
*    Temperature in Kelvin = 1 / {A + B[ln(R)] + C[ln(R)]3}
*    where A = 0.001129148, B = 0.000234125 and C = 8.76741E-08
*
* These coefficients seem to work fairly universally, which is a bit of a
* surprise.
*
* Schematic:
*   [Ground] -- [10k-pad-resistor] -- | -- [thermistor] --[Vcc (5 or 3.3v)]
*                                               |
*                                          Analog Pin 0
*
* In case it isn't obvious (as it wasn't to me until I thought about it), the analog ports
* measure the voltage between 0v -> Vcc which for an Arduino is a nominal 5v, but for (say)
* a JeeNode, is a nominal 3.3v.
*
* The resistance calculation uses the ratio of the two resistors, so the voltage
* specified above is really only required for the debugging that is commented out below
*
*
* I have used this successfully with some CH Pipe Sensors (http://www.atcsemitec.co.uk/pdfdocs/ch.pdf)
* which be obtained from http://www.rapidonline.co.uk.
*
*/

#include <math.h>

#define ThermistorPIN 0                 // Analog Pin 0

float vcc = 4.91;                       // only used for display purposes, if used
// set to the measured Vcc.
float thermr = 10000;                   // thermistor nominal resistance

long Resistance;
float Temp;  // Dual-Purpose variable to save space.

Temp = log(Resistance); // Saving the Log(resistance) so not to calculate  it 4 times later
Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp * Temp));
Temp = Temp - 273.15;  // Convert Kelvin to Celsius

// BEGIN- Remove these lines for the function not to display anything
//Serial.print("/1024");                           // Print out RAW ADC Number
//Serial.print(", vcc: ");
//Serial.print(vcc,2);
//Serial.print(" Kohms, Volts: ");
//Serial.print(", Resistance: ");
//Serial.print(Resistance);
//Serial.print(" ohms, ");
// END- Remove these lines for the function not to display anything

// Uncomment this line for the function to return Fahrenheit instead.
//temp = (Temp * 9.0)/ 5.0 + 32.0;                  // Convert to Fahrenheit
return Temp;                                      // Return the Temperature
}

void setup() {
Serial.begin(115200);
}

void loop() {
float temp;
Serial.print("Celsius: ");
Serial.print(temp,1);                             // display Celsius
//temp = (temp * 9.0)/ 5.0 + 32.0;                  // converts to  Fahrenheit
//Serial.print(", Fahrenheit: ");
//Serial.print(temp,1);                             // display  Fahrenheit
Serial.println("");
delay(5000);                                      // Delay a bit...
}

# Another way to get temperature, based on the idea/code above.

We have found 10k thermistor and wired it with 10k balance resistor as mentioned above.Our thermistor is episco k164. We have wrote function for temperature reading which covers 3 major temperature scales.

#include <math.h>
// enumerating 3 major temperature scales
enum {
T_KELVIN=0,
T_CELSIUS,
T_FAHRENHEIT
};

// manufacturer data for episco k164 10k thermistor
// simply delete this if you don't need it
// or use this idea to define your own thermistors
#define EPISCO_K164_10k 4300.0f,298.15f,10000.0f  // B,T0,R0

// Temperature function outputs float , the actual
// temperature
// Temperature function inputs
// 2.OuputUnit - output in celsius, kelvin or fahrenheit
// 3.Thermistor B parameter - found in datasheet
// 4.Manufacturer T0 parameter - found in datasheet (kelvin)
// 5. Manufacturer R0 parameter - found in datasheet (ohms)
// 6. Your balance resistor resistance in ohms

float Temperature(int AnalogInputNumber,int OutputUnit,float B,float T0,float R0,float R_Balance)
{
float R,T;

T=1.0f/(1.0f/T0+(1.0f/B)*log(R/R0));

switch(OutputUnit) {
case T_CELSIUS :
T-=273.15f;
break;
case T_FAHRENHEIT :
T=9.0f*(T-273.15f)/5.0f+32.0f;
break;
default:
break;
};

return T;
}
// example of use #1
// and 10k balance, getting result in celsius

void setup() {
Serial.begin(9600);
}

void loop() {

Serial.println("*************************");
Serial.println("10k Balance");
Serial.println(Temperature(1,T_CELSIUS,EPISCO_K164_10k,10000.0f));
Serial.println("*************************");

delay(500);
}

//example of use #2
// using numbers instead of episco k164 definition
// getting result in fahrenheit

void setup() {
Serial.begin(9600);
}

void loop() {

Serial.println("*************************");
Serial.println("10k Balance");
Serial.println(Temperature(2,T_FAHRENHEIT,4300.0f,298.15f,10000.0f,10000.0f));
Serial.println("*************************");

delay(500);
}

That's it, Milan Malesevic and Zoran Stupic 2011.