Top/Devel/電子工作/Arduino/モーションセンサ/MPU-9150

MPU-9150はてなブックマーク

mpu-9150.jpg

今回はモーションセンサをArduinoに接続し、AruinoとUnityを連携させて、Unity空間のオブジェクトの回転を制御してみます。


要するに../../PaxPowerGloveのページでやっているパワーグローブ近代化作業の要素技術確認です。



本ページで解説しているのはInvenSense社のMPU-9150についてですが、Bosch社のBNO055版の記事もあります。

必要なもの

ハードウェア

項目説明
Arduino Uno比較的小型で安価で簡単に使えるマイコンボード。
MPU-9150 9軸センサモジュールInvenSense社の3軸加速度+3軸ジャイロ+3軸コンパスのモーションセンサチップMPU-9150が載ったモジュール。
MPU-9150は、InvenSenseの加速度・ジャイロチップMPU-6050と旭化成のコンパスチップをAK8975を1パッケージにしたものです。
MPU-9150もしくはMPU-6050が搭載されているモジュールならば概ね同様だと思います。
これらのチップにはDMP(Digital Motion Processor)という機能があり、センサの生データではなく、センサの値からクォータニオンを算出してくれるので便利です。

ソフトウェア

項目説明
Arduino IDEArduino用の開発環境。
オフィシャルサイトからダウンロードしてください。
Unityマルチプラットフォーム対応のゲームエンジン。簡単に3D(or 2D)ゲームを作ることが出来る。
オフィシャルサイトからダウンロードしてください。
I2C Device LibraryI2Cデバイス用C++ライブラリとMPU-6050とMPU-9150のArduinoサンプルスケッチ。
https://github.com/jrowberg/i2cdevlib を開き、右側の「Download ZIP」をクリックしてダウンロードしてください。
Unity用C#スクリプト上記サンプルスケッチの出力をUnity側で受け取ってGameObjectを制御するC#スクリプト。本ページ下部からダウンロードしてください。

手順

ハードウェアの準備

  1. MPU-9150のSCL(今回のモジュールでは3番ピン)をArduinoのSCL(Arduino UnoではA5ピン)に接続する。
  2. MPU-9150のSDA(今回のモジュールでは4番ピン)をArduinoのSDA(Arduino UnoではA4ピン)に接続する。
  3. MPU-9150のINT(今回のモジュールでは8番ピン)をArduinoのinterrupt(Arduino UnoではD2ピン)に接続する。
  4. MPU-9150のGND(今回のモジュールでは10番ピン)とAD0(今回のモジュールでは9番ピン)をArduinoのGNDピンに接続する。
  5. MPU-9150のVDD(今回のモジュールでは1番ピン)とVLOGIC(今回のモジュールでは2番ピン)をArduinoの3.3Vピンに接続する。

ソフトウェアの準備(1):Arduinoスケッチ

  1. i2cdevlib-master.zipを解凍する。
  2. 下記2つのフォルダをArduino用フォルダのlibrariesにコピーする。
    • i2cdevlib-master/Arduino/I2Cdev
    • i2cdevlib-master/Arduino/MPU6050
    • i2cdevlib-master/Arduino/MPU9150
  3. MPU9150/MPU9150_9Axis_MotionApps41.hをエディタで開く。
  4. 61行目の"typedef unsigned char unsigned char;"をコメントアウトする。
  5. ファイル内の"prog_uchar"を"unsigned char"に置換する。
  6. Arduino IDEを起動する。
  7. メニューの[ファイル]>[スケッチの例]>[MPU6050]>[Example]>[MPU6050_DMP6]を選択する。
  8. 87行目を次のように変更する。
    (unidiff風に書いています。要するに先頭が-の行を削除して、先頭が+の行を追加するだけです。)
    -#include "MPU6050_6Axis_MotionApps20.h"
    +#include "MPU9150_9Axis_MotionApps41.h"
  9. 61行目を次のように変更する。
    -MPU6050 mpu;
    +MPU9150 mpu;
  10. 87行目を次のように変更する。
    -//#define OUTPUT_READABLE_QUATERNION
    +#define OUTPUT_READABLE_QUATERNION
  11. 100行目を次のように変更する。
    -#define OUTPUT_READABLE_YAWPITCHROLL
    +//#define OUTPUT_READABLE_YAWPITCHROLL
    
  12. 192-194行目を次のように変更する。
    -    while (Serial.available() && Serial.read()); // empty buffer
    -    while (!Serial.available());                 // wait for data
    -    while (Serial.available() && Serial.read()); // empty buffer again
    +//    while (Serial.available() && Serial.read()); // empty buffer
    +//    while (!Serial.available());                 // wait for data
    +//    while (Serial.available() && Serial.read()); // empty buffer again
    
  13. 201-204行目を次のように変更する。
    -    mpu.setXGyroOffset(220);
    -    mpu.setYGyroOffset(76);
    -    mpu.setZGyroOffset(-85);
    -    mpu.setZAccelOffset(1788); // 1688 factory default for my test chip
    +//    mpu.setXGyroOffset(220);
    +//    mpu.setYGyroOffset(76);
    +//    mpu.setZGyroOffset(-85);
    +//    mpu.setZAccelOffset(1788); // 1688 factory default for my test chip
    
  14. 保存してArduinoに書き込む。
  15. メニューの[ツール]>[シリアルモニタ]を選択する。
  16. 右下のボーレート選択リストから115200baudを選択する。
  17. 「Initializing I2C device..」に続いて、先頭に「quat」、その後に数値が出力されたら、成功。
    表示されない場合は、Arduino本体のリセットボタンを押してみてください。
  18. このとき、ウィンドウのタイトルに「COM〜」と表示されているはずなので、番号を覚えておく。

ソフトウェアの準備(2):Unity用C#スクリプト

  1. Unityを起動する。
  2. [Edit]>[Project Settings]>[Player]を開く。
  3. [Api Compatibility Level]を".NET 2.0 Subset"から".NET 2.0"に変更する。
  4. [GameObject]>[Create Other]>[Cube]を選択する。
  5. Scene Viewに立方体が表示され、Hierarchy Viewに「Cube」というGameObjectが出来ていることを確認する。
  6. Project Viewに本ページからダウンロードしたC#スクリプトをドラッグ&ドロップする。
  7. Project ViewにC#スクリプトが追加されていることを確認する。
  8. C#スクリプトをダブルクリックして開き、定数SERIAL_PORTを先ほど覚えておいた番号に書き換え、保存する。
  9. Project ViewのC#スクリプトをHierarchy Viewの「Cube」にドラッグ&ドロップする。

動作確認

  1. Unityの再生ボタンを押す。
  2. MPU-9150を傾けてみて、Cubeが動けば成功!
    動かない場合は、Arduino本体のリセットボタンを押してみてください。


お疲れ様でした。 :)

設定について

  • MPU-9150の調整はArduinoスケッチの201-204行目で変更できます。
  • シリアルポートの接続設定(ポート番号、ボーレート、タイムアウト値)はC#スクリプトの先頭の定数部分で変更できます。

Unity用C#スクリプト

fileControlObjectByMPU9150InUnity.cs
using System;
using System.IO.Ports;
using System.Threading;
using UnityEngine;

public class ControlObjectByMPU9150InUnity : MonoBehaviour {
    private const string SERIAL_PORT = "COM4";
    private const int SERIAL_BAUD_RATE = 115200;
    private const int SERIAL_TIMEOUT = 100;

    private Thread _readThread;
    private static SerialPort _serialPort;
    private static bool _continue;

    private static Quaternion _handQuaternion = new Quaternion();

    void Start() {
        _readThread = new Thread(Read);
        _serialPort = new SerialPort(SERIAL_PORT, SERIAL_BAUD_RATE);
        _serialPort.ReadTimeout = SERIAL_TIMEOUT;
        _serialPort.Open();
        _continue = true;
        _readThread.Start();
    }

    void Update() {
        transform.rotation = _handQuaternion;
    }

    void OnApplicationQuit() {
        _continue = false;
        _readThread.Join();
        _serialPort.Close();
    }

    private static void Read() {
        string[] values;
        float x, y, z, w;
        while (_continue) {
            if (_serialPort.IsOpen) {
                try {
                    values = _serialPort.ReadLine().Split('\t');
                    if (values[0] == "quat") {
                        x = float.Parse(values[2]);
                        y = -float.Parse(values[4]);
                        z = float.Parse(values[3]);
                        w = float.Parse(values[1]);
                        _handQuaternion.Set(x, y, z, w);
                    }
                } catch (TimeoutException) {
                }
            }
            Thread.Sleep(1);
        }
    }
}

参考

Amazon

差分 一覧