M5stackとRaspberry Pi zeroのBluetooth シリアル通信
ハードウェア
M5stackとRaspberry Pi zeroの2つのデバイス間でデータ通信することを目標にしています。
M5stackはディスプレイやボタンのインターフェイス用として,Raspberry Pi zeroはより高度な処理用として用います。 今回はM5stackが情報を送信するのみ,という仮定でやっています。
M5stackについて
M5Stackとはディスプレイ付きのマイコンその他もろもろ開発ボードです。
- 出版社/メーカー: スイッチサイエンス
- メディア: おもちゃ&ホビー
- この商品を含むブログを見る
開発手段には以下の2つが存在します。
前者のほうがライブラリなどが豊富ですが,後者はPythonベースなので記述量が非常に少ないというメリットがあります。 僕はファームウェアの書き換えが上手く行かなかったので前者を採用しました。
なお,WindowsPCでシリアル通信をしたことない場合などはドライバがない可能性があるのでこちらを参照にすれば良いと思います。
特定の通信機器を使う際にはそれに対応するCP210xのドライバが必要ということみたい? 本製品ではこちらからダウンロードするのが良さげです。
Raspberry Pi zeroについて
いわゆるRaspberry Piの小型軽量版です。省スペースかつ省電力なのにDebianベースのLinux OSが動かせるのでわりと使えそうです。
M5stack側の準備
ここではArduino開発環境を前提に進めていきます。 このサイトを参考に進めると良いでしょう。
また,Arduinoのエディタは正直言ってあまり使い勝手は良くないので,ここではVScodeで開発をしました。
「ファイル」の「環境設定」から「外部のエディタを使用する」にチェックを入れることで他のエディタで編集した.inoファイルの変更内容をArduinoIDEに反映させることが出来ます。ただし,IDEの方から文章を変更できなくなるのは注意。
BluetoothSerial.hの利用
Bluetoothで単に送信するだけの関数は驚くほど簡単で,"BluetoothSerial.h"
をインクルードして,BluetoothSerial クラスを呼ぶだけです。
その後,print,println,writeなどの関数で文字列や数値を送信することができます。
#include <M5Stack.h> #include "BluetoothSerial.h" byte counter; BluetoothSerial bts; void setup() { M5.begin(); M5.Lcd.println("Bluetooth Now"); Serial.begin(9600); bts.begin("M5Stack");//PC側で確認するときの名前 counter = 0; } void loop() { bts.println(counter); counter++; delay(100); }
Raspberry pi 側のセットアップ
M5stackが上記のようなプログラムですでに初期化・起動しているとします。
ペアリング,MACアドレスの取得
Bluetoothのペアリングはラズパイ側のGUIで設定する方法とCUIで設定する方法があります。その後の手順を考えるとCUIでやった方がいいのかなと思います。
- CUIでペアリング:bluetoothctlの起動
bluetoothctl
とコマンドを打つことでBluetoothの管理モードに移行します。
こんな感じの表記になるはずです。
pi@raspberrypi:~ $ bluetoothctl [NEW] Controller B8:27:EB:8C:43:C6 raspberrypi [default] [bluetooth]#
この後,以下のコマンドを順番に実行します。
agent on default-agent discoverable on scan on
しばらくするとscanの結果として,次のような画面に移行するので先程設定したM5Stack
の文字を探しましょう。
[bluetooth]# scan on Discovery started [CHG] Controller XX:XX:XX:XX:XX:XX Discovering: yes [NEW] Device 30:AE:A4:4F:A3:76 M5Stack
私の場合はこの30:AE:A4:4F:A3:76
がM5stackのMACアドレスということになります。(重要)
その後このMACアドレスを用いてpair <MACアドレス>
とコマンドを実行することでペアリングは完了です。
以下のような画面が出るかと思います。その後は適当にquitして元のターミナルに戻ってください。
[bluetooth]# pair 30:AE:A4:4F:A3:76 Attempting to pair with 30:AE:A4:4F:A3:76 [CHG] Device 30:AE:A4:4F:A3:76 Connected: yes Request confirmation [agent] Confirm passkey 952397 (yes/no): yes [CHG] Device 30:AE:A4:4F:A3:76 UUIDs: 000~ [CHG] Device 30:AE:A4:4F:A3:76 UUIDs: 000~ [CHG] Device 30:AE:A4:4F:A3:76 UUIDs: 000~ [CHG] Device 30:AE:A4:4F:A3:76 ServicesResolved: yes [CHG] Device 30:AE:A4:4F:A3:76 Paired: yes Pairing successful [CHG] Device 30:AE:A4:4F:A3:76 ServicesResolved: no [CHG] Device 30:AE:A4:4F:A3:76 Connected: no
接続も自動で行われるはずですが,不安ならば先程のbluetoothctlの画面にてconnect MACアドレス
を実行すると良いでしょう。
バインドしてシリアル受信確認
接続しただけではデバイスとして認識できないのでrfcommというコマンドを使ってBindを行います。 例えば先程メモしたMACアドレスを用いて,
sudo rfcomm bind 1 30:AE:A4:4F:A3:76 2
のように実行することで,/dev/rfcomm1
のポート2がBluetoothの入出力に対応するようになります。
シリアルにて流れてくる情報を単に閲覧したければ
cat /dev/rfcomm1
とうって確認できます。
Pythonで受信した文字列を表示
先程バインドしたrfcomm1
を引数にしてSerialモジュールを呼ぶことで通信が可能です。
import serial ser=serial.Serial('/dev/rfcomm1') while 1: print(ser.readline())
トラブルを避けるならKeyboardInterruptでser.close()を呼ぶなどした方が安全でしょうが,一応これでM5stackが発信している文字を確認できます。
逆にser.send()を用いてラズパイ側から送信した場合は,M5stack側でread()を用いて受信関数を書けば動作します。
ラズパイ起動時にプログラム実行
先程の接続やバインドなどをラズパイの起動時にキー入力なしでしたいと思った場合,/etc/rc.local
というファイルに書き込むという手段があります。
root権限で実行されるので少し気をつける必要がありますが,とりあえず動かしたい場合はこれでも良いかと。
# connect echo "connect 30:AE:A4:4F:A3:76 \nquit" | bluetoothctl #bind sudo rfcomm bind 1 30:AE:A4:4F:A3:76 2 # add your program below
何に使ったか
M5stackで作ったタイマーと組み合わせて起床時に徐々に明かりを明るくするIoT目覚ましセットを作成しました。 睡眠リズムの改善が求められる…
参考文献メモ置き場
記事で引用すると思ったけどしなかった参考文献たち: