温湿度センサー(DHT11)の詳しい機能についてデータシートを見ながら調べた
Contents
DHT11について
各種センサー類をRaspberryPiにつないでIoT化すれば色々と便利になるのではないかと思っている。
以前ラズベリーパイで温湿度を計るPythonのプログラムを作った時に温湿度センサー(DHT11)についてデータシートを見ながら色々と調べた。
その時の事を忘れないように記事にしておく。
尚、実際に温湿度を測定するプログラムについては以前の記事を参照の事。
この記事はデータシートとszazo氏がgithubに公開しているdht11.pyのプログラムを元にDHT11がどのようにして温湿度の数値を信号にしてOutputしているのかを中心に書いている。
データシートについて
データシートは秋月電子さんのこちらを参考にさせて頂いた。
Updateについて
2ページ目にアップデート履歴が載っている。
2017年3月31日のV1.3で温度と湿度の測定範囲が拡大した事が書いてあった。
- 温度:0~50℃が-20~60℃に拡大
- 湿度:10~90%が5~95%に拡大
今、自分が使っているDHT11がどのバージョンなのかは残念ながら分からなかった。
時期からしてV1.3だとは思っているが確認方法がいまいち分からない。
ピンについて
3ページ目には外観と4本のピンについての記述。
向かって左から、
- VDD(3.3~5.5V DC)
- DATA Serial
- NC(未使用)
- GND
自分が購入したDHT11は基盤についた状態で、基盤からの出力は3ピンだけだった。
シリアル通信
6~7ページ目にシリアル通信の手順が書いてあった。
- Start singnal(18~30ミリ秒)をホストからセンサーに送り、データ準備を通知する
- Start singnalを受信後に40のデータ(8✕5)が送信される
- 湿度データの説明(humidity low is partial data of humidityの意味がイマイチ分からなかった)
- 温度データの説明。温度のLow 8ビットはマイナスの時に使用
- チェックデジット=湿度(High)+湿度(Low)+温度(High)+温度(Low)
等が書いてある。
計算例
同じく7ページに受信する40のデータと温度と湿度の計算例が載っていた。
データは8ビット✕5種類=40ビットから構成されており、先頭から湿度(High)、湿度(Low)、温度(High)、温度(Low)、パリティビットの順番となる。
前述のdht11.pyのソースを眺めてみると湿度(High)、温度(High)はそれぞれ整数部、湿度(Low)、温度(Low)は小数部として扱っていた。
また湿度に関してはDHT11では小数点以下は計測できない模様、湿度(Low)には常に0(ゼロ)が入ってくる。
湿度の計算例
湿度の計算例は以下の通り(上記のデータシートの計算例とは値が異なる)
湿度(Hight)
1)0011 0111
2)2進数を10進数に変換
(128✕0)+(64✕0)+(32✕1)+(16✕1)+(8✕0)+(4✕1)+(2✕1)(1✕1)=55
湿度(Low)は0000 0000で0(ゼロ)
よって湿度は55.0%
温度の計算例
温度の計算例は以下の通り、温度(Low)には小数部が入ってくる。
温度(Hight)
1)0001 1001
2)2進数を10進数に変換
(128✕0)+(64✕0)+(32✕0)+(16✕1)+(8✕1)+(4✕0)+(2✕0)(1✕0)=25
温度(Low)
3)0000 1001
4)2進数を10進数に変換
(128✕0)+(64✕0)+(32✕0)+(16✕0)+(8✕1)+(4✕0)+(2✕0)(1✕1)=9
よって温度は25.9℃
パリティビット
5つ目の8ビットはパリティビットを表している。
パリティビットはデータの整合をチェックする為のビットで最初の4つの8ビットの合算値とパリティビットが一致するかをチェックすることにより、ビット落ち(化け)した時の不正データをエラーで弾くためにある。
※2ヶ所同時にビット化けしてしまえばチェックをすり抜けてしまうが、その確率は非常に低い
0011 0111+0000 0000+0001 1001+0000 1001= 0101 1001(パリティビットと比較する)
データタイミングダイアグラム
同じく7ページにはデータのタイミングについての説明がある。
最初の黒線がホスト(RaspberryPiなど)からDHT11へのStart Signal信号。
灰色の線がDHT11からの信号データを示している。
黒線のStart Signal後にLow(Response singnal)、High(Pulled ready output)が出力され、その後にデータ(40データ)がDHT11より出力される。
0と1を表すフォーマット
9ページ目に0ビット、1ビットを表すフォーマットが示されている。
前半はLow(0)で後半がHigh(1)になるパターンは双方同じだがHighの割合の違いによって0か1かを判断している。
- High(1)の割合が少ない→0ビットと判定
- High(1)の割合が多い→1ビットと判定
dht11.pyについて
データシートの情報を元にgithubのdht11.pyのソースを見比べてみる。
Githubに公開されていた dht11.py が __init__.py に変更されていた。
以下、自分なりの理解について記述しておく。
尚、下記の内容は動画でも解説しているのでそちらの方が分かりやすいかも知れない。
start signal
40行目がstart signal。
self.__send_and_sleep(RPi.GPIO.LOW, 0.02)
__collect_input()メソッド
while文で回しながらRPi.GPIO.inputでピンからの信号を読み取ってdataに保存している。
0または1が100回連続して続くとデータの終了とみなしている(実際にはデータが終了すると1が連続する)
データを読み込むに辺りマシン性能により読み込まれる数が異なってくる。
実際RaspberryPi 3 B+とRaspberryPi Zeroで比較した所、RaspberryPi 3 B+の方がより多くのデータを取得していた。
while文がより高速に回っているのだと思われる。
__parse_data_pull_up_lengthsメソッド
最初のデータのLow→High→Lowを読み飛ばした後、データ部のHighの数をカウントしてlengths配列に代入している。
Highの割合で0か1ビットを判定するのでHighの数を40データ分ためている。
__calculate_bitsメソッド
40のデータのうちのHighの数の最大値と最小値を足して2で割って平均を算出。
平均と比較して多いか少ないかを40データ分判定してTrue(1)、False(0)をbitsにセットする。
__bits_to_bytesメソッド
True、Falseを1、0に変換すると同時に8ビットづつthe_bytes[0~4]にセットする。
__calculate_checksumメソッド
the_bytes[0~3]を合算する。
後にthe_bytes[4]とパリティチェックで比較する。
動画
この記事の内容を動画で説明している。
初めましてヤマウチと申します。
現在大学に通っているのですが、ベンチャーにてIoTデバイスを制作しており、当記事について質問したくコメントをさせていただいております。
具体的には、ラズパイ3でDHT11を使用し、不快指数から異なる色のLEDを光らせるというものを独学で制作しています。
質問:「他の参考サイトを真似て 『import dht11』としていたのですが、dht11.py → __init__.pyへの変更後は『 import __init__』にすれば良いのでしょうか?? Terminalにて実行しても、ImportError: No module named dht11と表示されます。
さまざまなサイトを閲覧して制作を進めているのですが、中学の授業ぶりの電子工作のため苦戦しております。
素人で説明下手かもしれませんが、返信していただければと思っております。
参考サイトは、https://qiita.com/mininobu/items/1ba0223af84be153b850
https://odekake-asobi-blog.com/raspi-temp/ です。
ヤマウチユウジ さん
こんばんは。
__init__.py の内容をまるごと dht11.py にコピーして保存。
__init__.py は空ファイルでOKです。
以前は上記の様なファイル構成だったのですがGithubの作者の方がファイル構成を変更した様です。
記事が以前のファイル構成の前提で書いているので、ちょっとした不整合が起きています。
プログラムについてはこちらの記事を参照して下さい。
記事では DHT11_Python ディレクトリに dht11.py を保存しているので、プログラム中では
とimportしています。
ちなみに __init__.py はモジュールを import する時に初期化処理を行う役割のファイルです。
空であれば何もしません。