MLX90614
系列红外测温模块的原理及应用
南京航空航天大学 曾德志
摘要:
MLX90614
系列模块是一组通用的红外测温模块。在出厂前该模块已进行校验及线
性化,具有非接触、体积小、精度高,成本低等优点。被测目标温度和环境温度能通过单通
道输出,并有两种输出接口,适合于汽车空调、室内暖气、家用电器、手持设备以及医疗设
备应用等。本文以
MLX90614AAA
为例介绍其原理和应用。
1 引言
一般来说,测温方式可分为接触式和非接触式,接触式测温只能测量被测物体与测温传
感器达到热平衡后的温度,所以响应时间长,且极易受环境温度的影响;而红外测温是根据
被测物体的红外辐射能量来确定物体的温度,不与被测物体接触,具有影响动被测物体温度
分布场,温度分辨率高、响应速度快、测温范围广、不受测温上限的限制、稳定性好等特点,
近年来在家庭自动化、汽车电子、航空和军事上得到越来越广泛的应用。
2
测温原理概述
物体红外辐射能量的大小和波长的分布与其表面温度关系密切。因此,通过对物体自身
红外辐射的测量,能准确地确定其表面温度,红外测温就是利用这一原理测量温度的。红外
测温器由光学系统、光电探测器、信号放大器和信号处理及输出等部分组成。光学系统汇聚
其视场内的目标红外辐射能量,视场的大小由测温仪的光学零件及其位置确定。红外能量聚
焦在光电探测器上并转变为相应的电信号。该信号经过放大器和信号处理电路,并按照仪器
内的算法和目标发射率校正后转变为被测目标的温度值。
PWM
的全称是
Pulse Width Modulation
(脉冲宽度调制)即通过调节脉冲的周期、宽度,
以达到变压、变频的目的,数字式脉宽调制方式中,数字是控制信号,通过改变高低电平数
的比值达到改变占空比的目的,
PWM
控制电路在开关稳压电源、不间断电源(
UPS
)以及
直流电机调速,交流电机变频调速等控制电路中有着广泛应用。
SMBus
(
System Management Bus
,)是
1995
年由
intel
公司提出的一种高效同步串行总线,
SMBus
只有两根信号线
:
双向数据线和时钟信号线,容许 CPU 与各种外围接口器件以串行方
式进行通信、交换信息,即可以提高传输速度也可以减小器件的资源占用,另外即使在没有
SMBus
接口的单片机上也可利用软件进行模拟。
Melexis
公司生产的
MLX90614
系列测温模块是应用非常方便的红外测温装置,其所有
的模块都在出厂前进行了校验,并且可以直接输出线性或准线性信号,具有很好的互换性,
免去了复杂的校正过程。
该模块以
81101
热电元件作为红外感应部分。输出是被测物体温度(
TO
)与传感器自身
温度(
Ta
)共同作用的结果,理想情况下热电元件的输出电压为:
)(
44
TaToAVir
−=
其中温度单位均为
Kelvin
,
A
为元件的灵敏度常数。
目标温度和环境温度由
81101
内置的热电偶测定测量,从
81101
中输出的两路温度信号
分别经内部
MLX90302
器件上高性能、低噪声的斩波稳态放大器放大再经一个
17-bit
的模
数转换器(
ADC
)和强大的数字信号处理
(DSP)
单元后输出。
该系列模块的温度解析度可达
0.01°C
,体积小巧,被测目标和环境温度能通过单通道
(由
MLX90302
内的状态机控制)输出,有两种输出方式:
PWM
输出、可编程
SMBus
输
出,适于多种应用环境,下面以
MLX90614
为例,重点介绍其特性和使用方法。
通过
SMBus
编程可以更改模块
EEPROM
内的预设值并按照应用要求进行配置,并可
以读出
EEPROM
内的配置信息;还可以读出模块
RAM
内温度等数据。
MLX90614
有适用于
3
伏和
5
伏电源操作的两种类型。由于
3
伏型其小于
2
毫安的电流
消耗,它非常适用于手提装置和电池动力装置。为此,传感器也具有一个节能“休眠”模式,
此时电流消耗可低于
2
毫安。对于
12
伏汽车电池直接供电的情况,
5
伏型包含的电子部件
可与几个外部元件一起在较高电压下运行。
3
MLX90614
简介
3.1 MLX90614
管脚
表
1 MLX90614
的管脚功能
名称
功能描述
VSS
电源地,金属外壳和该管脚相连
SCL/Vz
SMBus
接口的时钟信号,或
8-16V
电源供电时接三极管基极
PWM/SDA
PWM
或
SMBus
接口的数据信号,通常模式下从该管脚通过
PWM
输出物体温度
VDD
电源
3.2 MLX90614
存储器
3.2.1 EEPROM
只有某些存储单元用户能够写入,但是可以读出全部存储单元。
MLX90614
的
EEPROM
有
32
个
16
位存储单元,其中存储单元
Tomax,Tomin,Ta
分
别是
用户物体温度上下限和环境温度范围,
PWMCTRL
是
PWM
配置寄存器。
3.2.2 RAM
用户不能向
RAM
写入数据,但是可以读一些存储单元。
MLX90614
的
RAM
有
32
个
17
位存储单元,其中
T
A
,T
OBJ1
,T
OBJ2
是环境温度和物体温度
,
在
SMBus
方式下,可以从这几个存储单元读出环境和被测物体的温度。
4
应用设计
4.1 MLX90614
测温特性
4.1.1 MLX90614
的
SMBus
协议
图
2 SMBus
的数据包组成
4.1.2
读器件(命令决定是读
RAM
或
EEPROM
)数据格式
4.1.3
写器件(命令决定是写
RAM
或
EEPROM
)数据格式
4.1.4
数据传输时序
图
3 MLX90614
的数据传输时序
PWM/SDA
上的数据在
SCL
变为低电平
300n
后即可改变,数据在
SCL
的上升沿被捕
获。
16
位数据分两次传输,每次传一个字节。每个字节都是按照高位
(MSB)
在前,低位
(LSB)
在后的格式传输,两个字节中间的第九个时钟是应答时钟。
4.2
单片机接口电路
MLX90614AAA
与单片机连接的硬件电路如图
4
所示。
SCL
、
PWM/SDA
管脚直接连接
MCU
的普通
I/O
口即可,由于
MLX90614AAA
的输入输出接口是漏级开路(
OD
)结构,
需要加上拉电阻。多个
MLX90614
可以用于一个系统中,每个
MLX90614
对应一个不同地
址,通过地址的不同而访问不同的
MLX90614
,最多可以达到
127
个。
图
4 MLX90614AAA
与单片机连接电路
4.3
软件流程图
多个
MLX90614
可以用于一个系统中,通过地址不同区分器件,器件默认的地址为
5AH
,
因此在多
MLX90614
系统中,需要给每个
MLX90614
分配一个不同的地址,在只有一个
MLX90614
的系统中,
MLX90614
识别地址
00h
,即在单个
MLX90614
系统中,可以使用该
地址访问它。
发送和接收数据是以字节为单位进行的,程序流程如图
7
、图
8
所示。每次发送一个字
节(按位发送,发送
8
个位就是一个字节),然后就判断对方是否有应答,如果有应答,就
接着发送下一个字节;如果没有应答,多次重发该字节,直到有应答,就接着发送下一个字
节,如果多次重发后,仍然没有应答,就结束。接收数据时,每次接收一个字节(按位接收,
接收
8
个位就是一个字节),然后向对方发送一个应答信号,然后就可以继续接收下一个字
节。
从
MLX90614
种读出的数据是
16
位的,由高
8
位(
DataH
)和低
8
位(
DataL
)两部分组
成,其中
RAM
地址
07H
单元存储的是
T
OBJ1
数据,数据范围从
0x27AD
到
0x7FFF,
表示的温度
范围是
-70.0
1℃到
+382.19
℃。
图
7
发送字节流程图
图
8
接收字节流程图
从
MLX90614
中读出的数据
(DataH:DataL)
换算为温度数据
(T,
单位为℃
)
如下所示
:
T= (DataH:DataL)*0.02-273.15
式(
1
)
例如:
DataH:DataL=0x27AD
,代入式(
1
)中
T=-70.01
℃
C 语言程序清单:
单片机 89S52、MLX90614、LCD1602
晶振:12M
#include"at89x52.h"
#include"intrins.h"
//************************************
#define uint unsigned int
#define uchar unsigned char
#define Nack_counter 10
//**************
端口定义
**************
//LCD
控制线接口
uchar flag1;
sbit RS=P2^7;
sbit RW=P2^6;
sbit LCDE=P2^5;
//mlx90614
端口定义
sbit SCL=P2^3;//
时钟线
sbit SDA=P2^2;//
数据线
//************
数据定义
****************
bdata uchar flag;//
可位寻址数据
sbit bit_out=flag^7;
sbit bit_in=flag^0;
uchar DataH,DataL,Pecreg;
//************
函数声明
*****************************************
void start_bit(); //MLX90614
发起始位子程序
void stop_bit(); //MLX90614
发结束位子程序
uchar rx_byte(void); //MLX90614
接收字节子程序
void send_bit(void); //MLX90614
发送位子程序
void tx_byte(uchar dat_byte); //MLX90614
接收字节子程序
void receive_bit(void); //MLX90614
接收位子程序
void delay(uint N); //
延时程序
uint memread(void); //
读温度数据
void init1602(void); //LCD
初始化子程序
void chk_busy_flg(void); //LCD
判断忙子程序
void dis_cmd_wrt(uchar cmd); //LCD
写命令子程序
void dis_dat_wrt(uchar dat); //LCD
写数据子程序
void display(uint Tem); //
显示子程序
//*************
主函数
*******************************************
void main()
{
uint Tem;
//
函数部分
SCL=1;SDA=1;_nop_();
_nop_();_nop_();_nop_();
SCL=0;
delay(1000);
SCL=1;
init1602();
while(1)
{
Tem=memread();
display(Tem);
delay(20);
}
}
//*********
输入转换并显示
*********
void display(uint Tem)
{
uint T,a,b;
T=Tem*2;
dis_cmd_wrt(0x01);//
清屏
if(T>=27315)
{
T=T-27315;
a=T/100;
b=T-a*100;
//---------------------------
if(a>=100)
{
dis_dat_wrt(0x30+a/100);
a=a%100;
dis_dat_wrt(0x30+a/10);
a=a%10;
dis_dat_wrt(0x30+a);
}
else if(a>=10)
{
dis_dat_wrt(0x30+a/10);
a=a%10;
dis_dat_wrt(0x30+a);
}
else
{
dis_dat_wrt(0x30+a);
}
dis_dat_wrt(0x2e);//
显示点
//---------------------------
if(b>=10)
{
dis_dat_wrt(0x30+b/10);
// b=b%10;
// dis_dat_wrt(0x30+b);
}
else
{
dis_dat_wrt(0x30);
// dis_dat_wrt(0x30+b);
}
}
//===========================
else
{
T=27315-T;
a=T/100;
b=T-a*100;
dis_dat_wrt(0x2d);
//--------------------------
if(a>=10)
{
dis_dat_wrt(0x30+a/10);
a=a%10;
dis_dat_wrt(0x30+a);
}
else
{
dis_dat_wrt(0x30+a);
}
dis_dat_wrt(0x2e);//
显示点
//--------------------------
if(b>=10)
{
dis_dat_wrt(0x30+b/10);
b=b%10;
dis_dat_wrt(0x30+b);
}
else
{
dis_dat_wrt(0x30);
dis_dat_wrt(0x30+b);
}
}
}
//************************************
void start_bit(void)
{
SDA=1;
_nop_();_nop_();_nop_();_nop_();_nop_();
SCL=1;
_nop_();_nop_();_nop_();_nop_();_nop_();
SDA=0;
_nop_();_nop_();_nop_();_nop_();_nop_();
SCL=0;
_nop_();_nop_();_nop_();_nop_();_nop_();
}
//------------------------------
void stop_bit(void)
{
SCL=0;
_nop_();_nop_();_nop_();_nop_();_nop_();
SDA=0;
_nop_();_nop_();_nop_();_nop_();_nop_();
SCL=1;
_nop_();_nop_();_nop_();_nop_();_nop_();
SDA=1;
}
//---------
发送一个字节
---------
void tx_byte(uchar dat_byte)
{
char i,n,dat;
n=Nack_counter;
TX_again:
dat=dat_byte;
for(i=0;i<8;i++)
{
if(dat&0x80)
bit_out=1;
else
bit_out=0;
send_bit();
dat=dat<<1;
}
receive_bit();
if(bit_in==1)
{
stop_bit();
if(n!=0)
{n--;goto Repeat;}
else
goto exit;
}
else
goto exit;
Repeat:
start_bit();
goto TX_again;
exit: ;
}
//-----------
发送一个位
---------
void send_bit(void)
{
if(bit_out==0)
SDA=0;
else
SDA=1;
_nop_();
SCL=1;
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
SCL=0;
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
}
//----------
接收一个字节
--------
uchar rx_byte(void)
{
uchar i,dat;
dat=0;
for(i=0;i<8;i++)
{
dat=dat<<1;
receive_bit();
if(bit_in==1)
dat=dat+1;
}
send_bit();
return dat;
}
//----------
接收一个位
----------
void receive_bit(void)
{
SDA=1;bit_in=1;
SCL=1;
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
bit_in=SDA;
_nop_();
SCL=0;
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
}
//------------
延时
--------------
void delay(uint N)
{
uint i;
for(i=0;i<N;i++)
_nop_();
}
//------------------------------
uint memread(void)
{
start_bit();
tx_byte(0x00); //Send SlaveAddress
tx_byte(0x07); //Send Command
//------------
start_bit();
tx_byte(0x01);
bit_out=0;
DataL=rx_byte();
bit_out=0;
DataH=rx_byte();
bit_out=1;
Pecreg=rx_byte();
stop_bit();
return(DataH*256+DataL);
}
//******************LCD
显示子函数
***********************
void init1602(void) //
初始化
LCD
{
dis_cmd_wrt(0x01);
dis_cmd_wrt(0x0c);
dis_cmd_wrt(0x06);
dis_cmd_wrt(0x38);
}
void chk_busy_flg(void) //LCD
忙标志判断
{
flag1=0x80;
while(flag1&0x80)
{
P0=0xff;
RS=0;
RW=1;
LCDE=1;
flag1=P0;
LCDE=0;
}
}
void dis_cmd_wrt(uchar cmd) //
写命令子函数
{
chk_busy_flg();
P0=cmd;
RS=0;
RW=0;
LCDE=1;
LCDE=0;
}
void dis_dat_wrt(uchar dat) //
写数据子函数
{
chk_busy_flg();
if(flag1==16)
{
P0=0XC0;
RS=0;
RW=0;
LCDE=1;
LCDE=0;
}
P0=dat;
RS=1;
RW=0;
LCDE=1;
LCDE=0;
}