# Optimization and simplification of the NTC Thermistor class

I have made some optimization and simplification of the NTC thermistor class. The first optimization is realizing and implementing the fact that we are not really interested in the absolute voltage at the center of the divider but rather the ratio of that voltage and the reference voltage. The operation of an ADC is such that the output gives that ratio that we are interested in, therefore it is completely unnecessary to measure Vdda. Second, I carried the design assumption that the bias resistor is equal to the nominal thermistor resistance to its ultimate conclusion and realized that there is no need to know the nominal or measured thermistor resistance since the calculations only rely on the ratio of the nominal and measured thermistor resistance. Finally, I added a short delay between the measurements that make up the averaging calculation to allow the ADC capacitance time to recharge, this should improve accuracy. To keep the code readable I renamed vtherm to vrat in the calculations. Here is the modified class, I would gratefully allow it to be merged into the github.

`class thermistor {

``````// thermistor constants are shown on your thermistor datasheet
// beta value (for the temp range your device will operate in)
b_therm = null;
t0_therm = null;

p_therm = null;

high_side_therm = null;

constructor(pin, b, t0, points = 10, _high_side_therm = true) {
this.p_therm = pin;
this.p_therm.configure(ANALOG_IN);

// force all of these values to floats in case they come in as integers
this.b_therm = b * 1.0;
this.t0_therm = t0 * 1.0;
this.points_per_read = points * 1.0;

this.high_side_therm = _high_side_therm;
}

// read thermistor in Kelvin
local vrat_raw = 0;
for (local i = 0; i < points_per_read; i++) {
imp.sleep(0.001); // sleep to allow thermistor pin to recharge
}
local v_rat = vrat_raw / (points_per_read * 65535.0);

local ln_therm = 0;
if (high_side_therm) {
ln_therm = math.log(v_rat / (1.0 - v_rat));
} else {
ln_therm = math.log((1.0 - v_rat) / v_rat);
}

return (t0_therm * b_therm) / (b_therm - t0_therm * ln_therm);
}

// read thermistor in Celsius
return this.read() - 273.15;
}

// read thermistor in Fahrenheit
return ((this.read() - 273.15) * 9.0 / 5.0 + 32.0);
}
``````

}
`

— edit fixed vratio to vrat in description to match actual code

Nice work! I’ll take it for a spin on some of my devices.

Would you like to submit a pull request on the thermistor class?

Thanks,

-Tom

Tom,

Yes I would like to submit a pull request on the Thermistor class. What needs to be done to set this up.

Thanks,
Glen

I believe the easiest way is to fork the thermistor class file from the EI GitHub account to your own, then you can submit a pull requests from there. If there is an easier way, please share.

Done. I needed to fork the whole Reference repository, but it was easy to do all in the web interface.

I’m a bit curious about “allow the ADC capacitance time to recharge”. I’ve been averaging a number of samples, as many as 200, in a (very) tight loop. Is it recommended that I introduce a 1 millisecond delay between readings to improve ADC accuracy? This could explain some of the variations I’m seeing.

I’ve taken a very different approach to calculating temperatures by loading the temperature-resistance tables from Precon (or wherever) and then interpolating based upon calculated resistance. Yes, this isn’t as elegant, but the calculated temperatures have seemed to be a whole lot more “accurate” than my previous Steinhart-Hart calculations. I also experienced problems getting the coefficients from suppliers. And yes, getting these tables isn’t always easy!

The ADC in the STM32 series is a 14 bit SAR (sucsessive appoximation). It works by charging 14 small capcitors and then comparing the voltage on each with a fraction on the reference voltage. Attached is an application note about the STM32 ADC that should help you.

Thanks for passing that along!