ESP32はWi-FiとBluetooth Low Energy (BLE)通信機能を持っています。この機能を使い、BLEセンサー端末からデーターを受けて、クラウドに送信するBLEゲートウェイを作ります。

BLE環境センサー端末は「M5StackでBLE環境センサー端末を作る」を、Raspberry Piを使ったBLEゲートウェイは「BLE環境センサー・ゲートウェイ(Raspberry Pi編)」をご覧ください。

全体の構成

センサー端末とBLEゲートウェイの両方をM5Stackで作ります。BLEゲートウェイはセンサー端末からBLEでデーターを受け、Wi-Fi経由でクラウド(Ambient)に送信します。

プログラムサイズの問題

ESP32はArduino、MicroPython、ESP-IDFでプログラミングできます。MicroPythonはBluetooth Low Energyがサポートされていないので、Arduinoでプログラミングします。ESP32 ArduinoのBLEライブラリーは非常にサイズが大きいことで知られています。実際にビルドしてサイズを調べてみます。

まず、ほぼ何もしないプログラムをビルドすると、次のようなメッセージが表示されます。

 #include <M5Stack.h>

 void setup() {
 }

 void loop() {
 }
 最大1310720バイトのフラッシュメモリのうち、スケッチが264500バイト(20%)を使っています。
 最大327680バイトのRAMのうち、グローバル変数が15184バイト(4%)を使っていて、ローカル変数で312496バイト使うことができます。

Arduino Coreは1.0.0-rc4を使っています。258kバイトがArduino Coreのサイズのようです。これにBLEDevice::init()だけを追加してビルドしてみます。BLEモジュールはArduino Coreに含まれているので、特にインストール作業は必要ありません。

 #include <M5Stack.h>
 #include "BLEDevice.h"

 void setup() {
     BLEDevice::init("");
 }

 void loop() {
 }
 最大1310720バイトのフラッシュメモリのうち、スケッチが1152833バイト(87%)を使っています。
 最大327680バイトのRAMのうち、グローバル変数が59068バイト(18%)を使っていて、ローカル変数で268612バイト使うことができます。

プログラムサイズが約1Mバイトになってしまいました。増えた分の約867kバイトがBLEモジュールのサイズのようです。さらにWiFi.begin()を足してみます。

 #include <M5Stack.h>
 #include "BLEDevice.h"
 #include <WiFi.h>

 void setup() {
     BLEDevice::init("");
     WiFi.begin("","");
 }

 void loop() {
 }
 最大1310720バイトのフラッシュメモリのうち、スケッチが1437438バイト(109%)を使っています。
 最大327680バイトのRAMのうち、グローバル変数が79416バイト(24%)を使っていて、ローカル変数で248264バイト使うことができます。
 スケッチが大きすぎます。http://www.arduino.cc/en/Guide/Troubleshooting#size には、小さくするコツが書いてあります。
 ボードM5Stack-Core-ESP32に対するコンパイル時にエラーが発生しました。

プログラムが100%を超えてビルドできなくなりました。

サイズ問題の対処

Arduinoはネットワーク経由でプログラムを更新するOTA(Over the Air)機能のために、デフォルトではメモリに同サイズの二つのプログラム領域を確保します。この2領域をまとめて使うことで、OTA機能をあきらめて、プログラム領域を拡大できます。設定ファイルを変更するので、変更を元に戻せばOTA機能は使えるようになります。

デフォルトのメモリマップは次のファイルに書かれています。

  • MacOSでは
    /Users/<アカウント名>/Library/Arduino15/packages/esp32/hardware/esp32/1.0.0-rc4/tools/partitions/default.csv
  • Windowsでは
    C:\Users\<アカウント名>\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.0-rc4\tools\partitions\default.csv
 # Name,  Type, SubType, Offset,   Size, Flags
 nvs,     data, nvs,     0x9000,   0x5000,
 otadata, data, ota,     0xe000,   0x2000,
 app0,    app,  ota_0,   0x10000,  0x140000,
 app1,    app,  ota_1,   0x150000, 0x140000,
 eeprom,  data, 0x99,    0x290000, 0x1000,
 spiffs,  data, spiffs,  0x291000, 0x16F000,

app0とapp1が同サイズの二つのプログラム領域です。これを次のように編集します。

 # Name,  Type, SubType, Offset,   Size, Flags
 nvs,     data, nvs,     0x9000,   0x5000,
 otadata, data, ota,     0xe000,   0x2000,
 app0,    app,  ota_0,   0x10000,  0x340000,
 eeprom,  data, 0x99,    0x350000, 0x1000,
 spiffs,  data, spiffs,  0x351000, 0xAF000,

さらにボードの定義ファイルboards.txt中の

 esp32.upload.maximum_size=1310720
 m5stack-core-esp32.upload.maximum_size=1310720

の2行を次のように変更します。

 esp32.upload.maximum_size=3407872
 m5stack-core-esp32.upload.maximum_size=3407872

boards.txtは次の場所にあります。

  • MacOSでは
    /Users/<アカウント名>/Library/Arduino15/packages/esp32/hardware/esp32/1.0.0-rc4/boards.txt
  • Windowsでは
    C:\Users\<アカウント名>\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.0-rc4\boards.txt

これで先程のBLEDevice::init()とWiFi.begin()を実行するプログラムをビルドします。

 最大3407872バイトのフラッシュメモリのうち、スケッチが1437438バイト(42%)を使っています。
 最大327680バイトのRAMのうち、グローバル変数が79416バイト(24%)を使っていて、ローカル変数で248264バイト使うことができます。

プログラム領域が1.25Mバイトから3.25Mバイトに拡張され、ビルドできるようになりました。

BLEゲートウェイ・プログラム

比較的プログラムが単純なブロードキャストモードのBLEゲートウェイを作ります。

ブロードキャストモードのBLEセンサー端末は、センサーデーターを次のような形式でアドバタイジングデーターに載せて発信します。

BLEゲートウェイはBLEをスキャンしてアドバタイジングパケットを受信し、AD TypeがManufacturer dataで、次のカンパニーIDが0xffffのデーターを探します。見つけたらその中から温度、湿度、気圧データーを取り出し、Ambientに送信します。

アドバタイジングデーターの中には送信するごとに1ずつ増加するシーケンス番号が入っており、同じデーターを重複して送信しないようにしています。

setup()関数は次のようになります。BLE、WiFi、Ambientの初期化をおこなっています。

loop()関数では、BLEをスキャンして、スキャンデータから対象の端末を探し、見つかったら、スキャンデーターからセンサーデーターを取り出し、Ambientに送ります。10行目のgetManufacturerData()関数でマニュファクチャラーデーターを取得します。その先頭のカンパニーIDが0xffffで、シーケンス番号が更新されていたら、マニュファクチャラーデーターから温度、湿度、気圧データーを取り出し、Ambientに送信します。

プログラム全体はGithubに置きました。

AmbientDataInc/EnvSensorBleGw

BLEゲートウェイは常にスキャンをおこない、対象のデバイスからのデーターがあれば、それを受けてデーターをクラウドに送信します。BLEセンサー端末が例えば5分に1回温度、湿度、気圧などを測定し、10〜20秒程度BLEでデーターをブロードキャストすると、BLEゲートウェイがそれを受信してクラウドに送ります。