ESP32[15] BMX055 9軸センサーのデータをBLEで送信する。

BMX055 9軸センサーをRaspberry Piで読んで姿勢推定に使おうと思っていましたが、9軸センサーから姿勢を出すことが難しいことがわかりました。しかし、ArduinoだとMadgwickライブラリーが提供されていて簡単に姿勢推定ができることもわかり、急遽、ESP32で姿勢推定をするように方針変換しました。最終的には、SIM⇒Softether⇒自席でデータを見ることが目的なので、このESP32で計算した姿勢推定値をラズパイに渡す必要があります。今まではBluetooth SerialでBluetoothを使ったことはありましたが、やはりここはBLEでデータを送るのが良いだろうなということで初めてBLEサーバーを使ってみました。スケッチ例にESP32のBLE_Server.ino があるのでこれを改造してます。BMX055とMadgwickの使い方は下記のページのほぼコピーです。

BMX055とESP32でMadgwickフィルタを使う

//================================================================//
//  AE-BMX055             ESP32                                   //
//    VCC                    +5V                                  //
//    GND                    GND                                  //
//    SDA                    DIO21 (I2C SDA)                      //
//    SCL                    DIO22 (I2C SCL)                      //
//                                                                //
//   (JP4,JP5,JP6はショートした状態)                                 //
//   http://akizukidenshi.com/catalog/g/gK-13010/                 //
//================================================================//

/*
    Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleServer.cpp
    Ported to Arduino ESP32 by Evandro Copercini
    updates by chegewara
*/

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include<Wire.h>
#include <MadgwickAHRS.h>
#include <math.h>
Madgwick MadgwickFilter;


// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID        "D5875408-FA51-4763-A75D-7D33CECEBC31"
#define CHARACTERISTIC_UUID "A4F01D8C-A037-43B6-9050-1876A8C23584"

#define Addr_Accl 0x19  // (JP1,JP2,JP3 = Open)
#define Addr_Gyro 0x69  // (JP1,JP2,JP3 = Open)
#define Addr_Mag 0x13   // (JP1,JP2,JP3 = Open)


#define GRYO 1
#define ACCL 2
#define MAG 3
#define XYZ_ROTATION 4
float xAccl = 0.00;
float yAccl = 0.00;
float zAccl = 0.00;
float xGyro = 0.00;
float yGyro = 0.00;
float zGyro = 0.00;
float   xMag  = 0;
float   yMag  = 0;
float   zMag  = 0;
float  roll = 0  ;
float  pitch = 0 ;
float  yaw = 0 ;


//=====================================================================================//
void BMX055_Init()
{
  //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Accl);
  Wire.write(0x0F); // Select PMU_Range register
  Wire.write(0x03);   // Range = +/- 2g
  Wire.endTransmission();
  delay(100);
  //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Accl);
  Wire.write(0x10);  // Select PMU_BW register
  Wire.write(0x08);  // Bandwidth = 7.81 Hz
  Wire.endTransmission();
  delay(100);
  //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Accl);
  Wire.write(0x11);  // Select PMU_LPW register
  Wire.write(0x00);  // Normal mode, Sleep duration = 0.5ms
  Wire.endTransmission();
  delay(100);
  //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Gyro);
  Wire.write(0x0F);  // Select Range register
  Wire.write(0x04);  // Full scale = +/- 125 degree/s
  Wire.endTransmission();
  delay(100);
  //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Gyro);
  Wire.write(0x10);  // Select Bandwidth register
  Wire.write(0x07);  // ODR = 100 Hz
  Wire.endTransmission();
  delay(100);
  //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Gyro);
  Wire.write(0x11);  // Select LPM1 register
  Wire.write(0x00);  // Normal mode, Sleep duration = 2ms
  Wire.endTransmission();
  delay(100);
  //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Mag);
  Wire.write(0x4B);  // Select Mag register
  Wire.write(0x83);  // Soft reset
  Wire.endTransmission();
  delay(100);
  //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Mag);
  Wire.write(0x4B);  // Select Mag register
  Wire.write(0x01);  // Soft reset
  Wire.endTransmission();
  delay(100);
  //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Mag);
  Wire.write(0x4C);  // Select Mag register
  Wire.write(0x00);  // Normal Mode, ODR = 10 Hz
  Wire.endTransmission();
  //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Mag);
  Wire.write(0x4E);  // Select Mag register
  Wire.write(0x84);  // X, Y, Z-Axis enabled
  Wire.endTransmission();
  //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Mag);
  Wire.write(0x51);  // Select Mag register
  Wire.write(0x04);  // No. of Repetitions for X-Y Axis = 9
  Wire.endTransmission();
  //------------------------------------------------------------//
  Wire.beginTransmission(Addr_Mag);
  Wire.write(0x52);  // Select Mag register
  Wire.write(0x16);  // No. of Repetitions for Z-Axis = 15
  Wire.endTransmission();
}
//=====================================================================================//
void BMX055_Accl()
{
  int data[6];
  for (int i = 0; i < 6; i++)
  {
    Wire.beginTransmission(Addr_Accl);
    Wire.write((2 + i));// Select data register
    Wire.endTransmission();
    Wire.requestFrom(Addr_Accl, 1);// Request 1 byte of data
    // Read 6 bytes of data
    // xAccl lsb, xAccl msb, yAccl lsb, yAccl msb, zAccl lsb, zAccl msb
    if (Wire.available() == 1)
      data[i] = Wire.read();
  }
  // Convert the data to 12-bits
  xAccl = ((data[1] * 256) + (data[0] & 0xF0)) / 16;
  if (xAccl > 2047)  xAccl -= 4096;
  yAccl = ((data[3] * 256) + (data[2] & 0xF0)) / 16;
  if (yAccl > 2047)  yAccl -= 4096;
  zAccl = ((data[5] * 256) + (data[4] & 0xF0)) / 16;
  if (zAccl > 2047)  zAccl -= 4096;
  xAccl = xAccl * 0.0098; // renge +-2g
  yAccl = yAccl * 0.0098; // renge +-2g
  zAccl = zAccl * 0.0098; // renge +-2g
}
//=====================================================================================//
void BMX055_Gyro()
{
  int data[6];
  for (int i = 0; i < 6; i++)
  {
    Wire.beginTransmission(Addr_Gyro);
    Wire.write((2 + i));    // Select data register
    Wire.endTransmission();
    Wire.requestFrom(Addr_Gyro, 1);    // Request 1 byte of data
    // Read 6 bytes of data
    // xGyro lsb, xGyro msb, yGyro lsb, yGyro msb, zGyro lsb, zGyro msb
    if (Wire.available() == 1)
      data[i] = Wire.read();
  }
  // Convert the data
  xGyro = (data[1] * 256) + data[0];
  if (xGyro > 32767)  xGyro -= 65536;
  yGyro = (data[3] * 256) + data[2];
  if (yGyro > 32767)  yGyro -= 65536;
  zGyro = (data[5] * 256) + data[4];
  if (zGyro > 32767)  zGyro -= 65536;

  xGyro = xGyro * 0.0038; //  Full scale = +/- 125 degree/s
  yGyro = yGyro * 0.0038; //  Full scale = +/- 125 degree/s
  zGyro = zGyro * 0.0038; //  Full scale = +/- 125 degree/s
}
//=====================================================================================//
void BMX055_Mag()
{
  int data[8];
  for (int i = 0; i < 8; i++)
  {
    Wire.beginTransmission(Addr_Mag);
    Wire.write((0x42 + i));    // Select data register
    Wire.endTransmission();
    Wire.requestFrom(Addr_Mag, 1);    // Request 1 byte of data
    // Read 6 bytes of data
    // xMag lsb, xMag msb, yMag lsb, yMag msb, zMag lsb, zMag msb
    if (Wire.available() == 1)
      data[i] = Wire.read();
  }
  // Convert the data
  xMag = ((data[1] << 8) | (data[0] >> 3));
  if (xMag > 4095)  xMag -= 8192;
  yMag = ((data[3] << 8) | (data[2] >> 3));
  if (yMag > 4095)  yMag -= 8192;
  zMag = ((data[5] << 8) | (data[4] >> 3));
  if (zMag > 16383)  zMag -= 32768;
}

BLEServer *pServer;
BLEService *pService;
BLECharacteristic *pCharacteristic;

void bele_server_setup() {
  BLEDevice::init("BLE-YTL");
  pServer = BLEDevice::createServer();
  pService = pServer->createService(SERVICE_UUID);
  pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID,
                      BLECharacteristic::PROPERTY_READ |
                      BLECharacteristic::PROPERTY_WRITE
                    );

  pService->start();
  // BLEAdvertising *pAdvertising = pServer->getAdvertising();  // this still is working for backward compatibility
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(true);
  pAdvertising->setMinPreferred(0x06);  // functions that help with iPhone connections issue
  pAdvertising->setMinPreferred(0x12);
  BLEDevice::startAdvertising();
  Serial.println("This server(Peripheral). Characteristic defined! Now you can read it in your phone!");
}

void setup()
{
  // Wire(Arduino-I2C)
  Wire.begin();
  // 115200bps
  Serial.begin(115200);
  //BMX055
  BMX055_Init();
  delay(300);
  MadgwickFilter.begin(10);

  // ble_server set up
  bele_server_setup();
}

void loop()
{
  char ble_buf[1256];

  BMX055_Gyro();
  Serial.print("GYO:");//gryo==1
  Serial.print(" x>");
  Serial.print(xGyro);
  Serial.print(" y>");
  Serial.print(yGyro);
  Serial.print(" z>");
  Serial.println(zGyro);

  BMX055_Accl();
  Serial.print("ACL:");//accl ==2
  Serial.print(" x>");
  Serial.print(xAccl);
  Serial.print(" y>");
  Serial.print(yAccl);
  Serial.print(" z>");
  Serial.println(zAccl);

  BMX055_Mag();
  Serial.print("MAG:");//mag==3
  Serial.print(" x>");
  Serial.print(xMag);
  Serial.print(" y>");
  Serial.print(yMag);
  Serial.print(" z>");
  Serial.println(zMag);
  MadgwickFilter.update(xGyro, yGyro, zGyro, xAccl, yAccl, zAccl, xMag, yMag, zMag);
  roll  = MadgwickFilter.getRoll();
  pitch = MadgwickFilter.getPitch();
  yaw   = MadgwickFilter.getYaw();
  Serial.print("ROT:");//XYZ_ROTATION=4
  Serial.print(" r>");
  Serial.print(roll);
  Serial.print(" p>");
  Serial.print(pitch);
  Serial.print(" y>");
  Serial.println(yaw);
  Serial.print("\n");

  //Set sensor data to ble_buf
  //  sprintf(ble_buf, "GYO_x:%f", xGyro);

  sprintf(ble_buf, "GYO_x:%f GYO_y:%f GYO_z:%f ACL_x:%f ACL_y:%f ACL_z:%f MAG_x:%f MAG_y:%f MAG_z:%f ROLL:%f PICH %f YAW:%f\n",
          xGyro, yGyro, zGyro, xAccl, yAccl, zAccl, roll, pitch, yaw );
  Serial.printf("%s\n", ble_buf);
  pCharacteristic->setValue(ble_buf);

  delay(2000);
}

}