前にUnityとArduinoをSerialで連携させるのをやってみました。
今度は照度センサではなく、加速度センサを連携させてUnity上の立方体をぐりぐり動かすというのをやっていこうと思います。
1:材料/開発環境
■開発環境
■材料
- Arduino Uno
- KXSC7-2050(加速度センサ)
- USBケーブル(ArduinoとPCを繋ぐもの)
- ブレッドボード
2:Arduino側の準備
以下のように回路を組みます。加速度センサのデータシート通りの回路です。
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を追加します。
位置やフォントサイズなどを適宜調節して画面上で見えるようにします。
自分は以下のように設定しました。
続いてHierarchyで右クリックをし、3D Object→Cubeを選択してCubeを追加します。
このCubeの位置や大きさなども適宜調節します。
自分は以下のように設定しました。
5:加速度の値を反映させるための空のGameObjectを作成する
Hierarchyで右クリックをし、Create Emptyを選択してからのGameObjectを追加し、名前を「SerialCube」に変更します。
次に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」にドラッグ&ドロップして追加します。
追加したらHierarchyの「SerialCube」を選択し、InspectorにあるSerialHander、Text、CubeにそれぞれのGameObjectを設定します。
6:Unityで実行する
ArduinoとPCをUSBケーブルで接続した状態で作成したUnityのプロジェクトを実行します。
加速度センサを傾けると以下のようにUnity上のCubeも傾きます。
楽しい(楽しい) pic.twitter.com/HrHjwWj455
— シン・ほいっぷ (@sin_deviding) 2018年2月8日
以上がUnityと加速度センサを連携してみた結果です。
現実の傾きと画面上の傾きが連動するというただそれだけですが、実際にやってみるとなかなか楽しかったです。
・参考資料