ラズパイで温湿度を測定(DHT11)
Contents
ラズパイで温湿度を測定
温湿度センサーをラズベリーパイに接続してIoT化を目指しているのだが一定間隔で温湿度を計るPythonのプログラムを作った時の備忘録。
尚、今回の記事中ではインターネットに接続していないので厳密にはIoT(Internet of Things)では無いが、ラズパイであれば容易にインターネットに接続が可能である。
以前にAWS IoTに接続して値をアップロード(Publish)する記事も書いているのでインターネットに接続するのであれば参考にして欲しい。
使用した温湿度のモジュールはDHT11とDHT22の2種類。
ラズパイはRaspberry Pi ZeroとRaspberryPi 3 B+の2種類を試した。
尚、今回はDHT11の記事とするが、より精度の高い温湿度が測定できるDHT22についてのこちらを参照して欲しい。
DHT11について
温湿度センサー(DHT11)のスペックは下記の通り。
尚、データシートはこちらを参照した。
尚、小数点以下の湿度を測定したい場合はDHT22にする必要があるがそれは別記事とする。
湿度測定範囲 | 20%~90%(0℃~50℃範囲) 湿度測定誤差:±5% 尚、データシートによると2017年3月31のVer1.3で5%~95%にアップデートされたとある 今回購入したDHT11のバージョンは分からなかった |
温度測定範囲 | 0℃~50℃ 温度測定誤差:±2℃ 尚、データシートによると2017年3月31のVer1.3で-20℃~60℃にアップデートされたとある また2つ同時に測定しても1℃程度の温度差があったので正直、個体による誤差はそれなりにあると考えた方が良いと思う |
動作電圧 | 3.3V~5V 3.3Vを使用する時はケーブルが長すぎるとセンサーに十分な電力を供給できなくなるとあったので5Vが推奨との事 |
ピン | DHT11からは4つのピンが出ている データシートによると左からVCC、I/O、NC、GND 3つ目のNCはNot Connect(接続しない)と思われ実際モジュールからはコネクタは3つしか出ていない。 前述の裏面の画像をみても接続されている様子が無い |
購入について | アマゾンで3個で639円で購入した(2019年8月) |
dht11.pyのインストール
事前にdht11関連のモジュールをダウンロードする。
データシートの6ページ目以降に信号のフォーマットやパリティチェックの仕方が載っている。
それによると温度と湿度は40bitのLow(0)とHigh(1)で値を返すのだが、このビットのエラーチェックを行い温湿度への変換を1から自分でコーディングするのは正直ちょっと骨が折れる。
ネットで検索してみるとszazo氏がライブラリー化してGithubに載せてくれているのでありがたく使わせてもらうことにした。
プログラムと同じディレクトリに移動して(← 重要)以下のコマンドでgit cloneする。
git clone https://github.com/szazo/DHT11_Python.git
DHT11_Pythonディレクトリが作成されて配下に以下のファイルがインストール(コピー)される。
├─DHT11_Python
│ LICENSE.md
│ README.md
│ __init__.py
│ dht11.py
│ dht11_example.py
dht11.pyが今回使用するモジュール。
ちなみに、
- LICENSE.md:MITライセンス(オープンソースのライセンス)である事が書いてある
- README.md:ReadMe、RaspberryPiで使用可能な事が書いてある
- __init__.py:dht11.pyをimportした時に実行される(空だった)
- dht11_example.py:dht11.pyの使用例(サンプルプログラム)
となっていた。
尚、dht11.pyの詳しい内容については別記事とする。
Github上のDHT11のファイル構成が変わっており、dht11.pyの代わりに__init__.pyに今までのロジックがすべてコーディングされていた。
変更後のフォルダー構成
├─DHT11_Python
│ │ LICENSE.md
│ │ README.md
│ │ dht11_example.py
│ │
│ ├─dht11
│ │ __init__.py
ただ使い方は変わらないのでソースコードはそのままとしている。
上記のフォルダー構成で、import dht11 とすると __init__.py が dht11モジュールとして呼び出される。
接続について
DHT11(温湿度モジュール)とRaspberryPi Zero(B+も同様)との接続は以下の通り。
まずはRaspberryPi Zeroと接続した。
プログラム
RaspberryPi Zeroに接続した時のテスト用プログラム。
# -*- coding: utf-8 -*-
"""
Created on Sat Sep 28 09:17:11 2019
RaspberryPi Zero and 3 B+
温度、湿度センサーのテスト
@author: Souichirou Kikuchi
"""
import RPi.GPIO as GPIO
from time import sleep
from DHT11_Python import dht11 # 温湿度センサーモジュール
TEMP_SENSOR_PIN = 4 # 温湿度センサーのピンの番号
INTERVAL = 10 # 監視間隔(秒)
RETRY_TIME = 2 # dht11から値が取得できなかった時のリトライまので秒数
MAX_RETRY = 20 # dht11から温湿度が取得できなかった時の最大リトライ回数
class EnvSensorClass: # 温湿度センサークラス
def GetTemp(self): # 温湿度を取得
instance = dht11.DHT11(pin=TEMP_SENSOR_PIN)
retry_count = 0
while True: # MAX_RETRY回まで繰り返す
retry_count += 1
result = instance.read()
if result.is_valid(): # 取得できたら温度と湿度を返す
return result.temperature, result.humidity
elif retry_count >= MAX_RETRY:
return 99.9, 99.9 # MAX_RETRYを過ぎても取得できなかった時に温湿度99.9を返す
sleep(RETRY_TIME)
GPIO.setwarnings(False) # GPIO.cleanup()をしなかった時のメッセージを非表示にする
GPIO.setmode(GPIO.BCM) # ピンをGPIOの番号で指定
#main
try:
if __name__ == "__main__":
env = EnvSensorClass()
while True:
temp, hum = env.GetTemp() # 温湿度を取得
print("温度 = ", temp, " 湿度 = ", hum, "%")
sleep(INTERVAL)
except KeyboardInterrupt:
pass
GPIO.cleanup()
実行結果
プログラムの実行結果は以下の通り。
10秒間隔で温湿度を取得してprintしている。
概ね、問題なく表示されているのだが表示間隔が10秒以上空いていたりすることが散見されたのでもう少し詳しく原因を調べてみることにした。(それについては後述)
プログラムの説明
その前にプログラムの大まかな説明。
INTERVAL(10秒)間隔で温湿度を取得&表示している。
result = instance.read()で温湿度を取得して失敗したらRETRY_TIME(2秒)間隔を空けて最大MAX_RETRY(20回)再取得を試みる。
MAX_RETRYを超えて失敗した場合に温度、湿度に99.9を返している。
継続して動かし続けていると10回~20回に1回程度だが99.9を返すことが分かった。
エラーになる原因
プログラムを見直したりネットを検索してみたのだがどうにも良く分からない。
試しに同じプログラムをRaspberryPi 3 B+の方で動かしてみたところ、MAX_RETRYを超えて失敗する事はほぼ無い。
またdht11.pyにprint文を入れて調べた所、DHT11から40ビットを取得できない時(39ビットの時が多い)や最後の8ビットはParity bit(データの整合性をチェックするためのビット)なのだがパリティチェックでエラーになっているケースがZeroの方で圧倒的に多い事が判明した。
※RaspberryPi 3 B+でもエラーは発生しているが頻度が少ないのでMAX_RETRY(20回)まで達しない
下記はdht11.pyにprint文を入れてエラーを表示した結果。
”len error”はDHT11から40ビット返って来ていない場合のエラー、checksum errorは40ビット返って来たのだが先頭から32ビットと残りの8ビットでパリティチェックでのエラー。
エラーがない時は温度、湿度が表示されている。
RaspberryPi 3 B+ではエラー頻度が少ないことからリソース(メモリーやCPU使用量)が少ない事がエラー率の高い原因の可能性があるのでRaspberryPi ZeroでCLI起動に切り替えて同じプログラムを動かしてみる。
下記が実行結果。
心なしエラー頻度が少ない気がしないでも無いが誤差の範囲かも知れない。
またDHT11は3個購入したので他の個体でも試したが結果は似たりよったりだった。
もしかしたら別のモジュールを試せばもっとエラーが少ないのかも知れないが、RaspberryPi ZeroでDHT11を使用する時はエラーが起きる前提でリトライ回数を増やして温湿度を取得するのが良い様に思った。
Start signalの調整
ちなみにデータシートによるとStart signalとして「LOWを少なくとも18ミリ秒(最大30ミリ秒以下)センサーに通知する」とある。
dht11.pyでは40行目付近に以下のコードがあるが、この値を0.025等に変えてみた所、多少エラー率が減少した様に思う(比較結果の明確な数値は取得できていない)
self.__send_and_sleep(RPi.GPIO.LOW, 0.02)
もちろん上記の変更は自己責任であるという事とRaspberryPi 3 B+では0.02のままで問題が無い事を追記しておく。
以上で今回の記事を終了とする。
この記事が何処かで誰かの役に立つことを願っている。
尚、当記事中の商品へのリンクはAmazonアソシエイトへのリンクが含まれています。Amazonのアソシエイトとして、当メディアは適格販売により収入を得ていますのでご了承ください。
最近、ラズパイを始めた者です。わたしは、元機械エンジニアなので、電気はおろかPCプログラムについて知識が乏しいです。それでも、本ページを参考にさせて頂いて、温湿度の表示が出せました。ありがとうございます。プログラムのコマンドの使い方も分からないのに、ちゃんとPCを動かせたので、うれしくなりました。これからも参考にさせて頂きたいと思います。
今回分かった事は、DHT11センサーを使うのに、事前にdht11.pyのプログラムをPC内に入れておかないと使えない、という事が分かりました。
それまでは、PCが3番ピンのsiganl bus?の信号を勝手に読んでくれるのだと、思っていました。
また、恐らくそうなんだろうな、と思っているのが、dht11.pyのプログラムが、モニタへの表示させる動作もやってくれているんだろうな、と思っています。
まだまだ、プログラムのことはよくわかりませんが、PCが思った通りに動作してくれるとうれしいですね。
将来的には、クラウドサーバーみたいなところにデータを集約させて、どこからでもデータを見れるようになりたいと思っています。
ありがとうございました。
ゆーじさん
コメントありがとうございます。
また温湿度の表示が出来たとの事、良かったですね。
プログラムの動作について補足しますね。
おっしゃる通りピンの信号をラズパイで読んでいるのですが信号はこちらのデータシート
(http://akizukidenshi.com/download/ds/aosong/DHT11_20180119.pdf)の6ページ目以降の
のフォーマットの信号を元に数値に変換する必要があります。
このデータシートのロジックを自分でコーディングしても良いのですが既に先人の方が
dht11.pyというモジュールをgithubに用意してくれていたので、ありがたく使わせて
もらったという事です。
自分のプログラムから既に用意してもらったモジュール(プログラム)を11行目で読み込み(インポート)しています。
ちなみにモニターへの表示は自分のプログラムの中でやっています。
記事中のソースコードの40行目の
がモニターへの表示のコーディングです。
プログラミングを楽しんで下さい。
こんにちは。
いつも参考にさせていただいております。
これまでラズパイzeroを使用していましたが、この度ラズパイ4Bにグレードアップしました。
しかしzeroで動作していたdht11ですが、4Bでは動作してくれません。
温度、湿度共に99.9が永遠に表示されます。GPIOピンを変更しても変わりませんでした。
4Bになり動作速度がかなり速くなっていると思いますが、それが原因でしょうか?
他のサンプルプログラムでも同様に4Bでは動作しませんでした。
何かヒントがありましたら教えていただけないでしょうか?
よろしくお願いします。
おはようございます。
自己解決しました。 4BではGPIOピンにプルアップが必要だったようです。
プルアップを付けたら問題なく動作しました。
ヤッチャさん
コメントありがとうございます。既に自己解決しているとの事ですが、
GPIO.setmode の下に、
を入れた方が良いかも知れませんね。
ご指摘ありがとうございます。
こんにちは
いつも参考にさせていただいております。
今日はラズパイ4でテストをやってみましたが、”ModuleNotFoundError: No module named ‘DHT11_Python’” という異常を出てしまった。どうすればいいですか?
よろしくお願いします。
ホアンさん
こんにちは
のコマンドをプログラムと同じディレクトリで実行するとDHT11_Python配下にdht11ディレクトリが作成される思いますが、ディレクトリは作成されていますか?
はい、作成しましたが、その異常を出ました
ホアンさん
今回のプログラムの場所とディレクトリ構造とファイル名を教えて下さい。
今回のスクリプト と __init__.py はどの様な位置関係にありますか?