工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

Arduino Nano 33 BLE Senseで作るTinyMLジェスチャー認識デバイス

部品と用品

Arduino Nano 33 BLE Sense 内蔵IMU(LSM9DS1)、マイク、温湿度・気圧・光・近接・色センサー搭載 1
micro USBケーブル 1
PC(Arduino IDE / Arduino Cloud) 1

このプロジェクトについて

Arduino Nano 33 BLE Senseに搭載された9軸IMU(加速度・ジャイロ・磁力)を使って、機械学習(TinyML)によるジェスチャー認識をエッジデバイス単体で実行するプロジェクトです。クラウド不要、オフラインで動作し、認識結果をBLEでスマホアプリやPCに通知できます。

TinyMLとは

TinyML(Tiny Machine Learning)は、マイクロコントローラー級のリソース制約デバイス上で機械学習モデルを推論する技術です。Arduino Nano 33 BLE Sense(Cortex-M4F 64MHz、1MB Flash、256KB RAM)でも、適切に量子化されたモデルならリアルタイム推論が可能です。

ワークフロー

  1. データ収集: ボード上のIMUから加速度・ジャイロデータを採取し、各ジェスチャーのサンプルを蓄積
  2. モデル訓練: Edge ImpulseやTensorFlow Lite for Microcontrollersでモデル作成・量子化
  3. デプロイ: 生成されたC++ライブラリをArduinoスケッチに組み込み
  4. 推論・通知: 実行中にジェスチャー検知したらBLEで通知

ステップ1:データ収集スケッチ


#include <Arduino_LSM9DS1.h>

const int SAMPLE_RATE = 100; // Hz
const int SAMPLES_PER_GESTURE = 100; // 1秒分
const float ACCEL_THRESHOLD = 2.0; // 着手検知閾値 (G)

enum Gesture { NONE, SHAKE, SWIPE_LEFT, SWIPE_RIGHT, CIRCLE };
Gesture currentGesture = NONE;
int sampleCount = 0;
float samples[100][6]; // ax, ay, az, gx, gy, gz

void setup() {
  Serial.begin(115200);
  while (!Serial);
  if (!IMU.begin()) {
    Serial.println("IMU init failed!");
    while (1);
  }
  Serial.println("Gesture Data Collector");
  Serial.println("Send gesture name (shake/swipe_left/swipe_right/circle) to start recording");
}

void loop() {
  // シリアルコマンドでジェスチャー指定
  if (Serial.available()) {
    String cmd = Serial.readStringUntil('\n');
    cmd.trim();
    if (cmd == "shake") currentGesture = SHAKE;
    else if (cmd == "swipe_left") currentGesture = SWIPE_LEFT;
    else if (cmd == "swipe_right") currentGesture = SWIPE_RIGHT;
    else if (cmd == "circle") currentGesture = CIRCLE;
    else currentGesture = NONE;
    sampleCount = 0;
    Serial.println("Recording: " + cmd);
  }
  
  // 加速度閾値超過で自動記録開始
  if (currentGesture != NONE && sampleCount < SAMPLES_PER_GESTURE) {
    float ax, ay, az, gx, gy, gz;
    if (IMU.accelerationAvailable() && IMU.gyroscopeAvailable()) {
      IMU.readAcceleration(ax, ay, az);
      IMU.readGyroscope(gx, gy, gz);
      
      float accelMag = sqrt(ax*ax + ay*ay + az*az);
      if (accelMag > ACCEL_THRESHOLD || sampleCount > 0) {
        samples[sampleCount][0] = ax;
        samples[sampleCount][1] = ay;
        samples[sampleCount][2] = az;
        samples[sampleCount][3] = gx;
        samples[sampleCount][4] = gy;
        samples[sampleCount][5] = gz;
        sampleCount++;
      }
    }
  }
  
  // 記録完了 → CSV出力
  if (currentGesture != NONE && sampleCount >= SAMPLES_PER_GESTURE) {
    Serial.println("GESTURE_DATA_START");
    for (int i = 0; i < SAMPLES_PER_GESTURE; i++) {
      Serial.print(currentGesture); Serial.print(",");
      for (int j = 0; j < 6; j++) {
        Serial.print(samples[i][j], 4);
        if (j < 5) Serial.print(",");
      }
      Serial.println();
    }
    Serial.println("GESTURE_DATA_END");
    currentGesture = NONE;
  }
}

ステップ2:Edge Impulseでモデル作成

  1. Edge Impulse でプロジェクト作成
  2. Data acquisitionタブでCSVアップロード(上記スケッチの出力をファイル保存)
  3. Impulse design: Time series data → Window size 1000ms, Window increase 100ms
  4. Processing block: Spectral Analysis / Flatten
  5. Learning block: Classifier (Neural Network, 20 epochs, learning rate 0.0005)
  6. Generate features → Train model → Test accuracy確認(目標90%以上)
  7. Deployment → Arduino library → Build で .zip ダウンロード

ステップ3:推論スケッチ(Edge Impulseライブラリ使用)


#include <Arduino_LSM9DS1.h>
#include <edge-impulse-inferencing.h>

#define CONFIDENCE_THRESHOLD 0.8

void setup() {
  Serial.begin(115200);
  while (!Serial);
  if (!IMU.begin()) {
    Serial.println("IMU init failed!");
    while (1);
  }
  Serial.println("TinyML Gesture Recognition Ready");
  ei_printf("Inferencing settings:\n");
  ei_printf("\tInterval: %.2f ms\n", (float)EI_CLASSIFIER_INTERVAL_MS);
  ei_printf("\tFrame size: %d\n", EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE);
  ei_printf("\tSample length: %d ms\n", EI_CLASSIFIER_RAW_SAMPLE_COUNT / 100);
}

void loop() {
  // 推論用バッファ確保
  float buffer[EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE] = {0};
  
  // データ収集(ノンブロッキング)
  static int bufIndex = 0;
  if (IMU.accelerationAvailable() && IMU.gyroscopeAvailable()) {
    float ax, ay, az, gx, gy, gz;
    IMU.readAcceleration(ax, ay, az);
    IMU.readGyroscope(gx, gy, gz);
    
    buffer[bufIndex++] = ax;
    buffer[bufIndex++] = ay;
    buffer[bufIndex++] = az;
    buffer[bufIndex++] = gx;
    buffer[bufIndex++] = gy;
    buffer[bufIndex++] = gz;
  }
  
  // フレーム完成で推論実行
  if (bufIndex >= EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE) {
    bufIndex = 0;
    
    signal_t signal;
    signal.total_length = EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE;
    signal.get_data = [](size_t offset, size_t length, float *out_ptr) {
      memcpy(out_ptr, buffer + offset, length * sizeof(float));
      return 0;
    };
    
    ei_impulse_result_t result = {0};
    EI_IMPULSE_ERROR res = run_classifier(&signal, &result, false);
    
    if (res != EI_IMPULSE_OK) {
      Serial.println("Inference failed");
      return;
    }
    
    // 結果表示
    Serial.print("Predictions: ");
    for (uint16_t i = 0; i < EI_CLASSIFIER_LABEL_COUNT; i++) {
      Serial.print(result.classification[i].label);
      Serial.print(": ");
      Serial.print(result.classification[i].value, 4);
      Serial.print("  ");
      
      // 閾値超過でジェスチャー検知
      if (result.classification[i].value > CONFIDENCE_THRESHOLD) {
        Serial.print(" *** DETECTED: ");
        Serial.println(result.classification[i].label);
        // ここでBLE通知やアクション実行
      }
    }
    Serial.println();
  }
  
  delay(10); // 100Hzサンプリング
}

ステップ4:BLE通知(オプション)


#include <ArduinoBLE.h>

BLEService gestureService("19B10000-E8F2-537E-4F6C-D104768A1214");
BLEStringCharacteristic gestureChar("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify, 20);

void setupBLE() {
  if (!BLE.begin()) return;
  BLE.setLocalName("GestureRecognizer");
  BLE.setAdvertisedService(gestureService);
  gestureService.addCharacteristic(gestureChar);
  BLE.addService(gestureService);
  gestureChar.writeValue("ready");
  BLE.advertise();
}

// 推論ループ内で検知時に:
// gestureChar.writeValue(detectedGesture);

精度向上のコツ

応用例

製造プロセス

  1. プリント基板:設計、製造、未来トレンド
  2. ロウソククレヨンで3Dプリント部品を着色:新しい後処理技法
  3. 3Dプリント義肢:切断患者のアクセスと負担を変革
  4. Google地形データから高品質な3Dプリント地形図を作成する方法
  5. 品質管理の向上:3Dプリント工具が製造精度を高める
  6. ケブラーCFFで機能的な3Dプリント自転車パニアアダプターを設計
  7. ゴーカートの再発明:3Dプリントカーボンファイバーパーツで比類なきパフォーマンスを実現
  8. 人間中心のサプライチェーン変革:効率とレジリエンスを両立
  9. スマート旋盤:精密加工のための先進タッチスクリーン制御
  10. 静電容量式加速度センサーの仕組み:質量バネ系から信号調整まで
  11. 電気機械的に結合した導体を用いた高度ユニバーサル触覚センシング