初玩树莓派 B 7物联网温湿度监控 bbs.pediy.com 这一节用温湿度传感器接入中移动物联网上报家中的温湿度。1 dht11传感器使用简介 DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。我购买的dht11只有三个针脚分别是 VCC DATA GND,(有些是四阵脚的,多一个NC空脚)。 常用电路图。 前面我们已经玩了一些常用模块,接线都比较熟悉了。正极接3.3V,负极接GND,DATA(OUT)针脚我接了物理的11号针脚,对应于WiringPi标号是0,同时为DATA针脚接入一个5K欧姆的上拉电阻,使得空闲状态的时候为高电平。 对于之前使用的一些模块,我们只需要知道高低电平就可以了,现在要得到的是温度和湿度的具体数据,那么如何通过DATA针脚得到温度和湿度呢?通过DATA针脚采用单总线格式进行数据通讯。依次完整的数据传输为40bit,先读出来的是高位的数据。40bit数据的格式是:8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验和。如果数据是准确的,那么8bit湿度整 8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据的结果的末8位等于8bit校验和。 通讯过程如下,主机首先向传感器发送开始信号,等开始信号发送完毕以后。dht11发送响应信号,依次传回40bit的数据,随后进入空闲状态。 沟通握手过程如下,初始空闲状态DATA为高电平,主机将DATA拉低等待DHT11响应,拉低的时间必须大于18ms保证DHT11可以检测到这个状态。随后dht11等待开始信号结束,主机可以通过拉高电平20-40us表明信号结束。以后就可以准备读取dht11的响应信号了。dht11会发送80us的低电平来响应然后dht11再次将电平拉高持续80us表示后面的数据传输要开始了。 通讯过程如下:dht11每次传输1bit数据的过程是先拉低电平50us。随后拉高电平,高电平的时间长短决定了这1bit的数据是0还是1。当最后一个bit的数据传输完毕以后,dht11拉低电平50ms。随后上拉电阻拉高进入空闲状态。一次数据传输过程完毕。 传输0的过程: 传输1的过程: 关键部分代码如下。
/* 当检测到的状态不是state的时候就返回。 如果参数state是HIGH,那么需要等到检测到LOW的时候返回。 返回值代表了状态改变所用的时间计数。 返回值如果是-1 表明和设备通讯出现了错误,需要重新开始通讯。 */ int loopCheckUntilStateChange(int state) { //初始时间计数为0 int count=0; //读取针脚的状态 while(digitalRead(DHT11PIN)==state) { //如果状态没变那么计数加1 count++; //如果计数超过了最大的计数,表明通讯错误,需要重新开始 if(count>MAX_COUNT) return -1; //延时1微秒。 delayMicroseconds(1); } return count; } /* 读取DHT11。如果读取成功,返回true,否则false。将温度放到 ptemp,将湿度放到 phumi */ bool readDHT11(float* ptemp,float* phumi) { int count=0,ibit=0; bool bret=false; //保存电平改变所用的时间计数 int bitsz[40]={0}; //保存读取到的4个温湿度数据和1个校验码 int data[5]={0}; //首先设置为输出模式 pinMode(DHT11PIN,OUTPUT); //写入低电平 digitalWrite(DHT11PIN,LOW); //低电平至少持续18ms。保证能够DHT检测到这个初始信号 delay(20); //随后主机将电平拉高,通知DHT信号结束 digitalWrite(DHT11PIN,HIGH); //将针脚转为输入模式,等待DHT的响应。 pinMode(DHT11PIN,INPUT); //经过20-40us,我们需要等待DHT将电平从高电平拉低 if(loopCheckUntilStateChange(HIGH)<0) { return bret; } //DHT的响应信号低电平持续80us,等待DHT再次由低拉高 if(loopCheckUntilStateChange(LOW)<0) { return bret; } //高电平将持续80us,等待DHT将高电平拉低。开始传输数据 if(loopCheckUntilStateChange(HIGH)<0) { return bret; } //数据传输开始。每次传输一个bit。一共40bit。5字节 for(ibit=0;ibit<40;ibit++) { //每个bit传输由50us的低电平开始。变为高电平就是开始传输0或者1了。 if(loopCheckUntilStateChange(LOW)<0) { return bret; } //这次我们要检测高电平到低电平经过了多少个计数的count //以此来决定这一bit是0还是1 count=loopCheckUntilStateChange(HIGH); //如果小于0,出错了 if(count<0) { return bret; } //将高电平持续的count保存在bitsz里面。 bitsz[ibit]=count; } /* 定义了区别 0 和1 的count 阈值。这个阈值要根据实际情况和你写的函数调整。 比如 loopCheckUntilStateChange里面如果没有delayMicroseconds(1);完全跑CPU,那么count值会比较大。 如果有delayMicroseconds(1)那么这个值会小一些。 */ #define THRESHOLD 20 for(ibit=0;ibit<40;ibit++) { /* 将data左移1位,因为ibit的传输是从高位到低位 每次填充后就要移动一次。 ibit/8 确定是第几个data */ data[ibit/8]<<=1; /* 根据传输时高电平占用时间的count来确定这个bit是0还是1 THRESHOLD阈值根据不同的情况来确定,1的时间长,count大。0的时间短。count小。确定 一个中间的值即可 */ if(bitsz[ibit]>THRESHOLD) { //如果超过了阈值。说明这一位是1。否则什么都不做。默认就是0了 data[ibit/8]|=1; } } //检查校验码。查看整个数据是否传输准确了 if(data[4]!=(data[3]+data[2]+data[1]+data[0])&0xff) { return bret; } /* 由于dht11设备默认小数位为0,没有小数位.所以这里小数位就不要了。只有整数位的温度和湿度。 否则就是(%d.%d data[0].data[1])湿度 (%d.%d data[2].data[3])温度 */ *ptemp=data[2]*1.0; *phumi=data[0]*1.0; return true; }
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
请教大神,你.c文件里面的#include <curl/curl.h>头文件是什么来的?我编译了一下提示没有这个头文件,求回答,感谢!