概要
ラズパイでモーター制御に挑戦してみます。SunFounder製の電子工作キットの中にモーターとファンおよび必要備品が予め内包されているため、マニュアルに従い環境構築します。ただモーター駆動させるだけでは面白くないため、ラズパイと別のPCを無線通信(通信プロトコルはMQTT)で通信できるようにし、別のPCから無線通信経由でモーターON/OFFしてみたいと思います。また、スマホアプリ経由でモーター制御にも挑戦します。
ラズパイ購入、セットアップ
ラズパイのセットアップに関しては以下記事をご参考ください。
環境構築
以下サイトを参考に環境構築します。
https://docs.sunfounder.com/projects/davinci-kit/ja/latest/python_pi5/pi5_1.3.1_motor_python.html
ちなみに、以下に類似のページがありますが、python向けのサンプルコードがDHT11用になっていました(2024年8月時点)。
https://docs.sunfounder.com/projects/davinci-kit/ja/latest/1.3.1_motor.html
なお、9Vの四角い乾電池が必要なため、追加で購入しました(ボタンをクリックするとAmazonのサイトへ飛びます)。
モーターを駆動させるには大きな電流が必要なため、ラズパイから直接モーターを駆動させようとすると破損の恐れがあります。
そのため、電源供給モジュールとモータードライバ(L293D)を利用し、モーターを駆動させる仕組みです。
写真には納まらなかったですが、電池が繋がっています。
ラズパイからはトリガをかけるだけです。
モーター駆動を実行
上記サイトに添付されているサンプルコードを試行します。
動きました!結構強力です。夏にはいいですね。
MQTT通信とは
ラズパイでモーター制御できるようになりましたので、今度は無線通信(MQTT)経由でラズパイに指示を出せるようにします。
MQTT通信とは、IoT製品向けに考案された軽量な通信プロトコルです。
昨今のIoT製品で広く利用されています。
従来のサーバー/クライアント形式の通信ではなく、パブリッシュ/サブスクライブという概念で通信します。
デバイス側(ここではラズパイのこと)がMQTTブローカーという中継装置に対し、「XXに関する配信があったら頂戴ね」というリクエストを送ります。
これをサブスクライブと言います。
そして、情報を配信する側(サーバー側)がMQTTブローカーに対してXXに関する配信(パブリッシュ)をすると、MQTTブローカーがデバイス側へXXに関する情報を送信します。
このXXのことを「トピック」と言います。
MQTTサーバーを構築
mosquittoを以下サイトからダウンロードし、PC(サーバー用)にインストールします。
https://mosquitto.org/download
次に、以下コマンドで必要なパッケージをインストールします。
$pip install paho-mqtt
そして、mqttサーバーを起動します。
C:\Program Files\mosquitto>mosquitto -v
1724042850: mosquitto version 2.0.18 starting
1724042850: Using default config.
1724042850: Starting in local only mode. Connections will only be possible from clients running on this machine.
1724042850: Create a configuration file which defines a listener to allow remote access.
1724042850: For more details see https://mosquitto.org/documentation/authentication-methods/
1724042850: Opening ipv4 listen socket on port 1883.
1724042850: Opening ipv6 listen socket on port 1883.
1724042850: mosquitto version 2.0.18 running
ログ内の2~4行目の内容をこの時はよく読んでおらず、後で大変なことになるとは。。。
MQTT送受信テスト(PC内)
testというトピックをサブスクします。
C:\Program Files\mosquitto>mosquitto_sub -h localhost -t test
1724043030: New connection from ::1:56065 on port 1883.
1724043030: New client connected from ::1:56065 as auto-xxx.
1724043030: No will message specified.
1724043030: Sending CONNACK to auto-xxx
1724043030: Received SUBSCRIBE from auto-xxx
1724043030: test (QoS 0)
1724043030: auto-xxx 0 test
1724043030: Sending SUBACK to auto-xxx
-hオプションでホスト名をlocalhostに指定しています。一旦、PC内でサブスクとパブリッシュ疎通を確認します。
パブリッシュしてみます。
C:\Program Files\mosquitto>mosquitto_pub -h localhost -t test -m "sample message"
サブスクしているターミナルから以下を受信できました。
sample message
MQTT送受信テスト(ラズパイ⇔PC)
ラズパイとPCの疎通を試行します。まずはPC側でMQTTブローカーを立ち上げます。オプションについては後で解説します。
$mosquitto -c mosquitto.conf -v
次に、ラズパイからMQTTブローカー(PC)へサブスクします。
$mosquitto_sub -h 192.168.x.x -p 1883 -t test -v
ラズパイへパブリッシュしてみます。
$mosquitto_pub -h localhost -t test -m "sample message"
無事、ラズパイ側で”sample message”を受信できました。
MQTTからモーターを駆動、停止してみる
PCからMQTT経由でラズパイのモーターを駆動、停止してみます。
ラズパイ側でpythonプログラムを実行すると、トピック:testにサブスクします。
$ python motor2.py
/home/xxx/motor2.py:29: DeprecationWarning: Callback API version 1 is deprecated, update to latest version
client = mqtt.Client(client_id=MQTT_CLIENT_ID, protocol=mqtt.MQTTv311)
Connected with result code 0
エラーが出ていますが接続成功した様子です。
ではモーター駆動させてみます。testトピックで”ON”をパブリッシュされたらモーター駆動するようにしています。一旦はMQTTブローカーであるPCからパブリッシュします。そのため-hオプションの値はlocalhostとしています。
$mosquitto_pub -h localhost -t test -m "ON"
無事起動できました!なお、以下コマンドで停止できます。
$mosquitto_pub -h localhost -t test -m "OFF"
ラズパイ側のpythonコード
ラズパイ側で実行していたpythonコードです。
#!/usr/bin/env python3
from gpiozero import Motor
from time import sleep
import paho.mqtt.client as mqtt
# GPIO pin configuration
motor = Motor(forward=17, backward=27, enable=22)
# MQTT configuration
MQTT_BROKER_IP = "192.168.128.118"
MQTT_TOPIC = "test"
MQTT_CLIENT_ID = "motor_controller"
# Callback function for when the client connects to the broker
def on_connect(client, userdata, flags, rc):
print(f"Connected with result code {rc}")
client.subscribe(MQTT_TOPIC) # Subscribe to the topic
# Callback function for when a message is received
def on_message(client, userdata, msg):
message = msg.payload.decode()
print(f"Received message '{message}' on topic '{msg.topic}'")
if message == "ON":
motor.forward() # Drive the motor forward
elif message == "OFF":
motor.stop() # Stop the motor
# Configure MQTT client
client = mqtt.Client(client_id=MQTT_CLIENT_ID, protocol=mqtt.MQTTv311)
client.on_connect = on_connect
client.on_message = on_message
try:
# Connect to the MQTT broker
client.connect(MQTT_BROKER_IP)
# Start the MQTT client loop
client.loop_start()
# Keep the program running
while True:
sleep(1) # Wait for MQTT messages
except KeyboardInterrupt:
# Handle keyboard interrupt (e.g., Ctrl+C) to stop the program gracefully
print("KeyboardInterrupt received, stopping motor and cleaning up.")
finally:
# Ensure motor is stopped and MQTT client loop is stopped
motor.stop() # Stop the motor
client.loop_stop() # Stop the MQTT client loop
client.disconnect() # Disconnect from the MQTT broker
print("Program stopped and GPIO cleaned up.")
気を付けること・ハマったところ
上記を実現する上で、以下を気を付ける必要があります。
- PC側でポート1883を解放する(ファイアウォール設定を変更する)
- ブローカー側のコンフィグファイル(mosquitto.conf)設定を修正する
上記2点のうち、下段のコンフィグファイルでハマりました。。。
コンフィグファイルを修正し保存しても、mosquitto起動時に「デフォルト設定で起動します。このモードでは外部からの通信はできずローカルのみです」というメッセージから変わらずで困り果てました。
C:\Program Files\mosquitto>mosquitto -v
1724042850: Using default config.
1724042850: Starting in local only mode. Connections will only be possible from clients running on this machine.
1724042850: Create a configuration file which defines a listener to allow remote access.
ログをよく見ると、「リモートアクセスしたければコンフィグファイルを用意せよ」という意味に見えます。つまり、mosquitto起動時にmosquitto.confというファイルを参照しているわけではなさそう。。。ということで起動時にコンフィグファイルを指定する必要があります。
$mosquitto -c mosquitto.conf -v
上記のように-cオプションをつけてコンフィグファイル名を指定する必要があったのです。。。これに気づくのが大変遅かった。。。mosquitto起動時に以下のように表示されていればOKです。
mosquitto version 2.0.18 starting
Config loaded from mosquitto.conf.
Opening ipv6 listen socket on port 1883.
Opening ipv4 listen socket on port 1883.
mosquitto version 2.0.18 running
-vオプションはログ出力するオプションです。あ、サブスク来たなーとかがわかります。
おまけ:スマホからパブリッシュしてみる
先ほどはPCからパブリッシュしましたが、せっかくなのでスマホからもパブリッシュしてみます。
IoTMQTTPanelをインストール
スマホアプリは候補が複数あるようでして、今回はIoTMQTTPanelというアプリを利用させていただきました。
IPhoneにインストールした後、以下手順で設定していきます。
ネットワーク設定
以下の手順で設定していきます。スマホの接続先ネットワークをPC/ラズパイと同じネットワークにする点に注意です。
- Connection nameを設定(適当な名前でOK)
- Client IDを設定(適当なIDでOK)
- Broker Web/IP addressを設定(ブローカーとして立ち上げているPCのIPアドレスを指定)
- Portを設定(mosquittoのポートである1883を指定)
- Network protocolを設定(TCPを指定)
- Add Dashboardを設定(適当な名称で追加)
スマホとブローカーが繋がりました!
スマホからブローカーへパブリッシュ!
スマホからモーター駆動をトリガしてみます。スマホの画面上で送信ボタンをタップ!
実際に試行している様子です。パソコンで頑張って撮影しているため、動画がゆらゆらしますがご容赦ください。
感動!
まとめ
モーター駆動させるために必要な環境について学べました。また、ローカルネットワークではありますが、MQTT経由でサブスクとパブリッシュを実現できました。時間があったらセキュリティ認証を取り入れてグローバルネットワークからトリガかけてみたいところです。
参考文献
以下サイトを参考にさせていただきました。ありがとうございました。