溫濕度傳感器器件介紹
DHT11是一款含有已校準(zhǔn)數(shù)字信號(hào)輸出的溫濕度復(fù)合傳感器,它應(yīng)用專用的數(shù)字模塊采集技術(shù)和溫濕度傳感技術(shù),確保產(chǎn)品具有極高的可靠性和卓越的長期穩(wěn)定性。傳感器包括一個(gè)電阻式感濕元件和一個(gè)NTC測溫元件,并與一個(gè)高性能8位單片機(jī)相連接。
溫濕度傳感器模塊溫濕度傳感器器件
引腳說明
VCC 供電3.5V-5.5V DC
DATA 串行數(shù)據(jù),單總線,必須接上拉電阻 5.1K左右,這樣空閑時(shí) DATA總是為高電平
GND 接地,電源負(fù)極
NC 空腳不連接
DHT11的工作原理
DHT11是通過單總線與微處理器通訊,只需要一根線,一次傳送40位數(shù)據(jù),高位先出。
數(shù)據(jù)格式
8bit濕度整數(shù)數(shù)據(jù) + 8bit濕度小數(shù)數(shù)據(jù) +8bit溫度整數(shù)數(shù)據(jù) + 8bit溫度小數(shù)數(shù)據(jù) + 8bit校驗(yàn)位。
校驗(yàn)算法
將濕度、溫度的整數(shù)小數(shù)累加,只保留低8位。MCU與DHT11通信約定:主從結(jié)構(gòu),DHT11為從機(jī),MCU作為主機(jī),只有主機(jī)呼叫從機(jī),從機(jī)才能應(yīng)答。
詳細(xì)流程
MCU發(fā)送起始信號(hào) -> DHT響應(yīng)信號(hào) -> DHT通知MCU準(zhǔn)備接受信號(hào) ->DHT發(fā)送準(zhǔn)備好的數(shù)據(jù) ->DHT結(jié)束信號(hào)-> DHT內(nèi)部重測環(huán)境溫濕度數(shù)據(jù)并記錄數(shù)據(jù)等待下一次MCU的起始信號(hào)。
由流程可知,每一次MCU獲取的數(shù)據(jù)總是DHT上一次采集的數(shù)據(jù),要想得到實(shí)時(shí)的數(shù)據(jù),連續(xù)兩次獲取即可,官方不建議連續(xù)多次讀取DHT,每次讀取的間隔時(shí)間大于5秒就足夠獲取到準(zhǔn)確的數(shù)據(jù),上電時(shí)DHT需要1S的時(shí)間穩(wěn)定。
MCU起始信號(hào)
1、設(shè)置DATA引腳為輸出狀態(tài)并輸出高電平
2、再將DATA輸出為低電平,持續(xù)時(shí)間大于18ms,此時(shí)DHT檢測到后從低功耗模式->高速模式
3、DATA引腳設(shè)置為輸入狀態(tài),由于上拉電阻的關(guān)系,DATA就變?yōu)楦唠娖剑瑥亩瓿梢淮纹鹗夹盘?hào)。
響應(yīng)信號(hào)、準(zhǔn)備信號(hào)
(DHT在MCU DATA引腳輸出低電平時(shí),從低功耗模式轉(zhuǎn)至高速模式,等待DATA引腳變?yōu)楦唠娖剑?br />
1、DHT輸出 80us低電平 作為應(yīng)答信號(hào)
2、DHT輸出 80us高電平 通知微處理器準(zhǔn)備接受數(shù)據(jù)
3、連續(xù)發(fā)送 40位數(shù)據(jù)(上次采集的數(shù)據(jù))
DHT數(shù)據(jù)信號(hào)
數(shù)據(jù)為“0”格式:50us的低電平 +26-28us的高電平
數(shù)據(jù)為“1”格式:50us的低電平 +70us的高電平
DHT結(jié)束信號(hào)
DHT的DATA引腳輸出40位數(shù)據(jù)后,繼續(xù)輸出低電平50us后轉(zhuǎn)為輸入狀態(tài),由于上拉電阻,DATA隨之變?yōu)楦唠娖健HT內(nèi)部開始重測環(huán)境溫濕度數(shù)據(jù),并記錄數(shù)據(jù),等待外部的起始信號(hào)。
實(shí)驗(yàn)?zāi)康?br />
利用溫濕度傳感器檢測空間內(nèi)的溫度和濕度,傳感器將數(shù)據(jù)收集到以后傳到RaspberryPi開發(fā)板中,經(jīng)過處理反映在LCD上,在LCD中第一行顯示的是溫度,第二行顯示的濕度。
組件清單
u 面包板*1
u DHT11傳感器*1
u 串行LCD1602*1
u 導(dǎo)線若干
連接
51hei.png (4.62 KB, 下載次數(shù): 63)
下載附件
2020-7-21 02:21 上傳
51hei.png (5.93 KB, 下載次數(shù): 56)
下載附件
2020-7-21 02:21 上傳
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()
復(fù)制代碼
實(shí)驗(yàn)結(jié)論
注意事項(xiàng):若LCD燈光太暗,可以通過調(diào)節(jié)LCD背面藍(lán)色的可變電阻(注:接背面的跳線帽)
通過樹莓派GPIO口控制DT11溫濕度傳感器 和 LCD1602 ,了解DT11溫濕度傳感器工作原理和LCD顯示方式。
|