【電子工作】Raspberry PiでGrove温湿度センサー(DHT20)を使ってみよう!

ラズパイ

今回は Raspberry Pi 3BGrove Temperature & Humidity Sensor v2.0(DHT20) を使って、温度と湿度をPythonで取得する方法を紹介します。

このセンサーは I²C通信 で簡単に扱えるので、初心者の方でも気軽にセンサープログラミングを体験できます!

スポンサーリンク
スポンサーリンク

使用するもの

No部品名型番・補足
1Raspberry Pi 3 Model BOS:Raspberry Pi OS
2Grove Temperature & Humidity Sensor v2.0DHT20
3Grove Base HAT(推奨)または ジャンパワイヤ
4microSDカード、電源、モニター、キーボードなど通常のPi環境一式

SeeedStudio Grove 温湿度センサーV2.0(DHT20)

今回使用する温湿度センサーです。千石電商の方が安い場合もありますので、そちらもご参照下さい。

SeeedStudio Grove Base HAT for Raspberry Pi

初心者向けで、Base HATをラズパイに付け、任意のGrove I²Cポートにセンサーを接続するだけです。

配線方法

① Grove Base HATを使う場合(おすすめ)

一番簡単な方法です!
Base HATをPiに装着し、任意のGrove I²Cポートにセンサーを接続するだけでOKです。

  • Groveケーブルを差し込むだけで配線完了
  • 電源や信号のレベル変換もBase HATが自動で処理してくれます

② ジャンパワイヤで直接接続する場合(今回はこちら)

ピン対応は以下の通りです。

DHT20ピンRaspberry Piピン
GNDGND(物理ピン6など)
VCC3.3V(物理ピン1)
SDAGPIO2(物理ピン3)
SCLGPIO3(物理ピン5)

注意:Raspberry PiのI²Cは3.3V系なので、センサーも3.3V給電にしましょう。

配線後のイメージです。参考になされて下さい。

Raspberry Pi側の準備

① I²Cを有効化する

ターミナルを開いて次のコマンドを実行します。

sudo raspi-config

メニューが開いたら
Interface Options → I2C → Enable
を選択して有効化し、再起動します。

② 必要なパッケージをインストール

sudo apt update
sudo apt install -y python3-pip python3-smbus i2c-tools

③ センサーが認識されているか確認

以下のコマンドを実行して、0x38 が見えればOKです。

i2cdetect -y 1

出力例:

     0 1 2 3 4 5 6 7 8 9 a b c d e f
00:          -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- 38 -- -- --

Pythonで温湿度を取得する

サンプルコード

以下を dht20_read.py という名前で保存します。

#!/usr/bin/env python3
import time
from smbus2 import SMBus, i2c_msg

I2C_BUS = 1
ADDR    = 0x38

def dht20_init(bus):
    while True:
        status = bus.read_byte(ADDR)
        busy   = (status & 0x80) != 0
        cal    = (status & 0x08) != 0
        if (not busy) and cal:
            return
        time.sleep(0.05)

def dht20_read(bus):
    bus.write_i2c_block_data(ADDR, 0xAC, [0x33, 0x00])
    time.sleep(0.08)

    read = i2c_msg.read(ADDR, 7)
    bus.i2c_rdwr(read)
    data = list(read)

    raw_h = ((data[1] << 12) | (data[2] << 4) | (data[3] >> 4)) & 0xFFFFF
    raw_t = (((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]) & 0xFFFFF

    humidity = raw_h / 1048576.0 * 100.0
    temperature = raw_t / 1048576.0 * 200.0 - 50.0

    return round(temperature, 2), round(humidity, 2)

def main():
    with SMBus(I2C_BUS) as bus:
        dht20_init(bus)
        while True:
            t, h = dht20_read(bus)
            print(f"Temp: {t:.2f} °C  Humidity: {h:.2f} %RH")
            time.sleep(2)

if __name__ == "__main__":
    main()

出力例

Temp: 24.12 °C  Humidity: 52.47 %RH
Temp: 24.09 °C  Humidity: 52.58 %RH

これでリアルタイムに温度・湿度が表示されます!

よくあるトラブルと対処法

症状対策
i2cdetect0x38 が出ないSDA/SCLの接続を確認。Groveケーブルを逆挿ししていないかもチェック。
値が出ない / 固まる待機時間(0.08秒)を0.1秒程度に増やしてみる。
読み取りが不安定電源電圧を3.3Vに変更。ケーブルを短くする。
5Vで動かしていた3.3V動作が推奨。PiのI²Cは5V非対応。

まとめ

  • DHT20はI²C接続で配線がシンプル
  • Python + smbus2 で簡単にデータ取得
  • CSV保存でログ解析も可能

Raspberry Piでの温湿度測定は、IoT入門や環境モニタ作りの第一歩にぴったりです!

おまけ: プログラム解説

全体像(このプログラムは何をしているか?)

  1. Raspberry Pi の I²C バス(配線した SDA/SCL)経由で、センサー(DHT20, アドレス 0x38)に「測定して」と命令を出す
  2. 少し待ってから、センサーの生データ(7バイト)を読み取る
  3. 生データを温度(℃)・湿度(%)に変換する式で計算
  4. 2秒おきに「温度・湿度」を表示し続ける

1) インポートと定数

import time
from smbus2 import SMBus, i2c_msg

I2C_BUS = 1
ADDR    = 0x38
  • smbus2:I²C 通信をするための Python ライブラリ。SMBus は「I²C バスを開くためのクラス」、i2c_msg は「まとめて読み書きするためのヘルパー」です。
  • I2C_BUS = 1:Raspberry Pi は標準で I²C-1 を使います(GPIO2/3 がそのバス)。
  • ADDR = 0x38:DHT20(AHT20互換)の I²C 7bit アドレス。i2cdetect -y 1 で見える「38」がこれ。

2) 初期化(センサーが準備OKになるのを待つ)

def dht20_init(bus):
    while True:
        status = bus.read_byte(ADDR)
        busy   = (status & 0x80) != 0
        cal    = (status & 0x08) != 0
        if (not busy) and cal:
            return
        time.sleep(0.05)
  • status = bus.read_byte(ADDR):センサーの ステータスレジスタ を1バイト読む
  • 0x80(bit7):busy ビット。1なら測定中や内部処理中。0になれば読み取り可能
  • 0x08(bit3):校正完了ビット。1なら内部キャリブレーション済み(= 使える状態)

busy=0 かつ 校正=1 になったら準備OK」。それまで 50ms 間隔で待っています。

3) 1回の測定シーケンス

def dht20_read(bus):
    bus.write_i2c_block_data(ADDR, 0xAC, [0x33, 0x00])  # 測定開始コマンド
    time.sleep(0.08)  # 80msほど待つ(データ変換時間)

    read = i2c_msg.read(ADDR, 7)  # 7バイト読み取り
    bus.i2c_rdwr(read)
    data = list(read)
  • 測定開始コマンドは AC 33 00(データシート既定)。これで「温湿度の同時測定」を開始。
  • 変換時間は約 80ms。足りないとデータが未確定のことがあるので 0.08~0.1s が目安。
  • 応答は 7バイト:[status, d1, d2, d3, d4, d5, d6](環境や実装差はありますが、この読み取りで問題ありません)

厳密には、コマンド後に busyビットが0になるまでループで待つ 実装もあります。今回は 80ms スリープで簡易化。

4) 生データのビット詰めをほどく(20bit×2)

raw_h = ((data[1] << 12) | (data[2] << 4) | (data[3] >> 4)) & 0xFFFFF
raw_t = (((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]) & 0xFFFFF
  • DHT20/AHT20 の生データは湿度20bit・温度20bitの計40bitで届きます。
  • 配列 data はバイト列。ビット演算で 20bit を取り出しています。

配列イメージ(7バイト)

data[0]=status
data[1]=H[19:12]
data[2]=H[11:4]
data[3]=H[3:0] | T[19:16]
data[4]=T[15:8]
data[5]=T[7:0]
data[6]=(未使用 or CRC 等 実装差)

ビット演算の意味(超ざっくり)

  • << は左シフト(桁上げ)、>> は右シフト(桁下げ)、| はOR(くっつける)、& はAND(マスク)
  • 0xFFFFF は 20bit の 1(= 2^20 – 1)。20bit 以上を切り落とすマスク。

豆知識(data[1] << 12)data[1] を 12ビット左にずらして、上位桁に置くイメージです。

5) 変換式(生の20bit → 実際の単位)

humidity = raw_h / 1048576.0 * 100.0      # 2^20 = 1048576
temperature = raw_t / 1048576.0 * 200.0 - 50.0
  • 湿度[%RH] = raw_h / 2^20 * 100
  • 温度[℃] = raw_t / 2^20 * 200 - 50

これは DHT20/AHT20 系の公式換算式(データシート)です。
最後に round(x, 2) で小数2桁に丸めています。

6) メインループ(2秒おきに測る)

def main():
    with SMBus(I2C_BUS) as bus:   # I²C-1 を開く
        dht20_init(bus)           # 準備OKになるまで待機
        while True:               # 無限ループ
            t, h = dht20_read(bus)
            print(f"Temp: {t:.2f} °C  Humidity: {h:.2f} %RH")
            time.sleep(2)         # 2秒おき
  • with SMBus(...):処理が終わったら自動でクローズしてくれる書き方
  • Ctrl + C を押すと終了(KeyboardInterrupt)します

タイトルとURLをコピーしました