这次项目是工作中用到的一个内容,本人才疏学浅,如有遗漏,请大家多多指教
首先介绍一下TS318_1B0814热电堆传感器,这个传感器用到的资料我在百度云上传,简单说一下就是这是个模拟量传感器,要采集两路模拟信号,一路判断传感器自身温度,另一路结合传感器自身温度就能算出测量物体的温度。
链接:https://pan.baidu.com/s/13zDIR82lZlg7AHqSE7ha1A?pwd=awsl
提取码:awsl
传感器电路图如下:
图1
下面是V1和R3两端代表Pin1和Pin3,放大倍数等于R5/R4(这里的放大倍数并不是最大,只是用了手边现有的电阻)
仿真电路
图二
直流扫描结果
横坐标是V1,纵坐标是探针1
图三
Cadence原理图
Header4 H2插传感器,H1接到开发板上供电,和接ad采集
图四
做一个3cm*3cm的板板
PCB
图五
stm32程序
c
#include "TS318_1B0814.h"
#include "delay.h"
/*-------------|----------------
AD PH4 <-> ADC3_INP15 红外温度 down
AD PH5 <-> ADC3_INP16 环境温度 up
-------------|----------------*/
float VTP_Value_Table[101]={-1.066,-1.028,-0.990,-0.952,-0.914,-0.874,-0.835,-0.795,-0.755,-0.714,-0.673,
-0.631,-0.589,-0.546,-0.503,-0.46,-0.416,-0.372,-0.327,-0.282,
-0.236,-0.19,-0.143,-0.096,-0.048,0,0.049,0.098,0.147,0.197,
0.248,0.299,0.351,0.403,0.455,0.509,0.562,0.617,0.671,0.726,
0.782,0.839,0.895,0.953,1.011,1.069,1.128,1.188,1.248,1.309,
1.370,1.432,1.495,1.558,1.621,1.685,1.750,1.816,1.882,1.948,
2.015,2.083,2.152,2.221,2.290,2.360,2.431,2.503,2.575,2.648,
2.721,2.795,2.870,2.945,3.021,3.098,3.175,3.253,3.332,3.412,
3.492,3.572,3.654,3.736,3.819,3.902,3.986,4.071,4.157,4.243,
4.330,4.418,4.507,4.596,4.686,4.776,4.868,4.960,5.053,5.147,
5.241};//0-100度
float RNI1000_Value_Table[86]={1000.0,1005.5,1011.0,1016.5,1022.0,1027.6,1033.1,1038.7,1044.3,1049.9,
1055.5,1061.1,1066.8,1072.4,1078.1,1083.8,1089.5,1095.2,1100.9,1106.6,
1112.4,1118.1,1123.9,1129.7,1135.5,1141.3,1147.1,1153.0,1158.8,1164.7,
1170.6,1176.5,1182.4,1188.3,1194.2,1200.2,1206.1,1212.1,1218.1,1224.1,
1230.1,1236.1,1242.2,1248.2,1254.3,1260.4,1266.5,1272.6,1278.8,1284.9,
1291.1,1297.2,1303.4,1309.6,1315.8,1322.0,1328.3,1334.5,1340.8,1347.1,
1353.4,1359.7,1366.0,1372.4,1378.7,1385.1,1391.5,1397.9,1404.3,1410.8,
1417.2,1423.7,1430.1,1436.6,1443.1,1449.7,1456.2,1462.8,1469.3,1475.9,
1482.5,1489.1,1495.7,1502.4,1509.1,1515.7};//0-85度
float NTC_Value_Table[86]={332.59,315.83,300.02,285.09,270.98,257.66,245.07,233.17,221.29,211.26,
201.18,191.64,182.60,174.05,165.94,158.25,150.96,144.05,137.50,131.28,
125.37,119.76,114.44,109.38,104.57,100.0,95.65,91.52,87.59,83.84,
80.28,76.89,73.66,70.58,67.65,64.85,62.19,59.65,57.22,54.91,
52.70,50.60,48.58,46.66,44.83,43.07,41.40,39.79,38.26,36.80,
35.40,34.05,32.77,31.54,30.37,29.24,28.16,27.13,26.14,25.19,
24.28,23.40,22.57,21.76,20.99,20.25,19.54,18.86,18.21,17.58,
16.97,16.39,15.84,15.30,14.79,14.29,13.81,13.36,12.92,12.49,
12.08,11.69,11.31,10.95,10.60,10.26};
/*********************************************************************************************************
* 函 数 名: TS318_1B0814_Init
* 功能说明: TS318_1B0814红外测温传感器AD功能引脚初始化
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************/
void TS318_1B0814_Init(void)
{
RCC->AHB4ENR|=1<<24; //使能ADC3时钟
RCC->AHB4ENR|=GPIOH_CLK; //使能PORTC时钟
GPIO_Set(GPIOH,PIN4|PIN5,GPIO_MODE_AIN,0,0,GPIO_PUPD_NONE);//PH4 PH5 模拟输入,不带上下拉
RCC->AHB1RSTR|=1<<24; //ADC3复位
RCC->AHB1RSTR&=~(1<<24); //复位结束
RCC->D3CCIPR&=~(3<<16); //ADCSEL[1:0]清零
RCC->D3CCIPR|=2<<16; //ADCSEL[1:0]=2,per_ck作为ADC时钟源,默认选择hsi_ker_ck作为per_ck,频率:64Mhz
ADC3_COMMON->CCR|=1<<18; //PRESC[3:0]=1,输入时钟2分频,即adc_ker_ck=per_ck/2=64/2=32Mhz(不能超过36Mhz)
ADC3->CR=0; //CR寄存器清零,DEEPPWD清零,从深度睡眠唤醒.
ADC3->CR|=1<<28; //ADVREGEN=1,使能ADC稳压器
delay_ms(10); //等待稳压器启动完成,约10us
ADC3->CR|=1<<8; //BOOST=1,ADC工作在boost模式(ADC频率大于20M的时候,必须设置boost位)
ADC3->CFGR&=~(1<<13); //CONT=0,单次转换模式
ADC3->CFGR|=1<<12; //OVRMOD=1,复写模式(DR寄存器可被复写)
ADC3->CFGR&=~(3<<10); //EXTEN[1:0]=0,软件触发
ADC3->CFGR&=~(7<<2); //RES[2:0]位清零
ADC3->CFGR|=0<<2; //RES[2:0]=0,16位分辨率(0,16位;1,14位;2,12位;3,10位;4,8位.)
ADC3->CFGR2&=~((u32)15<<28); //LSHIFT[3:0]=0,不左移,数据右对齐.
ADC3->CFGR2&=~((u32)0X3FF<<16);//OSR[9:0]=0,不使用过采样
ADC3->CR&=~((u32)1<<30); //ADCALDIF=0,校准单端转换通道
ADC3->CR|=1<<16; //ADCALLIN=1,线性校准
ADC3->CR|=(u32)1<<31; //开启校准
while(ADC3->CR&((u32)1<<31));//等待校准完成
ADC3->SQR1&=~(0XF<<0); //L[3:0]清零
ADC3->SQR1|=0<<0; //L[3:0]=0,1个转换在规则序列中 也就是只转换规则序列1
ADC3->SMPR2&=~(7<<15); //通道15采样时间清空
ADC3->SMPR2|=7<<15; //通道15 810.5个周期,提高采样时间可以提高精确度
ADC3->SMPR2&=~(7<<18); //通道16采样时间清空
ADC3->SMPR2|=7<<18; //通道16 810.5个周期,提高采样时间可以提高精确度
ADC3->CR|=1<<0; //开启AD转换器
}
/*********************************************************************************************************
* 函 数 名: Get_Adc3Value
* 功能说明: 获取ADC3指定通道的AD数值(16位,0-65535),10次采样,去除最大最小值取平均
* 形 参: Ch指定通道
* 返 回 值: 返回的AD数值
*********************************************************************************************************/
u16 Get_Adc3Value(u16 Ch)
{
u16 Data_Max,Data_Min,Data_Now,AD_Data;
u8 i;
u32 Data=0;
ADC3->PCSEL|=1<<Ch; //ADC转换通道预选择
ADC3->SQR1&=~(0X1F<<6*1); //规则序列1通道清零
ADC3->SQR1|=Ch<<6*1; //设置规则序列1的转换通道为ch
ADC3->CR|=1<<2; //启动规则转换通道
while(!(ADC3->ISR&1<<2)); //等待转换结束
Data_Max=ADC3->DR; //返回adc值
Data_Min=Data_Max;
Data+=Data_Min;
for(i=0;i<9;i++)
{
ADC3->PCSEL|=1<<Ch; //ADC转换通道预选择
ADC3->SQR1&=~(0X1F<<6*1); //规则序列1通道清零
ADC3->SQR1|=Ch<<6*1; //设置规则序列1的转换通道为ch
ADC3->CR|=1<<2; //启动规则转换通道
while(!(ADC3->ISR&1<<2)); //等待转换结束
Data_Now=ADC3->DR;
if(Data_Max<Data_Now)
Data_Max=Data_Now;
if(Data_Min>Data_Now)
Data_Min=Data_Now;
Data+=Data_Now;
}
Data=Data-Data_Min-Data_Max;
AD_Data=Data/8;
return AD_Data;
}
/*********************************************************************************************************
* 函 数 名: Caculate_T_sensor
* 功能说明: 输入电阻值,根据线性插补,算出传感器温度
* 形 参: float value
* 返 回 值: 一般应该会在0-85度
*********************************************************************************************************/
float Caculate_T_sensor(float value,u8 sensor)
{
float T_sensor;
if(sensor==0)
{
if(value<=RNI1000_Value_Table[0])
{
return 0;
}
if(value>=RNI1000_Value_Table[85])
{
return 85;
}
for(int i =0;i<86;i++)
{
if((value>RNI1000_Value_Table[i])&&(value<RNI1000_Value_Table[i+1]))
{
T_sensor=(value-RNI1000_Value_Table[i])/(RNI1000_Value_Table[i+1]-RNI1000_Value_Table[i])+i;
return T_sensor;
}
}
return -1;
}
if(sensor==1)
{
if(value<=NTC_Value_Table[0])
{
return 0;
}
if(value>=NTC_Value_Table[85])
{
return 85;
}
for(int i =0;i<86;i++)
{
if((value>NTC_Value_Table[i])&&(value<NTC_Value_Table[i+1]))
{
T_sensor=(value-NTC_Value_Table[i])/(NTC_Value_Table[i+1]-NTC_Value_Table[i])+i;
return T_sensor;
}
}
return -1;
}
}
/*********************************************************************************************************
* 函 数 名: Caculate_Voffs
* 功能说明: 输入温度,根据线性插补,算出电压
* 形 参: float value
* 返 回 值: Voffs
*********************************************************************************************************/
float Caculate_Voffs(float value)
{
float Voffs;
for(int i=0;i<101;i++)
{
if(value>=i&&value<i+1)
{
float k ,b;
k=VTP_Value_Table[i+1]-VTP_Value_Table[i];
b=VTP_Value_Table[i]-k*i;
Voffs=k*value+b;
return Voffs;
}
}
return -1;
}
/*********************************************************************************************************
* 函 数 名: Caculate_T_object
* 功能说明: 输入电压,根据线性插补,算出温度
* 形 参: float value
* 返 回 值: 0-100范围内的温度
*********************************************************************************************************/
float Caculate_T_object(float value)
{
float T_object;
for(int i=0;i<101;i++)
{
if((value>VTP_Value_Table[i])&&(value<VTP_Value_Table[i+1]))
{
T_object=(value-VTP_Value_Table[i])/(VTP_Value_Table[i+1]-VTP_Value_Table[i])+i;;
return T_object;
}
}
return -1;
}
/*********************************************************************************************************
* 函 数 名: Get_temperature
* 功能说明: 计算物体温度,太低可能监测不出来,这时候可以修改Sconv,
* 形 参:
* 说 明:
1号 2号
Sconv 0.1385 0.1335
237行常数项 5.8 -4.8
* 返 回 值: 0-100范围内的温度
*********************************************************************************************************/
float Get_temperature(void)
{
float Sconv=0.1335;
u16 Adc3_15=Get_Adc3Value(15);
u16 Adc3_16=Get_Adc3Value(16);
float temp_sen_volt=3.28*Adc3_16/65536;
float R_ni1000=1000*temp_sen_volt/3.28f/(1-temp_sen_volt/3.28f); //rni1000电阻值
float T_sensor=Caculate_T_sensor(R_ni1000,0)-4.8f; //计算传感器温度
float Vtp=1000*(3.28f*Adc3_15/65536-1.26f)/(313.65f); //放大前值,单位mv
float Vtpc=(Vtp)/Sconv;
float Tcf=1-((T_sensor-25)*0.0045f);
float Voffs=Caculate_Voffs(T_sensor); //第一次调用
float Voffs_tc=Voffs*Tcf;
float Vtp_ref=Vtpc+Voffs_tc;
float Vtp_ref_tc=Vtp_ref/Tcf;
float T_object=Caculate_T_object(Vtp_ref_tc); //第二次调用
return T_object;
}
h
#ifndef __TS318_1B0814_H
#define __TS318_1B0814_H
#include "sys.h"
void TS318_1B0814_Init(void);
u16 Get_Adc3Value(u16 Ch);
float Caculate_T_sensor(float value ,u8 sensor);
float Caculate_Voffs(float value);
float Caculate_T_object(float value);
float Get_temperature(void);
#endif
用的时候在main里面用初始化和最后一个就可以了。移植的话需要考虑你的adc用的和我不一样,要去查数据手册。
最后说一下
计算过程
(全部来自于泰科官网一份pdf资料)
1环境温度
表一
拿到从传感器之后,用万用表电阻档接2、4,室温下1100多欧姆就是正常的,这个电阻随温度上升而上升,很线性
图六
表二
用分压电路去测这个电阻值就可以。
2环境温度校准
计算得到传感器温度之后,看一下这个传感器温度准不准,可以用一个比较准的温度传感器,把热电堆和它放一起,差值就是常数项。
3计算物体温度
通常一个产品中热电堆和测量物体之间的相对位置是确定的,而且不同产品中 它们的相对位置也不同,经过测量,在同一组参数下,热电堆越靠近被测物体,测得温度越大。所以要固定一个距离,保持传感器为25度时,查看测得的原始电压值VTP1(mv),
表三
VTPC=VTP/(VTP1/5.241f)
计算依据如下
图七
之后按照下面的步骤计算就可以了
图八
有几个需要说明的地方,首先是Vtp是通过ad读取到的16位数值(最大65535)算出来的,参考前面mutisim的曲线,然后这里的LUT和RLUT就是参考表二,搞一下线性插值。