单片机_NTC精准读取温度
前言:给客户做的一个PID温控系统,采集温度的传感器就是使用NTC,结果控制效果极不稳定,调试好几个星期才确定是因为温度采集的不稳定导致的,所以仔细研究了NTC读取的方式,一般都采用查表法(想实现高精度不太容易),我的方法是采用数学模型采用函数计算的方式,这样就可以实现无极变速的那种精度。
核心思想:把电阻值与温度的曲线细分成无数段直线
我的NTC型号:
ntc.h
#ifndef __NTC_H_
#define __NTC_H_
#include "lib/STC15X.h"
void ntc_init();
float OneDimensionalEquation(uint32 x1,uint32 y1,uint32 x2,uint32 y2,uint32 Unkown_x,uint32 Unkown_y);
float Res_To_Temperature(uint32 NTC_Res);
uint32 Count_Ntc_R(void);
#endif
ntc.c
#include "ntc.h"
#include "lib/STC15_ADC.h"
#include "delay.h"
#include <stdio.h>
#define NTC_ADC_PIN ADC_P10
//X_Temp与Y_Res一一对应的关系
code uint32 X_Temp[91] =
{
-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,
0,1,2,3,4,5,6,7,8,9,10,
11,12,13,14,15,16,17,18,19,20,
21,22,23,24,25,26,27,28,29,30,
31,32,33,34,35,36,37,38,39,40,
41,42,43,44,45,46,47,48,49,50,
51,52,53,54,55,56,57,58,59,60,
61,62,63,64,65,66,67,68,69,70,
71,72,73,74,75,76,77,78,79,80
};
code uint32 Y_Res[91]=
{
55800,52851,50074,47457,44987,42657,40456,38376,36412,34555, //-10~-1
32800,31140,29572,28090,26689,25366,24116,22935,21820,20767,19773, //0~10
18834,17949,17112,16323,15577,14873,14208,13578,12983,12419, //11~20
11884,11377,10895,10437,10000,9513,9064,8648,8263,7904, //21~30
7569,7255,6960,6682,6419,6170,5932,5706,5490,5283, //31~40
5085,4895,4712,4536,4366,4203,4046,3895,3750,3610, //41~50
3475,3345,3221,3101,2986,2876,2770,2669,2572,2480, //51~60
2391,2306,2225,2148,2074,2003,1935,1871,1809,1750, //61~70
1693,1638,1585,1535,1486,1439,1393,1348,1304,1261 //71~80
};
void ntc_init() //初始化ADC
{
adc_init(NTC_ADC_PIN, ADC_540T, ADC_10BIT);
}
//输入两个坐标,计算出两点之间的直线方程,然后就可以输入该直线上任意一点的Y坐标(根据ADC的值换算出电阻值)而得到X坐标(温度值)
float OneDimensionalEquation(uint32 x1,uint32 y1,uint32 x2,uint32 y2,uint32 Unkown_x,uint32 Unkown_y)
{
float k = 0;
float b = 0;
k = ((float)y1-(float)y2)/((float)x1-(float)x2);
b = (float)y1-(float)x1*k;
if(0 == Unkown_x)
return ((float)Unkown_y-b)/k;
else
return ((float)Unkown_x*k+b);
}
//输入电阻值,获取到温度
float Res_To_Temperature(uint32 NTC_Res)
{
uint8 Loop = 0;
uint8 StartPoint = 0;
float RealTemp = 0;
for(Loop = 0;Loop < 91;Loop++)
{
if(NTC_Res > Y_Res[Loop])
{
StartPoint = Loop;
break;
}
}
RealTemp = (float)OneDimensionalEquation(X_Temp[StartPoint],Y_Res[StartPoint],X_Temp[StartPoint+1],Y_Res[StartPoint+1],0,NTC_Res);
return RealTemp;
}
uint32 Count_Ntc_R(void) //读取ADC的值
{
uint32 ntc_r;
uint32 adc;
adc = adc_read(NTC_ADC_PIN);
ntc_r = (10000*adc)/(1024-adc);
return ntc_r;
}
我的项目实践: