NTC 10K 温度传感器快速读取(C程序)区间线性回归
(升级版已经发布↓)
巧用Excel求解NTC 10K 温度传感器 (含程序)(区间线性回归)(升级版)
一、温度传感器
原本想选DS18B20,但是通过相关文件查到如下特性:测温精度高,单线通信节省端口资源;采样周期>500ms,且采样等待周期内不能有干扰。对比最终实现灵敏快速采样的目的,该传感器被pass。
然后调查了下NTC:
- 一种负温度系数热敏电阻,并且电阻值与温度呈一定的函数关系。由于热敏特性,遂经常用于做热敏探头;
- 阻值与温度函数关系为:RT =RT0×e^((Bn (1/T-1/T0)));
其中Bn材料系数;
Rt,Rt0为电阻在T温度下和在T0温度下的电阻值;
通常这种电阻在售卖时还会提供一个类似10K或者100K的说明,一般为NTC 10K,或者NTC100K,其中10K和100K是指在25摄氏度时材料本身的阻值
二、选型
我选择的是NTC10K,B值为3435。得出Rt0为10K,T0为(25+273.15)K。由于单片机可以采集到的是电阻值,因此函数关系反解出来为:1/T=1/3435×ln(RT/10)+1/25,其中Rt单位为KΩ
由于选用的单片机为8位单片机不擅长处理对数函数因此准备将函数关系离散化由单片机通过查表处理得出温度值
待测温度区间为-20—100度,将函数关系式输入Excel表格输入公式,求得每个温度对应的电阻值
Excel公式为:
=10EXP(3435(1/(B2+273.15)-1/298.15))
(可直接复制到Excel单元格中)
由于单片机直接读出的是AD值,用10K的电阻与NTC串联单片机读取中间的分压AD。
经过计算之后AD值与温度的对应关系是:AD = 210 * RT(RT+10)。(单片机10位AD)
此时转化为AD值与温度的关系。由于温度值较多想到可以近似线性化处理。简化单片机查表流程,并且尽可能提高精确度。拟准备用Excel功能中的插入散点图—显示趋势线—显示函数函数找出近似线性关系:
可以看到曲线本身是非线性关系,由于函数如果直接做线性回归误差会很大遂考虑区间线性回归。
三、区间线性回归
取10度间隔为一个区间,采取区间内回归:(批量图表来自Excel宏程序录制修改)
其中虚线为拟合线。使用Excel可以很方便的看到回归散点的回归方程
单独来看区间内的拟合效果不错
四、读取函数(C语言)
变量定义:
float K[12] = {0.1561, 0.122, 0.1047, 0.0985, 0.1009, 0.1112, 0.1297, 0.1578, 0.1976, 0.252, 0.3245, 0.4193};
//斜率值索引
float b[12] = {121.73, 92.853, 79.576, 75.389, 76.699, 81.447, 88.418, 96.869, 106.33, 116.51, 127.21, 138.3};
//截距值索引
// 索引值: 0 1 2 3 4 5 6 7 8 9 10 11
// 温度值:-20,-10, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90,100
int index[13] = {907,842,759,664,562,464,374,298,235,185,146,116,92};
// 索引值: 0 1 2 3 4 5 6 7 8 9 10 11 12
函数定义:
float AD_to_temp(int AD)
{
float T0;
if(AD > index[0]) {AD = index[0];}
if(AD < index[12]){AD = index[12];}
switch(AD/100)
{
// 百位 索引值
case 9: K_Value = K[0];b_Value = b[0];break;
case 8: if(AD <index[1]){K_Value = K[0];b_Value = b[0];}else{K_Value = K[1];b_Value = b[1];}break;
case 7: if(AD <index[2]){K_Value = K[1];b_Value = b[1];}else{K_Value = K[2];b_Value = b[2];}break;
case 6: if(AD <index[3]){K_Value = K[2];b_Value = b[2];}else{K_Value = K[3];b_Value = b[3];}break;
case 5: if(AD <index[4]){K_Value = K[3];b_Value = b[3];}else{K_Value = K[4];b_Value = b[4];}break;
case 4: if(AD <index[5]){K_Value = K[4];b_Value = b[4];}else{K_Value = K[5];b_Value = b[5];}break;
case 3: if(AD <index[6]){K_Value = K[5];b_Value = b[5];}else{K_Value = K[6];b_Value = b[6];}break;
case 2: if(AD <index[7]){K_Value = K[6];b_Value = b[6];}else if(AD <index[8]){K_Value = K[7];b_Value = b[7];}else{K_Value = K[8];b_Value = b[8];}break;
case 1:
if(AD > index[9]) {K_Value = K[8];b_Value = b[8];}
else if(AD > index[10]){K_Value = K[9];b_Value = b[9];}
else if(AD > index[11]){K_Value = K[10];b_Value = b[10];}
else{K_Value = K[11];b_Value = b[11];} break;
case 0: K_Value = K[11];b_Value = b[11];break;
}
T0 = b_Value - K_Value*AD;
return T0;
}
五、效果(arduino输出)
喜欢记得点赞