Arduino Measuring temperature with NTC – Steinhart-Hart Formula

From multiple experiences I have learned that digital sensors are not the most reliable when it comes to very important measurements related to the safety of a device.

Thermistors may not be as fast as a digital sensor and require more work and additional circuitry, but when safety is extremely important and you want a relatively inexpensive solution, analog sensors are unmatched!

So in projects that require maximum safety, I always use analog sensors!

To avoid headaches with technical details, I will not go into the mathematical details of the problem, I will only present below two useful functions, used for measuring temperature using Arduino as a microcontroller.

1) Steinhart–Hart model, using A, B, C parameters

// TPin = Analog Pin 
// THERMISTOR = NTC nominal value that is measured at 25*C
// R1 = R Serries
// A, B , C = the Steinhart–Hart coefficients, which vary depending on the type and model of thermistor and the temperature range of interest.

float f_ReadTemp_ThABC(byte TPin, long THERMISTOR, float R1, float A, float B, float C) {
 
  int Vo = analogRead(TPin);

  float Resistance = (1023 / (float)Vo) - 1;	           // for pull-up configuration
  float R2 = R1 / Resistance;
  
  float logR2 = log(R2);				   // Pre-Calcul for Log(R2)
  float T = (1.0 / (A + B*logR2 + C*logR2*logR2*logR2)); 
  T =  T - 273.15;					   // convert Kelvin to *C

  return T;
}

Example of use:

// ~~~~ analog IN ~~~~
#define THERMISTOR_CAZAN 3

// ~~~~~~ A,B,C ~~~~~~
#define A1 -0.2860629305E-03
#define B1 4.484292072E-04
#define C1 -8.321267622E-07  

...

pinMode(THERMISTOR_CAZAN, INPUT);

...
th_TC =  f_ReadTemp_ThABC(THERMISTOR_CAZAN, 22000, 4700, A1, B1, C1);  // 22k thermistor; ABC parameters were calculated using a digital precision sensor  !

2) and simplified function, using the B (beta) parameter:

// TPin = Analog Pin 
// THERMISTOR = NTC nominal value that is measured at 25*C
// R1 = R Serries
// BETA = the coefficient of the thermistor (3950 is a common value).
// TEMPNOMINAL = usual is 25 (*C)

float f_ReadTemp_Th(byte TPin, long THERMISTOR, float R1, float BETA, int TEMPNOMINAL) {
  
  int Vo = analogRead(TPin);

  float Resistance = (1023 / (float)Vo) - 1;	// for pull-up configuration
  float R2 = R1 / Resistance;
  
  float steinhart;
  steinhart = R2 / THERMISTOR;     		// (R/Ro)
  steinhart = log(steinhart);                  	// ln(R/Ro)
  steinhart /= BETA;                   		// 1/B * ln(R/Ro)
  steinhart += 1.0 / (TEMPNOMINAL + 273.15); 	// + (1/To)
  steinhart = 1.0 / steinhart;                 	// Invert
  steinhart -= 273.15;     			// convert Kelvin to *C
  return steinhart;
}

Example of use:

// ~~~~ analog IN ~~~~
#define THERMISTOR_PUFER_SUS 4
#define THERMISTOR_PUFER_JOS 5

...

pinMode(THERMISTOR_PUFER_SUS, INPUT);
pinMode(THERMISTOR_PUFER_JOS, INPUT);  

...

/* ~~~ analog, thermistor read ~~~ */      
th_TP_up =   f_ReadTemp_Th(THERMISTOR_PUFER_SUS, 21499, 4700, 4250, 25);  // 22k thermistor
th_TP_down = f_ReadTemp_Th(THERMISTOR_PUFER_JOS, 10000, 4700, 4150, 25);  // 10k thermistor

Note: For real use, several measurements must be made, otherwise there is a possibility that the results may not be as expected, especially due to parasites on the cables that connect the thermistor to the controller. In fact, the connection circuit should also contain an RC filter for electronic noises!

Below is a useful function for multiple analog measurements and get the median value (not the average value)  also written for Arduino:

/* ~~~~~~~~~~~ Median sorting function ~~~~~~~~~~~ */
// by Emilian Robert Vicol , https://robertvicol.com/ 
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 
#define READ_MEDIAN_COUNT 15
#define READ_MEDIAN_DELAY 2

void isort(int *a, int n)
{
 for (int i = 1; i < n; ++i)
 {
   int j = a[i];
   int k;
   for (k = i - 1; (k >= 0) && (j < a[k]); k--)
   {
     a[k + 1] = a[k];
   }
   a[k + 1] = j;
 }
}

/* ~~~~~~ analog reading median value from port ~~~~~~*/
// by Emilian Robert Vicol , https://robertvicol.com/ 
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 
int analogReadMedian(int port)
{
  int values[READ_MEDIAN_COUNT];
  for(int i =0; i != READ_MEDIAN_COUNT; ++i)
  {
    values[i] = analogRead(port);
    delay(READ_MEDIAN_DELAY);
  }
  isort(values, READ_MEDIAN_COUNT);
  return values[READ_MEDIAN_COUNT / 2 + 1];
}

Also experimentally I noticed that the median value is much better than the average value, especially if the connection cable between the sensor and the microcontroller is very long, 10m or even longer, up to 20m.

*** The average of multiple measurements can generate values even outside the measurement scale! 

Conclusion: Consequently, for such projects always use the median value, not the average of the values.

byrev Written by:

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *