粗大メモ置き場

個人用,たまーに来訪者を意識する雑記メモ

M5stackとRaspberry Pi zeroのBluetooth シリアル通信

ハードウェア

M5stackとRaspberry Pi zeroの2つのデバイス間でデータ通信することを目標にしています。

M5stackはディスプレイやボタンのインターフェイス用として,Raspberry Pi zeroはより高度な処理用として用います。 今回はM5stackが情報を送信するのみ,という仮定でやっています。

M5stackについて

M5Stackとはディスプレイ付きのマイコンその他もろもろ開発ボードです。

M5Stack Gray(9軸IMU搭載)

M5Stack Gray(9軸IMU搭載)

開発手段には以下の2つが存在します。

前者のほうがライブラリなどが豊富ですが,後者はPythonベースなので記述量が非常に少ないというメリットがあります。 僕はファームウェアの書き換えが上手く行かなかったので前者を採用しました。

なお,WindowsPCでシリアル通信をしたことない場合などはドライバがない可能性があるのでこちらを参照にすれば良いと思います。

特定の通信機器を使う際にはそれに対応するCP210xのドライバが必要ということみたい? 本製品ではこちらからダウンロードするのが良さげです。

Raspberry Pi zeroについて

いわゆるRaspberry Piの小型軽量版です。省スペースかつ省電力なのにDebianベースのLinux OSが動かせるのでわりと使えそうです。

ossyaritoori.hatenablog.com

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目覚ましセットを作成しました。 睡眠リズムの改善が求められる…

f:id:ossyaritoori:20190111231037p:plain
目覚ましセット

参考文献メモ置き場

記事で引用すると思ったけどしなかった参考文献たち:

Wifi接続などに関する参考文献