温湿度传感器器件介绍
DHT11是一款含有已校准数字信号输出的温湿度复合传感器,它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性和卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。
温湿度传感器模块温湿度传感器器件
引脚说明
VCC 供电3.5V-5.5V DC
DATA 串行数据,单总线,必须接上拉电阻 5.1K左右,这样空闲时 DATA总是为高电平
GND 接地,电源负极
NC 空脚不连接
DHT11的工作原理
DHT11是通过单总线与微处理器通讯,只需要一根线,一次传送40位数据,高位先出。
数据格式
8bit湿度整数数据 + 8bit湿度小数数据 +8bit温度整数数据 + 8bit温度小数数据 + 8bit校验位。
校验算法
将湿度、温度的整数小数累加,只保留低8位。MCU与DHT11通信约定:主从结构,DHT11为从机,MCU作为主机,只有主机呼叫从机,从机才能应答。
详细流程
MCU发送起始信号 -> DHT响应信号 -> DHT通知MCU准备接受信号 ->DHT发送准备好的数据 ->DHT结束信号-> DHT内部重测环境温湿度数据并记录数据等待下一次MCU的起始信号。
由流程可知,每一次MCU获取的数据总是DHT上一次采集的数据,要想得到实时的数据,连续两次获取即可,官方不建议连续多次读取DHT,每次读取的间隔时间大于5秒就足够获取到准确的数据,上电时DHT需要1S的时间稳定。
MCU起始信号
1、设置DATA引脚为输出状态并输出高电平
2、再将DATA输出为低电平,持续时间大于18ms,此时DHT检测到后从低功耗模式->高速模式
3、DATA引脚设置为输入状态,由于上拉电阻的关系,DATA就变为高电平,从而完成一次起始信号。
响应信号、准备信号
(DHT在MCU DATA引脚输出低电平时,从低功耗模式转至高速模式,等待DATA引脚变为高电平)
1、DHT输出 80us低电平 作为应答信号
2、DHT输出 80us高电平 通知微处理器准备接受数据
3、连续发送 40位数据(上次采集的数据)
DHT数据信号
数据为“0”格式:50us的低电平 +26-28us的高电平
数据为“1”格式:50us的低电平 +70us的高电平
DHT结束信号
DHT的DATA引脚输出40位数据后,继续输出低电平50us后转为输入状态,由于上拉电阻,DATA随之变为高电平。DHT内部开始重测环境温湿度数据,并记录数据,等待外部的起始信号。
实验目的
利用温湿度传感器检测空间内的温度和湿度,传感器将数据收集到以后传到RaspberryPi开发板中,经过处理反映在LCD上,在LCD中第一行显示的是温度,第二行显示的湿度。
组件清单
u 面包板*1
u DHT11传感器*1
u 串行LCD1602*1
u 导线若干
连接
IO1(wiringPi)/18(BCM)
DATE(OUT)
C++部分代码
#include <stdio.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <string.h>
#include <stdlib.h>
#include "LiquidCrystal_I2C.h"
#include "dht11.h"
int main()
{
char val1[3],val2[3],val3[3],val4[3];
init();
delay(100);
wiringPiSetup();
while(1)
{
pinMode(1,OUTPUT); // set mode to output
digitalWrite(1, 1); // output a high level
delay(100);
if(readSensorData())
{
printf("RH:%d.%d\n",(int)(databuf>>24)&0xff,(int)(databuf>>16)&0xff);
printf("TMP:%d.%d\n",(int)(databuf>>8)&0xff,(int)databuf&0xff);
int2str((int)(databuf>>24)&0xff,val1);
int2str((int)(databuf>>16)&0xff,val2);
int2str((int)(databuf>>8)&0xff,val3);
int2str((int)(databuf)&0xff,val4);
write(0, 0,"RH: ");
write(5, 0,val1);
write(7, 0,".");
write(8, 0,val2);
write(0, 1,"TMP: ");
write(5, 1,val3);
write(7, 1,".");
write(8, 1,val4);
databuf=0;
delay(1000);
}
}
}
Python部分代码
- import RPi.GPIO as GPIO
-
- import time
-
- import LCD1602 as LCD
-
-
-
- DHTPIN = 18
-
- LCD.init_lcd()
-
- time.sleep(2)
-
- GPIO.setmode(GPIO.BCM)
-
-
- MAX_UNCHANGE_COUNT = 100
-
-
- STATE_INIT_PULL_DOWN = 1
-
- STATE_INIT_PULL_UP = 2
-
- STATE_DATA_FIRST_PULL_DOWN = 3
-
- STATE_DATA_PULL_UP = 4
-
- STATE_DATA_PULL_DOWN = 5
-
-
- def read_dht11_dat():
-
- GPIO.setup(DHTPIN, GPIO.OUT)
-
- GPIO.output(DHTPIN, GPIO.HIGH)
-
- time.sleep(0.05)
-
- GPIO.output(DHTPIN, GPIO.LOW)
-
- time.sleep(0.02)
-
- GPIO.setup(DHTPIN, GPIO.IN, GPIO.PUD_UP)
-
-
- unchanged_count = 0
-
- last = -1
-
- data = []
-
- while True:
-
- current = GPIO.input(DHTPIN)
-
- data.append(current)
-
- if last != current:
-
- unchanged_count = 0
-
- last = current
-
- else:
-
- unchanged_count += 1
-
- if unchanged_count > MAX_UNCHANGE_COUNT:
-
- break
-
-
- state = STATE_INIT_PULL_DOWN
-
-
- lengths = []
-
- current_length = 0
-
-
- for current in data:
-
- current_length += 1
-
-
- if state == STATE_INIT_PULL_DOWN:
-
- if current == GPIO.LOW:
-
- state = STATE_INIT_PULL_UP
-
- else:
-
- continue
-
- if state == STATE_INIT_PULL_UP:
-
- if current == GPIO.HIGH:
-
- state = STATE_DATA_FIRST_PULL_DOWN
-
- else:
-
- continue
-
- if state == STATE_DATA_FIRST_PULL_DOWN:
-
- if current == GPIO.LOW:
-
- state = STATE_DATA_PULL_UP
-
- else:
-
- continue
-
- if state == STATE_DATA_PULL_UP:
-
- if current == GPIO.HIGH:
-
- current_length = 0
-
- state = STATE_DATA_PULL_DOWN
-
- else:
-
- continue
-
- if state == STATE_DATA_PULL_DOWN:
-
- if current == GPIO.LOW:
-
- lengths.append(current_length)
-
- state = STATE_DATA_PULL_UP
-
- else:
-
- continue
-
- if len(lengths) != 40:
-
- print ("Data not good, skip")
-
- return False
-
-
- shortest_pull_up = min(lengths)
-
- longest_pull_up = max(lengths)
-
- halfway = (longest_pull_up + shortest_pull_up) / 2
-
- bits = []
-
- the_bytes = []
-
- byte = 0
-
-
- for length in lengths:
-
- bit = 0
-
- if length > halfway:
-
- bit = 1
-
- bits.append(bit)
-
- print ("bits: %s, length: %d" % (bits, len(bits)))
-
- for i in range(0, len(bits)):
-
- byte = byte << 1
-
- if (bits[i]):
-
- byte = byte | 1
-
- else:
-
- byte = byte | 0
-
- if ((i + 1) % 8 == 0):
-
- the_bytes.append(byte)
-
- byte = 0
-
- print (the_bytes)
-
- checksum = (the_bytes[0] + the_bytes[1] + the_bytes[2] + the_bytes[3]) & 0xFF
-
- if the_bytes[4] != checksum:
-
- print ("Data not good, skip")
-
- return False
-
-
- return the_bytes[0], the_bytes[2]
-
-
- def main():
-
- print ("Raspberry Pi wiringPi DHT11 Temperature test program\n")
-
- while True:
-
- result = read_dht11_dat()
-
- if result:
-
- humidity, temperature = result
-
- print ("humidity: %s %%, Temperature: %s C`" % (humidity, temperature))
-
- LCD.print_lcd(0,0,'HUM: ' + str(humidity) + ' %')
-
- LCD.print_lcd(0,1,'TEM: ' + str(temperature) + ' C')
-
- time.sleep(1)
-
-
- def destroy():
-
- GPIO.cleanup()
-
-
- if __name__ == '__main__':
-
- try:
-
- main()
-
- except KeyboardInterrupt:
-
- destroy()
复制代码
实验结论
注意事项:若LCD灯光太暗,可以通过调节LCD背面蓝色的可变电阻(注:接背面的跳线帽)
通过树莓派GPIO口控制DT11温湿度传感器 和 LCD1602 ,了解DT11温湿度传感器工作原理和LCD显示方式。
|