2020電賽D題—可穿戴體溫測量儀LMT70

摘要:LMT70是一款模擬溫度傳感器,單片機與芯片的通訊方式是ADC採集芯片的模擬輸出口電壓,根據查表法能夠獲得相應的溫度,可是在具體測溫過程當中TI官方提供了輸出電壓與實際溫度的二階和三階線性方程,能夠經過提供的方程直接算出具體的溫度。另外這款芯片的供電電壓最好爲3.3V電壓框架

  LMT70是精密模擬溫度傳感器,其供電要求低、引腳簡單、具備很寬的溫度測量範圍,是一款醫用級的傳感器。LMT70幾乎適用於全部高精度、低功耗的經濟高效型溫度感測應用,例如物聯網傳感器節點、醫療溫度計、高精度儀器儀表和電池供電設備。根據其測量結果精確、體積小、電源要求低的特色,省賽應該會讓用LMT70設計一個可穿戴體溫測量儀或者那種測溫門禁測溫槍之類的設備。函數

一、引腳配置及功能


  一共有四個引腳,是BGA封裝,不方便手工焊接,建議要機器焊接。它的四個引腳功能以下:
ui

  • A1是地。
  • A2是電源,範圍是-0.3-6V,這裏建議用單片機的3.3V就好。
  • B1是模擬輸出。
  • B2是高有效使能端口,T_ON數字輸入經過控制與內部溫度傳感器電路輸出串聯的內部開關的狀態來啓用和禁用TAO引腳上提供的模擬輸出電壓。 當T_ON被驅動爲邏輯「高」時,TAO引腳上會出現溫度傳感器的輸出電壓。 當T_ON設置爲邏輯「低」時,TAO引腳設置爲高阻抗狀態。這裏咱們默認接高就好了。

二、測量精度

  這款芯片的測量精度已經在數據手冊中給出,以下表。例如:當咱們在被測物體溫度在20℃到42℃之間、芯片的供電電壓在2.7V時,測量的偏差在±0.05攝氏度。【精度定義爲在指定的電源電壓和溫度(以°C表示)條件下,轉換表中列出的測量輸出電壓與參考輸出電壓之間的偏差。】可見這款的芯片測溫的精度仍是很是高的。es5


  在數據手冊中咱們該能夠知道芯片的溫度—模擬輸出的大體對應關係:
spa

電氣特性溫度查詢表(LUT)

  也能夠經過查詢電氣特性溫度查詢表來獲得溫度值設計

LUT

  以室溫爲30℃爲例,在溫度爲30℃時,單片機的ADC採樣出來的最小值爲942.547,採樣最大值爲943.902,典型值也就是通常狀況下的採樣值爲943.227。知道了這個表,經過這個表和ADC採樣出來的值就能夠對應具體的溫度值了。3d

三、功能說明

3.1 溫度模擬輸出(TAO)

  TAO推輓輸出提供吸取和拉出電流的能力。 例如當在模數轉換器上驅動動態負載(例如輸入級)時,這將很是有用。 在應用中,須要電源電流以快速爲ADC的輸入電容器充電。code

3.2 LMT70輸出傳遞函數

  LMT70輸出電壓傳遞函數彷佛是線性的,但仔細檢查後發現它不是線性的,能夠用二階或三階傳遞函數方程更好地描述。blog


  可使用一階傳遞函數來計算LMT70所感測的溫度,可是在較寬的溫度範圍內,它是最不許確的方法。所以咱們的程序中至少也須要採用二階函數。使用在電氣特性溫度查找表(LUT)中找到的LUT(查找表)信息能夠輕鬆生成方程式。
ip

  在狹窄的10°C溫度範圍內,線性方程將得出很是準確的結果。 實際上,建議在10°C的溫度範圍內使用線性差值來計算設備所感測的溫度。 使用此方法時,最小和最大精度指標將知足圖3中給出的值。例如,可使用電氣特性溫度查找表(LUT)中給出的典型輸出電壓電平來生成20°C至30°C之間的一階方程式,例如假設待測物體的溫度爲20°C至50°C:

3.2.1 二階傳遞函數

  二階傳遞函數能夠在更寬的有限溫度範圍內提供良好的結果。 在-55°C至+ 150°C的整個溫度範圍內,單個二階傳遞函數在極端溫度下的偏差會增長。 使用最小二乘和方法,使用電氣特性溫度查找表(LUT)中的值生成了最合適的二階傳遞函數:

其中a,b,c的參數以下表:



3.2.3 三階傳遞函數

  在較寬的溫度範圍內,最精確的單個方程式是三階傳遞函數。 使用最小二乘和方法,使用圖3中的值生成了最合適的三階傳遞函數:

其中a,b,c,d的參數以下表:

  注意V_TAO的單位是mV,TM的單位是℃。



在電賽中建議使用三階方程,使用三階方程的精度確定比二階方程的精度要高,同時在這個方程中V_TAO是單片機採樣獲得的電壓(單位爲mV),a、b、c、d四個參數在表中是已知的。咱們只須要把採樣獲得的電壓值放進這個公式就能夠獲得被測物體的溫度。

四、電路圖

  TAO引腳上的負載電容器能夠幫助濾除噪聲,建議至少在LMT70的VDD和GND引腳之間放置至少100nF的電源去耦電容。

  TAO能夠很好地處理電容性負載。 在嘈雜的環境中,或者在ADC上驅動開關採樣輸入時,可能須要添加一些濾波以最大程度地下降噪聲耦合。 在沒有任何預防措施的狀況下,VTAO能夠驅動小於或等於1 nF的電容性負載。對於大於1nF的電容性負載,輸出端須要一個串聯電阻,以保持條件穩定。

小於或等於1nF的電容性負載 大於1nF的電容性負載

五、程序

若是單單是獲得LMT70的溫度,只須要一個ADC採樣便可。這種採樣程序在正點原子和野火的例程中都有,再加上一個三階線性函數便可,程序的大致框架以下(僅供參考):

ADC.c文件

/************************************************************************** * 文 件 名: adc.c * 使用芯片: STM32F103C8T6 * 硬件鏈接: ADC--PB0 * 描述功能: ADC檢測電池電壓,使用一個分壓電阻 * 日 期: 2018/12/22 * 做 者: 劉堯 * B 站: 果果小師弟 * 版 本: V1.0 * 修改記錄: 無 **************************************************************************/
#include "adc.h"
#include "delay.h"
void  Adc_Init(void)
{     
 	ADC_InitTypeDef ADC_InitStructure; 
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1, ENABLE );	  //使能ADC1通道時鐘
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //設置ADC分頻因子6 72M/6=12,ADC最大時間不能超過14M
	
	//PA0做爲模擬通道輸入引腳 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;		//模擬輸入引腳
	GPIO_Init(GPIOA, &GPIO_InitStructure);	
	
	//PA1做爲模擬通道輸入引腳 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;		//模擬輸入引腳
	GPIO_Init(GPIOA, &GPIO_InitStructure);	
	
	//PA2做爲模擬通道輸入引腳 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;		//模擬輸入引腳
	GPIO_Init(GPIOA, &GPIO_InitStructure);	
	
	ADC_DeInit(ADC1);  //復位ADC1,將外設 ADC1 的所有寄存器重設爲缺省值
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	//ADC工做模式:ADC1和ADC2工做在獨立模式
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;	//模數轉換工做在單通道模式
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;	//模數轉換工做在單次轉換模式
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//轉換由軟件而不是外部觸發啓動
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	//ADC數據右對齊
	ADC_InitStructure.ADC_NbrOfChannel = 1;	//順序進行規則轉換的ADC通道的數目
	ADC_Init(ADC1, &ADC_InitStructure);	//根據ADC_InitStruct中指定的參數初始化外設ADCx的寄存器 
	ADC_Cmd(ADC1, ENABLE);	//使能指定的ADC1
	ADC_ResetCalibration(ADC1);	//使能復位校準 
	while(ADC_GetResetCalibrationStatus(ADC1));	//等待復位校準結束 
	ADC_StartCalibration(ADC1);	 //開啓AD校準
	while(ADC_GetCalibrationStatus(ADC1));	 //等待校準結束
}		

/************************************************************************** 函數功能:AD採樣 入口參數:ADC1 的通道 返回 值:AD轉換結果 **************************************************************************/
u16 Get_Adc(u8 ch)   
{ 
	//設置指定ADC的規則組通道,一個序列,採樣時間
	ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );	//ADC1,ADC通道,採樣時間爲239.5週期 
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的軟件轉換啓動功能 
	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待轉換結束
	return ADC_GetConversionValue(ADC1);	//返回最近一次ADC1規則組的轉換結果
}
/************************************************************************** 函數功能:讀取ADC的具體值 入口參數:無 返回 值:電池電壓 單位MV **************************************************************************/

u16 Get_Adc_Average(u8 ch,u8 times)
{ 
	u32 temp_val=0;
	u8 t;
	for(t=0;t<times;t++)
	{  
		temp_val+=Get_Adc(ch);
	    delay_ms(5);
	}
	return temp_val/times;
}	

/************************************************************************** 函數功能:讀取ADC1的電壓 入口參數:無 返回 值:電池電壓 單位MV **************************************************************************/
float Get_Adc_Value_mV(u8 ch)
{ 
	float temp_val=0;

	temp_val=Get_Adc(ch)*3300/4096;//arduino的ADC有12位2^12=4096,3表明量程是0-3.3V

	return temp_val;
}

main.c文件

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h" 
#include "oled.h"
#include "adc.h"
#include "math.h"
#include "stdio.h"

double a= -1.064200E-09;
double b= -5.759725E-06;
double c= -1.789883E-01;
double d=  2.048570E+02;

//溫度的單位 ℃
uint8_t TempCompany[][16]=
{ 
	0x06,0x09,0x09,0xE6,0xF8,0x0C,0x04,0x02,0x02,0x02,0x02,0x02,0x04,0x1E,0x00,0x00,
	0x00,0x00,0x00,0x07,0x1F,0x30,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x10,0x00,0x00,/*"℃",0*/

};
int main(void)
{ 	
	uint8_t i,j;	
	float V_TAO;
    float T_m;	
	char value_A0[80] = { 0}; 
	char value_Tm[80] = { 0}; 
	delay_init();	//延時函數初始化 
	uart_init(9600);//串口初始化爲9600
	OLED_Init()	;
	OLED_Clear() ;
 	LED_Init();	//LED端口初始化
	Adc_Init();
	display();
	while(1)
	{ 	
		//溫度單位顯示(℃)
		for(i = 7;i < 8;i++)
		{ 
			j = i - 7;
			OLED_ShowCHinese16x16(i*16,4,j,TempCompany);			
		}
		V_TAO=Get_Adc_Value_mV(1);	
		T_m=a*(V_TAO)*(V_TAO)*(V_TAO)+b*(V_TAO)*(V_TAO)+c*(V_TAO)+d;
		sprintf(value_A0,"%0.f", V_TAO); //浮點型轉換成字符串
	    sprintf(value_Tm,"%0.1f", T_m);  //浮點型轉換成字符串 
		OLED_ShowString(0,2,"ADC_mV:",16);//在OLED上顯示字符串Temperature
		OLED_ShowString(0,4,"Tempte:",16);//在OLED上顯示字符串Temperature
		OLED_ShowString(60,2,(uint8_t *)value_A0,16);//oled顯示電壓
		OLED_ShowString(60,4,(uint8_t *)value_Tm,16);//oled顯示溫度
		printf("如今溫度%.2f度,電壓%.2f\r\n",T_m,V_TAO);
		OLED_ShowString(10,6,"liuyao-blog.cn",16);//在OLED上顯示字符串Temperature
		delay_ms(1000);		
	}
}

完整程序請後臺回覆:LMT70,便可免費獲取測溫代碼。程序所使用的單片機是STM32F103C8T6,顯示屏爲0.96寸OLED。代碼測溫準確,僅供參考。

相關文章
相關標籤/搜索