Top/Devel/電子工作/Arduino/PaxPowerGlove

PaxPowerGlove の変更点はてなブックマーク


#author("2018-06-27T20:59:16+09:00","default:admin","admin")
#author("2018-06-27T21:06:27+09:00","default:admin","admin")
This page is also available in English. Please visit [[here>../PaxPowerGlove_en]].

~

#ref(powerglove04.jpg,right,around,33%)

Oculus Riftの仮想空間内の物体に干渉したい。

~

~

ということで、ファミコンの特殊コントローラであるところの[[パックス社製パワーグローブ>http://www.amazon.co.jp/exec/obidos/ASIN/B001VII7PA/cubic9com-22]]にモーションセンサを埋め込み、[[Arduino>../]]→PCと接続して、Unityの仮想空間内の手のモデルの動きを制御してみようと思います。

~

完成動画はこちら。


#youtube(WVCC-bLIjpU)
#youtube(6coz8Nx0RFI)

~

パワーグローブは本来、2つの超音波振動子から時間差で超音波を発生させてモーションキャプチャを実現しています。

発想は革新的・野心的で素晴らしいのですが、精度がいまいちなので、今回はその機構は使わず、新たにモーションセンサを搭載しています。

本来の機構で残っているのは曲げセンサのみです。

~

#ref(board.jpg,around,right,33%)
次の順序で進めます。
+パワーグローブの指の曲げ具合の取得
+モーションセンサによる手のモーションの取得とUnity空間のオブジェクトの回転制御
+1と2の統合
+近接無線通信モジュールXBeeによる無線通信
+3と4の統合
+振動モーターによるハプティック(触覚フィードバック)の実現
+5と6の統合
#clear


*必要なもの
**ハードウェア
|項目|説明|h
|[[Arduino>http://www.amazon.co.jp/exec/obidos/ASIN/B0044X2E5S/cubic9com-22]]|比較的小型で安価で簡単に使えるマイコンボード。&br;無線化してパワーグローブに内蔵する場合は、後述するArduino Fioが小型かつXBeeが直接接続でき、便利です。|
|[[パックスパワーグローブ>http://www.amazon.co.jp/exec/obidos/ASIN/B001VII7PA/cubic9com-22]]|通常はファミコンに接続して使う手袋型コントローラ。|
|抵抗(100kΩ)* 4|何でも良いです。今回は千石電子通商で購入しました。|
|[[MPU-9150 9軸センサモジュール>http://strawberry-linux.com/catalog/items?code=12150]]|InvenSense社の3軸加速度+3軸ジャイロ+3軸コンパスのモーションセンサチップMPU-9150が載ったモジュール。|

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

*手順1.パワーグローブの指の曲げ具合の取得
まずは指の曲げ具合を取得してみます。

**ハードウェアの準備
#ref(powerglove_circuit.png,right,around,25%)
+手の甲の部分のカバーと基板をプラスドライバーで外す。
+はんだ吸い取り線などを使って、配線を基板から外す。
+手の甲側の4本の赤い線をすべてGNDに接続する。
+Arduinoの5V→抵抗→手の甲側のセンサ線と繋ぎ、抵抗とセンサの間にArduinoのアナログ入力を接続する。~
後述のスケッチでのセンサ線とアナログ入力の関係は次の通り。
|指|センサ線|アナログ入力端子|h
|親指|青|A0|
|人差し指|黒|A1|
|中指|白|A2|
|薬指|茶|A3|
|小指|センサなし|-|

~
曲げセンサは出力が抵抗値なので、同程度の抵抗器を使うことで抵抗値→電圧値に変換してArduinoに入力する、という回路が上記です。

#clear

**ソフトウェアの準備
+
+下記ArduinoスケッチをArduinoに書き込む。

**動作確認
+シリアルモニタを開く。
+指を曲げ伸ばしして数値が変化することを確認する。

**Arduinoスケッチ
#code(C,nonumber,nooutline,PowerGlove.ino)

抵抗値は個体毎に違うと思うので、適宜調整してください。


*手順2.モーションセンサによる手のモーションの取得とUnity空間のオブジェクトの回転制御
パワーグローブはグローブ側から超音波を発射し、テレビの周りに設置した超音波センサで検知することによって、位置を検出しています。

~
今回はこの機構をInvenSense社のモーションセンサチップMPU-9150で置き換えて、手全体のモーションを取得し、Unity空間のオブジェクトの回転を制御してみます。

~
詳細は、[[../モーションセンサ]]をご覧ください。

*手順3.1と2の統合
さあついに、上記1と2を統合します。

**ハードウェアの準備
+1と2の回路を組み合わせる。~
Arduino Unoであれば、ピンが重複しないので、単に組み合わせるだけです。

**ソフトウェアの準備(1):Arduinoスケッチ
+[[../モーションセンサ]]で作成したArduinoスケッチを次のように修正する。
+286-297行目を次のように変更する。~
(unidiff風に書いています。要するに先頭が-の行を削除して、先頭が+の行を追加するだけです。)
#code(C,nonumber,nooutline){{
        #ifdef OUTPUT_READABLE_QUATERNION
            // display quaternion values in easy matrix form: w x y z
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            Serial.print("quat\t");
            Serial.print(q.w);
            Serial.print("\t");
            Serial.print(q.x);
            Serial.print("\t");
            Serial.print(q.y);
            Serial.print("\t");
-            Serial.println(q.z);
+            Serial.print(q.z);
+            Serial.print("\t");
+            Serial.print(constrain(map(analogRead(A0), 678, 760, 0, 10), 0, 10) * 6);
+            Serial.print("\t");
+            Serial.print(constrain(map(analogRead(A1), 835, 935, 0, 10), 0, 10) * 6);
+            Serial.print("\t");
+            Serial.print(constrain(map(analogRead(A2), 770, 905, 0, 10), 0, 10) * 6);
+            Serial.print("\t");
+            Serial.println(constrain(map(analogRead(A3), 750, 910, 0, 10), 0, 10) * 6);
        #endif
}}

**ソフトウェアの準備(2):Unityプロジェクト
+下記ファイルをダウンロードし、解凍して、PaxPowerGlove.unityを開く。
#ref(PaxPowerGloveUnity.zip)

**動作確認
+Unityの再生ボタンを押す。
+パワーグローブを傾けてみて、手のモデルが動けば成功!~
動かない場合は、Arduino本体のリセットボタンを押してみてください。

~

お疲れ様でした。 :)

**【参考】Unity用C#スクリプト(上記PaxPowerGlove.zipに含まれています)
#code(C,nonumber,nooutline,ControlHandByPaxPowerGloveAndMPU9150InUnity.cs)

*手順4.XBeeによる無線通信
#ref(xbee.jpg,right,around,33%)
上記までは有線で通信をしていましたが、近接無線通信モジュールXBeeを使って無線通信をしてみます。

詳細は [[../XBee]] をご覧ください。
#clear

*手順5.3と4の統合
さあついに、上記3と4を統合します。

+先ほどのArduinoスケッチを次のように修正する。~
(unidiff風に書いています。要するに先頭が-の行を削除して、先頭が+の行を追加するだけです。)
#code(C,nonumber,nooutline){{
    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        Wire.begin();
-        TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
+        TWBR = 12; // for Arduino Fio
}}
#code(C,nonumber,nooutline){{
    // initialize serial communication
    // (115200 chosen because it is required for Teapot Demo output, but it's
    // really up to you depending on your project)
-    Serial.begin(115200);
+    Serial.begin(57600); // for Arduino Fio
}}


*手順6.振動モーターによるハプティック(触覚フィードバック)の実現
**ハードウェアの準備
#ref(vibrate_circuit.png,right,around,25%)
右図のような回路を5本分用意する。
#clear

**ソフトウェアの準備
執筆中。
#code(C,nonumber,nooutline){{
char c = Serial.read();
if (c != -1) {
  c -= '0';
  for (int i = 0; i < 5; i++) {
    if ((c & 0b00010000) != 0) {
        digitalWrite(3, HIGH);
    }
    if ((c & 0b00001000) != 0) {
        digitalWrite(4, HIGH);
    }
    if ((c & 0b00000100) != 0) {
        digitalWrite(5, HIGH);
    }
    delay(7);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    digitalWrite(5, LOW);
    if ((c & 0b00000010) != 0) {
        digitalWrite(6, HIGH);
    }
    if ((c & 0b00000001) != 0) {
        digitalWrite(7, HIGH);
    }
    delay(7);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
  }
}
}}

*手順7.5と6の統合
執筆中。

*備考
SerialPort.ReadLine()をUpdate()内で使うと遅延が大きく、使い物になりません。

今回はMSDNの記述にしたがって、別スレッドでReadLine()しています。

*パワーグローブを入手できない場合
市販の手袋に[[スイッチサイエンスの曲げセンサSEN-08606>http://www.amazon.co.jp/exec/obidos/ASIN/B009ARJD34/cubic9com-22]]を接着するとよいかもしれません。

*プロトタイプからの変遷
#ref(powerglove01.jpg,around,33%)
#ref(powerglove02.jpg,around,33%)
#ref(powerglove03.jpg,around,33%)
#clear

*参考
-[[Power Glove を楽器にする - Radium Software>http://d.hatena.ne.jp/KZR/20090817/p1]]
-[[PowerGloveの解析>http://nagasm.org/ASL/globe/]]
-[[Arduino でモータを動かす:息子と一緒に Makers:So-netブログ>http://makers-with-myson.blog.so-net.ne.jp/2013-11-11]]

*Amazon
#amazon(B003LJK77I,left)
#amazon(B01CE4D0U6,left)
#amazon(4800711460,left)
#amazon(4873117895,left)
#amazon(4797393521,left)
差分 一覧