Nano 33 BLE Senseでマルチセンサ・ペリフェラルを作る (7) 9軸慣性センサ IMU LSM9DS1
LSM9DS1は、3軸の加速度センサ、3軸のジャイロ・センサ、3軸の磁気(コンパス)センサを搭載しています。総合的にセンサの情報を使って、ロボットやゲーム機器の動きを検知するために使われるようです。
●LSM9DS1のおもなスペック
- 動作電圧 1.9~3.6V
- 電流 エコ・パワー・モード;1.9mA、ジャイロ・センサ通常動作時4.0mA
- インターフェース I2C、SPI
- 加速度:±2/±4/±6/±8/±16g
- ジャイロ・センサ:±245/±500/±2000dps
- 磁気センサ:±4/±8/±12/±16gauss
●ライブラリのインストール
ライブラリ管理でLSM9DS1を入れて検索して出てきたArduino_LSM9DS1をインストールします。
サンプル・スケッチは3種類用意されています。ひとつずつ動かして動作を確認します。
●サンプル・スケッチSimpleAccelerometer
加速度センサのスケッチを、コンパイル、書き込み、実行しました。
動作開始時にAccelerometer sample rate = 119.00 Hzを表示し、以降の表示の値は、左から、X、Y、Zです。次の図は、マイコン・ボードを手でもって揺らしているところです。加速度を測定することで、物体の傾きや振動などの情報が得られます。
●サンプル・スケッチSimpleGyroscope
ジャイロ・センサのスケッチを、コンパイル、書き込み、実行しました。
表示の値は、左から、X、Y、Zです。マイコン・ボードを手でもっている状態です。このセンサは、物体が回転している速度を表す「角速度」が得られます。手持ちによるブレを補正するときなどに有用といわれています。
●サンプル・スケッチSimpleMagnetometer
磁気(コンパス)センサのスケッチを、コンパイル、書き込み、実行しました。
動作開始時の出力です。
ボードを水平に回転させているときの出力です。
四つのファイルをそれぞれ更新します。
●センサの値を読み取る関数 nano33senseに追加
#include <Arduino_HTS221.h>
#include <Arduino_LPS22HB.h>
#include <Arduino_APDS9960.h>
#include <Arduino_LSM9DS1.h> float HTS221_temperature; float HTS221_humidity; float LPS22HB_pressure; uint8_t APDS9960_proximity = 0; int APDS9960_gesture = 0; int r = 0, g = 0, b = 0; int APDS9960_color_Red = 0, APDS9960_color_Green = 0, APDS9960_color_Blue = 0; float AccelerationX = 0, AccelerationY = 0, AccelerationZ = 0; float GyroscopeX = 0, GyroscopeY = 0, GyroscopeZ = 0; float MagneticX = 0, MagneticY = 0, MagneticZ = 0; void readHTS221() { HTS221_temperature = HTS.readTemperature(); HTS221_humidity = HTS.readHumidity(); } void readLPS22HB() { LPS22HB_pressure = BARO.readPressure() * 10; // hpa } void readAPDS9960() { if (APDS.proximityAvailable()) { APDS9960_proximity = APDS.readProximity(); // -0 => close, -255 => far, - -1 => error } delay(100); if (APDS.gestureAvailable()) { APDS9960_gesture = APDS.readGesture(); // GESTURE_UP, GESTURE_DOWN, GESTURE_LEFT, GESTURE_RIGHT } delay(100); if (APDS.colorAvailable()) { APDS.readColor(r, g, b); } APDS9960_color_Red = r; APDS9960_color_Green = g; APDS9960_color_Blue = b; delay(100); } void readLSM9DS1() { if (IMU.accelerationAvailable()) { IMU.readAcceleration(AccelerationX, AccelerationY, AccelerationZ); } if (IMU.gyroscopeAvailable()) { IMU.readGyroscope(GyroscopeX, GyroscopeY, GyroscopeZ); } if (IMU.magneticFieldAvailable()) { IMU.readMagneticField(MagneticX, MagneticY, MagneticZ); } }
●nano33senseServiceに追加
サービス名とサービスのUUIDを記述を追加しました。
#include <ArduinoBLE.h> #define HTS221_SERVICE_UUID "F000AA20-0451-4000-B000-000000000000" #define LPS22HB_SERVICE_UUID "F000AA40-0451-4000-B000-000000000000" #define APDS9960_SERVICE_UUID "F000AA00-0451-4000-B000-000000000000" #define LSM9DS1_SERVICE_UUID "F000AA30-0451-4000-B000-000000000000" // BLE Service BLEService Sensor_HTS221_Service(HTS221_SERVICE_UUID); BLEService Sensor_LPS22HB_Service(LPS22HB_SERVICE_UUID); BLEService Sensor_APDS9960_Service(APDS9960_SERVICE_UUID); BLEService Sensor_LSM9DS1_Service(LSM9DS1_SERVICE_UUID);
●nano33senseCharacteristicに追加
キャラ名とキャラのUUIDを記述を追加しました。
BLEStringCharacteristic の三つ目の引数は文字数です。最大いくつかは不明ですが、40を試したときはもんだなく送れました。Arduino.ccにあるArduinoBLEには、このコンストラクタの説明はありません。GitHubのソースを見ます。
#include <ArduinoBLE.h>
#define HTS221_Temp_Characteristic_UUID "F000AA21-0451-4000-B000-000000000000"
#define HTS221_Humi_Characteristic_UUID "F000AA22-0451-4000-B000-000000000000"
#define LPS22HB_Press_Characteristic_UUID "F000AA41-0451-4000-B000-000000000000"
#define APDS9960_Proximity_Characteristic_UUID "F000AA01-0451-4000-B000-000000000000"
#define APDS9960_Gesture_Characteristic_UUID "F000AA02-0451-4000-B000-000000000000"
#define APDS9960_Color_Red_Characteristic_UUID "F000AA03-0451-4000-B000-000000000000"
#define APDS9960_Color_Blue_Characteristic_UUID "F000AA04-0451-4000-B000-000000000000"
#define APDS9960_Color_Green_Characteristic_UUID "F000AA05-0451-4000-B000-000000000000"
#define LSM9DS1_Acceleration_Characteristic_UUID "F000AA31-0451-4000-B000-000000000000"
#define LSM9DS1_Gyroscope_Characteristic_UUID "F000AA32-0451-4000-B000-000000000000"
#define LSM9DS1_MagneticField_Characteristic_UUID "F000AA33-0451-4000-B000-000000000000"
// BLE Characteristic
BLEUnsignedCharCharacteristic HTS221_Temp(HTS221_Temp_Characteristic_UUID,
BLERead);// | BLENotify);
BLEUnsignedCharCharacteristic HTS221_Humi(HTS221_Humi_Characteristic_UUID,
BLERead);// | BLENotify);
BLEUnsignedIntCharacteristic LPS22HB_Press(LPS22HB_Press_Characteristic_UUID,
BLERead);// | BLENotify);
BLEUnsignedCharCharacteristic APDS9960_Proximity(APDS9960_Proximity_Characteristic_UUID,
BLERead);// | BLENotify);
BLEUnsignedCharCharacteristic APDS9960_Gesture(APDS9960_Gesture_Characteristic_UUID,
BLERead);// | BLENotify);
BLEUnsignedCharCharacteristic APDS9960_Color_Red(APDS9960_Color_Red_Characteristic_UUID,
BLERead);// | BLENotify);
BLEUnsignedCharCharacteristic APDS9960_Color_Blue(APDS9960_Color_Blue_Characteristic_UUID,
BLERead);// | BLENotify);
BLEUnsignedCharCharacteristic APDS9960_Color_Green(APDS9960_Color_Green_Characteristic_UUID,
BLERead);// | BLENotify);
BLEStringCharacteristic LSM9DS1_Acceleration(LSM9DS1_Acceleration_Characteristic_UUID, BLERead, 24);
BLEStringCharacteristic LSM9DS1_Gyroscope(LSM9DS1_Gyroscope_Characteristic_UUID, BLERead, 24);
BLEStringCharacteristic LSM9DS1_MagneticField(LSM9DS1_MagneticField_Characteristic_UUID, BLERead, 24);
●メインnano33sense_Peripheral
localNAMEをHTS221_LPS22HB_APDS9960_LSM9DS1に変更しました。
#include <ArduinoBLE.h>
#define localNAME "HTS221_LPS22HB_APDS9960_LSM9DS1"
#define DeviceNAME "nano33BLE"
float oldValue = 0; // last value
long previousMillis = 0; // last time value was checked, in ms
void setup() {
Serial.begin(9600); // initialize serial communication
while (!Serial);
// begin initialization
if (!BLE.begin()) {
Serial.println("starting BLE failed!");
while (1);
}
if (!HTS.begin()) { // HTS221
Serial.println("Failed to initialize humidity temperature sensor!");
while (1);
}
if (!BARO.begin()) { // LPS22HB
Serial.println("Failed to initialize pressure sensor!");
while (1);
}
readLPS22HB(); // karayomi
if (!APDS.begin()) { // APDS9960
Serial.println("Error initializing APDS9960 sensor.");
while (true); // Stop forever
}
readAPDS9960(); // karayomi
if (!IMU.begin()) { // LSM9DS1
Serial.println("Failed to initialize IMU!");
while (1);
}
BLE.setLocalName(localNAME);
BLE.setDeviceName(DeviceNAME);
// add the service UUID
BLE.setAdvertisedService(Sensor_HTS221_Service);
BLE.setAdvertisedService(Sensor_LPS22HB_Service);
BLE.setAdvertisedService(Sensor_APDS9960_Service);
BLE.setAdvertisedService(Sensor_LSM9DS1_Service);
// add characteristic
Sensor_HTS221_Service.addCharacteristic(HTS221_Temp);
Sensor_HTS221_Service.addCharacteristic(HTS221_Humi);
Sensor_LPS22HB_Service.addCharacteristic(LPS22HB_Press);
Sensor_APDS9960_Service.addCharacteristic(APDS9960_Proximity);
Sensor_APDS9960_Service.addCharacteristic(APDS9960_Gesture);
Sensor_APDS9960_Service.addCharacteristic(APDS9960_Color_Red);
Sensor_APDS9960_Service.addCharacteristic(APDS9960_Color_Blue);
Sensor_APDS9960_Service.addCharacteristic(APDS9960_Color_Green);
Sensor_LSM9DS1_Service.addCharacteristic(LSM9DS1_Acceleration);
Sensor_LSM9DS1_Service.addCharacteristic(LSM9DS1_Gyroscope);
Sensor_LSM9DS1_Service.addCharacteristic(LSM9DS1_MagneticField);
// Add service
BLE.addService(Sensor_HTS221_Service);
BLE.addService(Sensor_LPS22HB_Service);
BLE.addService(Sensor_APDS9960_Service);
BLE.addService(Sensor_LSM9DS1_Service);
// set initial value for this characteristic
HTS221_Temp.writeValue(oldValue);
HTS221_Humi.writeValue(oldValue);
LPS22HB_Press.writeValue(oldValue);
APDS9960_Proximity.writeValue(oldValue);
APDS9960_Gesture.writeValue(oldValue);
APDS9960_Color_Red.writeValue(oldValue);
APDS9960_Color_Blue.writeValue(oldValue);
APDS9960_Color_Green.writeValue(oldValue);
LSM9DS1_Acceleration.writeValue(String(oldValue));
LSM9DS1_Gyroscope.writeValue(String(oldValue));
LSM9DS1_MagneticField.writeValue(String(oldValue));
// start advertising
BLE.advertise();
Serial.println("Bluetooth 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("Connected to central: ");
// print the central's BT address:
Serial.println(central.address());
// check the battery level 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());
}
}
void updateValue() {
readHTS221();
int valueof_HTS221_temperature = int(HTS221_temperature);
int valueof_HTS221_humidity = int(HTS221_humidity);
readLPS22HB();
int valueof_LPS22HB_pressure = int(LPS22HB_pressure);
readAPDS9960();
uint8_t valueof_APDS9960_proximity = int(APDS9960_proximity);
uint8_t valueof_APDS9960_gesture = int(APDS9960_gesture);
uint8_t valueof_APDS9960_color_Red = int(APDS9960_color_Red);
uint8_t valueof_APDS9960_color_Green = int(APDS9960_color_Green);
uint8_t valueof_APDS9960_color_Blue = int(APDS9960_color_Blue);
readLSM9DS1();
String valueof_LSM9DS1_Acceleration = String(AccelerationX) + "," + String(AccelerationY) + "," + String(AccelerationZ);
String valueof_LSM9DS1_Gyroscope = String(GyroscopeX) + "," + String(GyroscopeY) + "," + String(GyroscopeZ);
String valueof_LSM9DS1_MagneticField = String(MagneticX) + "," + String(MagneticY) + "," + String(MagneticZ);
// if value has changed
if ((valueof_HTS221_temperature+valueof_HTS221_humidity) != oldValue) {
Serial.print("- - = - -\nHTS221_temperature % is now: ");
Serial.println(valueof_HTS221_temperature);
Serial.print("HTS221_humidity % is now: ");
Serial.println(valueof_HTS221_humidity);
Serial.print("---\nLPS22HB_Pressure % is now: ");
Serial.println(valueof_LPS22HB_pressure);
Serial.print("---\nAPDS9960_proximity % is now: ");
Serial.println(valueof_APDS9960_proximity);
Serial.print("APDS9960_gesture % is now: ");
Serial.println(valueof_APDS9960_gesture);
Serial.print("APDS9960_color_Red % is now: ");
Serial.println(valueof_APDS9960_color_Red);
Serial.print("APDS9960_color_Green % is now: ");
Serial.println(valueof_APDS9960_color_Green);
Serial.print("APDS9960_color_Blue % is now: ");
Serial.println(valueof_APDS9960_color_Blue);
Serial.print("---\nLSM9DS1_Acceleration % is now: ");
Serial.println(String(AccelerationX) + "," + String(AccelerationY) + "," + String(AccelerationZ));
Serial.print("LSM9DS1_Gyroscope % is now: ");
Serial.println(String(GyroscopeX) + "," + String(GyroscopeY) + "," + String(GyroscopeZ));
Serial.print("LSM9DS1_MagneticField % is now: ");
Serial.println(String(MagneticX) + "," + String(MagneticY) + "," + String(MagneticZ));
// update characteristic
HTS221_Temp.writeValue(valueof_HTS221_temperature);
HTS221_Humi.writeValue(valueof_HTS221_humidity);
LPS22HB_Press.writeValue(valueof_LPS22HB_pressure);
APDS9960_Proximity.writeValue(valueof_APDS9960_proximity);
APDS9960_Gesture.writeValue(valueof_APDS9960_gesture);
APDS9960_Color_Red.writeValue(valueof_APDS9960_color_Red);
APDS9960_Color_Blue.writeValue(valueof_APDS9960_color_Green);
APDS9960_Color_Green.writeValue(valueof_APDS9960_color_Blue);
LSM9DS1_Acceleration.writeValue(valueof_LSM9DS1_Acceleration);
LSM9DS1_Gyroscope.writeValue(valueof_LSM9DS1_Gyroscope);
LSM9DS1_MagneticField.writeValue(valueof_LSM9DS1_MagneticField);
oldValue = valueof_HTS221_temperature+valueof_HTS221_humidity; // save the level for next comparison
}
}
実行中の様子です。
正しく送れていることが確認できました。
カンマで区切ったデータを取り出す事例は、
初めてのBLE (19) CircuitPythonでペリフェラル③ BME280
のセントラルの項目でArduinoBLEを使ってスケッチを掲載しています。
一連のArduinoBLEを使ってBLEのペリフェラルの機能を実装してきました。ベースとなったスケッチでは、200msごとにセンサのデータが新しくなったかを監視していました。これは、Notifyの機能のためだと思われますが、うまく働いていないように見えます。
キャラは、addDescriptor()でDescriptorを追加できるようになっていますが、記述の方法が間違っているのか、セントラル側へ情報が送られません。