Nicla Sense MEをデータ入力に使う①クオータニオンのデータをBLEで出力するペリフェラル
Arduino.ccのNicla Sense MEボード(写真右)にはボッシュの各種センサが搭載されています。
- BHI260AP(32ビットCPU)は6軸(Accelerometer;加速度、Gyroscope;ジャイロ)のIMUを搭載
- BMP390は気圧センサ
- BMM150はmagnetometer;磁気センサ
- BME688は環境センサで、BMP280/BME280の系列にCO2が測れる
ただし、BHI260APにBMP390とBMM150およびBME688がぶら下がっている形にみえます。なので、I2CやSPIバスをアクセスしてセンサを利用できません。
Arduino IDEが対象とするCPUは、BLEモジュールのnRF52832(Cortex-M4)です。型番で検索すると、技適が取れています。
●Arduino IDEの開発環境
Adruinoのボードのように、USBケーブルをPCとつないで、Arduino IDEでスケッチを書く方法が用意されています。その開発ソフトは、次の2種類があります。
- Arduino.ccの用意したGitHub arduino https://github.com/arduino/nicla-sense-me-fw
- Arduino.ccの用意したGitHub arduino-libraries https://github.com/arduino-libraries/Arduino_BHY2
ボードの発売当時、GitHub arduinoは半年ほど古い日付でした。GitHub arduino-librariesは更新頻度が高く、2021年11月16日には1.0.3になっていました。2日遅れで、GitHub arduinoも更新されました。
それまで、GitHub arduinoの扱うセンサIDが古く、gasセンサのデータが読み出せませんでした。
●そのほかの開発環境
Arduino IDEで開発する方法は、Nicla standalone modeと呼ばれています。それ以外に、Control Nicla from an arduino board through eslovとControl Nicla from a PC - web server、Control Nicla from a PC - command line toolがあります。
このボードは、Arduino.ccにはシリーズ化されるような記述があります。半年ほど前に、ボッシュが高校生のコンテストを行ったときのボードによく似ています。
BHI260APは、新製品発表当時、数万円した記憶があって、このボードは、販促用なのかもしれません。
●セットアップ
GitHub arduinoを使います。
ボードマネージャを開きます。
検索欄にNiclaを入れ、インストールします。
ツールー>ボードで、Nicla Sense MEを選択します。シリアルポートも設定します。
Nicla Sense MEボードは、USBケーブルでPCとつなぎます。ほかのボードと同じく、USBハブ経由で認識します。しかし、筆者の2台のPCでは、アップロードに失敗しました。解決方法は、PCのUSB2.0の口に直接つなぎます。
サンプル例から、Lチカを選択します。ほかのボードのようにBlinkは動作しません。
●センサのサンプルを実行
を新規スケッチに張り込み、コンパイル、実行します。
実行したときの様子です。
Accelerometer(加速度)、Gyroscope(ジャイロ)、Temperature(温度)、gas(空気の汚れ度)、rotation(クオータニオン;四次元数)の値を表示しています。
●クオータニオンのデータをBLEで出力
クオータニオンのデータだけを出力するスケッチです。
#include "Arduino.h"
#include "Arduino_BHY2.h"
SensorQuaternion quater(SENSOR_ID_RV);
void setup(){
Serial.begin(115200);
while(!Serial);
BHY2.begin();
quater.begin();
}
void loop(){
static auto printTime = millis();
// Update function should be continuously polled
BHY2.update();
delay(500);
if (millis() - printTime >= 1000) {
printTime = millis();
Serial.println(String("Quaternion : x,y,z,w ") + String(quater.x()) + ", " + String(quater.y()) + ", " + String(quater.z())+ ", "+ String(quater.w()));
}
}
出力例です。
このスケッチにBLE部分を追加します。
#include "Arduino.h"
#include "Arduino_BHY2.h"
#include <ArduinoBLE.h>
SensorQuaternion quater(SENSOR_ID_RV);
// BLE Service
#define BHI260_SERVICE1_UUID "F000AA30-0451-4000-B000-000000000000"
BLEService Sensor_BHI260_Service1(BHI260_SERVICE1_UUID);
// BLE Characteristic
#define BHI260_QuaterX_Characteristic_UUID "F000AA5A-0451-4000-B000-000000000000"
#define BHI260_QuaterY_Characteristic_UUID "F000AA5B-0451-4000-B000-000000000000"
#define BHI260_QuaterZ_Characteristic_UUID "F000AA5C-0451-4000-B000-000000000000"
#define BHI260_QuaterW_Characteristic_UUID "F000AA5D-0451-4000-B000-000000000000"
BLEFloatCharacteristic BHI260_QuaternionX(BHI260_QuaterX_Characteristic_UUID, BLERead | BLENotify);
BLEFloatCharacteristic BHI260_QuaternionY(BHI260_QuaterY_Characteristic_UUID, BLERead | BLENotify);
BLEFloatCharacteristic BHI260_QuaternionZ(BHI260_QuaterZ_Characteristic_UUID, BLERead | BLENotify);
BLEFloatCharacteristic BHI260_QuaternionW(BHI260_QuaterW_Characteristic_UUID, BLERead | BLENotify);
// BLE Descriptor
#define BHI260_Quater_Descriptor_UUID "2901"
BLEDescriptor BHI260_Quater_Descriptor(BHI260_Quater_Descriptor_UUID, "Quaternion x,y,z,w IEEE754 binary32");
#define localNAME "Nicla_BHI260"
#define DeviceNAME "NiclaBLE"
float previousMillis = 0; // last time value was checked, in ms
void setup(){
Serial.begin(115200);
while(!Serial);
BHY2.begin();
quater.begin();
if (!BLE.begin()) {
Serial.println("starting BLE failed!");
while (1);
}
BLE.setLocalName(localNAME);
BLE.setDeviceName(DeviceNAME);
//// set the service
BLE.setAdvertisedService(Sensor_BHI260_Service1);
// add characteristic
Sensor_BHI260_Service1.addCharacteristic(BHI260_QuaternionX);
Sensor_BHI260_Service1.addCharacteristic(BHI260_QuaternionY);
Sensor_BHI260_Service1.addCharacteristic(BHI260_QuaternionZ);
Sensor_BHI260_Service1.addCharacteristic(BHI260_QuaternionW);
// add descriptor
BHI260_QuaternionX.addDescriptor(BHI260_Quater_Descriptor);
// add service
BLE.addService(Sensor_BHI260_Service1);
// set initial value for this characteristic ; PASS
// start advertising
BLE.advertise();
Serial.println("\nBluetooth device active, waiting for connections...");
}
void loop(){
// wait for a BLE central
BLEDevice central = BLE.central();
// if a central is connected to the peripheral:
if (central) {
delay(100);
Serial.print("\nConnected to central: ");
// print the central's BT address:
Serial.println(central.address());
// check data every 200ms
// while the central is connected:
while (central.connected()) {
long currentMillis = millis();
// if 200ms have passed, check value:
if (currentMillis - previousMillis >= 200) {
previousMillis = currentMillis;
updateValue();
//delay(1000);
}
}
// when the central disconnects
Serial.print("Disconnected from central: ");
Serial.println(central.address());
goto brout;
}
brout: ;
}
void updateValue() {
BHY2.update();
delay(500);
Serial.println(String("Quaternion : x,y,z,w ") + String(quater.x(),3) + ", " + String(quater.y(),3) + ", " + String(quater.z(),3)+ ", "+ String(quater.w(),3));
BHI260_QuaternionX.writeValue(quater.x());
BHI260_QuaternionY.writeValue(quater.y());
BHI260_QuaternionZ.writeValue(quater.z());
BHI260_QuaternionW.writeValue(quater.w());
}
RLS10で実行しているBLEセントラルの画面です。実数はIEEE 754 binary32のフォーマットで送られてきます。