在Arduino的世界中有一款型號為MFRC522的模組,可用來讀取一些RFID電子標籤,尤其是符合IOS14444A或是稱為Mifare規範的電子標籤,而這一種規範的電子標籤遍佈在我們的身邊,例如常見的優遊卡、一卡通、智慧信用卡、門禁卡或是學生證等等,都是屬於這類的系統,有興趣多了解一些這類的RFID的讀者可到下面筆者的部落格去看一看,應該會有一個更清楚的概念。
圖六、6-6_1 各式IOS14444A/Mifare規範電子標籤
在本實習中會示範如何使用ESP8266連接MFRC522這塊RFID讀寫器模組,並讓ESP8266以伺服器的腳色供使用者用手機等行動通信裝置連線上後,在螢幕上顯示MFRC522所讀取到的RFID電子標籤UID號碼。
RFID相關知識部落格網址:
https://htcarduino.blogspot.com/2020/06/rfid.html
◎ 功能與動作說明:
1、以ESP8266建立一無線WiFi AP存取點(即Soft--AP模式),這個AP存取點的SSID名稱為『ESP_softAP01』,而且不使用連線密碼。
2、此AP存取點內建伺服器的IP位址為:[ 192.168.4.1 ]。
3、當有客戶端(Client:手機、平板或筆電)裝置以瀏覽器連線上此伺服器時,會將接在ESP8266上的MFRC522這塊RFID讀寫器模組所讀取到的RFID電子標籤UID號碼顯示在手機瀏覽器的螢幕上。
4、如果客戶端裝置持續的連線,則系統會以固定的時間(在此為3秒)持續測試及讀取RFID電子標籤的UID號碼,並主動傳送給客戶端裝置。
圖六、6-6_2 MFRC522/RFID讀寫器模組與客戶端瀏覽器連線後預期畫面
上面的【圖六、6-6_2】是本範例程式在客戶端瀏覽器連線後預期出現的畫面,畫面的左半部是正常讀取到電子標籤或卡片的結果,一般會讀取到4個位元組的UID標籤序號值,不過目前也有一些卡片的UID是6個位元組。而右半部的內容則是讀取失敗或是沒有診測到卡片的存在,如果同一張卡片一直放在RC522模組板上也會得到同樣的結果,同樣的卡片必須拿開後再次靠近,才能再次讀取到卡片的UID值,。
◎電路圖:
圖六、6-6_3 MFRC522與NodeMcu SPI匯流排介面電路圖
圖六、6-6_4 MFRC522與WeMos D1/R2 SPI匯流排介面電路圖
上面的【圖六、6-6_3】與【圖六、6-6_4】分別是MFRC522與NodeMcu 及WeMos D1/R2 SPI匯流排介面接線的電路圖,讀者可依自己所使用的ESP8266模組種類去連線。MFRC522/RFID讀寫器模組使用的是所謂的SPI匯流排介面,它與ESP8266模組電路連接方式如下表:
/* wiring the MFRC522 to ESP8266 (ESP-12/E)
【RC522】 【ESP8266】
RST = GPIO5
SDA(SS) = GPIO4
MOSI = GPIO13
MISO = GPIO12
SCK = GPIO14
GND = GND
3.3V = 3.3V
要注意的是這塊模組的工作電壓為3.3V,如果接到5V便可能有燒毀之虞!至於NodeMcu上腳位與標準ESP8266的對應則如下所示:
【NodeMcu】 【ESP8266】
D1 = GPIO5(RST)
D2 = GPIO4 (SS)
D7 = GPIO13(MOSI)
D6 = GPIO12(MISO)
D5 = GPIO14(SCK)
◎ 程式列表與說明:
#include <ESP8266WiFi.h>
#include "index.h"
#include <SPI.h>
#include "MFRC522.h"
/* wiring the MFRC522 to ESP8266 (ESP-12)
RST = GPIO5
SDA(SS) = GPIO4
MOSI = GPIO13
MISO = GPIO12
SCK = GPIO14
GND = GND
3.3V = 3.3V
*/
#define RST_PIN 5 // RST-PIN für RC522 - RFID - SPI - Modul GPIO5
#define SS_PIN 4 // SDA-PIN für RC522 - RFID - SPI - Modul GPIO4
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
String softSsid = "ESP_softAP01";
//String softSsid = "ESP"+String(ESP.getChipId());
const char* softPassword = "12345678";
WiFiServer server(80);
String tmpString = ""; // html網頁程式字串變數
unsigned int count = 0; // 測輛次數值
int rTime=3; // 網頁更新時間
String uid="";
// 初始化程式區setup()開始 :
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println("Setting soft-AP Mode... ");
pinMode(2,OUTPUT);
boolean result=WiFi.softAP(softSsid);
if(result==true)
{
Serial.println("soft-AP ready!");
Serial.print("softAP = ");
Serial.println(softSsid);
Serial.print("softIP = ");
Serial.println(WiFi.softAPIP());
server.begin();
}
else
Serial.println("soft-AP failed");
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522
Serial.println("Ready!");
Serial.println("======================================================");
Serial.println("Scan for Card and print UID:");
digitalWrite(2,1);
} // setup()結束
// 主迴圈 loop()開始 :
void loop()
{
// Check if a client has connected
WiFiClient client = server.available();
if (!client)
return;
count++;
tmpString = MAIN_page; // 取出html網頁回應程式
tmpString.replace("%rTime%", String(rTime) ); // 帶入測量的時間值到網頁html程式中
digitalWrite(2,0);
// Look for new cards
uid="未偵測到卡片!";
for(int i=0;i<(rTime/0.05);i++) // 依照網頁更新的時間來決定是否偵測到卡片
{
if ( mfrc522.PICC_IsNewCardPresent())
{
if ( ! mfrc522.PICC_ReadCardSerial())
Serial.println("Read DIU Error!! ");
else
{
// Select one of the cards
// Show some details of the PICC (that is: the tag/card)
Serial.print("Card UID:");
dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
}
mfrc522.PICC_HaltA(); // Halt PICC
mfrc522.PCD_StopCrypto1(); // Stop encryption on PCD
}
delay(50);
}
tmpString.replace("%uid%", String(uid) ); // 帶入測量的UID到網頁html程式中
tmpString.replace("%count%", String(count) ); // 帶入測量次數
client.flush();
client.print( tmpString );
digitalWrite(2,1);
delay(500);
} // loop() 結束
// 將偵測到的卡片UID轉換至網頁變數(uid)內並顯示在Arduino IDE的監控視窗:
void dump_byte_array(byte *buffer, byte bufferSize) {
uid="";
for (byte i = 0; i < bufferSize; i++) {
if(buffer[i] < 0x10) // 如果卡號小於16(0f)在前面補0
uid+=" 0";
else
uid+=" ";
uid+=String(buffer[i],HEX);
}
Serial.println(uid);
}
const char MAIN_page[] PROGMEM = R"=====(
HTTP/1.1 200 OK
Content-Type:text/html
Connection: close
<!DOCTYPE html>
<html>
<head>
<meta name='viewport' content='width=device-width, initial-scale=1.0'/>
<meta charset='utf-8'>
<meta http-equiv='refresh' content='%rTime%'>
<style>
body {font-size:100%;}
#main {display: table; margin: auto; padding: 0 10px 0 10px; }
</style>
<title>Soft AP模式-RFID/RC522電子標籤UID讀取</title>
</head>
<body>
<div id='main'>
<h2><center>[Soft AP模式] <br>
RFID/RC522電子標籤UID讀取實習<br></center><br>
卡片UID序號 = %uid% <br>
Card UID = %uid%<br>
Count = %count%<br>
</h2>
</div>
</body>
</html>
)=====";
程式名稱:ESP_CH6_6_6_RC522.ino
在本範例的程式中會引用到兩個外部的函式庫,分別是<SPI.h>及"MFRC522.h",其中的<SPI.h>是Arduino IDE內建的程式庫,因此可以直接引用沒有問題,但是因為「MFRC522」這塊模組板並不是Arduino IDE中的標準內建元件,所以必須另外加裝相關的函示庫之後才能引用。上面程式中第4、5行便是宣告引用了<SPI.h>與"MFRC522.h"這兩個函式庫。
4. #include <SPI.h> // 引入<SPI.h>函式庫
5. #include "MFRC522.h" // 引入"MFRC522.h"函式庫
要按裝"MFRC522.h"這個函示庫,請先在Arduino IDE中點選上方的【草稿碼】🡺【匯入程式庫】🡺【管理程式庫】,在看到下面的【圖六、6-6_5】程式庫管理員視窗後,在標記1的欄位輸入『MFRC522』搜尋字串,便可以找到標記2的目標函式庫,然後在標記3的地方選擇所需的版本(一般都會選擇最新的版本),並按下[安裝]鍵,便可成功安裝,如果系統已經安裝過的話就會在標記2中看到「INSTALLED」這樣的訊息文字。
圖六、6-6_5 MFRC522.h函式庫安裝畫面
由於MFRC522使用的是SPI匯流排介面,如果沒有特別指定的話,在初始化時會使用ESP8266內建的MISO(GPI12)、MOSI(GPIO13)及SCK(GPIO14)這3根接腳,不過RST與SS這兩根腳必須另外宣告使用的腳位:
17. #define RST_PIN 5 // RST-PIN RC522 - RFID SPI – ESP/ GPIO5
18. #define SS_PIN 4 // SDA-PIN RC522 – RFID SPI – ESP/ GPIO4
本範例程式的初始化程式區(setup())內容和前面幾個實習非常類似,差別只在下面這兩行用來初始化SPI匯流排與MFRC522的指令而已:
55. SPI.begin(); // Init SPI bus
56. mfrc522.PCD_Init(); // Init MFRC522
在主迴圈(loop())程式中一開始同樣是在等待客戶端連線(67~69行),當有客戶端裝置連線時會先把連線次數(count)加一,並把網頁首頁程式碼MAIN_page[]傳送到「tmpString」這個字串變數中,同時也把測量的時間間隔值(即'rTime')帶入到網頁html程式中:
70. count++;
71. tmpString = MAIN_page; // 取出html網頁回應程式
72. tmpString.replace("%rTime%", String(rTime) );
為了配合網頁自動更新的時間(在此為3秒),因此我們利用76~93行的for()迴圈流程控制方式去測試,在此特定的時間內是否有卡片出現在MFRC522模組的感應範圍內﹖不過在此之前我們先預設回傳的訊息為沒有偵測到:
75. uid="未偵測到卡片!";
接著使用下列指令測試是否有新的電子標籤或卡片出現在MFRC522模組的感應範圍內:
78. if ( mfrc522.PICC_IsNewCardPresent())
如果有便開始讀取該卡片的UID號碼,假如讀取失敗會將訊息「"Read DIU Error!! "」顯示在Arduino IDE的序列監控視窗中,反之則以16進制的形式列印出卡片的UID號碼,而卡片UID號碼真正的顯示與轉換是由『dump_byte_array()』這個副程式負責:
79. {
80. if ( ! mfrc522.PICC_ReadCardSerial())
81. Serial.println("Read DIU Error!! ");
82. else
83. {
84. // Select one of the cards
85. // Show some details of the PICC (that is: the tag/card)
86. Serial.print("Card UID:");
87. dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
88. }
MFRC522模組在操作時不管是否讀取成功,最後都必須停止感應與讀取的動作,以便可以正確的處理下一次程序;如果不關閉動作,在讀取成功後假如卡片沒有移開,則會不斷的送出同一張卡片的UID號碼而造成困擾。下面的程式便是用來停止MFRC522模組動作之用:
89. mfrc522.PICC_HaltA(); // Halt PICC
90. mfrc522.PCD_StopCrypto1(); // Stop encryption on PCD
至於95、96行程式會把『dump_byte_array()』這個副程式轉換的卡片UID結果(即變數”uid”),與量測次數值(count)分別帶入「tmpString」這個字串變數中的「uid」、與「count」這兩個變數中
95. tmpString.replace("%uid%", String(uid) ); //帶入測量的UID到網頁html程式中
96. tmpString.replace("%count%", String(count) ); // 帶入測量次數
最後執行下列程式,便可以把MFRC522模組量測到的結果回應給連線的客戶端瀏覽器。
99. client.println( tmpString );
106~116 行程式是『void dump_byte_array(byte *buffer, byte bufferSize)』這個副程式的主體部分,這個副程式會將將偵測到的卡片UID號碼轉換至網頁字串變數(uid),並顯示在Arduino IDE的監控視窗中;此外為了美觀起見,如果該號碼位元組(byte)的值小於16時,會在前面補一個字元’0’,以便每個位元組都是以兩位數16進制的方式呈現出來。
圖六、6-6_6 index.h程式頁面畫面
程式列表的118~147行是ESP8266內建伺服器的網頁首頁程式碼,它們是放在Arduino IDE程式中的「index.h」分頁上(如上圖所示),整個html程式的字串變數名稱跟之前一樣命名為「MAIN_page[]」。為了能讓客戶端的瀏覽器能更快的取得MFRC522讀取電子標籤的結果,在這裡一樣把更新時間加快到3秒鐘;為了能讓程式更有彈性,所以在此是以參數(即'%rTime%')的方式去定義!
128. <meta http-equiv='refresh' content='%rTime%'>
【圖六、6-6_2】的中標記1也就是本實習名稱的提示訊息部分,是由下面兩行程式完成:
138. <h2><center>[Soft AP模式] <br>
139. RFID/RC522電子標籤UID讀取實習<br></center><br>
網頁中MFRC522讀取電子標籤的結果也就是UID值,則是由下面幾行程式負責帶入網頁程式中,而這兩個參數(即「uid」與「count」)的傳遞是由前面介紹的主程式95、96行程式所負責:
140. 卡片UID序號 = %uid% <br>
141. Card UID = %uid%<br>
142 Count = %count%<br>
至於「count」同樣代表網頁更新的次數,也等同於MFRC522讀取電子標籤的次數。
◎ 執行結果:
圖六、6-6_7 MFRC522讀取各種電子標籤UID畫面
【圖六、6-6_7】是使用者客戶端(如手機)瀏覽器與系統連線後,系統上的MFRC522模組測量周邊是否有電子標籤或卡片接近後,所回傳給瀏覽器的畫面,畫面左邊三個頁面是MFRC522模組偵測並讀取到三個不同標籤的UID號碼畫面,而最右邊則是在網頁更新的時間(3秒)內沒有偵測到任何卡片出現,或是上一次測到的卡片沒有移開,仍然在MFRC522模組偵測的範圍內時所出現的訊息。
本實習主要是示範ESP8266如何與MFRC522模組連接,進而讓使用者可以透過WiFi無線傳輸的方式直接與行動通訊裝置連線,當這些通訊連線的基本問題都解決之後,我們可以讓ESP6266從存取點(AP點)的腳色轉換為站點(Station)的腳色,然後連接已經連上網際網路(Internet)的WiFi分享器(或Router),這樣便可以讓我們這MFRC522/RFID讀寫器裝置成為IOT物聯網的一份子,至於這個系統能夠做那些應用,就要靠讀者們自己動動腦發揮一下創意了!
沒有留言:
張貼留言