iT邦幫忙

2022 iThome 鐵人賽

DAY 21
1

平常我們在實驗室會使用到一些硬體裝置,比如Arduino 或 Feather 的 Adafruit 的開發板,故需要與 Unity 做串接與一同使用,所以這邊我希望跟大家介紹如何將 Arduino 與 Unity 結合一起使用。 今天我使用的開發板是最基本的 Arduino 的 Uno 板,很常見所以也非常好上手。這邊幾個步驟就可以將其與 Unity 串接,透過 Port 來讀取該 Arduino 輸出的結果。也希望這篇幫助到需要將Unity 與 Arduino 一同使用的人有些幫助。

C# API 變更

  1. 因為需要使用 System.IO.Ports 所以需要先將 .net 版本更新。這邊到 Edit → Porject Settings → Player 中去找到 Api Comptibility Level 。並設定成 .Net 4.x

  2. 接下來就可以實際的使用到 Serial Ports 的這些在 System IO 特定的組件。 Serial Ports 就是我們要使用到電腦的Serial Port。之後請接上你的 Arduino 板。然後到裝置管理員查看一下你接的 Port 是哪一個。 我這邊是 COM 7。

撰寫腳本

  1. 新增一個空白物件 GetArduino,並且新增一個腳本 ArduinoPort。

  2. 要將我們需要使用到的函示庫引入

using UnityEngine;
using System;
using System.IO.Ports;
using System.Threadings;
  1. 接下來要設定基本參數。
string portName_1 = "COM7";    // 將板子插進的USB接口 到裝置管理員查看
int baudRate = 9600;           // 顯示的胞率
Parity parity = Parity.None;
int dataBits = 8;
StopBits stopBits = StopBits.One;
  1. 最重要的就是 SerialPort 的物件,需要取得該 Port 的參數。
SerialPort serialPort = null;
  1. 接下來要加上一個控制SerialPort 接口的關閉,這是避免Unity 在讀取數值的時候,Arduino 又要重新燒錄造成衝突或 busy的狀況發生。但我們這邊會先以 button 來控制 SerialPort 的開啟或關閉。
public int isClosedPort = 1;
  1. 一開始先開啟 Port 直接讀取該 Arduino 輸出的結果。
void Start()
{
	OpenPort();
}

OpenPort( )

  1. 獲取接口訊息並且開啟 SerialPort 接收來自Port 的訊息。
public void OpenPort()
{
	serialPort_1 = new SerialPort(portName_1, baudRate, parity, dataBits, stopBits);
	try{
		serialPort_1.Open();
		Debug.Log("Open Port Success");
	}catch(Exception ex)
	{
		Debug.Log(ex.Message);
	}
}
  • 先將正確的接口名稱設定好
serialPort_1 = new SerialPort(portName_1, baudRate, parity, dataBits, stopBits);
  • 透過 try catch 實現安全的控制Port 的開啟。
try{
		serialPort_1.Open();
		Debug.Log("Open Port Success");
	}catch(Exception ex)
	{
		Debug.Log(ex.Message);
	}
  • 完整的程式碼如下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO.Ports;
using System;
using System.Threading;


public class ArduinoPort : MonoBehaviour
{
    string portName_1 = "COM7";
    int setBaudRate = 9600;
    Parity parity = Parity.None;
    int dataBits = 8;
    StopBits stopBits = StopBits.One;

    SerialPort serialPort = null;
    public int isClosePort = 1;

    // open the port 
    void Start() 
    {
        OpenPort();
    }


    void OpenPort() 
    {
        serialPort = new SerialPort(portName_1, setBaudRate, parity, dataBits, stopBits);
        
        // check whether port is open 
        try{
            serialPort.Open();
            Debug.Log("Open Port Success...");
        }catch(Exception e)
        {
            Debug.Log(e.Message);
        }
    }


}

ClosePort( )

  1. 為了要避免衝突產生,我們要隨時的關閉 Port 讀取。要記得不可以邊 OpenPort 的期間邊進行 Arduino 的寫入,會造成錯誤。
public void ClosePort() 
    {
        try{
            serialPort_1.Close();
        }catch(Exception ex)
        {
            Debug.Log(ex.Message);
        }
    }

ReadData( )

  1. 我們需要取得該 Port 的資訊,這邊就是偵測如果 serialPort 是開啟的情況,就將Arduino 輸出的數值存入。這邊回傳的數值會是string 的樣式。所以說如果要切換成需要的 浮點數數值就需要使用 float.Parse( )。在這邊我也用UI Text 去顯示我接收到的數值。
void ReadData() 
    {
        if(serialPort.IsOpen)
        {
            string a = serialPort.ReadExisting();
            valueText.text = a;
            Thread.Sleep(500);              // delay 0.5s to read the data
            
        }
    }
  1. 回到 Unity 去設計一下 UI,將我們的 Text 放進到我們的環境中。

  2. 接下來新增兩個 Button 去控制該 Arduino Port 開啟或關閉。不要忘記要設定 function 到 Onclick 事件中。


  3. 完整的 Code。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO.Ports;
using System;
using System.Threading;
using UnityEngine.UI;

public class ArduinoPort : MonoBehaviour
{
    string portName_1 = "COM7";
    int setBaudRate = 9600;
    Parity parity = Parity.None;
    int dataBits = 8;
    StopBits stopBits = StopBits.One;

    SerialPort serialPort = null;
    public int isClosePort = 1;

    public Text showStatusTxt;
    public Text valueText;


    // open the port 
    void Start() 
    {
        OpenPort();
    }

    void Update() 
    {
        ReadData();
    }


    public void OpenPort() 
    {
        serialPort = new SerialPort(portName_1, setBaudRate, parity, dataBits, stopBits);
        
        // check whether port is open 
        try{
            serialPort.Open();
            showStatusTxt.text = "Open Port Success...";
        }catch(Exception e)
        {
            Debug.Log(e.Message);
        }
    }

    public void ClosePort() 
    {
        try{
            serialPort.Close();
            showStatusTxt.text = "Close Port Success...";
        }catch(Exception ex) 
        {
            Debug.Log(ex.Message);
        }
    }

    public void ReadData() 
    {
        if(serialPort.IsOpen)
        {
            string a = serialPort.ReadExisting();
            valueText.text = a;
            Thread.Sleep(100);              // delay 0.5s to read the data
            
        }
    }


}

Arduino 環境與執行

  1. 這邊就先將 Serial.begin 設定好Baud率在 setup 部分 (很重要否則無法有效地顯示)。
Serial.begin(9600);
  1. 接下來就是要將資料撰寫,我們寫一個讓數值增加的code,寫在 loop 裡面就會無窮進行
int p1 = 0;
void loop()
{
  Serial.println(p1++);
  delay(1000);
  if(p1== 100)
  {
    p1 = 0;
  }
  
}
  1. 整個程式碼如下
void setup() {
  Serial.begin(9600);
  
}

int count = 1;
void loop() {
  // put your main code here, to run repeatedly:
  Serial.println(count++);
  delay(1000);
  if(count == 100)
  {
    count = 0;
  }
  

}
  1. 最後進行編譯且上傳。

  2. 接下來點開 工具 > 序列監控視窗。請先務必檢查一下你們的開發板與序列是否正確,抱歉細節設定我就不細說了。

  3. 請務必點開先確認你的 Baud 是否正確,若錯誤你就看不到任何數值。

執行開始

  1. 回到 Unity 後執行就會直接讀取該在 Arduino 輸出的數值。可以看到 Console 會顯示當前從Arduino 取出數值的結果。而因為該變化比較快所以 Get Value 的數值在UI上會閃爍。但從 Console 確切知道有取得該 Arduino 的輸出。

  2. 請注意到若要停止執行前務必要將該 Port 關閉,也就是一定要按下 Close Port 的 Button,這樣在改寫Arduino 並且上傳時才不會出錯,造成Port相互的衝突。所以務必要關閉。按下 Close Port Button 後看到 Close Port Success… 代表就是成功關閉。若需要重新開啟接收Arduino Import 的數值就在點選該 Open Port 的 Button 即可。但請注意若要更改Arduino 的腳本並上船的時候請注意Unity自身的 Port 為關閉的狀態避免不必要的衝突。

  3. 今天我們成功將該 Arduino 輸出的結果取出,下次我們會結合 MPU6050 來將數值取出掛在物件上並使用! 將會很有趣XDD。

結論:

  1. 了解如何透過 Arduino 結合 Unity 將Arduino 硬體輸出的資料傳至該 Unity 環境中顯示。
  2. 注意到當兩個 Port 使用的時候其中一個必須要關閉避免造成 Port 的衝突,比如 Arduino 上傳時 Unity 必須要關閉,Unity 執行時 Arduino 不要同時上傳。

上一篇
Day20: Object Recorded
下一篇
Day22: MPU6050 Arduino to Unity
系列文
Unity 基本功能實作與日常紀錄30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言