投稿日更新日

【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.cs
using 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.cs
using 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.ino
void 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への乗り換えという形で進めようと思います。

最後までご閲覧いただきありがとうございました。

関連記事

に投稿

【Unity】MediaPipeUnityPluginを使って超簡単に指認識をM1 Macで試す

に投稿

【Unity】M1 Macで"The Progressive CPU lightmapper is not supported on Apple silicon, switching to the Progressive GPU lightmapper."と警告が出たときの対処法

に投稿

【DOTS】Unity Physicsで大量のオブジェクトの物理演算を試す

に投稿

【Unity】Mapbox SDKでマップ上の任意の緯度経度の座標にオブジェクトを配置する

に投稿

【Unity】Mapbox Maps SDK for Unityで3D地形マップを召喚する

に投稿

【DOTS】Unity Physicsの公式デモをさわってみる