Application of TS318_1B0814 thermopile sensor on stm32

This project is a piece of content used in my work. I have little talent and knowledge. If there are any omissions, please give me some advice.

First, let’s introduce the TS318_1B0814 thermopile sensor. I uploaded the data used by this sensor on Baidu Cloud. To put it simply, this is an analog sensor. It needs to collect two analog signals, one to determine the sensor’s own temperature, and the other to combine the sensor’s own temperature. Can calculate the temperature of the measured object.

Link: https://pan.baidu.com/s/13zDIR82lZlg7AHqSE7ha1A?pwd=awsl
Extraction code: awsl

The sensor circuit diagram is as follows:

figure 1

Below is the two ends of V1 and R3 representing Pin1 and Pin3. The amplification factor is equal to R5/R4 (the amplification factor here is not the maximum, but the existing resistors on hand are used)

Simulation circuit

Figure II

DC scan results

The abscissa is V1, the ordinate is probe 1

Figure 3

Cadence Schematic

Header4 H2 is plugged into the sensor, and H1 is connected to the development board for power supply and AD collection.

Figure 4

Make a 3cm*3cm board

PCB

Figure 5

stm32 program

c

#include "TS318_1B0814.h"
#include "delay.h"
/*-------------|----------------
AD PH4 <-> ADC3_INP15 infrared temperature down
AD PH5 <-> ADC3_INP16 ambient temperature 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 degrees

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 degrees

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};
\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t 
\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t 
/****************************************************** *************************************************** ****
* Function name: TS318_1B0814_Init
* Function description: TS318_1B0814 infrared temperature sensor AD function pin initialization
*Formal parameters: None
* Return value: None
*************************************************** *************************************************** *****/
void TS318_1B0814_Init(void)
{
RCC->AHB4ENR|=1<<24; //Enable ADC3 clock
RCC->AHB4ENR|=GPIOH_CLK; //Enable PORTC clock
GPIO_Set(GPIOH,PIN4|PIN5,GPIO_MODE_AIN,0,0,GPIO_PUPD_NONE);//PH4 PH5 analog input, without pull-down
RCC->AHB1RSTR|=1<<24; //ADC3 reset
RCC->AHB1RSTR & amp;=~(1<<24); //Reset ends
RCC->D3CCIPR & amp;=~(3<<16); //ADCSEL[1:0] cleared
RCC->D3CCIPR|=2<<16; //ADCSEL[1:0]=2, per_ck is used as ADC clock source, hsi_ker_ck is selected as per_ck by default, frequency: 64Mhz
ADC3_COMMON->CCR|=1<<18; //PRESC[3:0]=1, the input clock is divided by 2, that is, adc_ker_ck=per_ck/2=64/2=32Mhz (cannot exceed 36Mhz)

ADC3->CR=0; //Clear the CR register, clear DEEPPWD, and wake up from deep sleep.
ADC3->CR|=1<<28; //ADVREGEN=1, enable ADC regulator
delay_ms(10); //Wait for the voltage regulator to start up, about 10us
ADC3->CR|=1<<8; //BOOST=1, ADC works in boost mode (when the ADC frequency is greater than 20M, the boost bit must be set)
ADC3->CFGR & amp;=~(1<<13); //CONT=0, single conversion mode
ADC3->CFGR|=1<<12; //OVRMOD=1, rewrite mode (DR register can be rewritten)
ADC3->CFGR & amp;=~(3<<10); //EXTEN[1:0]=0, software trigger
ADC3->CFGR & amp;=~(7<<2); //RES[2:0] bits cleared
ADC3->CFGR|=0<<2; //RES[2:0]=0,16-bit resolution (0,16-bit;1,14-bit;2,12-bit;3,10-bit;4,8 Bit.)

ADC3->CFGR2 & amp;=~((u32)15<<28); //LSHIFT[3:0]=0, no left shift, data is right-aligned.
ADC3->CFGR2 & amp;=~((u32)0X3FF<<16);//OSR[9:0]=0, do not use oversampling


ADC3->CR & amp;=~((u32)1<<30); //ADCALDIF=0, calibrate single-ended conversion channel
ADC3->CR|=1<<16; //ADCALLIN=1, linear calibration
ADC3->CR|=(u32)1<<31; //Turn on calibration
while(ADC3->CR & amp;((u32)1<<31));//Waiting for calibration to be completed

ADC3->SQR1 & amp;=~(0XF<<0); //L[3:0] cleared
ADC3->SQR1|=0<<0; //L[3:0]=0, 1 conversion is in the rule sequence, that is, only rule sequence 1 is converted

ADC3->SMPR2 & amp;=~(7<<15); //Clear channel 15 sampling time
ADC3->SMPR2|=7<<15; //Channel 15 810.5 cycles, increasing the sampling time can improve the accuracy
ADC3->SMPR2 & amp;=~(7<<18); //Clear channel 16 sampling time
ADC3->SMPR2|=7<<18; //Channel 16 810.5 cycles, increasing the sampling time can improve the accuracy
\t
ADC3->CR|=1<<0; //Turn on the AD converter
}
/****************************************************** *************************************************** ****
* Function name: Get_Adc3Value
* Function description: Get the AD value of the specified channel of ADC3 (16 bits, 0-65535), sample 10 times, remove the maximum and minimum values and average
*Formal parameter: Ch specifies the channel
* Return value: Returned AD value
*************************************************** *************************************************** *****/
u16 Get_Adc3Value(u16 Ch)
{
u16 Data_Max,Data_Min,Data_Now,AD_Data;
u8i;
u32 Data=0;
ADC3->PCSEL|=1<<Ch; //ADC conversion channel pre-selection
ADC3->SQR1 & amp;=~(0X1F<<6*1); //Regular sequence 1 channel cleared
ADC3->SQR1|=Ch<<6*1; //Set the conversion channel of rule sequence 1 to ch
ADC3->CR|=1<<2; //Start the rule conversion channel
while(!(ADC3->ISR & amp;1<<2)); //Wait for the conversion to end
Data_Max=ADC3->DR; //Return adc value
Data_Min=Data_Max;
Data + =Data_Min;
for(i=0;i<9;i + + )
{
ADC3->PCSEL|=1<<Ch; //ADC conversion channel pre-selection
ADC3->SQR1 & amp;=~(0X1F<<6*1); //Regular sequence 1 channel cleared
ADC3->SQR1|=Ch<<6*1; //Set the conversion channel of rule sequence 1 to ch
ADC3->CR|=1<<2; //Start the rule conversion channel
while(!(ADC3->ISR & amp;1<<2)); //Wait for the conversion to end
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;
}
/****************************************************** *************************************************** ****
* Function name: Caculate_T_sensor
* Function description: Input the resistance value and calculate the sensor temperature based on linear interpolation
*Formal parameter: float value
* Return value: Generally it should be between 0-85 degrees
*************************************************** *************************************************** *****/
float Caculate_T_sensor(float value,u8 sensor)
{
float T_sensor;
\t
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]) & amp; & amp;(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;
}
\t
\t
\t
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]) & amp; & amp;(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;
}
\t
}
/****************************************************** *************************************************** ****
* Function name: Caculate_Voffs
* Function description: Input the temperature and calculate the voltage based on linear interpolation
*Formal parameter: float value
* Return value: Voffs
*************************************************** *************************************************** *****/
float Caculate_Voffs(float value)
{
float Voffs;
for(int i=0;i<101;i + + )
{
if(value>=i & amp; & amp;value<i + 1)
{
\t\t\t
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;
}
/****************************************************** *************************************************** ****
* Function name: Caculate_T_object
* Function description: Input voltage, calculate temperature based on linear interpolation
*Formal parameter: float value
* Return value: temperature in the range of 0-100
*************************************************** *************************************************** *****/
float Caculate_T_object(float value)
{
float T_object;
for(int i=0;i<101;i + + )
{
if((value>VTP_Value_Table[i]) & amp; & amp;(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;
}
/****************************************************** *************************************************** ****
* Function name: Get_temperature
* Function description: Calculate the object temperature. If it is too low, it may not be detected. At this time, Sconv can be modified.
*Formal parameters:
*\tillustrate:
                            No. 1 No. 2
                   Sconv 0.1385 0.1335
              237 lines of constant items 5.8 -4.8
* Return value: temperature in the range of 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 resistance value
float T_sensor=Caculate_T_sensor(R_ni1000,0)-4.8f; //Calculate sensor temperature
\t\t
float Vtp=1000*(3.28f*Adc3_15/65536-1.26f)/(313.65f); //Value before amplification, unit mv
\t
float Vtpc=(Vtp)/Sconv;
\t\t
float Tcf=1-((T_sensor-25)*0.0045f);
\t\t
float Voffs=Caculate_Voffs(T_sensor); //First call
\t\t
float Voffs_tc=Voffs*Tcf;
\t\t\t
float Vtp_ref=Vtpc + Voffs_tc;
\t\t\t
float Vtp_ref_tc=Vtp_ref/Tcf;
\t\t
float T_object=Caculate_T_object(Vtp_ref_tc); //Second call
\t
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

When using it, just use initialization and the last one in main. When transplanting, you need to consider that your ADC is different from mine, and you need to check the data manual.

One final word

Calculation process

(All from a pdf information on Tyco’s official website)

1Ambient temperature

Table I

After getting the slave sensor, use a multimeter to connect the resistance range 2 and 4. It is normal to have more than 1100 ohms at room temperature. This resistance increases as the temperature rises, which is very linear.

Figure 6

Table II

Just use a voltage divider circuit to measure the resistance value.

2Ambient temperature calibration

After calculating the sensor temperature, check whether the sensor temperature is accurate. You can use a relatively accurate temperature sensor and put the thermopile together with it. The difference is the constant term.

3 Calculate object temperature

Usually the relative position between the thermopile and the measured object in a product is determined, and their relative positions are also different in different products. After measurement, under the same set of parameters, the closer the thermopile is to the measured object, the higher the measured temperature. big. Therefore, we need to fix a distance, keep the sensor at 25 degrees, and check the measured original voltage value VTP1 (mv),

Table 3

VTPC=VTP/(VTP1/5.241f)

The calculation is based on the following

Figure 7

Then just follow the steps below to calculate

Figure 8

There are a few things that need to be explained. First, Vtp is calculated from the 16-bit value (maximum 65535) read by ad. Refer to the previous mutisim curve. Then the LUT and RLUT here are based on Table 2. Do some linear interpolation. .