LoginSignup
3
0

More than 1 year has passed since last update.

matlab SimulinkのBLE functionを作ってみた 備忘録

Last updated at Posted at 2021-11-22

 Simulinkには、BLEのブロックがありません。BLEのセントラルを作ります。

センサのデータを送るペリフェラル

 Arduino Nano 33 BLE senseボードには、 9軸IMUのLSM9DS1が搭載されています。このボードで、ペリフェラルを作ります。

ファイル名

 キャラクタUUIDはAcceleration、Gyroscope、Magneticの三つです。次のように、それぞれx、y、zは、カンマで区切ってテキストで送ります。
   0.12,34.56,7.89


#include <Arduino_LSM9DS1.h>
#include <ArduinoBLE.h>

// LSM9DS1

// BLE Service
#define Nano33BLESense_Service7_UUID   "F000AE00-0451-4000-B000-000000000000"
BLEService Nano33BLESense_Service7(Nano33BLESense_Service7_UUID);

// BLE  Characteristic
#define LSM9DS1_Acceleration_Characteristic_UUID    "F000AE01-0451-4000-B000-000000000000"
#define LSM9DS1_Gyroscope_Characteristic_UUID    "F000AE02-0451-4000-B000-000000000000"
#define LSM9DS1_Magnetic_Characteristic_UUID    "F000AE03-0451-4000-B000-000000000000"
BLEStringCharacteristic    LSM9DS1_Acceleration(LSM9DS1_Acceleration_Characteristic_UUID, BLERead | BLENotify, 37);
BLEStringCharacteristic    LSM9DS1_Gyroscope(LSM9DS1_Gyroscope_Characteristic_UUID, BLERead | BLENotify, 37);
BLEStringCharacteristic    LSM9DS1_Magnetic(LSM9DS1_Magnetic_Characteristic_UUID, BLERead | BLENotify, 37);


// BLE  Descriptor
#define LSM9DS1_Acceleration_Descriptor_UUID    "2901"
#define LSM9DS1_Gyroscope_Descriptor_UUID       "2901"
#define LSM9DS1_Magnetic_Descriptor_UUID        "2901"
BLEDescriptor   LSM9DS1_Acceleration_Descriptor(LSM9DS1_Acceleration_Descriptor_UUID, "Hz  Acceleration in G's  X  Y  Z");
BLEDescriptor   LSM9DS1_Gyroscope_Descriptor(LSM9DS1_Gyroscope_Descriptor_UUID, "Hz  Gyroscope in degrees/second  X  Y  Z");
BLEDescriptor   LSM9DS1_Magnetic_Descriptor(LSM9DS1_Magnetic_Descriptor_UUID, "uT  Magnetic Field in uT X  Y  Z");

#define localNAME  "LSM9DS1"
#define DeviceNAME "LSM9DS1_BLE"

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

void setup() {
  Serial.begin(9600);
  while (!Serial);
  Serial.println("\nStarted\n");

  if (!IMU.begin()) {
    Serial.println("Failed to initialize IMU!");
    while (1);
  }

  Serial.print("Accelerometer sample rate = ");
  Serial.print(IMU.accelerationSampleRate());
  Serial.println("Hz  Acceleration in G's X\tY\tZ");

  Serial.print("Gyroscope sample rate = ");
  Serial.print(IMU.gyroscopeSampleRate());
  Serial.println("Hz  Gyroscope in degrees/second X\tY\tZ");

  Serial.print("Magnetic field sample rate = ");
  Serial.print(IMU.magneticFieldSampleRate());
  Serial.println("uT  Magnetic Field in uT X\tY\tZ");

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

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

  //// set the service
  BLE.setAdvertisedService(Nano33BLESense_Service7);

  // add characteristic
  Nano33BLESense_Service7.addCharacteristic(LSM9DS1_Acceleration);
  Nano33BLESense_Service7.addCharacteristic(LSM9DS1_Gyroscope);
  Nano33BLESense_Service7.addCharacteristic(LSM9DS1_Magnetic);

  // add descriptor
  LSM9DS1_Acceleration.addDescriptor(LSM9DS1_Acceleration_Descriptor);
  LSM9DS1_Gyroscope.addDescriptor(LSM9DS1_Gyroscope_Descriptor);
  LSM9DS1_Magnetic.addDescriptor(LSM9DS1_Magnetic_Descriptor);

  // add service
  BLE.addService(Nano33BLESense_Service7);

  // 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("\n Connected 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() {
  float xa, ya, za, xg, yg, zg, xm, ym, zm;
  Serial.println("");
  if (IMU.accelerationAvailable()) {
    IMU.readAcceleration(xa, ya, za);

    Serial.println("acceleration "+String(xa)+'\t'+String(ya)+'\t'+String(za));
  }
  if (IMU.gyroscopeAvailable()) {
    IMU.readGyroscope(xg, yg, zg);
    Serial.println("gyroscope    "+String(xg)+'\t'+String(yg)+'\t'+String(zg));
    }
  if (IMU.magneticFieldAvailable()) {
    IMU.readMagneticField(xm, ym, zm);
    Serial.println("magneticField "+String(xm)+'\t'+String(ym)+'\t'+String(zm));
  }
  // update  characteristic
  LSM9DS1_Acceleration.writeValue(String(xa)+","+String(ya)+","+String(za));
  LSM9DS1_Gyroscope.writeValue(String(xg)+","+String(yg)+","+String(zg));
  LSM9DS1_Magnetic.writeValue(String(xm)+","+String(ym)+","+String(zm));
}

 つながったときのシリアルモニタの様子です。
image.png

セントラル

 Arduino Nano 33 BLE senseボードとの接続は、事前に調べたアドレスで行っています。
 % initialize outputに記述したの三つの出力変数の初期化は、正しくない記述のような気がします。
 このファンクションに入力はないです。出力は三つです。
 persistentは永続変数の定義で、空の行列 ([]) に初期化されます。
 coder.extrinsicで定義された命令は、本体のコードを生成せず、代わりに MATLABエンジンを使用して呼び出しを実行します。
 Accelerationは、gの単位で送られてきたのをm/s^2に換算しています。

function [Acceleration, Gyroscope, MagneticField] = fcn()
      % automatically initialized to []
      persistent b;    
      persistent g11; 
      persistent g12; 
      persistent g13; 
      % extrinsic declarations
      coder.extrinsic('ble');
      coder.extrinsic('characteristic');
      coder.extrinsic('read');
      coder.extrinsic('subscribe');
      coder.extrinsic('split');

      if(isempty(b))
          Nano33BLE_address="88A2EDC9F60C";
          b = ble(Nano33BLE_address);
          ServiceUUID    = "F000AE00-0451-4000-B000-000000000000";
          LSM9DS1_Acceleration_Characteristic_UUID  =  "F000AE01-0451-4000-B000-000000000000";
          LSM9DS1_Gyroscope_Characteristic_UUID     =  "F000AE02-0451-4000-B000-000000000000";
          LSM9DS1_MagneticField_Characteristic_UUID =  "F000AE03-0451-4000-B000-000000000000";

          g11 = characteristic(b, ServiceUUID, LSM9DS1_Acceleration_Characteristic_UUID);
          subscribe(g11);  % Notify
          g12 = characteristic(b, ServiceUUID, LSM9DS1_Gyroscope_Characteristic_UUID);
          subscribe(g12);
          g13 = characteristic(b, ServiceUUID, LSM9DS1_MagneticField_Characteristic_UUID);
          subscribe(g13);
      end

      % initialize output
      Acceleration=[0 0 0];
      Gyroscope=[0 0 0];
      MagneticField=[0 0 0];

      accelerationXYZ = char(read(g11));
      dataA = split(accelerationXYZ, ",");
      aX = dataA(1);
      aY = dataA(2);
      aZ = dataA(3);
      Acceleration = [str2double(aX)*9.8 str2double(aY)*9.8 str2double(aZ)*9.8];

      gyroscopeXYZ = char(read(g12));
      dataG = split(gyroscopeXYZ, ",");
      gX = dataG(1);
      gY = dataG(2);
      gZ = dataG(3);
      Gyroscope = [str2double(gX), str2double(gY), str2double(gZ)];

      magneticFieldXYZ = char(read(g13));
      dataM = split(magneticFieldXYZ, ",");
      mX = dataM(1);
      mY = dataM(2);
      mZ = dataM(3);
      MagneticField = [str2double(mX), str2double(mY), str2double(mZ)];
end

 実行している様子です。
2021-11-22 (4).png

環境

Arduino IDEは1.8.16
matlabはR2021b update1
Simulinkはバージョン10.4
Windows10 21H2

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0