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を追加できるようになっていますが、記述の方法が間違っているのか、セントラル側へ情報が送られません。

前へ

Nano 33 BLE Senseでマルチセンサ・ペリフェラルを作る (6) マイク  MP34DT05