やり方が分かるまでに数日かかったので、方法を共有します。
全体像
この流れで説明します。- 背景
- 使ったものの紹介
- ESP32のIDF(開発環境)の設定
- シリアル通信環境を構築
- BLEの操作環境を構築
- ESP32にbluetootn serverのプログラムを書き込み
- BLEデバイスとしてESP32を認識
- ESP32からBluetooth経由で信号を取得
- ESP32にBluetooth経由で信号を送信
背景
ESP32とはESP8266(500円位で買えるwifiモジュール)の後継機です。ESP32はESP8266に比べて、デュアルコアでマルチタスクが可能、WiFiに加えてBluetoothも利用可能などの利点があります。
今回の記事の内容(Bluetooth経由での情報のやりとり)を行うにあたり、ネット上に情報が不足していると感じたので、今回の記事を残します。
使ったものの紹介
これらのものを利用しました。
ハードウェア
- PC
ubuntuを入れて使います。 - ESP32開発ボード
2016.11月頃にaliexpressで$25位で購入しました。
2017.04.26時点では$10位で買えるようです。 aliexpress esp32
秋月電子で売っているesp32開発ボードでも同じことができると思います。 - USB microBケーブル
PCとESP32開発ボードの接続に使います。
手持ちのケーブルを利用しました。
ソフトウェア
- ubuntu16.04
linuxのディストリビューションのひとつです。
この記事では64bit版を利用しています。 - esp-idf
esp32開発に必要な開発環境です。
IDFは「Espressif IoT Development Framework」の略です。 - bluez
linuxからbluetoothデバイスのスキャンや接続ができるプログラムです。
そのプログラムに含まれるhcitoolとgatttoolを今回利用しました。 - screen
unix系のPCでシリアル通信をするためのプログラムです。
ESP32の動作確認に利用しました。
ESP32のIDF(開発環境)の設定
基本的にesp-idfのlinux向けのドキュメントに従ってubuntu16.04にIDFを設定します。esp-idf/docs/linux-setup
作業フォルダを作成
ドキュメントに沿って「esp」というディレクトリをホームディレクトリに作成します。このディレクトリの中にESP32に関連するファイルを置いていきます。
mkdir ~/esp
関連プログラムのインストール
IDFの実行に必要な関連プログラムをインストールします。sudo apt-get install git wget make libncurses-dev flex bison gperf python python-serial
バイナリで公開されているファイルを設置
esp32を作っているメーガーが公開しているコンパイル済みのファイル(binary toolchain)をPCに設置します。64ビット版のubuntuを使っているので、それ用のファイル使います。
(バイナリファイルは頻繁に更新されるので、本家ドキュメントのToolchain Setupで最新版をチェックし、そちらをインストールするのがおすすめです。)
cd ~/esp wget https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-75-gbaf03c2-5.2.0.tar.gz tar -xzf xtensa-esp32-elf-linux64-1.22.0-75-gbaf03c2-5.2.0.tar.gz
ファイルを設置できたら、プログラムから呼べるようにパスを通します。
bachrcに下記の記述を追加します。
~/.bashrc
export PATH=$PATH:$HOME/esp/xtensa-esp32-elf/bin
追加できたらターミナルを再起動するか、bashrcを下記のコマンドで再読み込みします。
source ~/.bashrc
IDFを設置
プログラムをダウンロードします。cd ~/esp git clone --recursive https://github.com/espressif/esp-idf.git
ネットワークの都合などでダウンロードが途中で失敗した場合は、下記のコマンドでダウンロードを再開できます。
cd ~/esp/esp-idf git submodule update --recursive
プログラムのダウンロードができたら下記の記述をbashrcに追加して、makeコマンド実行時にプログラムを呼べるようにします。
~/.bashrc
export IDF_PATH=~/esp/esp-idf
ESP32の開発環境を構築できました。
シリアル通信環境を構築
下記のコマンドでscreenをインストールします。sudo apt-get install screen
コマンドでscreenを通してシリアル通信ができるようになりました。
BLEの操作環境を構築
下記のコマンドでbluezをインストールします。sudo apt-get install bluez
hcitoolとgatttoolを使えるようになりました。
ESP32にbluetootn serverのプログラムを書き込み
bluetooth serverのプログラムIDFのサンプルプログラムに含まれています。ビルド(コンパイル)
サンプルプログラムのディレクトリに移動して、下記のコマンドでビルドします。cd ~/esp/esp-idf/examples/bluetooth/gatt_server/ make all
初めてビルドする場合は、下記のように設定画面が出ます。
サンプルプログラムの設定は、プログラムの意図する設定になっているので、左右矢印で「exit」を選択して、エンターを押して終了します。
(ちなみに、この設定画面は「make menuconfig」で表示できます。)
makeが成功すると、下記のようにビルドできたプログラムがずらずらと表示されます。
書き込み
ESP32の開発ボードとPCをUSB microBケーブルで接続します。開発ボードのBOOTのボタンを押したままEN(リセットボタン)を押して、ESP32を書き込みモードにします。
開発モードで起動できたら、BOOTボタンは離しても大丈夫です。
ビルドしたプログラムのあるディレクトリでmake flashコマンドを実行すると書き込みが始まります。
cd ~/esp/esp-idf/examples/bluetooth/gatt_server/ make flash
1分位で書き込みが終了します。
書込みできたらENボタンを押すかUSBケーブルを挿し直すかして、ESP32を再起動すると、ESP32上でプログラムが動き始めます。
動作確認
ESP32をPCに接続した状態で下記のコマンドを入力すると、ESP32から出力されるログを確認できます。screen /dev/ttyUSB0 115200
screenで接続した後にenボタンを押すと、gatt_serverの場合下記のようなログが出力されます。
エラーのような赤字が出力されますが、bluetoothの機能は動いているようです。
Bluetoothのアドレスもログに表示されます。
アドレスはモジュールによって異なりますが、今回使っているESP32のアドレスは「24:0A:C4:04:2C:AA」だと分かりました。
BLEデバイスとしてESP32を認識
下記のコマンドでhcitoolを使うとBLEデバイスをスキャンできます。sudo hcitool lescan
「ESP_GATTS_DEMO」というデバイスがESP32です。
BLEデバイスとして動いていることを確認できました。
ESP32のBLEプロファイルを確認
下記のようにgatttoolを使うとBLEのGATTプロファイルなどを確認できます。hcitoolで今回使っているESP32のアドレス、下記のコマンドでGATTに関するやりとりを開始できます。
gatttool -b 24:0A:C4:04:2C:AA -I
gatttoolを開けたら、情報を取得するために、接続します。
connect
helpで使い方を見れます。
> help help Show this help exit Exit interactive mode quit Exit interactive mode connect [address [address type]] Connect to a remote device disconnect Disconnect from a remote device primary [UUID] Primary Service Discovery included [start hnd [end hnd]] Find Included Services characteristics [start hnd [end hnd [UUID]]] Characteristics Discovery char-desc [start hnd] [end hnd] Characteristics Descriptor Discovery char-read-hnd <handle> Characteristics Value/Descriptor Read by handle char-read-uuid <UUID> [start hnd] [end hnd] Characteristics Value/Descriptor Read by UUID char-write-req <handle> <new value> Characteristic Value Write (Write Request) char-write-cmd <handle> <new value> Characteristic Value Write (No response) sec-level [low | medium | high] Set security level. Default: low mtu <value> Exchange MTU for GATT/ATT
GATTの内容についてまだ理解できていないので、取得できた情報を記述します。
primary
[24:0A:C4:04:2C:AA][LE]> primary attr handle: 0x0001, end grp handle: 0x0005 uuid: 00001801-0000-1000-8000-00805f9b34fb attr handle: 0x0014, end grp handle: 0x001c uuid: 00001800-0000-1000-8000-00805f9b34fb attr handle: 0x0028, end grp handle: 0x002b uuid: 000000ff-0000-1000-8000-00805f9b34fb attr handle: 0x002c, end grp handle: 0xffff uuid: 000000ee-0000-1000-8000-00805f9b34fb
characteristics
[24:0A:C4:04:2C:AA][LE]> characteristics handle: 0x0002, char properties: 0x20, char value handle: 0x0003, uuid: 00002a05-0000-1000-8000-00805f9b34fb handle: 0x0015, char properties: 0x02, char value handle: 0x0016, uuid: 00002a00-0000-1000-8000-00805f9b34fb handle: 0x0017, char properties: 0x02, char value handle: 0x0018, uuid: 00002a01-0000-1000-8000-00805f9b34fb handle: 0x0019, char properties: 0x02, char value handle: 0x001a, uuid: 00002aa6-0000-1000-8000-00805f9b34fb handle: 0x0029, char properties: 0x1a, char value handle: 0x002a, uuid: 0000ff01-0000-1000-8000-00805f9b34fb handle: 0x002d, char properties: 0x1a, char value handle: 0x002e, uuid: 0000ee01-0000-1000-8000-00805f9b34fb
char-desc
[24:0A:C4:04:2C:AA][LE]> char-desc handle: 0x0001, uuid: 00002800-0000-1000-8000-00805f9b34fb handle: 0x0002, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x0003, uuid: 00002a05-0000-1000-8000-00805f9b34fb handle: 0x0014, uuid: 00002800-0000-1000-8000-00805f9b34fb handle: 0x0015, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x0016, uuid: 00002a00-0000-1000-8000-00805f9b34fb handle: 0x0017, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x0018, uuid: 00002a01-0000-1000-8000-00805f9b34fb handle: 0x0019, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x001a, uuid: 00002aa6-0000-1000-8000-00805f9b34fb handle: 0x0028, uuid: 00002800-0000-1000-8000-00805f9b34fb handle: 0x0029, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x002a, uuid: 0000ff01-0000-1000-8000-00805f9b34fb handle: 0x002b, uuid: 00002902-0000-1000-8000-00805f9b34fb handle: 0x002c, uuid: 00002800-0000-1000-8000-00805f9b34fb handle: 0x002d, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x002e, uuid: 0000ee01-0000-1000-8000-00805f9b34fb handle: 0x002f, uuid: 00002902-0000-1000-8000-00805f9b34fb
characteristicsで確認できたuuidのchar-read-uuid
[24:0A:C4:04:2C:AA][LE]> char-read-uuid 00002a05-0000-1000-8000-00805f9b34fb Error: Read characteristics by UUID failed: Attribute can't be read [24:0A:C4:04:2C:AA][LE]> char-read-uuid 00002a00-0000-1000-8000-00805f9b34fb handle: 0x0016 value: 45 53 50 5f 47 41 54 54 53 5f 44 45 4d 4f [24:0A:C4:04:2C:AA][LE]> char-read-uuid 00002a01-0000-1000-8000-00805f9b34fb handle: 0x0018 value: 00 00 [24:0A:C4:04:2C:AA][LE]> char-read-uuid 00002aa6-0000-1000-8000-00805f9b34fb handle: 0x001a value: 00 [24:0A:C4:04:2C:AA][LE]> char-read-uuid 0000ff01-0000-1000-8000-00805f9b34fb handle: 0x002a value: de ed be ef [24:0A:C4:04:2C:AA][LE]> char-read-uuid 0000ee01-0000-1000-8000-00805f9b34fb handle: 0x002e value: de ed be ef
characteristicsで確認できたhandleのchar-read-hnd
[24:0A:C4:04:2C:AA][LE]> char-read-hnd 0x0002 Characteristic value/descriptor: 20 03 00 05 2a [24:0A:C4:04:2C:AA][LE]> char-read-hnd 0x0015 Characteristic value/descriptor: 02 16 00 00 2a [24:0A:C4:04:2C:AA][LE]> char-read-hnd 0x0017 Characteristic value/descriptor: 02 18 00 01 2a [24:0A:C4:04:2C:AA][LE]> char-read-hnd 0x0019 Characteristic value/descriptor: 02 1a 00 a6 2a [24:0A:C4:04:2C:AA][LE]> char-read-hnd 0x0029 Characteristic value/descriptor: 1a 2a 00 01 ff [24:0A:C4:04:2C:AA][LE]> char-read-hnd 0x002d Characteristic value/descriptor: 1a 2e 00 01 ee
characteristicsで確認できたvalue handleのchar-read-hnd
[24:0A:C4:04:2C:AA][LE]> char-read-hnd 0x0003 Error: Characteristic value/descriptor read failed: Attribute can't be read [24:0A:C4:04:2C:AA][LE]> char-read-hnd 0x0016 Characteristic value/descriptor: 45 53 50 5f 47 41 54 54 53 5f 44 45 4d 4f [24:0A:C4:04:2C:AA][LE]> char-read-hnd 0x0018 Characteristic value/descriptor: 00 00 [24:0A:C4:04:2C:AA][LE]> char-read-hnd 0x001a Characteristic value/descriptor: 00 [24:0A:C4:04:2C:AA][LE]> char-read-hnd 0x002a Characteristic value/descriptor: de ed be ef [24:0A:C4:04:2C:AA][LE]> char-read-hnd 0x002d Characteristic value/descriptor: 1a 2e 00 01 ee
ESP32からbluetooth経由で信号を取得
下記の情報読み取りコマンドに関して、対応するESP32のプログラムを見つけられました。[24:0A:C4:04:2C:AA][LE]> char-read-uuid 0000ff01-0000-1000-8000-00805f9b34fb handle: 0x002a value: de ed be efまたは
[24:0A:C4:04:2C:AA][LE]> char-read-hnd 0x002a Characteristic value/descriptor: de ed be ef
上記コマンド実行時は、screenで表示しているESP32のログに下記の情報が出力されます。
I (1370541) GATTS_DEMO: GATT_READ_EVT, conn_id 0, trans_id 26, handle 42
これは「~/esp/esp-idf/examples/bluetooth/gatt_server/main/gatts_demo.c」のESP_GADDS_READ_EVTに関するcaseで処理されているようです。
ESPの内部状態を配信したい場合、この周辺のプログラムが参考になるかもしれません。
ESP32にbluetooth経由で信号を送信
下記の情報送信コマンドに関しては、対応するESP32のプログラムを見つけられました。ちなみに、下記のコマンドは「3939」を送信しています。
[24:0A:C4:04:2C:AA][LE]> char-write-req 0x002a 3939 Characteristic value was written successfully
上記コマンド実行時は、screenで表示しているESP32のログに下記の情報が出力されます。
I (1740351) GATTS_DEMO: GATT_WRITE_EVT, conn_id 0, trans_id 2, handle 42 I (1740351) GATTS_DEMO: GATT_WRITE_EVT, value len 2, value 00003939
これはreadと同じ「~/esp/esp-idf/examples/bluetooth/gatt_server/main/gatts_demo.c」のESP_GADDS_WRITE_EVTに関するcaseで処理されているようです。
受け取った情報を元にESPの振る舞いを変えるようなプログラムを書く場合、この周辺のプログラムの記述方法が参考になるかもしれません。
方法の共有は以上です。
間違いがありましたら、コメントなどで指摘していただけると嬉しいです。
参考
Flashing ESP32 with Template AppESP32でのプログラムの書き込みを解説している動画です。
ツールの動きがわからない時に参考になりました。
HOW TO GET STARTED WITH THE ESP32
上記の動画を紹介している記事です。
BT LE FindMe profile in Bluez
hcitool利用の参考にしました。
Bluetooth Low Energy: listening for notifications/indications in linux
gatttool利用時の参考にしました。
更新履歴
2017/03/09乾電池でも動くことを利点として紹介していましたが、ESP8266でもできそうなので、その説明を削除しました。
2017/03/17
binary toolchainのパスを現時点の最新版(xtensa-esp32-elf-linux64-1.22.0-61-gab8375a-5.2.0.tar.gz)に変更しました。
screenのインストールコマンドを追加しました。
gatt_serverファイルのパスを修正しました。
2017/04/24
gatt_serverのパスが古いままになっていた部分を修正しました。
2017/04/25
ESP32の解説がESP8266と混じって分かりにくく感じたので、単語の順序を変更しました。
bluetoothのアドレスに関する最初の具体的な記述を「BLEプロファイル」の部分から「動作確認」の部分に変更しました。
2017/04/26
ESP32の開発ボードの購入先がリンク切れになっていたので修正しました。
また、開発ボードの購入先として秋月電子のリンクを追加しました。
2017/06/18
primaryに関する情報が重複していたので、余計な部分を削除しました。
2017/11/26
バイナリファイルのパスを更新しました。
0 件のコメント :
コメントを投稿