NTC routine problems - beginners level

Hi,

Been using this NTC code from the Adafriut site and initially it worked ok using the default NUMSAMPLES.

However to increase its stability I increased the value to 255, but then the result became strange, instead of increasing the temperature by 0.1c it would show an increase of 0.2 or 0.3c

I reverted back to a lower NUMSAMPLEs value of 16 and it returns to correct result again.

Looking at the code they all seem to be valid data types and able to handle to values used, but think somewhere there must be something wrong, but as yet cannot see where ?

Another point about this type of “steinhart” conversion is that when the ntc used does not give exactly the same temp as that measured, how can it be made to give the correct temperature reading.

On my old Pic based system the 10K fixed resistor is replaced with a variable type to allow such calibration, would this upset the steinhart method ?
Would it be better to use a simple software value to correct/calibrate the result instead .

/*
 * NTC_Sensor.ino
 *
 * Created: 7/6/2015 10:51:07 AM
 
 */ 
    // 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 255
    // The beta coefficient of the thermistor (usually 3000-4000)
    #define BCOEFFICIENT 3950
    // the value of the 'other' resistor
    #define SERIESRESISTOR 10000
    
    int samples[NUMSAMPLES];
    
    void setup(void) {
    Serial.begin(9600);
    analogReference(EXTERNAL);
    }
    
    void loop(void) {
    uint8_t i;
    float average;
    
    // take N samples in a row, with a slight delay
    for (i=0; i< NUMSAMPLES; i++) {
    samples[i] = analogRead(THERMISTORPIN);
    delay(250);
    }
    
    // average all the samples out
    average = 0;
    for (i=0; i< NUMSAMPLES; i++) {
    average += samples[i];
    }
    average /= NUMSAMPLES;
    
    Serial.print("Average analog reading ");
    Serial.println(average);
    
    // convert the value to resistance
    average = 1023 / average - 1;
    average = SERIESRESISTOR / average;
    Serial.print("Thermistor resistance ");
    Serial.println(average);
    
    float steinhart;
    steinhart = average / 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 to C
    
    Serial.print("Temperature ");
    Serial.print(steinhart);
    Serial.println(" *C");
    
    delay(1000);
    }

Anytime you use a floating point number in an expression that involves numeric constants, you should clearly indicate floating point constants are being used by appending ".0" to the constants. Therefore, the line:

    #define SERIESRESISTOR 10000
    average = 0;
    average = 1023 / average - 1;

// should be written:

  #define SERIESRESISTOR 10000.0
   average = 0.0;
   average = 1023.0 / average - 1.0;

Also, expressions that mix data types should use casts:

    average += samples[i];

  // should be:

    average += (float) samples[i];

There are other constants and expressions that need similar fixes. This may not solve your problem, but it won't hurt, either.

for (i=0; i< NUMSAMPLES; i++) {
    samples[i] = analogRead(THERMISTORPIN);
    delay(250);
    }

So with 255 samples, does the above take just over a minute to fill in the array? Allows for a fairly long time for temp to fluctuate. Also this:

analogReference(EXTERNAL);

Is that reference rock solid for the duration of filling in this array? If it is not, then you’re values will be dragged down/up.

econjack: Anytime you use a floating point number in an expression that involves numeric constants, you should clearly indicate floating point constants are being used by appending ".0" to the constants. Therefore, the line:

Thanks, that does seem to have done the trick, currently running on 255 passes and its returning correct looking results like the 16 passes did.

Am a beginner with C++ code and just coming back into things again after a break so my mind still tyring to remember what little I learnt last time :blush: , though not helped by this poor example from Adafriuts site

tammytam: So with 255 samples, does the above take just over a minute to fill in the array? Allows for a fairly long time for temp to fluctuate. Also this:

Is that reference rock solid for the duration of filling in this array? If it is not, then you're values will be dragged down/up.

Its used to control an aquarium and have used this 255 method to sample the temp over a 90 sec period to avoid any relay chatter. Always thought it better to sample with long delays between each sample over the 90 secs rather than do lots of samples in just a few seconds...?

Have used it this way for many years with a Pic controller ( Assembly code ) without fault, just trying to update the whole controller onto the ease (? !! ) of the C++ and the more available Arduino hardware.

Like on the Pic its currently running from the +5v rail, but with a 100nf across A0. Think using a choke/filter cap on the +5v line to the NTC would further reduce any interference; though on the finished project, like my old Pic it will be powered from an off board regulated psu.

Its running on a Mega2560 so external is the only option I think.