ソースに絡まるエスカルゴ

貧弱プログラマの外部記憶装置です。

【Unity/Arduino】UnityとArduinoの加速度センサを連携してみた

rikoubou.hatenablog.com

 前にUnityとArduinoをSerialで連携させるのをやってみました。

 今度は照度センサではなく、加速度センサを連携させてUnity上の立方体をぐりぐり動かすというのをやっていこうと思います。


1:材料/開発環境
■開発環境

■材料


2:Arduino側の準備
 以下のように回路を組みます。加速度センサのデータシート通りの回路です。
f:id:rikoubou:20180208161502p:plain

 ArduinoUnoに以下のスケッチを書き込みます。

/**
 * Arduino UnoでのKXSC7-2050加速度センサーのスケッチ
 */
const int X_PIN = A3;
const int Y_PIN = A4;
const int Z_PIN = A5;

/* 加速度センサの値の構造体 */
struct Coordinate {
  long cx;
  long cy;
  long cz;
};

/* 角度の構造体 */
struct Angle {
  int ax;
  int ay;
  int az;
};

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

void loop() {
  Coordinate c = getCoordinate();
  // showCoordinate(c); // ここのコメントアウトを外して最大値・最小値を記録してください
  Angle a = angleCalculation(c);
  showAngle(a);

  delay(50) ;
}

/**
 * 加速度センサーの値を取得する関数
 */
Coordinate getCoordinate() {
  Coordinate c;
  long x = 0, y = 0, z = 0;

  // 各データを100回読込んで平均化する
  for (int i = 0; i < 100; i++) {
    x = x + analogRead(X_PIN);  // X軸を読込む
    y = y + analogRead(Y_PIN);  // Y軸を読込む
    z = z + analogRead(Z_PIN);  // Z軸を読込む
  }

  c.cx = x / 100;
  c.cy = y / 100;
  c.cz = z / 100;
  return c;
}

/**
 * センサの値から各座標の角度を計算する関数
 */
Angle angleCalculation(Coordinate c){
  // 以下のx,y,zの最大値最小値は各自で測定してください
  int MAX_X = 524, MAX_Y = 514, MAX_Z = 526;
  int MIN_X = 222, MIN_Y = 214, MIN_Z = 227;

  // 各座標の1度あたりの角度を計算
  float oneAngleX = (MAX_X - MIN_X) / 180.000;
  float oneAngleY = (MAX_Y - MIN_Y) / 180.000;
  float oneAngleZ = (MAX_Z - MIN_Z) / 180.000;

  // 各座標の角度を計算
  Angle a;
  a.ax = (c.cx - MIN_X) / oneAngleX - 90;
  a.ay = (c.cy - MIN_Y) / oneAngleY - 90;
  a.az = (c.cz - MIN_Z) / oneAngleZ - 90;
  return a;
}

/**
 * 角度を表示する関数
 */
void showAngle(Angle a) {
  Serial.print(a.ax);
  Serial.print(",");
  Serial.print(a.ay);
  Serial.print(",");
  Serial.println(a.az);
}

/**
 * 加速度センサーの値を表示する関数
 */
void showCoordinate(Coordinate c) {
  Serial.print("x:");
  Serial.print(c.cx);
  Serial.print(" y:");
  Serial.print(c.cy);
  Serial.print(" z:");
  Serial.println(c.cz);
}

 Aduino IDEのシリアルモニタを立ち上げて「115200bps」を選択するとコンマ区切りでx,y,zの角度が表示されます。

 角度を計算する関数「angleCalculation」での各座標の最大値、最小値が環境によってブレがあるので、loop関数内でコメントアウトしてあるところを有効にし、加速度センサを傾けて各自で計測して書き換えてください。


3:Unity側のシリアル読み込み準備
rikoubou.hatenablog.com
 前回の記事の3、4の手順でSerialHandlerのスクリプトをアタッチさせたGame Objectまで作成します。


4:TextとCubeを追加する
 Hierarchyで右クリックをし、UI→Textを選択してTextを追加します。
f:id:rikoubou:20180208172027p:plain

 位置やフォントサイズなどを適宜調節して画面上で見えるようにします。
 自分は以下のように設定しました。
f:id:rikoubou:20180208172308p:plain

 続いてHierarchyで右クリックをし、3D Object→Cubeを選択してCubeを追加します。
f:id:rikoubou:20180208172349p:plain

 このCubeの位置や大きさなども適宜調節します。
 自分は以下のように設定しました。
f:id:rikoubou:20180208172634p:plain


5:加速度の値を反映させるための空のGameObjectを作成する
 Hierarchyで右クリックをし、Create Emptyを選択してからのGameObjectを追加し、名前を「SerialCube」に変更します。
f:id:rikoubou:20180208172759p:plain

 次にScriptフォルダを右クリックし、Create→C# Scriptを選択して「SerialCube」という名前でスクリプトファイルを作成します。

 SerialCubeを開いて以下のソースコードを記述します。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class SerialCube : MonoBehaviour {

	public SerialHandler serialHandler;
	public Text text;
	public GameObject cube;

	// Use this for initialization
	void Start () {
		//信号を受信したときに、そのメッセージの処理を行う
		serialHandler.OnDataReceived += OnDataReceived;
	}

	// Update is called once per frame
	void Update () {

	}

	/*
	 * シリアルを受け取った時の処理
	 */
	void OnDataReceived(string message) {
		try {
			string[] angles = message.Split(',');
			text.text = "x:" + angles[0] + "\n" + "y:" + angles[1] + "\n" + "z:" + angles[2] + "\n"; // シリアルの値をテキストに表示

			// Vectorは前から順番にx,y,zだけど、そのままセットすると
			// Unity上の回転の見た目が変になるので、y,zの値を入れ替えている。
			Vector3 angle = new Vector3(float.Parse(angles[0]), float.Parse(angles[2]), float.Parse(angles[1]));
			cube.transform.rotation = Quaternion.Euler(angle);
		} catch (System.Exception e) {
			Debug.LogWarning(e.Message);
		}
	}
}

 SerialCubeの記述が完了したら、SerialCubeのソースをHierarchyの「SerialCube」にドラッグ&ドロップして追加します。
f:id:rikoubou:20180208173409p:plain

 追加したらHierarchyの「SerialCube」を選択し、InspectorにあるSerialHander、Text、CubeにそれぞれのGameObjectを設定します。
f:id:rikoubou:20180208173503p:plain


6:Unityで実行する
 ArduinoとPCをUSBケーブルで接続した状態で作成したUnityのプロジェクトを実行します。
 加速度センサを傾けると以下のようにUnity上のCubeも傾きます。


 以上がUnityと加速度センサを連携してみた結果です。
 現実の傾きと画面上の傾きが連動するというただそれだけですが、実際にやってみるとなかなか楽しかったです。


・参考資料