1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Wio Terminalの加速度センサ値をMATLABでリアルタイム可視化する

Last updated at Posted at 2023-05-07

はじめに

タイトルの通り、Wio Terminalの加速度センサ値を、MATLABに送ってそれをリアルタイムに可視化するやり方についてです。Wio TerminalとMATLABの入ったPCの間はBLEで接続し、ワイヤレスで動作します。

元ネタはSeeed公式サイトのこちらで、もともとPC側のアプリケーションがHTMLだったのをMATLABに記述しなおしました。

こんな感じの動きをします

wio_accelerometor_movie.gif

Wio Terminalのセットアップ

Wio TerminalでBluetooth接続するにあたっては、ワイヤレス通信用CPU(RTL8720DN)のファームウェアアップデートを行う必要があります。公式ページはこちらで、日本語記事はこちらが参考になります。

コード

MATLAB側

MATLAB側コードを実行する前に、Wio Terminal側にファームウェアを書き込んだうえで電源を入れておいてください。
Wio Terminal側と問題なく接続できれば、

  • Scanning for devices...
  • Connecting to device...
  • Receiving data...

のメッセージが出た後、加速度センサ値のグラフが表示されます。

ちなみに、ChatGPTで公式のhtmlからMATLABに変換させました。3,4か所ほどの手直しでかなり簡単にできました。

ble_accel_freerun.m
% Bluetooth Accelerometer Plotter for Wio Terminal

% 1. Upload the sketch to your Wio Terminal
% 2. Run this MATLAB script

clear;
close;
% Set up BLE
serviceUuid = "19B10000-E8F2-537E-4F6C-D104768A1214";
characteristicUuid = "19B10010-E8F2-537E-4F6C-D104768A1214";

% Connect to BLE device
disp("Scanning for devices...");
devices = blelist;
device = [];
numDevices = size(devices, 1);
for i = 1:numDevices
    if any(strcmp(serviceUuid, devices.Advertisement(i).CompleteServiceUUIDs))
        device = devices(i, :);
        break;
    end
end

if isempty(device)
    error("No compatible device found.");
end

disp("Connecting to device...");
b = ble(device.Address{1});
c = characteristic(b, serviceUuid, characteristicUuid);

% Set up plot
xyz_color = ['r','g','b'];
figure;
for i = 1:3
    h(i) = animatedline('Marker', 'o', 'Color', xyz_color(i), 'LineStyle', 'none');
end

title('Bluetooth Accelerometer Plotter for Wio Terminal');
xlabel('Time');
ylabel('Acceleration');
legend('X', 'Y', 'Z');
axis([0, 100, -2, 2]);
grid on;
dataPoints = 100;
accelData = zeros(dataPoints, 3);

% Read data and update plot
disp("Receiving data...");
tic;
i = 0;
while isvalid(b)
    i = i + 1;
    value = read(c, "latest");
    accel = sscanf(native2unicode(value), "%f|%f|%f");
    
    % Update data buffer
    if i <= dataPoints
        accelData(i, :) = accel';
    else
        accelData = [accelData(2:end, :); accel'];
    end
    
    % Update plot
    for j = 1:3
        clearpoints(h(j));
        addpoints(h(j), 1:size(accelData, 1), accelData(:, j));
    end
    drawnow limitrate;
end

Wio Terminal側

Arduino IDEを使う場合には、適当にコードをIDEにコピペして使ってください。
ほぼ公式のサンプルコードのままですが、画面に加速度センサ値を表示するところだけ追加しました。

こちらの記事にある通り、「Seeed_Arduino_rpcBLE」、「Seeed_Arduino_rpcUnified」などのライブラリが必要です。

main.cpp
// Sample code to send Accelerometer values via Bluetooth.
// Original↓
// https://wiki.seeedstudio.com/Wio-Terminal-Web-Bluetooth/#arduino-set-up-1

#include <rpcBLEDevice.h>
#include <BLEServer.h>
#include <LIS3DHTR.h>
 
#define accelerometerService "19b10000-e8f2-537e-4f6c-d104768a1214"
#define firstCharacteristic  "19b10010-e8f2-537e-4f6c-d104768a1214"
#define DESCRIPTOR_UUID      "19b10010"
 
LIS3DHTR<TwoWire> lis;

#include"TFT_eSPI.h"
TFT_eSPI tft;
 
bool deviceConnected = false;
bool oldDeviceConnected = false;
 
BLEServer *pServer = NULL;
BLECharacteristic * pCharacteristic;
 
class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      Serial.println("MyServerCallbacks onConnect ");
      deviceConnected = true;
    };
 
    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
    }
};
 
class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string rxValue = pCharacteristic->getValue();
 
      if (rxValue.length() > 0) {
        Serial.println("*********");
        Serial.print("Received Value: ");
        for (int i = 0; i < rxValue.length(); i++)
          Serial.print(rxValue[i]);
 
        Serial.println();
        Serial.println("*********");
      }
    }
};
 
void setup() {
  Serial.begin(115200);
//  while(!Serial){};
 
  lis.begin(Wire1);
  if (!lis) {
    Serial.println("Accelerater Error!");
    while(1);
  }
  lis.setOutputDataRate(LIS3DHTR_DATARATE_25HZ); //Data output rate
  lis.setFullScaleRange(LIS3DHTR_RANGE_2G); //Scale range set to 2g
  Serial.println("Accelerater Initialised!");
 
  Serial.println("Starting BLE work!");
 
  BLEDevice::init("Accelerometer");
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());
 
  BLEService *pService = pServer->createService(accelerometerService);
  pCharacteristic = pService->createCharacteristic(
                                         firstCharacteristic,
                                         BLECharacteristic::PROPERTY_READ |
                                         BLECharacteristic::PROPERTY_WRITE
                                       );
  pCharacteristic->setAccessPermissions(GATT_PERM_READ | GATT_PERM_WRITE);
  BLEDescriptor *pDescriptor = pCharacteristic->createDescriptor(
                                         DESCRIPTOR_UUID,
                                          ATTRIB_FLAG_VOID | ATTRIB_FLAG_ASCII_Z,
                                         GATT_PERM_READ | GATT_PERM_WRITE,
                                         2
                                         );
  pCharacteristic->setCallbacks(new MyCallbacks());
  pService->start();
 
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(accelerometerService);
  pAdvertising->setScanResponse(true);
  pAdvertising->setMinPreferred(0x06);  // functions that help with iPhone connections issue
  pAdvertising->setMinPreferred(0x12);
  BLEDevice::startAdvertising();
  Serial.println("Characteristic defined! Now you can read it in your phone!");

  // setup for display
  tft.begin();
  tft.setRotation(3);
  tft.fillScreen(TFT_BLACK); //Black background
  tft.setTextColor(TFT_WHITE, TFT_BLACK); //White text color 
}
 
void loop() { 
  if (deviceConnected) {
    updateAcceleration();
  }
      // disconnecting
    if (!deviceConnected && oldDeviceConnected) {
        delay(500); // give the bluetooth stack the chance to get things ready
        pServer->startAdvertising(); // restart advertising
        Serial.println("start advertising");
        oldDeviceConnected = deviceConnected;
    }
    // connecting
    if (deviceConnected && !oldDeviceConnected) {
    // do stuff here on connecting
        oldDeviceConnected = deviceConnected;
    }
}
 
void updateAcceleration() {
  float x_values, y_values, z_values;
  x_values = lis.getAccelerationX();
  y_values = lis.getAccelerationY();
  z_values = lis.getAccelerationZ();
 
  String accelerometerData = String(x_values)+"|"+String(y_values)+"|"+String(z_values);
  Serial.println(accelerometerData);
  pCharacteristic->setValue(accelerometerData.c_str());
  pCharacteristic->notify();

  // show xyz values on the display
  char x_str[100], y_str[100], z_str[100];
  dtostrf(x_values, 6, 2, x_str);
  dtostrf(y_values, 6, 2, y_str);
  dtostrf(z_values, 6, 2, z_str);

  tft.drawString(x_str, 70, 60, 6);
  tft.drawString(y_str, 70,110, 6);
  tft.drawString(z_str, 70,160, 6);
  
  delay(20);
}

おわりに

Wio Terminalの加速度センサ値を、MATLABでリアルタイム可視化するやり方について書きました。間違い等ありましたらコメントお願いします。

Wio Terminal、最近あまり見かけなくなりましたが私は好きです。画面でかくてボタン多いところとか。
しばしばセールで4000円台で売ってたりするので、またブームになって欲しいです。

1
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?