NTC测量环境温度的计算方法
工作中接触到了NTC测量环境温度的内容,要求测量温度范围为-20到80摄氏度。本文中采用了分段拉直线的方法去计算数值,这种方法优点是计算方法简单,运行速度快。但缺点也比较明显,就是精度不够。如果需要更高的精度建议可以使用直接查表的方法。
1.理论依据
理论依据很重要,这里稍微介绍一下,NTC电阻的特性就是当温度变化时,电阻的温度也随之变化,NTC电阻为温度升高电阻下降,PTC电阻为温度升高电阻增大。这个就是NTC测温的理论依据。但这里有个问题,NTC并不不是线性的,也就是说当温度线性升高时,电阻的阻值并不是线性下降的。所以我们并不能直接使用线性关系去计算温度值。这里我们引入分段拉直线的方法进行计算,也就是说在NTC整个测温范围内取几个准确的点,点与点之间使用线性方法计算,这样即减少了查表方法的查找过程,相对于直接线性计算又改善了测量精度。
2.分段线性计算
这种方法其实在接近线性的传感器应用比较多,如N型和K型等热电偶。理论上NTC精度最好的方法还是查表。
#define NTC_TABLE 11//温度取点个数
const s32 Ntc_Tempc[NTC_TABLE]= {-2000, -1000, 0, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000};//各个点对应的温度值,两位小数
const s32 Ntc_val[NTC_TABLE]= {51064, 49650, 47527,44546,40672, 36042, 30950, 25803, 20977, 16722, 13167}; //各个点对应的AD值
void calcu_envtemp(AD_PARA* adpara)//温度计算
{
u8 i;
s32 a = 0;
s32 temp = 0;
//计算当前的环境温度【16位AD;3.3V系统】
if (adpara->SAMPVAL < Ntc_val[NTC_TABLE-1])//温度值限制在80度以内
{
adpara->CLVAL = 8000;
ALARM_SIG.ENVTempSpill_SIG = 1;//温度溢出标志
}else if(adpara->SAMPVAL > Ntc_val[0])
{
adpara->CLVAL = -2000;
ALARM_SIG.ENVTempSpill_SIG = 1;//温度溢出标志
}else if((adpara->SAMPVAL <= Ntc_val[0])&&(adpara->SAMPVAL >= Ntc_val[NTC_TABLE-1]))
{
ALARM_SIG.ENVTempSpill_SIG = 0;//温度溢出标志
for (i = 0; i < NTC_TABLE-2; i++)
{
if (adpara->SAMPVAL >= Ntc_val[i + 1])
{
temp = (s32)adpara->SAMPVAL - Ntc_val[i];
a = temp * (Ntc_Tempc[i+1] - Ntc_Tempc[i]);
temp = a / (Ntc_val[i+1] - Ntc_val[i]);
adpara->CLVAL = temp + Ntc_Tempc[i];
break;
}
}
adpara->CLVAL+= (UTempPARA.ENVTAmendPARA*10);//校正偏差
}
}
/*
代码中:
adpara->SAMPVAL为ADC采样值
adpara->CLVAL为计算得到温度值
*/
3.代码解读
代码中引入了两个量,温度溢出标志和偏差校准参数。这两个量是供后面对温度显示、报警和温度校准等使用。代码一共分为四个步骤。
(1)判断是否超过80度。
(2)判断是否低于-20度。
(3)温度计算。
(4)温度校准。
其实我当时看到前辈们这个方法时最大的问题并不是程序理解或者使用方法,最大问题时上面数组中断点是从那来的。其实很简单,找NTC的厂家要,一般厂家每一批NTC电阻的特性都是很接近的,所以会有一个电阻与温度值的对应关系,找厂家要到这个表格。再根据你使用的电路计算出AD值并使用硬件电路确认这个计算值。很多NTC的厂家会给出NTC的参考电路甚至给出计算公式或者16位ADC或者12位ADC的参考值。以上方法仅供参考。