# NTC linearization and implementation on a microcontroller

#### andrew74

Joined Jul 25, 2022
102
Hi.

I first made a classic resistive divider between an NTC with R0=10k at 25°C (connected to ground) and a resistor (connected to Vin=5V) and following these steps I derived the measured temperature T:
1) connecting the ends of the NTC to an analog pin on the Arduino Uno.
2) converting on the Arduino the digital value read into voltage (multiplying it by Vref/2^10)
3) derived from the partition equation Vntc=Vin*Rntc/(Rntc+R) the value of Rntc
4) put the "Rntc" value just derived into the nonlinear NTC equation Rntc=R0*e^b(1/T-1/T0) to find T (the actual measured temperature)

Clearly at T0=25°C the temperature is quite true, but when I use the NTC (in this configuration just described) in contact with a hot object (for example, the pot with hot water at 50°C) the thermperature read is even 3 or 4 degrees lower (I compared it with a classic kitchen thermometer) than the real termperature.
First quick question ... is the NTC appropriate for measuring the temperature of an object?
Or is it suitable for measuring the temperature of an environment?
(of the air)

Turning to the main issue of this post:
A friend of mine who works in the field (I am just an amateur!) told me that I need to take advantage of the NTC convertion table and implement it on the microcontroller.
I really don't know what this means ... can you explain to me what it is and how I should implement it?
Let's work together on this NTC ... which is what I have at my disposal (R0=10k at 25°C)

Thank you very much!

Last edited:

#### ericgibbs

Joined Jan 29, 2010
18,873
hi andrew,
E

#### Ian0

Joined Aug 7, 2020
9,847
You need a look-up table to get the temperature.
Input the value of B and your pullup resistor, and the resistance at 25°C. The outputs are in tenths of a degree.
Don't forget that most thermistors have quite a wide tolerance, and ±4°C might be good for an uncalibrated one.
If you have a better than 8-bit ADC, and want better accuracy, you can use a feedforward technique, or a bigger lookup table.

#### Attachments

• 34.3 KB Views: 7

#### andrew74

Joined Jul 25, 2022
102

#### andrew74

Joined Jul 25, 2022
102
You need a look-up table to get the temperature.
Input the value of B and your pullup resistor, and the resistance at 25°C. The outputs are in tenths of a degree.
Don't forget that most thermistors have quite a wide tolerance, and ±4°C might be good for an uncalibrated one.
If you have a better than 8-bit ADC, and want better accuracy, you can use a feedforward technique, or a bigger lookup table.

Done. What's next? I don't understand what this table is.
How did you make it?
What does it do?

#### Ian0

Joined Aug 7, 2020
9,847
If you save the output as .csv then cut and paste it into your code you have a look-up table. (It generates assembler. If you want C then delete the .hwords and put {} round it.
Take the 8 most significant bits from your ADC and use it as the index. Then load the value from the table. That is the temperature in tenths of degrees C

If you have a 12-bit ADC then use the most-significant 8-bits as the index. Then save the least significant 4-bits and add them to your next reading before you look it up.
Then IIR filter the results. That will increase your overall accuracy.

#### andrew74

Joined Jul 25, 2022
102
If you save the output as .csv then cut and paste it into your code you have a look-up table. (It generates assembler. If you want C then delete the .hwords and put {} round it.
Take the 8 most significant bits from your ADC and use it as the index. Then load the value from the table. That is the temperature in tenths of degrees C

If you have a 12-bit ADC then use the most-significant 8-bits as the index. Then save the least significant 4-bits and add them to your next reading before you look it up.
Then IIR filter the results. That will increase your overall accuracy.

put {} round it
First, thank you very much for your helpfulness. The table you provided is exactly what I would like to learn and do.

Yes, I need it in C.
I don't understand what you mean ... which of these 2 is correct?

In addition to these technical questions that I ask you (and I'll ask you step by step if it's not a problem) to actually implement this solution on the code ... I would also have some more "theoretical" questions ... for example how did you make this table.

#### andrew74

Joined Jul 25, 2022
102
If you save the output as .csv then cut and paste it into your code you have a look-up table. (It generates assembler. If you want C then delete the .hwords and put {} round it.
Take the 8 most significant bits from your ADC and use it as the index. Then load the value from the table. That is the temperature in tenths of degrees C

If you have a 12-bit ADC then use the most-significant 8-bits as the index. Then save the least significant 4-bits and add them to your next reading before you look it up.
Then IIR filter the results. That will increase your overall accuracy.
I think I figured it out a little bit by following this example:

On the left (in light blue) there are the data shown on the datasheet ... on the right the highlighted part can be copied and pasted directly into the code.
But how was the red column calculated?
You also did something like that ... right?

#### Ian0

Joined Aug 7, 2020
9,847
First, thank you very much for your helpfulness. The table you provided is exactly what I would like to learn and do.

Yes, I need it in C.
I don't understand what you mean ... which of these 2 is correct?
View attachment 296177

In addition to these technical questions that I ask you (and I'll ask you step by step if it's not a problem) to actually implement this solution on the code ... I would also have some more "theoretical" questions ... for example how did you make this table.
The equation for the resistance of an NTC thermistor is the Steinhart-Hart equation. A simplified version of it will usually suffice.
R/Ro = exp(B(1/T - 1/To))
where Ro and To are the values at 25°C, and B will (or should) be in the Thermistor datasheet.
Then V/Vo= Rt/(Rt+Rpullup)
where Vo is the supply voltage and Rt is the thermistor resistance.
You can think of Vo as being 256 or 4096 because that is the number your ADC will read.
This is a handy online calculator. If you know your thermistor resistance at three temperature values, but don't know B it will work out the coefficients.
The spreadsheet calculates T from V.
You have to choose Rpullup. It can be any value, but it works best if you choose Rpullup to be approximately equal to Rt at the sort of temperature you will be measuring (middle of the range of temperatures).

If you are working in C get rid of .hword altogether, it is required for assembler.
The csv file (Open it in a TEXT EDITOR) will then have lots of values followed by commas and C likes that.
All you have to do then for the compiler to be happy with it is to add
const int16_t celsius5k[]=
{
before the values and
};
after them.
Leave the rest in as it will be generated as comments by the "//" column.
I call it "celsius5k" because it has a 4.7k pullup resistor (maybe I should have called it "celsius4k7". I also use the same thermistor to measure higher temperatures, which requires a 1k pullup resistor and that table is called "celsius1k".
Perhaps those Americans are on to something using Fahrenheit - you can measure from -18°C to +124°C an an 8-bit unsigned number.

Last edited:

#### ericgibbs

Joined Jan 29, 2010
18,873
Hi,
For reference the Arduino , Mega, UNO, Nano are 10 Bit ADC, the ESP32 is 12 Bit, has very poor ADC linearity.

E

#### Ian0

Joined Aug 7, 2020
9,847
Hi,
For reference the Arduino , Mega, UNO, Nano are 10 Bit ADC, the ESP32 is 12 Bit, has very poor ADC linearity.

E
Thanks for telling me that. I use Renesas RA4M1 (14 bit) and NPC LPC15x (12bit) but the principle is the same. I still use an 8-bit table and interpolate. I wrote the spreadsheet some time ago . ...

#### andrew74

Joined Jul 25, 2022
102
Può essere qualsiasi valore, ma funziona meglio se scegli Rpullup in modo che sia approssimativamente uguale a Rt al tipo di temperatura che misurerai (metà dell'intervallo di temperature).
So, given my NTC with R0=10k at T0=25°C and beta=3977 (written on the datasheet, I don't need the online calculator but thanks anyway) and working in a range of thermperature=[25 ... 43]°C --> Tavg=34°C
$Rpullup=Rntc(34°C)=R0*e^{\beta(1/(273.15+34) - 1/(273.15+25))}$

Am I wrong?

#### MrChips

Joined Oct 2, 2009
30,824
You can use the manufacturer's resistance vs temperature chart or formula. Then you still have to convert from ADC voltage to temperature. This does not take into account errors in supply voltage V1, resistance R1, ADC reference voltage, and ADC linearity.

A more direct approach is to use your kitchen thermometer (or one with reliable accuracy) and a water bath.
Display the ADC reading vs temperature over the range of temperature that you want to measure. About 10 data points would be sufficient. Show us your collected data and we will take it from there.

#### Ian0

Joined Aug 7, 2020
9,847
So, given my NTC with R0=10k at T0=25°C and beta=3977 (written on the datasheet, I don't need the online calculator but thanks anyway) and working in a range of thermperature=[25 ... 43]°C --> Tavg=34°C
$Rpullup=Rntc(34°C)=R0*e^{\beta(1/(273.15+34) - 1/(273.15+25))}$

Am I wrong?
correct. Seems like 6.8k might be a good value to choose.

Last edited:

#### Ian0

Joined Aug 7, 2020
9,847
You can use the manufacturer's resistance vs temperature chart or formula. Then you still have to convert from ADC voltage to temperature. This does not take into account errors in supply voltage V1, resistance R1, ADC reference voltage, and ADC linearity.

A more direct approach is to use your kitchen thermometer (or one with reliable accuracy) and a water bath.
Display the ADC reading vs temperature over the range of temperature that you want to measure. About 10 data points would be sufficient. Show us your collected data and we will take it from there.
Actually, 3 data points is sufficent to calculate beta. One can be 0°C, one can be 100°C and the third can be room temperature, all of which are reasonably stable. Otherwise you will have problems keeping it at a steady temperature long enough to get an accurate reading.

#### andrew74

Joined Jul 25, 2022
102
The equation for the resistance of an NTC thermistor is the Steinhart-Hart equation. A simplified version of it will usually suffice.
R/Ro = exp(B(1/T - 1/To))
where Ro and To are the values at 25°C, and B will (or should) be in the Thermistor datasheet.
Then V/Vo= Rt/(Rt+Rpullup)
where Vo is the supply voltage and Rt is the thermistor resistance.
You can think of Vo as being 256 or 4096 because that is the number your ADC will read.
This is a handy online calculator. If you know your thermistor resistance at three temperature values, but don't know B it will work out the coefficients.
The spreadsheet calculates T from V.
You have to choose Rpullup. It can be any value, but it works best if you choose Rpullup to be approximately equal to Rt at the sort of temperature you will be measuring (middle of the range of temperatures).

If you are working in C get rid of .hword altogether, it is required for assembler.
The csv file (Open it in a TEXT EDITOR) will then have lots of values followed by commas and C likes that.
All you have to do then for the compiler to be happy with it is to add
const int16_t celsius5k[]=
{
before the values and
};
after them.
Leave the rest in as it will be generated as comments by the "//" column.
I call it "celsius5k" because it has a 4.7k pullup resistor (maybe I should have called it "celsius4k7". I also use the same thermistor to measure higher temperatures, which requires a 1k pullup resistor and that table is called "celsius1k".
Perhaps those Americans are on to something using Fahrenheit - you can measure from -18°C to +124°C an an 8-bit unsigned number.
I performed the steps you listed, try to summarize them with these 3 photos ... tell me if and where I did something wrong:

1) I delete the .hwords and choose (for example) these values at the top.

2) I save the file as a .csv .. open it in Windows WordPad and adding const int16.. and also at the end of everything the };

3) Copy and paste on the IDE I'm using:

I think there is something wrong here.

Forgive my inexperience in these things, but I've really just started and I'm probably making some stupid mistakes

#### MrChips

Joined Oct 2, 2009
30,824
Actually, 3 data points is sufficent to calculate beta. One can be 0°C, one can be 100°C and the third can be room temperature, all of which are reasonably stable. Otherwise you will have problems keeping it at a steady temperature long enough to get an accurate reading.
True. Three points will get you started. More points collected will give more accurate results as individual errors be averaged.

#### Ian0

Joined Aug 7, 2020
9,847
I performed the steps you listed, try to summarize them with these 3 photos ... tell me if and where I did something wrong:

1) I delete the .hwords and choose (for example) these values at the top.
View attachment 296183
2) I save the file as a .csv .. open it in Windows WordPad and adding const int16.. and also at the end of everything the };View attachment 296185

3) Copy and paste on the IDE I'm using:
View attachment 296186
I think there is something wrong here.

Forgive my inexperience in these things, but I've really just started and I'm probably making some stupid mistakes
You seem to have semicolons where there should be commas. That might have been Windows trying to be "helpful".
csv files should have commas separating the variables, otherwise they should be called something else.
When you delete .hword, also delete the comma that comes after it.
Also swap the DIV/0 error for some random large number. It's the value it will read if your thermistor gets shorted to 0V.

#### Ian0

Joined Aug 7, 2020
9,847
True. Three points will get you started. More points collected will give more accurate results as individual errors be averaged.
Three data points around the area you are interested in is better than ten datapoints including values of no interest (but you are right that ten data points around the area of interest would be better still)

#### MrChips

Joined Oct 2, 2009
30,824
Three data points around the area you are interested in is better than ten datapoints including values of no interest (but you are right that ten data points around the area of interest would be better still)
You don’t have to aim for 10 points. Even 5 is better than 3.