2
\$\begingroup\$

I'm using the analog input on the Controllino Maxi Automation to determine the temperature of a 10K NTC thermistor. I'm having some difficulty understanding how the ADC works.

On a regular arduino nano, this code from Adafruit works okay, only off by a degree. But on the Controllino it's off by anywhere between 6-10 degrees. Fine tuning the parameters (temp @25C, series resistor and B coff) doesn't help at all.

Looking at the documentation they mention a scaling factor (last couple lines in the image below) but I'm not sure how to apply it or what it means.

enter image description here

I assume this means I can't just convert straight from an ADC value into a voltage reading?

#include <Arduino.h>
#include <Controllino.h>

// which analog pin to connect
#define THERMISTORPIN A0         
// resistance at 25 degrees C
#define THERMISTORNOMINAL 10000      
// temp. for nominal resistance (almost always 25 C)
#define TEMPERATURENOMINAL 25   
// how many samples to take and average, more takes longer
// but is more 'smooth'
#define NUMSAMPLES 5
// The beta coefficient of the thermistor (usually 3000-4000)
#define BCOEFFICIENT 3895 // datasheet - https://www.mouser.com/datasheet/2/240/Littelfuse_Thermistor_Probes_Assemblies_Threaded_U-1372560.pdf
// the value of the 'other' resistor
#define SERIESRESISTOR 9760 
 
void setup(void) {
  Serial.begin(921600);
}
 
void loop(void) {
  float reading;
 
  reading = analogRead(THERMISTORPIN);
 
  Serial.print("Analog reading "); 
  Serial.println(reading);
 
  // convert the value to resistance
  reading = (1023/ reading)  - 1;     // (1023/ADC - 1) 
  reading = SERIESRESISTOR / reading;  // 10K / (1023/ADC - 1)
  Serial.print("Thermistor resistance ");   
  Serial.println(reading);
 
  float steinhart;
  steinhart = reading / THERMISTORNOMINAL;     // (R/Ro)
  steinhart = log(steinhart);                  // ln(R/Ro)
  steinhart /= BCOEFFICIENT;                   // 1/B * ln(R/Ro)
  steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
  steinhart = 1.0 / steinhart;                 // Invert
  steinhart -= 273.15;                         // convert absolute temp to C
  
  Serial.print("Temperature "); 
  Serial.print(steinhart);
  Serial.println(" *C");

  delay(1000);
}

schematic

The schematic editor didn't have the thermistor symbol just btw

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Show us the exact actual code you are using for the conversion and provide a schematic of how you have connected the thermistor to the analog input. \$\endgroup\$ Apr 16 at 14:47
  • 1
    \$\begingroup\$ @ElliotAlderson added! \$\endgroup\$
    – Simeon R
    Apr 16 at 15:33
5
\$\begingroup\$

The "scaling factor" referred to in the linked page is related to how you calculate the ADC voltage from the raw ADC number that the Arduino gives you.

Your algorithm never calculates the voltage, so you don't need to worry about that.

Your algorithm uses a proportional calculation to go straight from the raw ADC value to the NTC resistance without ever needing to know the voltage. All it needs is the ratio of the ADC value to the ADC range and the value of the external series resistor.

The external series resistor and the 24V supply are the cause of your problems.

You need to look into self heating in NTC thermistors.

The current through the series resistor and the NTC causes the NTC itself to heat up.

This chart from the TI document linked to above shows the problem quite clearly:

enter image description here

That dotted red line with the big hump is the problem you are seeing.

Yours is probably worse since you are using 24V rather than just 12V.

A larger series resistor would reduce the self heating and reduce the error.

It would also cause more noise in the readings and reduce the range over which the ADC values are measured. With the resistor values you are using, you can expect ADC values between 0 and 512. If you increased the series resistor to 100k (factor of 10) then you would only see ADC values from 0 to 51, greatly decreasing the precision.

Your options are:

  1. Account for self heating in code (attempt to calibrate away that big ugly hump.)
  2. Use a larger series resistor to reduce the error.
  3. Use a PTC thermistor instead of the NTC. The calibration is then fairly simple - a constant to be subtracted from the calculated temperature.

I don't know how you'd do (1.) (3) requires you to purchase a new thermistor, which you might not be able to do.

(2) has some down sides, but you can turn one of the disadvantages into a useful thing.

The first disadvantage to (2) is that it will reduce the effective number of bits you will receive - your measurements will have bigger "steps."

The second disadvantage is that the readings will be noiser.

What I'd do (for hobby stuff, anyway) is to increase the series resistor to 100k. That reduces the self heating by a factor of 10. That goes from an error of 10 degree to an error of 1 degree.

Since it is now noisier, I'd oversample and average the ADC values. Averaging reduces the noise, but the combination of oversampling with noise gains you back some of those lost bits of resolution.

That factor of 10 is about equivalent 3 to 4 bits of resolution.

If you oversample, average and decimate by a factor of 256, then you will gain 4 bits of resolution, bringing your resolution back up to about what it was with the original circuit.

  1. Read the ADC 256 times, summing the values in a large integer.
  2. Convert the sum to a float and divide by 256. (Assign to "reading" - but "reading" must be a float.)
  3. Continue with the rest of your algorithm.

That will get you a more accurate temperature reading. There will still be some error from the self heating, but it will be much smaller than before.

You may need to put a capacitor in parallel with the NTC to reduce some of the noise before it gets to the ADC and to reduce the impedance of the NTC circuit so that the ADC doesn't "pull" it away from the correct value. Some noise is good, too much is bad.

\$\endgroup\$
4
  • \$\begingroup\$ Wow thanks a lot! I'll definitely try that. What value of capacitor do you suggest? \$\endgroup\$
    – Simeon R
    Apr 16 at 16:35
  • \$\begingroup\$ I'd probably start with a 100nF capacitor. \$\endgroup\$
    – JRE
    Apr 16 at 16:39
  • \$\begingroup\$ I've dropped the supply voltage to 5V and I still have the same issue, I'll open a new question and link it here \$\endgroup\$
    – Simeon R
    Apr 16 at 16:59
  • \$\begingroup\$ electronics.stackexchange.com/questions/560572/… . I'd be really happy if you could take a look \$\endgroup\$
    – Simeon R
    Apr 16 at 17:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.