STM32 Logger Beacon
はじめに
STM32リーフに搭載されたFlashメモリを使って、温湿度と測定時間を記録することが可能なBLE Beaconのサンプルデザインです。
STM32リーフとBLEリーフを使った、センサデータのログ機能付きの実用的なIoTシステムのサンプルデザインです。
このサンプルには下記の機能が実装されています。
- 温度、湿度、照度の観測
- 測定データをBLEのBeacon機能で送信
- オンチップFlashに測定データを保存
- リアルタイムクロックを使った測定時刻の保存
- ブラウザアプリでデバイスの設定変更
- ブラウザアプリで測定データの吸い出しとグラフ化
- 加速度センサを使った振動検知機能によるBLE送信モードの変更
- 低電力動作モードで半年以上の連続駆動
サンプルのソースコード
使用するスケッチやツールのソースコードは下記のリポジトリで閲覧可能です。
対応環境
- Windows 10 Version 1703以降
- Beacon機能は利用不可
- Mac OS X Yosemite以降
- Android 6.0 Marshmallow以降
- Linux Kernel 3.19+ 以降 対応状況詳細はWebbluetooth Implementation Statusを御覧ください。
用意するもの
- Leafony
- Google Chrome
使用するリーフ
Type | Name | Q’ty |
---|---|---|
AI01 | 4-Sensors | 1 |
AP03 | STM32 MCU | 1 |
AZ01 | USB | 1 |
AC02 | BLE Sugar | 1 |
AV01 | CR2032 | 1 |
- | CR2032 coin cell battery | 1 |
- | M2*18mm screw | 2 |
動作方法
-
STM32リーフにサンプルスケッチ
STM32_Logger_Beacon.ino
を書き込んでください。 -
Google ChromeでSTM32 Sensors Logger Webアプリケーションを開いてださい。
-
Start Scanning
ボタンを押すと、Bluetooth利用許可を求めるポップアップウィンドウ表示されます。許可
を押すとBeaconの電波の受信を開始します。
Leafonyから発されるBeaconの電波を受信すると、画面の温度/電池電圧/受信時刻表示が更新されます。 -
Connect
ボタンを押すとLeafonyに接続され、数秒ほど待つとFlashメモリに保存されていた過去の測定データを受信し、画面上のグラフが更新されます。 -
受信完了後は
Disconnect
ボタンを押しLeafonyと切断すると、Leafonyは再度Beaconモードに移行し、センサ情報の記録を再開します。
動作解説
回路全体のブロック図
本サンプルコードで利用する回路は下図のとおりです。
主にBLE、センサ、STM32リーフで構成され、特にSTM32リーフでは内部のRTC(リアルタイムクロック)とFlashを利用しています。
RTCは、BLEを経由してPCやスマートフォンから時刻を設定して使います。
Flashはプログラムメモリの保存以外に、末尾2kBをユーザがデータを保存できる領域として使うことができます。本サンプルでは、この領域にセンサデータと測定時刻を保存し、本体の電源が切れた後もデータを保持できる仕組みとなっています。
センサリーフからは温度、湿度、照度センサがSTM32によって読み出され、BLEでデータが送信されます。加速度センサは振動によって割り込み信号を発生し、STM32をスリープから復帰させる役割があります。
動作の流れ
このサンプルコードでは主に以下の2つの動作モードが存在します。
- Beaconモード
- Connectionモード
Leafonyに電源を入れると、まず初めに本体の初期化を行なった後にBeaconモードに入ります。
Beaconモードでは、通常は本体が長時間のスリープ状態に入り、一定時間が経過すると本体がスリープから復帰します。(このスリープ時間はユーザが任意に設定できます。)
本体がスリープから復帰すると、まずSTM32が起動し、センサを起動させ、温度、湿度、照度を測定します。
このとき、STM32に搭載されたリアルタイムクロックに時刻が設定されている場合、測定されたデータはSTM32に搭載されたFlashに保存されます。
その後、BLEリーフを起動し、Advertisingパケットにセンサデータを設定し、BLEリーフが一定期間Advertisingを開始します。
このAdvertisingパケットをウェブアプリで受信することで、温度、湿度、照度のデータをPCやスマートフォンで見ることができます。
一定期間のAdvertising後は即座に本体がスリープし、消費電力を最小に抑えます。
Beaconモードでの動作時間が長いほど、電池消費を抑えることが可能です。
Connectionモードでは、主にPCやスマートフォンでと双方向で通信して、スリープ時間やAdvertising時間を設定したり、Flashに保存されたデータの吸い出しを行い、ウェブアプリでグラフ化するための通信を行います。
このモードでは通信中、またはPCやスマートフォンと接続を確立するためのAdvertising期間、常に本体がアクティブ状態にあり、電池消費が大きくなります。
Connectionモードは、本体の時刻を設定するなどの初回起動時や、ある程度ログデータが溜まった後にデータを吸い出すといったような、利用シーンが限られてくるため、特定の条件でのみこのモードに入るよう設定されています。
このサンプルではConnectionモードに入るためには、Leafony本体を左右に強く振ることでConnectionモードに入ることができます。
これは、4-Sensorsリーフに搭載された加速度センサが、常に振動を観測し、振動を検知すると即座にSTM32リーフに割り込み信号を送信することで実現されています。
動作モードの切り替え
BeaconモードとConnectionモードの切り替えには加速度センサによる割り込みを使います。
ウェブアプリでBluetoothデバイスを検出するためには、LeafonyがConnectionモードに切り替わり、最低でも数秒から数十秒程度の長い間BLEがAdvertisingする必要があります。
これを毎スリープからの復帰後に行なっていると電池消費が非常に大きくなってしまうため、BLEで接続したい時だけConnectionモードに入り長時間Advertisingさせたくなります。
今回はこれを加速度センサを使った振動検出割り込みで実現しました。
4-Sensorsに搭載された加速度センサは、振動(指で本体をタップする動作)を検出すると、STM32のINT1ピン
に割り込み信号を出します。
下記の記述で加速度センサのタップ検出を有効化し、その割り込みによってSTM32がスリープから復帰する仕組みを実現しています。
か速度センサの割り込みによって起動した場合のみConnectモードとして起動させることで、必要な時だけBLEで接続可能な仕組みを実現しました。
accel.setClick(DOUBLETAP, CLICKTHRESHHOLD); // enable click interrupt
// enable interrupt from accelerometer click event
LowPower.attachInterruptWakeup(INT_1, onClicked, RISING, DEEP_SLEEP_MODE);
不揮発メモリのアドレスマップ
STM32リーフには内部に不揮発性メモリ(Flashメモリ)が搭載されています。
本サンプルでは、このFlashメモリを、ユーザ設定の保存と、測定データ保存用のリングバッファとして扱います。
下図のように、メモリの先頭からいくつかの番地には、スリープ時間や起動時間などのユーザ設定を保存する領域があります。
それらを除いた部分を、時刻とセンサのデータを保持するリングバッファとして扱います。
また、Flashに書き込まれているデータが、本サンプルスケッチによって書き込まれたものなのかを確かめるため、先頭2バイトに0xAA
という値を保存しています。
本サンプルではこの0xAA
が書き込まれていればいれば、保存されている設定を読み込み、書き込まれていなければ新規に初期値をFlashに保存するという動作をします。
Beacon送信データ
Beaconモードで動作している場合、BLEはセンサのデータを含むAdvertisingパケットを送信しています。
Advertisingパケットの構造は次の図のように、AD Structure
というデータの塊が連なった形式となっています。
AD Structureはさらに細かく見ると、Length
:データの長さ、AD Type
:データの種類・意味、AD Data
:送信したいデータで構成されています。
実際に本サンプルでは下記のコードのように、AD Structure 1
にAdvertisingのモード設定、AD Structure 2
にデバイス名、AD Structure 3
にセンサのデータを保存して送信しています。
Beaconで送信するデータを変更したい場合はAD Structure 3
を任意に変更してください。
//-------------------------
// Advertising Packet
//-------------------------
// AD Structure 1 (Flags)
adv_data[index++] = 0x02; // field length
adv_data[index++] = BGLIB_GAP_AD_TYPE_FLAGS; // AD Type (Flags)
adv_data[index++] = (1 << 1) | (1 << 2); // LE General Discover Mode | BR/EDR Not Supported
// AD Structure 2 (Complete Local Name)
adv_data[index++] = strDeviceName.length() + 1; // field length
adv_data[index++] = BGLIB_GAP_AD_TYPE_LOCALNAME_COMPLETE; // AD Type (Complete Local Name)
for (uint8_t i = 0; i < strDeviceName.length(); i++) {
adv_data[index++] = strDeviceName.charAt(i); // Local Name
}
// AD Structure 3 (Manufacturer Specific Data)
adv_data[index++] = 9; // field lengh
adv_data[index++] = 0xff; // AD Type (Manufacturer Specific Data)
adv_data[index++] = (illum >> 8) & 0xFF; // Illuminance (Upper)
adv_data[index++] = illum & 0xFF; // Illuminance (Lower)
adv_data[index++] = (temp >> 8) & 0xFF; // Temperature (Upper)
adv_data[index++] = temp & 0xFF; // Temperature (Lower)
adv_data[index++] = (humid >> 8) & 0xFF; // Humidity (Upper)
adv_data[index++] = humid & 0xFF; // Humidity (Lower)
adv_data[index++] = (battVolt >> 8) & 0xFF; // Battery Voltage (Upper)
adv_data[index++] = battVolt & 0xFF; // Battery Boltage (Lower)
// register advertising packet
stLen = index;
ble112.ble_cmd_le_gap_set_adv_data(SCAN_RSP_ADVERTISING_PACKETS, stLen, adv_data);
while (ble112.checkActivity(1000));
センサの変更方法
本サンプルでは4-Sensorsリーフに搭載された、温度・湿度・照度センサ、バッテリーリーフに搭載されたADCを読み出す仕組みとなっています。
これらのセンサは、setup()
関数内のsetupSensors()
関数で初期化し、loop()
関数内のwakeupSensors()
でスリープから復帰、getSensors()
でデータを取得、sleepSensors()
でスリープを行なっています。
任意のセンサを追加したい場合はこれらの関数内に必要な処理を記述してください。
BLEコマンドの変更方法
BLEで接続したPCやスマートフォンからコマンドを送信してLeafony側の設定を変更したり、データの転送を開始したりすることができます。
下記のソースコードの部分でそのコマンドと処理を記述しています。
== 任意のコマンドを追加する場合は上記部分を修正してください。