ESP32とDHT11で取得した温湿度をAWS IoT Coreへ送信してみた

ESP32とDHT11で取得した温湿度をAWS IoT Coreへ送信してみた

ESP32とDHT11を使ってAWS IoT CoreへMQTT送信する方法を、環境構築から実装、つまずき解決まで全ステップでご紹介します。
2026.08.20

こんにちは!コンサルティング部のくろすけです!

今回は、ESP32とDHT11を使い、取得した温度・湿度をAWS IoT CoreへMQTTで送信してみました。
本記事では、環境構築からつまずいたポイント、解決方法までをまとめます。

前提

今回使用したのは、Freenove Basic Starter Kit for ESP32(FNK0061)です。
ESP32-WROVERを中心に、拡張ボード、カメラ、各種センサー、電子部品などを含むスターターキットです。

項目 内容
スターターキット Freenove FNK0061
MicroPythonファームウェア MicroPython v1.28.0
デプロイ・REPL mpremote v1.28.0
センサー DHT11
MQTT送信間隔 5分

今回はMicroPythonを使用します。MicroPythonはESP32上でPythonを実行するための処理系です。
また、使い慣れているCursorを使用したかったので、ESP32へのファイル転送やREPL接続にはmpremoteを利用しました。

やってみた

1. MicroPythonを書き込む

最初にMicroPythonのファームウェアを書き込みます。
ファームウェアはMicroPython ESP32_GENERIC Downloadsからダウンロードします。

esptool --chip esp32 --port "<SERIAL_PORT>" erase-flash
esptool --chip esp32 --port "<SERIAL_PORT>" \
  write-flash -z 0x1000 "ESP32_GENERIC-<version>.bin"

書き込み後は、以下のコマンドでREPLへ接続できます。

mpremote connect "<SERIAL_PORT>" repl

>>>プロンプトが表示され、print("Hello, ESP32!")が正常に出力されれば準備完了です。

CleanShot20260820at19.17.06.png

2. mpremoteで開発中のスクリプトを実行・転送する

開発中のスクリプトは、runでESP32上に一度だけ送って実行できます。

mpremote connect "<SERIAL_PORT>" run <SCRIPT_NAME>.py

CleanShot20260820at19.26.39.png

一方、ESP32をMacから外しても自律実行させる場合は、ファイルをESP32のルートへ転送します。

mpremote connect "<SERIAL_PORT>" cp <SCRIPT_NAME>.py :<SCRIPT_NAME>.py

3. DHT11をGPIO 27へ接続する

DHT11はI²Cではなく、1本のDATA線で通信するセンサーです。DATA線には入力・出力の両方で使えるGPIOを選ぶ必要があります。

今回は以下のように配線しました。

IMG_7243 (1).jpg

温湿度の取得には、MicroPython標準のdhtモジュールを使います。

検証中のサンプルコード
import dht
from machine import Pin

sensor = dht.DHT11(Pin(27))
sensor.measure()

print(sensor.temperature())
print(sensor.humidity())

4. Wi-Fiへ接続する

ESP32のWi-Fi接続は、プログラムからSSIDとパスワードを指定します。
ESP32-D0WD-V3は2.4GHz帯のみをサポートするため、5GHzのSSIDを指定すると接続できませんでした。

検証中のサンプルコード
import network

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(WIFI_SSID, WIFI_PASSWORD)

5. AWS IoT CoreへMQTT送信する

AWS IoT Coreの設定については、他の記事での紹介が多いため、ここでは割愛します。
公式ドキュメントでは下記が参考になるかと思います。

https://docs.aws.amazon.com/ja_jp/kinesisvideostreams/latest/dg/gs-create-thing.html

AWS IoT Coreとの接続には、MQTT over TLS(ポート8883)とX.509証明書を使用します。
ESP32側には次のファイルを配置しました。

/main.py
/config.py
/AmazonRootCA1.der
/device.pem.crt
/private.pem.key

MicroPythonにはAWS IoT Device SDKはないため、軽量なMQTTクライアントであるumqtt.simpleを利用しました。
AWS IoTのエンドポイント、Wi-Fi認証情報、デバイス証明書、秘密鍵、Amazon Root CA 1のパスなどはconfig.pyへ設定しています。

config.py
WIFI_SSID = "<WIFI_SSID>"
WIFI_PASSWORD = "<WIFI_PASSWORD>"

AWS_IOT_ENDPOINT = "<AWS_IOT_ENDPOINT>"
THING_NAME = "dht11-esp32"
MQTT_TOPIC = "devices/dht11-esp32/telemetry"
MQTT_PORT = 8883

DHT_PIN = 27

AMAZON_ROOT_CA = "<AMAZON_ROOT_CA_PATH>"
DEVICE_CERTIFICATE = "<DEVICE_CERTIFICATE_PATH>"
PRIVATE_KEY = "<PRIVATE_KEY_PATH>"
main.py
import dht
import json
import network
import ntptime
import ssl
import time
from machine import Pin
from umqtt.simple import MQTTClient

from config import (
    AMAZON_ROOT_CA,
    AWS_IOT_ENDPOINT,
    DEVICE_CERTIFICATE,
    DHT_PIN,
    MQTT_PORT,
    MQTT_TOPIC,
    PRIVATE_KEY,
    THING_NAME,
    WIFI_PASSWORD,
    WIFI_SSID,
)

sensor = dht.DHT11(Pin(DHT_PIN))

def read_binary(path):
    with open(path, "rb") as file:
        return file.read()

def connect_wifi():
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)

    if not wlan.isconnected():
        print("Connecting to Wi-Fi...")
        wlan.connect(WIFI_SSID, WIFI_PASSWORD)

        for _ in range(20):
            if wlan.isconnected():
                break
            time.sleep(1)

    if not wlan.isconnected():
        raise OSError("Wi-Fi connection timed out")

    print("Wi-Fi connected:", wlan.ifconfig()[0])

def sync_clock():
    try:
        ntptime.settime()
        print("Clock synchronized with NTP")
    except OSError as error:
        print("NTP synchronization failed:", error)

def connect_mqtt():
    client = MQTTClient(
        client_id=THING_NAME,
        server=AWS_IOT_ENDPOINT,
        port=MQTT_PORT,
        ssl=True,
        ssl_params={
            "key": PRIVATE_KEY,
            "cert": DEVICE_CERTIFICATE,
            "cadata": read_binary(AMAZON_ROOT_CA),
            "cert_reqs": ssl.CERT_REQUIRED,
            "server_hostname": AWS_IOT_ENDPOINT,
        },
    )
    client.connect()
    print("Connected to AWS IoT Core")
    return client

def read_telemetry():
    sensor.measure()
    return json.dumps(
        {
            "thing_name": THING_NAME,
            "temperature_c": sensor.temperature(),
            "humidity_percent": sensor.humidity(),
            "timestamp": time.time(),
        }
    )

def disconnect(client):
    if client is None:
        return

    try:
        client.disconnect()
    except OSError:
        pass

def main():
    connect_wifi()
    sync_clock()

    client = None

    while True:
        try:
            if client is None:
                client = connect_mqtt()

            message = read_telemetry()
            client.publish(MQTT_TOPIC, message)
            print("Published:", message)
        except OSError as error:
            print("DHT11, network, or MQTT error:", error)
            disconnect(client)
            client = None

        time.sleep(300)

if __name__ == "__main__":
    main()

つまずき: CA証明書の形式

最初はAmazon Root CA 1のPEMファイルのパスをcadataへ渡しており、以下のエラーになりました。

ValueError: invalid cert

MicroPython v1.28では、cadataへDER形式の証明書バイト列を渡す必要があります。
PEM形式のAmazon Root CA 1をDER形式へ変換し、バイト列として読み込むことで解決しました。

openssl x509 \
  -in AmazonRootCA1.pem \
  -outform DER \
  -out AmazonRootCA1.der

送信するデータ

送信するJSONは以下の形式です。温度・湿度はDHT11から読み取り、5分ごとにdevices/dht11-esp32/telemetryへ送信しています。

{
  "thing_name": "dht11-esp32",
  "temperature_c": 27,
  "humidity_percent": 56,
  "timestamp": 840529808
}

IoT Core側で確認できました!

CleanShot20260820at21.17.42.png

あとがき

実際にデバイスを含めて動かしてみると、アイデアが湧いてきて楽しいですね!
今後は IoT データのAWS上での分析や処理についても試してみたいと思います。

以上、くろすけでした!

この記事をシェアする

関連記事