[Unity 進階] RFID 整合:Arduino MFRC522 感應控制影片播放

2024.05.05 / Unity 引擎
RFID 是一門被廣泛應用的感測技術,我們的門禁卡、悠遊卡、愛金卡、全聯福利卡…等感應媒介中都裝有 RFID 的晶片。在本文中,我們將使用 Arduino 與 Unity 來實作一套互動系統,系統可以藉由感應器來辨識使用者的 RFID 卡片內部資訊,並於螢幕上播放對應的影片。這個系統可以應用在許多互動裝置設計的專題上,只要先規劃好作品的核心理念並製作數個良好的動畫影片,再配合 Unity 腳本來設計互動流程,即可設計出一套有品質的互動裝置作品。

本文所使用之資源來自於國立雲林科技大學數位媒體設計系互動多媒體實驗室。

前言

RFID 是一門很成熟的非接觸式技術,在我們的日常生活中已被廣泛應用。早上出門時,首先可能會刷門禁卡;搭公車或捷運時,要刷悠遊卡;到超商買早餐時,也能用悠遊卡或愛金卡 (icash) 結帳;晚上到全聯補充日用品時,感應福利卡即可累積點數;行車經過高速公路 ETC 收費點時,上方的感測器將藉由感應車輛前擋風玻璃上的 eTag 貼紙中的車輛資訊來收取過路費……,這些都是 RFID 的很常見的應用案例。

另一特別的例子是日本的 Uniqlo 商場, Uniqlo 的衣服中藏了一張 RFID 晶片,使用者只要將所有要購買的衣服一股腦兒的放到感應區中,旁邊的結帳螢幕就會自動將所有品項條列出來並顯示價格,使用者就能用信用卡、行動支付等方式進行自助結帳,能夠減少使用者的排隊時間與店面的管理成本。

RFID 介紹

RFID 是「Radio Frequency Identification」的縮寫,中文翻譯成無線射頻識別系統,是由感應器與標籤組成的一套非接觸式系統。RFID 始於 1940 年代,是英國於二次大戰期間為了要能有效辨識領空中的戰機是敵是友而發明的技術。

RFID 的基本運作原理主要是讓標籤接收感應器發送的無線電波,藉由電磁感應作用讓標籤中的線圈產生電流,讓晶片運作並產生夾帶標籤資料的電波來回應感應器,達到交換資料的目的。如用標籤的電源驅動方式進行分類,RFID 標籤可被分為主動式、被動式與半被動式三種:

一、主動式標籤

主動式標籤的是成本最高的 RFID 種類,這種標籤中配備了電池或具有能連接外部電源的特性,讓晶片可以在沒有接收感應器的電波時還仍能夠正常運作。主動式 RFID 能承載的儲存空間和感應距離是三種標籤類型中最優秀的。但因為價格比較高,這種標籤在我們日常生活中會比較少見到,一般只會應用在高價物品、汽車或軍用設備上。

二、被動式標籤

被動式標籤是最常見的 RFID 種類,它的內部不具備電池,用來驅動晶片的電源完全依靠感應器提供的電流。這種標籤具有價格低、體積小、重量輕、壽命長的優勢,我們常用的各式感應卡片都是這種標籤的應用。

由於被動式標籤需藉由感應器提供電流,因此具有最嚴格的感應區域限制。

三、半被動式標籤

半被動式標籤同時具備了主動式與被動式標籤的特點,這種標籤內部配有電池,可以解決感應器所產生的電流不足時無法運作的問題,不受到感應器的電波強弱影響。半被動式標籤的感應距離與反應速度都比被動式標籤還要更長、更快,價格也落在主動式與被動式標籤之間。

開發工具

在這篇文章中,我們將使用成本最低的被動式標籤來實作,請見以下開發工具說明。

Arduino 開發板

Arduino 是一套軟硬體皆開源的開發工具,開發板上已內建了處理輸入輸出的處理單元和方便我們連接各種電子元件或擴充模組的 PIN 腳位。在本文的實作中,我們會使用到 Arduino UNO 開發板,並搭配 MFRC522 模組進行 RFID 標籤的辨識。如欲購買可參考:iCShop (蝦皮)

MFRC522 模組

MFRC522 是一個價格低廉的 RFID 讀取器,可感應 13.56MHz 頻率的 RFID 標籤,一件約 100 多元新台幣,非常適合用於實驗或專題實作。如欲購買可參考:傑森創工 (蝦皮)

13.56MHz RFID 標籤

由於本文使用的 MFRC522 讀取器僅支援 13.56MHz 頻率,因此我們也只能採用相同頻率的 RFID 標籤。常見的 RFID 標籤外觀有像是鑰匙圈或卡片型。應用於互動裝置設計時,卡片型因為輕薄且好隱藏,很適合用來塞進互動物件中。如欲購買可參考:iCShop (蝦皮)

實作步驟

連接 Arduino 與 MFRC522 電路

MFRC522 模組總共有八個腳位,分別是 SDA、SCK、MOSI、MISO、IRQ、GND、RST、3.3V。請以下列方法連接 MFRC522 模組與 Arduino 開發板,一律使用數位輸入。

MFRC522 腳位Arduino 腳位
SDA10
SCK13
MOSI11
MISO12
IRQ不用連接
GNDGND
RST9
3.3V3.3V

安裝 MFRC522 模組函式庫

開啟 Arduino IDE,點擊左側像是書架的按鈕進入 Library Manager,搜尋「MFRC522」安裝作者為 GithubCommunity 的 MFRC522 專用套件。

撰寫 Arduino 程式碼

複製貼上以下程式碼,並燒錄至 Arduino UNO 開發板中。

#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN 10
#define RST_PIN 9
 
MFRC522 rfid(SS_PIN, RST_PIN);

MFRC522::MIFARE_Key key; 

byte nuidPICC[4];

void setup() { 
  Serial.begin(9600);
  SPI.begin();
  rfid.PCD_Init();

  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;
  }

  Serial.println(F("This code scan the MIFARE Classsic NUID."));
  Serial.print(F("Using the following key:"));
  printHex(key.keyByte, MFRC522::MF_KEY_SIZE);
  Serial.println();
}
 
void loop() {
  if (!rfid.PICC_IsNewCardPresent())
    return;

  if (!rfid.PICC_ReadCardSerial())
    return;

  MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);

  if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI &&  
    piccType != MFRC522::PICC_TYPE_MIFARE_1K &&
    piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
    Serial.println(F("Your tag is not of type MIFARE Classic."));
    return;
  }

  printHex(rfid.uid.uidByte, rfid.uid.size);
  Serial.println();

  rfid.PICC_HaltA();

  rfid.PCD_StopCrypto1();
}

void printHex(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : "");
    Serial.print(buffer[i], HEX);
  }
}

安裝 Ardity 套件

建立一個新的 Unity 專案,並進入 Project Settings > Player > Other Settings,修改 Api Compatibility Level 設定為 .NET Framework。

前往 Ardity 官網,點擊左邊的「Download the Unity Package」下載套件檔案。

回到 Unity 編輯器,執行 Assets > Import Package > Custom Package 來準備匯入自訂套件。

選擇下載到的 Ardity.unitypackage 並點擊「開啟」。

匯入 MP4 影片

準備至少兩部格式為 MP4 的影片,可以到 Pixabay 等免費圖庫網站中搜尋。接下來在 Project 面板中點擊滑鼠右鍵 > Import New Asset。

選擇多個 MP4 影片檔案並點擊「Import」。

撰寫 Unity C# 腳本

在 Project 面板空白處點擊滑鼠右鍵 > Create > C# Script,並命名為 ArduinoManager。

01. 接收 Arduino 序列埠資料

建立 SerialController 公開變數,並在 Update 方法中讀取 Serial 訊息。如果讀取到的資料為空字串或 Null 時,跳過這次週期不繼續執行,反之在 Console 中列印讀取到的訊息。

 1using UnityEngine;
 2
 3public class ArduinoManager : MonoBehaviour
 4{
 5    public SerialController serialController;
 6
 7    private void Update()
 8    {
 9        var msg = serialController.ReadSerialMessage();
10        if (string.IsNullOrEmpty(msg))
11            return;
12
13        Debug.Log(msg);
14    }
15}

02. 建立 RFID 卡片與影片的配對資料

建立一個可序列化的類別 Card,並加入用來存放 RFID 編號和影片檔案的成員,最後在 ArduinoManager 中建立一個 Card 類別的 List。

 1using System.Collections.Generic;
 2using UnityEngine;
 3using UnityEngine.Video;
 4
 5[System.Serializable]
 6public class Card
 7{
 8    public string uuid;
 9    public VideoClip clip;
10}
11
12public class ArduinoManager : MonoBehaviour
13{
14    public List<Card> cardList;
15    public SerialController serialController;
16
17    private void Update()
18    {
19        var msg = serialController.ReadSerialMessage();
20        if (string.IsNullOrEmpty(msg))
21            return;
22
23        Debug.Log(msg);
24    }
25}

03. 感應 RFID 卡片時播放影片

最後的步驟是將所有程式碼串在一起。首先建立一個 VideoPlayer 公開變數,並在成功讀取到 RFID 資料時,先將字串進行 Trim 後,再用 LinQ 尋找相符的 Card 物件。如果有找到有效的物件,先停止影片播放,接著修改影片檔案來源,最後再播放影片。

 1using System.Collections.Generic;
 2using System.Linq;
 3using UnityEngine;
 4using UnityEngine.Video;
 5
 6[System.Serializable]
 7public class Card
 8{
 9    public string uuid;
10    public VideoClip clip;
11}
12
13public class ArduinoManager : MonoBehaviour
14{
15    public VideoPlayer player;
16    public List<Card> cardList;
17    public SerialController serialController;
18
19    private void Update()
20    {
21        var msg = serialController.ReadSerialMessage();
22        if (string.IsNullOrEmpty(msg))
23            return;
24
25        Debug.Log(msg);
26
27        var card = cardList.FirstOrDefault(x => x.uuid == msg.Trim());
28        if (card is null)
29            return;
30
31        player.Stop();
32        player.clip = card.clip;
33        player.Play();
34    }
35}

建立場景物件

回到 Unity 編輯器,在 Hierarchy 面板空白處點擊滑鼠右鍵 > Create Empty,先建立一個名為 ArduinoManager 的空物件,再點擊 ArduinoManager 物件的 Inspector 面板的 Add Component 按鈕,搜尋「Serial」加入 SerialComponent 元件,也用同樣方法加入 ArduinoManager 元件。

現在 ArduinoManager 物件中應該要存在 SerialController 和 ArduinoManager 兩個元件。

再次到 Hierarchy 面板空白處點擊滑鼠右鍵 > Video > Video Player,並修改以下 Video Player 的設定:

  1. 取消勾選 Play On Awake。
  2. 修改 Render Mode 為 Camera Far Plane。
  3. 拖拉場景中的 Main Camera 到 Camera 欄位。

回到 ArduinoManager 物件的 Inspector,首先修改 SerialController 的 Port Name 為 Arduino 連接的連接埠名稱,再拖拉場景上的 VideoPlayer 物件到 Player 欄位、拖拉同物件的 SerialContrller 元件到 Serial Contrller 欄位。

最後在 Card List 欄位中建立數個配對資料,分別於 Uuid 中填入 RFID 的標籤編號、從 Project 面板中拖拉影片到 Clip 欄位。

總結

最後執行 Unity 專案,你應該要能觀察到以下功能正常運作:

  1. 拿 RFID 標籤靠近 MFRC522 時,Unity 中應會在 Console 中列印 RFID 標籤的數值。
  2. 拿 RFID 標籤靠近 MFRC522 時,如果剛才有建立有效的配對資料,Unity 應會播放對應的影片。

如果發生感應後沒反應的問題,請檢查:

  1. Arduino IDE 的 Serial Monitor 有沒有關閉。
  2. 連接 Arduino 與 MFRC522 的線路是否正確或連接線故障。
  3. SerialController 元件的 Port Name 有沒有填寫正確。

參考資料

相關文章

Ted Liou

雲科碩士在讀中,專注於 Unity C#、TouchDesigner 技術,常把技術筆記分享到部落格,偶爾還直接挪用文章來當教材的研究生。