1
传感器
DHT11数字温度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个8位单片机相连接。该产品具有通信便捷、超快响应、抗干扰能力强等优点。每个DHT11传感器都在OTP内存中存入了在湿度校验室中获得的校准系数。校准系数以程序的形式储存,在传感器内部在检测信号的处理过程中要调用这些校准系数。单总线串行接口,仅需1个I/O口即可实现对温度和湿度的同时测量,使系统集成变得简易快捷,小体积、低功耗,信号传输距离远(20米以上),使其成为一种温湿度测量原件的不错选择。产品外观如图所示
备注:由图一,传感器引脚顺序从左到右依次为VCC,DAT,NC,GND,DHT11的供电电压为3-5.5V。传感器上电后,要等待1s以越过不稳定状态在此期间无需发送任何指令。电源引脚(VDD,GND)之间可增加一个100nF的电容用以去耦滤波。
测量条件:VDD=5V,T=25℃
建议连接线长度短于20米时用5K上拉电阻,大于20米时根据实际情况使用合适的上拉电阻(若购买的是已集成的模块,模块上已加上拉电阻,以下请忽略),当然,如果你想要精简电路的话,STC增强型单片机自带的推挽输出功能不失为一个选择,其相当于外接了一个2k的上拉电阻,但在设计电路时需注意:整个单片机的电流推荐不超过55mA,即从MCU-VCC流入的电流不超过55mA,从MCU-GND流出的电流不超过55mA,整体流入、流出电流均不超过55mA,封装尺寸及典型应用电路图如图所示。
arduinoUNO、面包板、DHT11温湿度传感器、连接线
这里说一下DHT11的基本情况:
(1)引脚说明:
1、VDD供电3.5V-5.5VDC
2、DATA串行数据,单总线
3、GND接地,电源负极。
(2)DHT11data数据格式:
一次传输40位数据=8bit湿度整数数据+8bit湿度小数数据+8bint温度整数数据+8bit温度小数数据+8bit校验位
3、时序图
如图所示,将DHT11的正极与5V电源接口相连,负极与GND相连,中间的数据接口与2号引脚相连。
#include《dht11.h》
dht11DHT11;
#defineDHT11PIN2
voidsetup(){
Serial.begin(9600);
}
voidloop(){
Serial.println(“/n”);
intchk=DHT11.read(DHT11PIN);
Serial.print(“Readsensor:”);
switch(chk)
{
caseDHTLIB_OK:
Serial.println(“OK”);
break;
caseDHTLIB_ERROR_CHECKSUM:
Serial.println(“Checksumerror”);
break;
caseDHTLIB_ERROR_TIMEOUT:
Serial.println(“Timeouterror”);
break;
default:
Serial.println(“Unknownerror”);
break;
}
Serial.print(“Humidity(%):”);
Serial.println((float)DHT11.humidity,2);
Serial.print(“Temperature(oC):”);
Serial.println((float)DHT11.temperature,2);
delay(2000);
}
1、代码中引用了#include《dht11.h》,这个是操作DHT11的库文件,有了它,就可以轻松操作我们这个温湿度传感器了。但是引用这个库文件的操作步骤是:
(1)在网上找到并下载该库文件,包括一个头文件和一个.cpp文件。
(2)在arduinoIDE中点击菜单:程序–导入库–addlibrary,然后选择你存放库文件的那个文件夹。
(3)在代码中引用#include《dht11.h》,这样就可以使用了。
2、#defineDHT11PIN2,表示定义引脚2的名字为DHT11PIN,注意这个定义语句后面没有分号。
在硬件编程过程中,当你拿到一个器件,首先要了解他的引脚定义,这会告诉你这个东西应该怎么连接,在一个就是要看他的时序图,看了时序图你就知道主从设备之间进行数据采集过程中的代码应该怎么写,比如怎么启动,如何握手,怎么采集真正的数据等等。
在我们这个试验中,DHT11的时序图是这样的:
下面对照dht11.cpp源代码说说我们采集温湿度信息的原理(在代码中加了注释,说明相关内容。):
#include“dht11.h”
intdht11::read(intpin)
{
//BUFFERTORECEIVE
uint8_tbits[5];//这里定义了5个八位的数组,也就是40位数据,用来存储数据采集的结果。
uint8_tcnt=7;//这个是用来给每一个数据的每一位输入值时计数用的。
uint8_tidx=0;//这个是给5个数组计数用的。
//EMPTYBUFFER
for(inti=0;i《5;i++)bits[i]=0;
//首先在这里把这5个八位的数组全部填0,也就是初始值为0.
//REQUESTSAMPLE
pinMode(pin,OUTPUT);
//将引脚定义为输出,也就是由arduino给DHT11写数据。从上面的时序图可以看出,要启动DHT11首先要给他发送18毫秒的低电平,再发送20~40微秒的高电平,DHT11只有看到了这样的信号,才会采集数据。
digitalWrite(pin,LOW);
delay(18);//这里就是发送18毫秒的低电平
digitalWrite(pin,HIGH);
delayMicroseconds(40);//这里就是发送40微秒的高电平
pinMode(pin,INPUT);
//发送完之后,这就等于把DHT11启动了,这时候我们就要从这个引脚上接受数据了,所以这时候要将这个引脚定义为输入引脚。
//ACKNOWLEDGEorTIMEOUT
unsignedintloopCnt=10000;
while(digitalRead(pin)==LOW)
if(loopCnt--==0)returnDHTLIB_ERROR_TIMEOUT;
//从时序图中可以看出,接受数据一开始首先要读取80微秒的低电平,这里是一个等待,要把这80微秒等过去,但是有时候也有可能是传感器出现了故障,他一直发低电平,如果你持续等待不就相当于死机了,所以在这里要设置一个超时,也就是说要等待,但时间长了,就认为出问题了,返回一个异常信息。
loopCnt=10000;
while(digitalRead(pin)==HIGH)
if(loopCnt--==0)returnDHTLIB_ERROR_TIMEOUT;
//从时序图中可以看出,在80微秒的低电平之后是80微秒的高电平,这里仍然要等待,超时的原理与上面的低电平一样。
//READOUTPUT-40BITS=》5BYTESorTIMEOUT
//根据时序图,从下面开始就是40位的真正要读取的数据了,那么这里用了一个for循环来一位一位的读取这40bit的数据(注意是bite)。
for(inti=0;i《40;i++)
{
//根据时序图,可以看出,对于每一个bite位数据,都是由一个低电平和一个高电平组成,区分这一位数据是1还是0取决于高电平的时常,如果高电平的时常为70微秒则表示1,如果高电平的时常为26~28微秒则表示0,因此读取每一位数据时,都是先等待把50微秒的低电平等过去,然后判断高电平的时常,根据这个时常来判断这bite的数据是1还是0.
loopCnt=10000;
while(digitalRead(pin)==LOW)
if(loopCnt--==0)returnDHTLIB_ERROR_TIMEOUT;
//这一句就是要把低电平等过去。
unsignedlongt=micros();
//这里使用函数micros()获取了一个当前的时间,就是为了比较高电平的时常用的。
loopCnt=10000;
while(digitalRead(pin)==HIGH)
if(loopCnt--==0)returnDHTLIB_ERROR_TIMEOUT;
//这里就把高电平读出来了。
if((micros()-t)》40)bits[idx]|=(1《《cnt);
//然后再次使用micros()函数获取当前时间,减去读取高电平之前的时间点,也就是这个高电平的时常了,然后看这个时常是否大于40微秒,如果大于就认为是1,否则就认为这位是0.那么这里又是怎么运算的呢?分析下:bits[idx]表示一个8位的数组,假设他是00000000,运算符“|=”表示按位进行或运算,然后再把运算的结果赋给运算符左边的变量。而(1《《cnt)表示把数字1的二进制表示法向左移动cnt位,移动后的空位用0来填充。因此,对于一个八位的1可以表示为:00000001,刚才的初始化过程中我们知道cnt的值为7,所以,把这个00000001左移七位就变成了:10000000.然后将这个数与00000000进行|=运算,之后bits[idx]中的值就是10000000。可见这段代码实现的功能就是如果的到的这位数据是1,就将他存储到bits[idx]相应的位上去。
//下面这段代码就是在循环的过程中修改cnt和idx的值,然后进行一位一位的读数而已。
if(cnt==0)//nextbyte?
//cnt为0表示一个8位的数组已经装满了,要换到下一个八位的数组上去,于是就把cnt复原为7,idx++让idx直到bits的下一个八位的数组上去。
{
cnt=7;//restartatMSB
idx++;//nextbyte!
}
elsecnt--;
//如果cnt不为0就表示这个八位的数据还没有读完,这时只需要让cnt-1,来填充下一位数据就可以了。
//注意,在初始化的过程中我们把这40位的数据都初始化为0了,所以只有当有1出现时才需要进行改变。
}
//WRITETORIGHTVARS
//asbits[1]andbits[3]areallwayszerotheyareomittedinformulas.
//从开始的时候的原理中我们知道这40位数据第1个8位是湿度的整数部分,第3个8位是温度的整数部分,下面这两句代码就是把数据分别放在这两个变量里了。
humidity=bits[0];
temperature=bits[2];
uint8_tsum=bits[0]+bits[2];
if(bits[4]!=sum)returnDHTLIB_ERROR_CHECKSUM;
returnDHTLIB_OK;
//最后再用校验和验证一下数据是否正确。
}
//
//ENDOFFILE
//
通电之后,在电脑上打开串口就可以看到采集到的温湿度信息。
全部0条评论
快来发表一下你的评论吧 !