ちょっと話題の記事

【試したらできた】ChatGPT ではじめる IoT と電子工作

ChatGPT でも IoT できた!!
2023.03.10

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

今回は、今話題の ChatGPT を使って、簡単な IoT システムを作れるか試してみました。

想定

今回は「IoT、電子工作、プログラミングが初めてな人が ChatGPT でどこまで作れるか?」という想定のもとで検証してみたいと思います。

作るもの

「Raspberry Pi で 温湿度センサーから温度と湿度を取得してクラウドに送信するシステム」を ChatGPT を使いながら作ります。

それではやっていきましょう。

用意するものを聞いてみる

今回は Raspberry Pi は既存のものを使いますが、「準備するものは何か?」という質問から始めました。

01-q1

詳細な製品名までは回答にありませんでしたが、必要となる機材を全てリストアップしてくれました。さらに温湿度センサーとして「DHT11」や「DHT22」といった定番のものを教えてくれました。

尚、今回は Raspberry Pi 本体や周辺機器は既に手持ちのものを使うことにしたので、Raspberry Pi 関連機器については質問をしていません。

次に、温湿度センサーについて詳しく聞いてみます。

02-q2

なんと 3 種類も教えてくれました。ここで得られた情報を元に「adafruit dht22センサー amazon」というキーワードで検索すると、Amazon の商品がヒットしました。これで実際に購入すべきセンサーまでたどり着けました。

この基板付きのセンサー(3ピンのもの)はプルアップ抵抗が内蔵されているので、ジャンパーワイヤーで直接 Raspberry Pi と接続することが可能です。

しかし、基板がない 4 ピンのものも販売されており、そちらを使う場合は別途抵抗が必要となります。そのあたりの事が回答に含まれていなかったのは注意が必要です。

Raspberry Pi とセンサーのつなぎ方を聞いてみる

材料は揃ったものとして、センサーを Raspberry Pi の GPIO ピンに繋げなければデータは取れません。ググればたくさん情報が出てきますが、つなぎ方も ChatGPT に質問してみます。

03-q3

購入したセンサーの基板には「VCC」「DAT」「GND」と記載されているので、上記の回答で特に迷うことはないかと思います。(データ信号が「DOUT」と回答されていますが、許容できる範疇ではないでしょうか)

22-dht22

少々見づらいかもしれませんが、回答どおりに接続したものが以下の写真です。

20-rpi-dht22-connect

21-rpi-connect

Raspberry Pi を使ったことがある人ならピンへの接続は問題ないと思いますが、初めての場合だとどの GPIO ピンに接続すればいいか分かりません。慣れていても忘れている場合があるので、そんなときは pinout コマンドが便利です。

Raspberry Pi 上でコマンドを実行するとグラフィカルにピン配置が確認できます。

23-pinout

とはいえ、やはり初めての場合だと pinout コマンドなんて知らない人が多いはずなので、ピン配置も ChatGPT に聞いてみました。

24-chatgpt-rpi-pin

図で教えてほしかったのですが、URL のリンクが正しくないので図が見れません。再び質問してみると markdown 形式ではなく 画像の URL を直接教えてくれました。

25-not-visualized-pin-assign

このリンクをコピペしてブラウザで開くと分かりますが、URL が変わっており新しい URL にリダイレクトされます。
リダイレクト先の正しい URL を ChatGPT に伝えて、改めてピン配置の図を提示してもらいました。
(リダイレクト先のページをスクロールしていけば、同じ図が見れますが…)

26-correct-url

説明と図が合ってない部分がありますが、図を見ればセンサーをどこのピンに接続すればいいか分かりました。

データを取得する Python スクリプトを聞いてみる

実は先程の回答には続きがあり、Python を使ったデータ取得のスクリプトも提示してくれていました。

04-q4

pip installsudo が付いているのが気になりますが、Python のコードは見た感じだとそのままでも良さそうな内容です。下記は同じ内容のコードです。コピペ用に使ってください。

dht22.py

import Adafruit_DHT

sensor = Adafruit_DHT.DHT22
pin = 4

humidity, temperature = Adafruit_DHT.read_retry(sensor, pin)

if humidity is not None and temperature is not None:
    print('Temp={0:0.1f}*C  Humidity={1:0.1f}%'.format(temperature, humidity))
else:
    print('Failed to read sensor')

回答のあったコマンドを実行して Adafruit_DHT のライブラリをインストールした後、提示されたコードを適当なファイル( dht22.py )に保存して実行します。

$ python dht22.py
Temp=24.8*C  Humidity=33.6%

特にエラーもなく温度と湿度のデータが取れました。
ChatGPT との会話だけでデータ取得できました!

では次に進みましょう。どこまでできるのか楽しみです。

新しいライブラリを使うようにする

実は、当初提示された Adafruit_DHT のライブラリは既に非推奨となっています。

27-adafruit-dht-deprecated

そこで、新しいライブラリである CircuitPython-DHT を使うように ChatGPT に聞いてみました。

05-q5 06-q6

pip installsudo が気になりますが)ライブラリが古い旨を指摘すると CircuitPython-DHT の利用を勧められました。あわせて、Python のコードも新しいものを教えてくれています。

他の案として別のライブラリ DHT-sensor-library というものを提案してくれているのですが、これは最初に紹介された非推奨のライブラリです。一旦これはスルーします。

07-q7

CircuitPython-DHT を使ったコードは下記になります。

dht22_circuit.py

import adafruit_dht

dht_pin = 4 # DHT22のデータピンに接続したGPIOピン番号を指定
dht_sensor = adafruit_dht.DHT22(dht_pin)

try:
    temperature = dht_sensor.temperature
    humidity = dht_sensor.humidity
    print(f"Temperature: {temperature:.1f} C   Humidity: {humidity:.1f} %")
except RuntimeError as e:
    print("Failed to read DHT22 sensor data:", e.args[0])

これを適当な名前(dht22_circuit.py)で保存して、実行するとエラーになりました。

$ python dht22_circuit.py

(中略)

    raise RuntimeError(
RuntimeError: Timed out waiting for PulseIn message. Make sure libgpiod is installed.

このエラーについて、ChatGPT に質問してみます。

08-time-out-error 09-time-out-error2

回答の通り、libgpiod2 をインストールして、コードも提示されたもの(dht22_circuit_v2.py)に入れ替えます。

dht22_circuit_v2.py

import board
import adafruit_dht

dht_pin = board.D4  # DHT22の信号ピンに接続されたGPIOピンの番号

dht_device = adafruit_dht.DHT22(dht_pin)  # DHT22を使用する場合はDHT22クラスを使用

try:
    temperature_c = dht_device.temperature
    humidity = dht_device.humidity
    print("Temperature: {:.1f}C, Humidity: {}%".format(temperature_c, humidity))
    
except RuntimeError as e:
    print("Error: ", e.args[0])

これを実行すると温度と湿度の値が取れましたが、今度は Lost access to message queue というメッセージも出るようになってしまいました。

$ python dht22_circuit_v2.py

Temperature: 25.4C, Humidity: 31.9%
Lost access to message queue

そこで、このメッセージの原因と解消方法も ChatGPT に質問してみます。

13-lost-access2mesg-queue 14-lost-access2mesg-queue2 15-lost-access2mesg-queue3

3つの原因と解決策を教えてくれました。しかし、1と2は既に設定済みなので該当しません。3つ目の解決策にある use_pulseio=False を試してみることにします。

use_pulseio=False パラメータの使い方も聞いてみます。

28-before-use-pulseio-false 29-after-use-pulseio-false

dht22_circuit_v3.py

import board
import adafruit_dht

dht_pin = board.D4  # DHT22の信号ピンに接続されたGPIOピンの番号

dht_device = adafruit_dht.DHT22(dht_pin, use_pulseio=False)  # use_pulseio=Falseを指定

try:
    temperature_c = dht_device.temperature
    humidity = dht_device.humidity
    print("Temperature: {:.1f}C, Humidity: {}%".format(temperature_c, humidity))
    
except RuntimeError as e:
    print("Error: ", e.args[0])

これをまた適当な名前(dht22_circuit_v3.py)で保存して実行したところ、温湿度データだけ取得できるようになりました。

$ python dht22_circuit_v3.py

Temperature: 26.8C, Humidity: 32.6%

MQTTブローカーに Publish する処理を追加してもらう

せっかくなので IoT らしく取得したデータを MQTT ブローカーに publish するところまでやってみましょう。
今回は、簡単にするために EMQ 社のパブリックブローカーを使うことにします。

40-add-publish-to-emqx 41-code-publish-to-emq

提示されたコードは下記のとおりです。

dht22_publish_to_emqx.py

import board
import adafruit_dht
import paho.mqtt.publish as publish

dht_pin = board.D4  # DHT22の信号ピンに接続されたGPIOピンの番号

dht_device = adafruit_dht.DHT22(dht_pin, use_pulseio=False)  # use_pulseio=Falseを指定

# EMQXのMQTTブローカーの情報を設定
mqtt_broker_host = "broker.emqx.io"
mqtt_broker_port = 1883
mqtt_topic = "topic/temperature_humidity"

while True:
    try:
        temperature_c = dht_device.temperature
        humidity = dht_device.humidity
        print("Temperature: {:.1f}C, Humidity: {}%".format(temperature_c, humidity))
        
        # MQTTメッセージをpublishする
        message = f"Temperature: {temperature_c:.1f}C, Humidity: {humidity}%"
        publish.single(mqtt_topic, message, hostname=mqtt_broker_host, port=mqtt_broker_port)
    
    except RuntimeError as e:
        print("Error: ", e.args[0])

このコードでもいいのですが、このままだと連続的にデータを送ってしまい、ブローカーに負荷がかかる恐れがあるので 5秒間隔で送るように処理を追加しておきます。( 1 行目と 28 行目を追加)
これも ChatGPTに「5秒間隔でデータをpublishするように修正してください」と依頼したものです。

dht22_publish_to_emqx.py

import time
import board
import adafruit_dht
import paho.mqtt.publish as publish

dht_pin = board.D4  # DHT22の信号ピンに接続されたGPIOピンの番号

dht_device = adafruit_dht.DHT22(dht_pin, use_pulseio=False)  # use_pulseio=Falseを指定

# EMQXのMQTTブローカーの情報を設定
mqtt_broker_host = "broker.emqx.io"
mqtt_broker_port = 1883
mqtt_topic = "topic/temperature_humidity"

while True:
    try:
        temperature_c = dht_device.temperature
        humidity = dht_device.humidity
        print("Temperature: {:.1f}C, Humidity: {}%".format(temperature_c, humidity))
        
        # MQTTメッセージをpublishする
        message = f"Temperature: {temperature_c:.1f}C, Humidity: {humidity}%"
        publish.single(mqtt_topic, message, hostname=mqtt_broker_host, port=mqtt_broker_port)
    
    except RuntimeError as e:
        print("Error: ", e.args[0])

    time.sleep(5)

次に、動作確認のため適当な MQTT クライアントで上記スクリプトに記載されているトピックを Subscribe しておきます。

  • ホスト:broker.emqx.io
  • ポート:1883
  • トピック:topic/temperature_humidity

今回は「MQTT X」というクライアントアプリを使います。動作確認の準備ができたら先程のスクリプトを実行してみましょう。
(データを送りながらセンサーを手で握って温度と湿度が変わるようにしています。)

$ dht22_publish_to_emqx.py

Temperature: 25.6C, Humidity: 35.9%
Temperature: 25.6C, Humidity: 40.6%
Temperature: 25.7C, Humidity: 51.5%
Temperature: 26.3C, Humidity: 68.7%

下記は MQTTX による subscribe の様子ですが、ブローカー側にもデータが届いていることが確認できました。

42-mqttx-subscribe

最後に

ChatGPT の回答だけでデバイス側の設定からプログラムの作成までを試してみました。
簡単なケースだったのでネット上にもたくさん情報がある題材でしたが、特に困ること無くデータ送信まで実装することができたのは衝撃的です。

とはいえ、筆者は以前に DHT22 でデータ取得したことがあるので、無意識のうちに「正解にたどりつく質問」をしていた可能性があります。そのため全く初めての場合だとうまくできないことがあるかもしれないので、今回の内容は参考程度に見ていただければと思います。

また、電子工作の部分についてですが、回答を鵜呑みにして間違った接続をするとデバイスを壊してしまう可能性もあるので、「困ったときに調査するためのヒントをもらう」ような感覚で使っていくのがいいかなと思いました。

API も利用できるようになったので、他に面白そうなネタがあれば試してみたいと思います。

以上です。