硬體安裝:
參考ref.1的Figure.1 (page 5)在pin 2的部份與RPi的GPIO 4連接,並使用一電阻與VCC相連
python程式:
1. 快速上手方式:
在RPi已經安裝好pip的狀態下,只需要額外安裝Adafruit_DHT (ref.2)sudo pip install Adafruit_DHT接著,在python環境中輸入:
import Adafruit_DHT as dht sensor = dht.DHT11 gpio = 4 print( dht.read_retry(sensor, gpio) )可以快速得到DHT11偵測到的相對濕度與溫度:
(76.0, 29.0)
在Googled結果,可以看到許多類似的maker分享,許多是從git clone Adafruit_DHT 開始,安裝Adafruit_DHT,有興趣的可以參考ref.4。
要透過GPIO操控DHT11,基本上要了解DHT11的運作機制 (ref.1):2. 透過GPIO方式:
RPi GPIO控制階段:
a. pin 2針腳在高電位下時,給予不少於18ms長的低電位,讓DHT11能截取到電壓變化
b. 恢復pin 2針腳回高電位
DHT11初始化階段:
c. DHT11將pin 2針腳調整為低電壓,持續80μs
d. DHT11將pin 2針腳調整為高電壓,持續80μs
DHT11訊號傳回階段:
e. DHT11會連續的將pin 2針腳,在低電壓與高電壓之間變換共40個循環;
低電位維持50μs,高電位維持26~28μs時,表示為0
低電位維持50μs,高電位維持70μs時,表示為1
f. DHT11將pin 2針腳調整為低電位50μs後,結束控制pin 2針腳電位控制
DHT11輸出的40個bits,共由5個8 bits所組成:
1~8 bits: 相對濕度整數部位
9~16 bits: 相對濕度小數部位
17~24 bits: 溫度整數部位
25~32 bits: 溫度小數部位
33~40 bits: checksum檢查碼,等於前4個數字的總和
在了解DHT11的訊號控制方式,可以寫相對應的GPIO控制來讀取訊號
import RPi.GPIO as GPIO import time PIN = 4 # initial GPIO GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) GPIO.cleanup() # step a, b GPIO.setup(PIN, GPIO.OUT) GPIO.output(PIN, GPIO.LOW) time.sleep(0.0181) GPIO.output(PIN, GPIO.HIGH) # step c, d GPIO.setup(PIN, GPIO.IN, GPIO.PUD_UP) while GPIO.input(PIN) == GPIO.LOW: continue while GPIO.input(PIN) == GPIO.HIGH: continue # step e bits = [] MAXCount = 3000 for n in range(40): lowCount = 1 highCount = 1 while GPIO.input(PIN) == GPIO.LOW: lowCount += 1 while GPIO.input(PIN) == GPIO.HIGH: highCount += 1 if highCount > MAXCount: print("missing data") exit(1) if lowCount < highCount: bits.append(1) else: bits.append(0) # bits to bytes RH = 0 RHD = 0 T = 0 TD = 0 checksum = 0 for bit in bits[:8]: RH = (RH << 1) | bit for bit in bits[8:16]: RHD = (RHD << 1) | bit for bit in bits[16:24]: T = (T << 1) | bit for bit in bits[24:32]: TD = (TD << 1) | bit for bit in bits[32:40]: checksum = (checksum << 1) | bit # checksum if RH+RHD+T+TD != checksum: print("checksum error") exit(1) print("RH: {}%, T: {}C".format(RH+0.1*RHD, T+0.1*TD))執行結果:
RH: 76.0%, T: 29.6C
程式下載:
https://github.com/1412chen/rpi_learning/tree/master/dht11- dht11.py: 直接呼叫Adafruit_DHT讀取溫濕度值
- dht11_gpio_direct.py: 透過GPIO讀取溫濕度值
- dht11_gpio.py: 透過GPIO讀取溫濕度值,一次讀取完DHT11電壓變化後才解析。
討論:
1. 在寫這個document的時候,我發現到使用Adafruit_DHT跑出來的結果,不會有小數點,讓我在確認GPIO結果一直充滿疑問。我想這個應該是Adafruit_DHT故意忽略小數位輸出,DHT11本身的誤差太大(相對濕度±5%,溫度±2°C),描述到小數點,確實沒有太大意義。2. 控制GPIO擷取資料,蠻容易出現missing data與checksum error的結果。
3. 相對於Adafruit_DHT是python呼叫C的GPIO控制,ref.3中的dht11是python透過GPIO對DHT11進行操作,該程式為了避免python在擷取pin 2電位過程中額外的操作的時間差導致電位資料遺失或延遲,先將所有電位資料擷取下來後再解析。這樣也許能比較穩定得到結果,我有參照這個邏輯重新撰寫,參考程式下載的dht11_gpio.py。
參考:
1. https://www.mouser.com/ds/2/758/DHT11-Technical-Data-Sheet-Translated-Version-1143054.pdf2. https://github.com/adafruit/Adafruit_Python_DHT
3. https://github.com/szazo/DHT11_Python
4. https://kknews.cc/zh-tw/digital/ea26b4q.html