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

PaxPowerGlove_enはてなブックマーク

日本語ページはこちら


powerglove04.jpg

I want to touch objects in virtual space.


So I set motion sensor in PAX Power Glove, a legendary NES controller, to control the movement of my hand in the virtual space of Unity .



The original Power Glove generate ultrasonic waves from the two ultrasonic transducers at different times to realize the motion capture.

That idea was great. But it lacked accuracy. So I decided to use motion sensor.

I used only flex sensor, out of original components.


So I set motion sensor in PAX Power Glove, a legendary NES controller, to control the movement of my hand in the virtual space of Unity .

board.jpg

I made that with following procedure.

  1. getting value of bending of fingers.
  2. detecting the movement of my hand with motion sensor.
  3. Integrating 1 and 2.
  4. communication by XBee.
  5. Integrating 3 and 4.
  6. realizing haptics with vibration motor.
  7. Integrating 5 and 6.

NOTICE: Oh, Don't you have PowerGlove? Try "DroidGlove"!

Materials

Hardware

Item
Arduino
PAX PowerGlove
Resistance (100k ohm * 4)
MPU-9150

Software

Item
Arduino IDE
Unity3d
I2C Device Library
C# script for Unity3d

1.detecting the movement of my hand with motion sensor.

Hardware

powerglove_circuit.png
  1. Remove solder. Take off wires from board.
  2. Connect red wires to GND.
  3. Connect Other wires to resistance to Arduino's 5V. Connect Analog input between wire and resistance.
    fingerwireanalog input
    thumbblueA0
    index fingerblackA1
    middle fingerwhiteA2
    ring fingerbrownA3
    littte fingerno wire-

Software

  1. Write following sketch to Arduino.

Arduino sketch

filePowerGlove.ino
int fingers[4];

void setup() {
  Serial.begin(9600);
}

void loop() {
  int i;
  fingers[0] = constrain(map(analogRead(A0), 678, 760, 0, 10), 0, 10) * 10;
  fingers[1] = constrain(map(analogRead(A1), 835, 935, 0, 10), 0, 10) * 10;
  fingers[2] = constrain(map(analogRead(A2), 770, 905, 0, 10), 0, 10) * 10;
  fingers[3] = constrain(map(analogRead(A3), 750, 910, 0, 10), 0, 10) * 10;

  for (i = 0; i < 4; i++) {
    Serial.print("finger");
    Serial.print(i);
    Serial.print(":");
    Serial.print(fingers[i]);
    Serial.print("\t");
  }
  Serial.println();
  delay(200);
}

NOTE: resistance may be different with your PowerGlove.

2.detecting the movement of my hand with motion sensor.

for details, see ../モーションセンサ. (written in Japanese)

3.Integrating 1 and 2.

Hardware

  1. Integrate circuit of 1 and 2.

Software(1):Arduino sketch

  1. Modify sketch, which you made at ../モーションセンサ.
  2. Modify line 286-297.
            #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

Software (2):Unity project

  1. Download following zip, and open PaxPowerGlove.unity.

C# script for Unity3d (PaxPowerGlove.zip include this.)

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

public class ControlHandByPaxPowerGloveAndMPU9150InUnity : 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();

    private static int[] _fingerVal = new int[4];
    private GameObject[,] _fingerObject = new GameObject[5,3];

    void Start() {
        _fingerObject[0,2] = GameObject.Find ("Finger0_3Dummy");
        _fingerObject[0,1] = GameObject.Find ("Finger0_3Dummy/Finger0_2Dummy");
        _fingerObject[0,0] = GameObject.Find ("Finger0_3Dummy/Finger0_2Dummy/Finger0_1Dummy");
        _fingerObject[1,2] = GameObject.Find ("Finger1_3Dummy");
        _fingerObject[1,1] = GameObject.Find ("Finger1_3Dummy/Finger1_2Dummy");
        _fingerObject[1,0] = GameObject.Find ("Finger1_3Dummy/Finger1_2Dummy/Finger1_1Dummy");
        _fingerObject[2,2] = GameObject.Find ("Finger2_3Dummy");
        _fingerObject[2,1] = GameObject.Find ("Finger2_3Dummy/Finger2_2Dummy");
        _fingerObject[2,0] = GameObject.Find ("Finger2_3Dummy/Finger2_2Dummy/Finger2_1Dummy");
        _fingerObject[3,2] = GameObject.Find ("Finger3_3Dummy");
        _fingerObject[3,1] = GameObject.Find ("Finger3_3Dummy/Finger3_2Dummy");
        _fingerObject[3,0] = GameObject.Find ("Finger3_3Dummy/Finger3_2Dummy/Finger3_1Dummy");
        _fingerObject[4,2] = GameObject.Find ("Finger4_3Dummy");
        _fingerObject[4,1] = GameObject.Find ("Finger4_3Dummy/Finger4_2Dummy");
        _fingerObject[4,0] = GameObject.Find ("Finger4_3Dummy/Finger4_2Dummy/Finger4_1Dummy");

        _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;

        _fingerObject[0,2].transform.localRotation = Quaternion.Euler (_fingerVal [0], -40, 60);
        _fingerObject[0,1].transform.localRotation = Quaternion.Euler (_fingerVal [0], 0, 0);
        _fingerObject[0,0].transform.localRotation = Quaternion.Euler (_fingerVal [0], 0, 0);
        _fingerObject[1,2].transform.localRotation = Quaternion.Euler (_fingerVal [1], 0, 0);
        _fingerObject[1,1].transform.localRotation = Quaternion.Euler (_fingerVal [1], 0, 0);
        _fingerObject[1,0].transform.localRotation = Quaternion.Euler (_fingerVal [1], 0, 0);
        _fingerObject[2,2].transform.localRotation = Quaternion.Euler (_fingerVal [2], 0, 0);
        _fingerObject[2,1].transform.localRotation = Quaternion.Euler (_fingerVal [2], 0, 0);
        _fingerObject[2,0].transform.localRotation = Quaternion.Euler (_fingerVal [2], 0, 0);
        _fingerObject[3,2].transform.localRotation = Quaternion.Euler (_fingerVal [3], 0, 0);
        _fingerObject[3,1].transform.localRotation = Quaternion.Euler (_fingerVal [3], 0, 0);
        _fingerObject[3,0].transform.localRotation = Quaternion.Euler (_fingerVal [3], 0, 0);
        _fingerObject[4,2].transform.localRotation = Quaternion.Euler (_fingerVal [3], 0, 0);
        _fingerObject[4,1].transform.localRotation = Quaternion.Euler (_fingerVal [3], 0, 0);
        _fingerObject[4,0].transform.localRotation = Quaternion.Euler (_fingerVal [3], 0, 0);
    }

    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);
                        _fingerVal[0] = int.Parse(values[5]);
                        _fingerVal[1] = int.Parse(values[6]);
                        _fingerVal[2] = int.Parse(values[7]);
                        _fingerVal[3] = int.Parse(values[8]);
                    }
                } catch (TimeoutException) {
                }
            }
            Thread.Sleep(1);
        }
    }
}

4.communication by XBee.

xbee.jpg

for details, see ../XBee. (written in Japanese)

5.Integrating 3 and 4.

  1. Modify Arduino sketch.
        #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
            Wire.begin();
    -        TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
    +        TWBR = 12; // for Arduino Fio
    
        // 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
    
  1. 6.realizing haptics with vibration motor.

Hardware

vibrate_circuit.png

Software

W.I.P.

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);
  }
}
  1. 7.Integrating 5 and 6. W.I.P.

Prototypes

powerglove01.jpg
powerglove02.jpg
powerglove03.jpg

Reference

Amazon

差分 一覧