【ESP32】UbuntuとBluetooth ClassicでSPP通信する方法【Arduino】

テック

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と繋ぐ需要が壊滅的に無いって感じですかね?

教えてエライ人!

テック
スポンサーリンク
スポンサーリンク
もりをフォローする
スポンサーリンク
みゆともり

コメント