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));
}
###セントラル
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
###環境
Arduino IDEは1.8.16
matlabはR2021b update1
Simulinkはバージョン10.4
Windows10 21H2