ESP32(Arduino)とUbuntuをBluetooth ClassicのSPPプロトコルで通信させるためにえらく苦労したのでメモ。
なお試行錯誤の結果をメモしたものなので間違ってたり、不要な操作が含まれているかもしれません。あしからず。
全然動かなかったり変なことが起こったりしても自己責任でお願いします。
ESP32とUbuntuのバージョン
Arduino前提になりますが、ボードライブラリを入れたらついてくる「SerialToSerialBT」を使えばとりあえずスケッチ弄らなくてもテストできます。
ただ、ボードライブラリのバージョンによってはESP32のBluetoothにバグがあるようです。バージョン1.0.0はダメでした。
うちの環境では1.0.1と1.0.2では動いたので、1.0.1以降を使ってください。
また、Ubuntu 18.04でテストしています。
問題:Ubuntuで普通にペアリングしに行っても蹴られる
Ubuntuの設定からBluetoothを開くと出てくるデバイス一覧から接続したいデバイスをクリックしてペアリングする。
これがUbuntuのGUIでペアリングする際の一般的な方法ですが、この方法で接続しても数秒で切断されてしまいます。
もう少し詳しく現象を記載すると、
①デバイスをクリックして接続試行
②Ubuntuの画面にPINコードが表示され、デバイス側の表示を確認するよう求められるが、ESP32で確認する術がないので確認したことにする
③接続表示になるものの数秒で切断される
④その後何度接続を試みても、デバイスを削除してやり直しても改善しない
ということで、SPPで通信も何もできません。
対処法を色々探してみましたがピッタリ解決するものは見つけられず……(-_-;)
一瞬でも繋がってはいる(ように見える)ので、何とかできないか試行錯誤し、一応動く方法を見つけました。
解決手順1:ModemManagerを停止
Ubuntu上でModemManagerが動作していた場合、接続中にATコマンドが送信され通信の邪魔になります。
以下のコマンドでModemManagerを停止してください。
$ sudo systemctl stop ModemManager
続けて以下のコマンドでModemManagerが停止していることを確認してください。
$ sudo systemctl status ModemManager.service
解決手順2:SDPクライアントの設定
SDPはBluetoothのプロトコルの一種で、通信相手がどのようなサービスに対応しているかを確認する役割を持ちます。サービスを提供する側(デバイス側)をサーバと呼び、サービスを受ける側(ホスト側)をクライアントと呼んでいます。
以下のコマンドでローカルのサービスを確認してください。
$ sdptool browse local
下記のようなエラーが出た場合はbluetoothdの設定変更が必要です。
Failed to connect to SDP server on FF:FF:FF:00:00:00: No such file or directory
適当なエディタで /etc/systemd/system/dbus-org.bluez.service を開き、以下 のように変更してください。
変更前
ExecStart=/usr/lib/bluetooth/bluetoothd
変更後
ExecStart=/usr/lib/bluetooth/bluetoothd --compat
変更後、bluetoothdを再起動します。
$ sudo systemctl daemon-reload $ sudo systemctl restart bluetooth $ sudo chmod 777 /var/run/sdp
下記コマンドを再度実行し、サービス一覧を確認してください。
$ sdptool browse local
表示されたサービスの中に Service Name: Serial Port が無かった場合は、SPPを追加しましょう。
$ sudo sdptool add --channel=22 SP
もう一度サービス一覧を取得し、Service Name: Serial Port が追加さ れていることを確認してください。
$ sdptool browse local
解決手順3:BDアドレスの確認
bluetoothctlを起動します。
$ bluetoothctl
bluetoothctlのインタフェースに移行したことを確認したら、コントローラを起動します。
$ power on
ESP32のBDアドレスを調べます。ESP32の電源は入れておいてください。
$ devices
デバイスが見つからない場合は以下のコマンドでスキャンできるハズです。
$ scan on
見つかったESP32のBDアドレスを控えておいてください。
解決手順4:ペアリング
bluetoothctlで以下のコマンドを実行しペアリングを行います。
& pair BDアドレス
ペアリングが実行されると下記のような表示がされると思います。
[CHG] Device BDアドレス ServicesResolved: yes [CHG] Device BDアドレス Paired: yes Pairing successful [CHG] Device BDアドレス ServicesResolved: no [CHG] Device BDアドレス Connected: no
ペアリング直後に Connected が no になるかと思います。
GUIでペアリングしたときに起こっていたのはこの現象のようです。
やっぱり一度サクセスした後に切断されているみたいですね。
ここではこれは放っておいて、先へ進みます。
解決手順5:rfcommの設定
rfcommを使って仮想シリアルポートのデバイスファイルを作成しESP32と紐づけします。
bluetoothctlを終了するか、新しいシェルで以下のコマンドを実行していください。
$ sudo rfcomm -r -M -L 0 bind 0 BDアドレス
デバイスファイルrfcomm0が作成されていることを確認します。
$ rfcomm -a
rfcomm0: BDアドレス channel 1 closed といったように表示されていればOKです。
解決手順6:デバイスファイルの設定
手順5で作成した、仮想シリアルポートの設定をします。
$ sudo stty -F /dev/rfcomm0 115200 cs8
sttyは標準入出力に設定されている端末の設定を見たり変更したりするコマンドですが、”-F”オプションを使用することで特定デバイスの設定をコントロールできます。
上記コマンドでは、ボーレートを115200に設定し、文字サイズをcs8に設定しています。
ボーレートの値についてはとりあえず115200で使えてるのでそれにしているだけで、妥当性については特に検証していません。というかSPPにおけるボーレート設定に意味あるんでしょうか?
文字サイズの設定は確実に意味ありませんから、もしかするとこの手順全く不要かもしれません()
解決手順7:ターミナルソフトで動作確認
適当なターミナルソフトを使ってメッセージを送信し、動作を見てみてください。
以下はgtktermを使った場合です。
gtktermの起動(ポート/ボーレート指定)
$ gtkterm -p /dev/rfcomm0 -s 115200
メニューの Control signals から Open Port を選択します。
bluetoothctlで状態を監視していた場合は以下のようなダイアログが表示されます。
[CHG] Device BDアドレス Connected: yes
以下のコマンドでも接続を確認することができます。
$ rfcomm -a
rfcomm0: BDアドレス channel 1 connected [tty-attached] といった表示であ れば接続されています。
Ubuntuの設定のBluetoothのデバイス一覧からも確認可能です。
あとはUSBシリアルの側から何か送ってみたり、Bluetoothの側から何か送ってみたりして試してみてください。
BLEならいける?
本筋と関係ないオマケです。
BLEなら行けるのかと軽く調べてみましたが、こっちもピタッとした情報は見つからず。
見つからないってことは特に問題なく使えるんでしょうか?
スマホやmacと繋ぐ情報は色々出てくるので、もしかして単純にUbuntuと繋ぐ需要が壊滅的に無いって感じですかね?
教えてエライ人!
コメント