Processing3の描画に6軸センサの動きを反映させたい



![SS 192.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565043/a41cd967-f549-8677-1efa-2e99bf69518d.png) 手に持ったモノが画面の中でも同じようにうごくやつ

<img src ="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565043/512e6e86-266f-66e1-5de3-e15fd1353b1e.gif" width = 150>

## 前回記事

https://qiita.com/Ninagawa_Izumi/items/25cc0469ef1dee8481a5

これの続きです。
いきなりDMPのセンサーフュージョンを使いたい場合は[こちらの記事](https://qiita.com/Ninagawa_Izumi/items/2646c7d3d98943919f80)へ。


## やること
手元のセンサを傾けると、画面の中のオブジェクトもシンクロして傾く、ということをします。
6軸センサーのGY-521(MPU6050)の値をarduino（手元のものはTeensy3.2）で読みとってシリアルに送信し、その結果をProcessing3の描画に反映させます。
公式のチュートリアルなどもあるようですが、さらに要素を絞って理解しやすい小さなスケッチにします。

## 6軸センサーとは？
加速度センサーは重力加速度を検知し、水平に対する傾きを捉えることができます。
ジャイロセンサーは角速度を検知し、回転の動きを捉えることができます。
それぞれxyz3軸ずつ、合計6軸のデータを検出できるのが6軸センサーです。
MPU6050のデータを使いやすく補正・加工して出力するパッケージの一つがGY-521です。

## processing3とは？
描画やアニメーションをコードによって実行するアプリケーションです。
よくArduinoといっしょに使われます。

## 準備物・実施環境
- Arduino系のもの（今回の狙いはTeensy3.2)
- processing3
- 6軸センサ　GY-521(MPU6050)
- 手元の環境はMac

## 参考
下記のサイトでシリアルの取り扱い方などを参考にさせていただきました。
ZawaWorks’s diary
http://zawaworks.hatenablog.com/entry/2018/04/26/204155


## 接続
| GY-521 | Arduino |
|:-----------|------------:|
| VCC      | 5V| 
| GND     | GND| 
| SCL       | SCL(Pin19)|
| SDA       | SDA(Pin18)|
| XDA       | none|
| AD0   | none|
| INT   | none|

SCL0はArduinoUno,Teensy3.2共にPin19です。
SDA0はArduinoUno,Teensy3.2共にPin18です。
接続は電源2本、信号2本の計4本で動きます。


## プログラム

#### Arduino系側のスケッチ

```c++:Arduino系

#include "MPU6050.h"
MPU6050 accelgyro;

int16_t ax, ay, az;//加速度　int16_tは2バイトの符号付き整数 
int16_t gx, gy, gz;//角速度　同上

void setup()
{
  Wire.begin();
  Serial.begin(115200);
  accelgyro.initialize();//I2Cデバイスの初期化
  delay(300);
}

void loop()
{
  accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  Serial.print(ax/16384.0); Serial.print(",");
  Serial.print(ay/16384.0); Serial.print(",");
  Serial.print(az/16384.0); Serial.print(",");
  Serial.print(gx/131.0); Serial.print(",");
  Serial.print(gy/131.0); Serial.print(",");
  Serial.print(gz/131.0); Serial.print(",");
  Serial.print("\n");
  delay(10);
}
```
ax, ay, azは各軸方向の加速度で、出力される+32767〜−32768の値がおよそ +2g〜−2g に対応するようです。よって値を16384.0で割るとgに近似できます。
gx, gy, gzは角速度で，出力される+32767〜−32768の値がおよそ+250°/s〜−250°/s に対応するようです。よって値を131.0で割ると°/sに近似できます。
この数値をProcessingに渡します。

### 実行

Arduino側のプログラムは以上です。実行するとシリアルモニタ上にずらりとデータが表示されるようになります。
加速度x,加速度y,加速度z,ジャイロx,ジャイロy,ジャイロz の順で書き出されます。

#### Processing側のスケッチ

```c++:Processing3
import processing.serial.*;
Serial myPort;
printArray(Serial.list());
```
まずProcessing3の画面で上記のスケッチを実行します。
Processing3のスクリプト画面の下段にあるシリアル通信のコンソール画面がに、シリアルポートのリストが出力されます。
ここで、Arduino系で使っているシリアルポートと同じものの番号を調べて控えておきます。
Arduinoで使用中のポートはArduinoSDKのメニューから「ツール」→「シリアルポート」で確認できます。


```c++:Processing3
import processing.serial.*; // シリアルライブラリをインポート

Serial myPort;  //シリアルポートのインスタンス
int available_serialport = 2; // シリアル検索プログラムで調べたシリアルポートの番号に設定数値を変更しておく
String arduinoPort = Serial.list()[available_serialport ]; //シリアルポートの設定
float []data = new float [6]; //シリアルのデータを格納する配列を宣言

void setup() {
  lights();
  size(300, 300, P3D); // キャンバスサイズ
  myPort = new Serial(this, arduinoPort, 115200); // シリアルポートの設定
}

void draw() {
  background(230); //背景グレー
  translate(width / 2, height / 2, 0); // 原点を図形の中心に
  rotateX(radians(data[0])*90); //dataの中身は重力加速度gなので、90を掛けると角度に概算できる
  rotateZ(radians(-data[1])*90); //dataの中身は重力加速度gなので、90を掛けると角度に概算できる

  int size = 10;//図形のサイズ倍率。キャンバスを大きくする時に変更可
  box(20 * size, 1 * size, 15 * size); //GY-521基盤のような直方体を描く
  translate(0, -4 * size, 0);
}

void serialEvent(Serial p) { //シリアルを監視
  String inString = myPort.readStringUntil('\n'); //データがあったら改行のところまで読み込む
  if (inString != null) { //シリアルの文字列データが何か入っていれば
    inString = trim(inString); //シリアル文字列の前後の空白を削除
    data = float(split(inString, ',')); //ピリオドで分割して配列に格納
    println(data);//受信した配列データをprocessingのコンソールに出力
  }
}
```

### 実行
前述のプログラムが入ったArduinoをPCにUSB接続した状態で、上記のProcessing3用スケッチを実行すると、画面に板が現れます。
Arduinoに接続したセンサを傾けると、画面の中の板もシンクロして傾くはずです。

今回はセンサー基盤の板の水平が上図のようになるよう設定しています。
前後（ピッチ軸）、左右（ロール軸）の傾きは検知していますが、上から見て時計回りの回転（ヨー軸）は反映させていません。

### このあと
今回はGY-521のデータをそのまま反映させましたが、基盤自体である程度の補正をおこなってくれているのですでにそこそこ使える状態になっています。
さらにセンサーの値を安定させるように数ミリ秒単位で平均をとったり、端数をまるめて安定させたりするとさらに画面とのシンクロ感や手触りがよくなると思います。

**次の記事ではMPU6050のDMP(Digital Motion Processor)という内部処理機能を利用したセンサーフュージョンを試します↓**

https://qiita.com/Ninagawa_Izumi/items/2646c7d3d98943919f80