【Unity】Arduino Uno R4 Minimaとシリアル通信しようとしたらできなかった話
はじめに
Unityにおいて、Arduino等のマイコンをコントローラーとして利用する事例は多いと思います。 私も同じようなことをやりたいと考え、最新版のArduinoであるArduino Uno R4 Minimaとのシリアル通信の検証を行いました。
結論
UnityとArduino Uno R4 Minimaとのシリアル通信は実現できませんでした。 代わりにArduino Nanoの最新版であるArduino Nano Everyを用いた場合、従来のコードでシリアル通信できました。
やりたいこと
Arduinoに接続したジャイロセンサ(BMX055)の値をシリアル通信でUnityに送ります。Unity側でジャイロセンサの姿勢を用いてゲームを実装します。 今回はArduino-Unity間の通信のみにフォーカスを当てます。 使用するArduinoには最新のArduino Uno R4 Minimaを何も考えずに採用しました。これが誤りでした。
実装
Unity
バージョン: 2021.3.36f1
Unity側の下の記事を参考にさせていただきました。感謝いたします。
https://qiita.com/yjiro0403/items/54e9518b5624c0030531
一応ソースコードを貼っておきます。 Serial通信の実装部分であるSerialHandlerとそれを呼び出すSerialReceiverがあります。 両方ともコンポーネントにアタッチした上で、SerialReceiverのpublicにSerialHandlerをアタッチします。
SerialHandler.csusing UnityEngine; using System.Collections; using System.IO.Ports; using System.Threading; public class SerialHandler : MonoBehaviour { public delegate void SerialDataReceivedEventHandler(string message); public event SerialDataReceivedEventHandler OnDataReceived; public string portName = "/dev/tty.usbmodem101"; public int baudRate = 9600; private SerialPort serialPort_; private Thread thread_; private bool isRunning_ = false; private string message_; private bool isNewMessageReceived_ = false; void Awake() { Open(); } void Update() { if (isNewMessageReceived_) { OnDataReceived(message_); } } void OnDestroy() { Close(); } private void Open() { serialPort_ = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One); serialPort_.Open(); isRunning_ = true; thread_ = new Thread(Read); thread_.Start(); } private void Close() { isRunning_ = false; if (thread_ != null && thread_.IsAlive) { thread_.Join(); } if (serialPort_ != null && serialPort_.IsOpen) { serialPort_.Close(); serialPort_.Dispose(); } } private void Read() { while (isRunning_ && serialPort_ != null && serialPort_.IsOpen) { try { if (serialPort_.BytesToRead > 0) { message_ = serialPort_.ReadLine(); isNewMessageReceived_ = true; } } catch (System.Exception e) { Debug.LogWarning(e.Message); } } } public void Write(string message) { try { serialPort_.Write(message); } catch (System.Exception e) { Debug.LogWarning(e.Message); } } }
SerialReceiver.csusing System.Collections; using System.Collections.Generic; using UnityEngine; public class SerialReceiver : MonoBehaviour { public SerialHandler serialHandler; public RotateController rotateController; void Start() { serialHandler.OnDataReceived += OnDataReceived; } void Update() { } //受信した信号(message)に対する処理 void OnDataReceived(string message) { try { Debug.Log("received: " + message); } catch (System.Exception e) { Debug.LogWarning(e.Message); } } }
Arduino
テスト用のシリアル通信のコードです。「Hello from Arduino!」と1秒おきに送信します。
serialTest.inovoid setup() { Serial.begin(9600); } void loop() { Serial.print("Hello from Arduino!"); Serial.println(""); delay(1000); }
検証
ArduinoとUnityの通信速度とシリアルポートが一致していることを確認します。 Unityを実行します。
Arduino Uno R4 Minima
まずはUno R4 Minimaから。
はい。
うんともすんとも言いません。 シリアルポートは認識しているようなのですが、実際のデータを受信できていないようです。
下の記事を見させていただいたのですが、Uno R4 Minimaは以前のArduinoとは異なる部分が多いようです。 シリアル通信のプロトコルにも影響があるのではと仮説を立てました。
https://note.com/electric_mecha60/n/nbee952a948a9
Arduino Nano Every
昔ながらのArduino Nanoの最新版Nano Everyで試してみます。
なんということでしょう。いとも簡単にシリアル通信できたではありませんか。
おわりに
今回は、Arduino Uno R4 MinimaとUnityの間でのシリアル通信を試みましたが失敗に終わりました。 結論としては失敗の原因は分かっておらず、R4 MinimaとUnity特有の仕様が影響しているからだと考えられます(Arduino IDEのシリアルモニタでは確認できる)。 これに関する研究は継続しますが、一旦は Arduino Nano Everyへの乗り換えという形で進めようと思います。
最後までご閲覧いただきありがとうございました。