今回は Raspberry Pi 3B と Grove Temperature & Humidity Sensor v2.0(DHT20) を使って、温度と湿度をPythonで取得する方法を紹介します。
このセンサーは I²C通信 で簡単に扱えるので、初心者の方でも気軽にセンサープログラミングを体験できます!
使用するもの
No | 部品名 | 型番・補足 |
---|---|---|
1 | Raspberry Pi 3 Model B | OS:Raspberry Pi OS |
2 | Grove Temperature & Humidity Sensor v2.0 | DHT20 |
3 | Grove Base HAT(推奨)または ジャンパワイヤ | |
4 | microSDカード、電源、モニター、キーボードなど | 通常の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ピン |
---|---|
GND | GND(物理ピン6など) |
VCC | 3.3V(物理ピン1) |
SDA | GPIO2(物理ピン3) |
SCL | GPIO3(物理ピン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
これでリアルタイムに温度・湿度が表示されます!
よくあるトラブルと対処法
症状 | 対策 |
---|---|
i2cdetect で 0x38 が出ない | 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入門や環境モニタ作りの第一歩にぴったりです!
おまけ: プログラム解説
全体像(このプログラムは何をしているか?)
- Raspberry Pi の I²C バス(配線した SDA/SCL)経由で、センサー(DHT20, アドレス 0x38)に「測定して」と命令を出す
- 少し待ってから、センサーの生データ(7バイト)を読み取る
- 生データを温度(℃)・湿度(%)に変換する式で計算
- 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)します