Nicla Sense MEプラスArduino IDEでBLEペリフェラル

 　Arduino.ccのNicla Sense MEボード（写真右）にはボッシュの各種センサが搭載されています。

<img width="500" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/2aa7fc88-3a55-47c0-066e-220ba3b9b082.png">

- BHI260AP（32ビットCPU）は6軸（Accelerometer；加速度、Gyroscope；ジャイロ）のIMUを搭載
- BMP390は気圧センサ
- BMM150はmagnetometer；磁気センサ
- BME688は環境センサで、BMP280/BME280の系列にCO2が測れる

ただし、BHI260APにBMP390とBMM150およびBME688がぶら下がっている形にみえます。
　Arduino IDEが対象とするCPUは、BLEモジュールのnRF52832（Cortex-M4）です。

###BHI260APのセンサにアクセスする

　BMP390とBMM150およびBME688にアクセスする方法が、現時点で不明です。BHI260APへは、GitHubに記述がありました。
　　　https://github.com/arduino/nicla-sense-me-fw/tree/0.4
このArduino_BHY2の部分に、Ardui IDEで直接センサの値を読み取るサンプルがあります。
　上記のページから、zipファイルをダウンロードします。

![nic100.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/66351b69-d337-1f01-8017-17943d8a8fea.png)
　zipファイルをダブルクリックします。
　Arduino_BHY2フォルダを、C:\Users\ユーザ名\Documents\Arduino\librariesにコピー（解凍）します。

###Arduino IDEでNicla Sense MEを使う
　Arduino IDEは1.8.16を利用します。
　次のページにしたがって、Nicla Sense MEボードを利用できるようにします。
　　https://docs.arduino.cc/software/ide-v1/tutorials/getting-started/cores/arduino-mbed_nicla
　大まかな利用事例は次のページに書かれています。
　　https://docs.arduino.cc/tutorials/nicla-sense-me/cheat-sheet#temperature

　Nicla Sense MEボードは、USBケーブルでPCとつなぎます。ほかのボードと同じく、ハブ経由で認識します。しかし、筆者の2台のPCでは、**アップロードに失敗**しました。解決方法は、PCのUSB2.0の口に直接つなぎます。
###動作確認
　スケッチ例に入っているBlink_Niclaを読み出し、コンパイル、書き込みをし、LEDの点滅を確認します。3色LEDなので、ほかのボードのようなLチカ・プログラムでは点滅しません。


```C
#include "Nicla_System.h"

void setup() {
  nicla::begin();
  nicla::leds.begin();
}

void loop() {
  nicla::leds.setColor(green);
  delay(1000);
  nicla::leds.setColor(off);
  delay(1000);
}
```

###BHI260APのセンサ値の読み出し

　　https://github.com/arduino/nicla-sense-me-fw/tree/0.4/Arduino_BHY2/examples/Standalone
に入っているStandalone.inoを読み込んで、コンパイルします。
　実行したときの様子です。
　Accelerometer（加速度）、Gyroscope（ジャイロ）、Temperature（温度）の値を表示しています。
![2021-10-12 (10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/78342f39-5dc1-6b0f-14f5-696dac658fe8.png)
　少し元のスケッチを修正しています。

```C
/* 
 * This sketch shows how nicla can be used in standalone mode.
 * Without the need for an host, nicla can run sketches that 
 * are able to configure the bhi sensors and are able to read all 
 * the bhi sensors data.
*/

#include "Arduino.h"
#include "Arduino_BHY2.h"

SensorXYZ accel(SENSOR_ID_ACC);
SensorXYZ gyro(SENSOR_ID_GYRO);
SensorTemperature temp(SENSOR_ID_TEMP);

void setup()
{
  Serial.begin(9600);

  BHY2.begin();

  accel.configure(1, 0);
  gyro.configure(1, 0);
  temp.configure(1, 0);
}

void loop()
{
  static auto printTime = millis();

  // Update function should be continuously polled
  BHY2.update();

  if (millis() - printTime >= 1000) {
    printTime = millis();

    Serial.print("acceleration: ") ;Serial.print(accel.x());Serial.print(", ");Serial.print(accel.y());Serial.print(", ");Serial.println(accel.z());
    Serial.print("gyroscope: ") ; Serial.println(gyro.toString());
    Serial.print("temperature: ") ; Serial.println(temp.value());
  }
}
```

###BLEペリフェラルのプログラム
　ライブラリを管理から、Arduino BLEライブラリをインストールします。
　UUIDは適当な値です。現在のArduino BLEライブラリのバージョンでは、Notifyが正常に動きます。
　　https://qiita.com/jamjam/items/08d524e6113703f9547b
　　https://www.denshi.club/cookbook/sensor/co2/co24adafruitscd-30arduino-nano-rp2040-connectble3.html
を修正しているので、いくらかのごみが残っています。
　readBHI260()はreadと名前がついていますが、何も読んでいません。

```C
#include "Nicla_System.h"
#include <ArduinoBLE.h>
#include "Arduino.h"
#include "Arduino_BHY2.h"

SensorXYZ accel(SENSOR_ID_ACC);
SensorXYZ gyro(SENSOR_ID_GYRO);
SensorTemperature temp(SENSOR_ID_TEMP);

#define BHI260_SERVICE_UUID   "F000AA30-0451-4000-B000-000000000000"

// BLE Service
BLEService Sensor_BHI260_Service(BHI260_SERVICE_UUID);

#define BHI260_Acceleration_Characteristic_UUID    "F000AA31-0451-4000-B000-000000000000"
#define BHI260_Gyroscope_Characteristic_UUID       "F000AA32-0451-4000-B000-000000000000"
#define BHI260_Temp_Characteristic_UUID       "F000AA33-0451-4000-B000-000000000000"

// BLE  Characteristic
BLEStringCharacteristic    BHI260_Acceleration(BHI260_Acceleration_Characteristic_UUID, BLERead | BLENotify, 24);
BLEStringCharacteristic    BHI260_Gyroscope(BHI260_Gyroscope_Characteristic_UUID, BLERead | BLENotify, 24);
BLEStringCharacteristic    BHI260_Temp(BHI260_Temp_Characteristic_UUID, BLERead | BLENotify, 24);

#define BHI260_A_Descriptor_UUID    "2901"
#define BHI260_G_Descriptor_UUID    "2901"
#define BHI260_T_Descriptor_UUID    "2901"

// BLE  Descriptor
BLEDescriptor   BHI260_A_Descriptor(BHI260_A_Descriptor_UUID, "Acceleration x,y,z");
BLEDescriptor   BHI260_G_Descriptor(BHI260_G_Descriptor_UUID, "Gyroscope x,y,z");
BLEDescriptor   BHI260_T_Descriptor(BHI260_T_Descriptor_UUID, "Temperature;`C");

float AccelerationX = 0, AccelerationY = 0, AccelerationZ = 0;
float GyroscopeX = 0, GyroscopeY = 0, GyroscopeZ = 0;
float Temp = 0;

#define localNAME  "Nicla_BHI260"
#define DeviceNAME "NiclaBLE"

float oldValue = 0;  // last value 
float previousMillis = 0;  // last time value was checked, in ms

void readBHI260() {
  static auto printTime = millis();

  // Update function should be continuously polled
  BHY2.update();

  if (millis() - printTime >= 200) {
    printTime = millis();
  }
}

void setup() {
  nicla::begin();
  Serial.begin(9600);
  while (!Serial);
  Serial.println("BHI260 test");
  BHY2.begin();

  if (!BLE.begin()) {
    Serial.println("starting BLE failed!");
    while (1);
  }

  accel.configure(1, 0);
  gyro.configure(1, 0);
  temp.configure(1, 0);

  BLE.setLocalName(localNAME);
  BLE.setDeviceName(DeviceNAME);

  // add the service UUID
  BLE.setAdvertisedService(Sensor_BHI260_Service);

  // add characteristic
  Sensor_BHI260_Service.addCharacteristic(BHI260_Acceleration);
  Sensor_BHI260_Service.addCharacteristic(BHI260_Gyroscope);
  Sensor_BHI260_Service.addCharacteristic(BHI260_Temp);

  // add descriptor
  BHI260_Acceleration.addDescriptor(BHI260_A_Descriptor);
  BHI260_Gyroscope.addDescriptor(BHI260_G_Descriptor);
  BHI260_Temp.addDescriptor(BHI260_T_Descriptor);

  // Add service
  BLE.addService(Sensor_BHI260_Service);

  // set initial value for this characteristic
  BHI260_Acceleration.writeValue("1");
  BHI260_Gyroscope.writeValue("2");
  BHI260_Temp.writeValue("3");
  
  // 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());
  }
}

void updateValue() {
  readBHI260();
  delay(500);
  Serial.println(String("acceleration: ") + accel.toString());
  Serial.println(String("gyroscope: ") + gyro.toString());
  Serial.println(String("temperature: ") + String(int(temp.value())));
  String valueof_BHI260_Acceleration = String(accel.x()) + "," +  String(accel.y()) + "," + String(accel.z());
  String valueof_BHI260_Gyroscope = String(gyro.x()) + "," +  String(gyro.y()) + "," + String(gyro.z());
  String valueof_BHI260_Temp = String(temp.value());

  // if value has changed
  if (( accel.x() + gyro.y()) != oldValue) {

    // update  characteristic
    BHI260_Acceleration.writeValue(valueof_BHI260_Acceleration);
    BHI260_Gyroscope.writeValue(valueof_BHI260_Gyroscope);    
    BHI260_Temp.writeValue(valueof_BHI260_Temp);
    oldValue = accel.x() + gyro.y(); // save the level for next comparison
  }
}
```

　Windows10で動いているオンセミのRSL10 Bluetooth Low Enaergy Exploerを使って接続します。
　センサの値はテキストで送っています。

　![2021-10-12 (13).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/1f95a93a-f9b2-5d8e-dfe7-229ea9bf60e3.png)