Mifare RFID-RC522模組實驗(四):Mifare RFID的門禁系統實驗

本文旨在補充《超圖解 Arduino 互動設計入門》第17章的RFID應用單元。

實驗說明:典型的RFID應用,例如門禁卡,都是事先在微電腦中儲存特定RFID卡片的識別碼。當持卡人掃描門禁卡時,系統將讀取並且比對儲存值,如果有相符,就開門讓持卡人通過。本文採用一個伺服馬達來模擬旋轉門鎖的動作。

一開始,伺服馬達位於0度位置,掃描有效的卡片時,伺服馬達將旋轉到90度;再次掃描有效的卡片,它將轉回0度。

感應RFID開鎖

若掃描無效的卡片,伺服馬達將維持在0度,或者從90度轉回0度。

實驗材料:

  • Mifare RFID-RC522模組×1
  • Mifare Classic標籤,至少兩個。
  • 伺服馬達×1

實驗電路:
Mifare RFID-RC522模組與Arduino板的接線與「Mifare RFID-RC522模組實驗(二)」單元相同,另外在數位2腳連接伺服馬達:

連接伺服馬達

實驗程式:
本文的程式延續「Mifare RFID-RC522模組實驗(二)」單元,在其中加入控制伺服馬達的程式,一開始先定義與伺服馬達相關的變數:

#include <Servo.h> // 引用伺服馬達程式庫 
#define SERVO_PIN 2 // 伺服馬達的控制訊號接腳 

bool lockerSwitch = false; // 伺服馬達(模擬開關)的切換狀態,預設為「關」 
Servo servo; // 宣告伺服馬達物件

接著定義控制伺服馬達轉動(模擬開鎖或關鎖)的自訂函式:

// 開鎖或關鎖 
void locker(bool toggle) { 
  if (toggle) { 
    servo.write(90); // 開鎖 
  } else { 
    servo.write(0); // 關鎖 
  } 
  delay(15); // 等伺服馬達轉到定位 
}

在setup()函式裡面初始化伺服馬達物件,接著關鎖(轉動到0度)。

void setup() { 
    :
    :
  mfrc522.PCD_Init(); // 初始化MFRC522讀卡機模組 
  servo.attach(SERVO_PIN); // 將伺服馬達物件附加在數位2腳 
  locker(lockerSwitch); // 關鎖 
}

最後,修改loop()函式裡面的比對卡片UID值的程式碼當中,加入開鎖或解鎖的敘述(一開始,lockerSwitch的值為false,每執行一次,就反轉一次):

處理開鎖或解鎖的程式敘述

完整的程式碼:

#include <SPI.h>
#include <MFRC522.h>     // 引用程式庫
#include <Servo.h>         // 引用伺服馬達程式庫

#define RST_PIN      A0  // 讀卡機的重置腳位
#define SS_PIN       10  // 晶片選擇腳位
#define SERVO_PIN    2   // 伺服馬達的控制訊號接腳

bool lockerSwitch = false;  // 伺服馬達的狀態

Servo servo;    // 宣告伺服馬達物件

struct RFIDTag {   // 定義結構
   byte uid[4];
   char *name;
};

struct RFIDTag tags[] = {  // 初始化結構資料,請自行修改RFID識別碼。
  {{60,209,110,133}, "Arduino"},
  {{212,211,192,97}, "Raspberry Pi"},
  {{21,8,10,83}, "Espruino"}
};

byte totalTags = sizeof(tags) / sizeof(RFIDTag);  // 計算結構資料筆數,結果為3。

MFRC522 mfrc522(SS_PIN, RST_PIN);  // 建立MFRC522物件

// 開鎖或關鎖
void locker(bool toggle) {
  if (toggle) {
      servo.write(90);  // 開鎖
  } else {
      servo.write(0);   // 關鎖
  }
  delay(15);    // 等伺服馬達轉到定位
}

void setup() {
  Serial.begin(9600);
  Serial.println();
  Serial.print("size of RFIDTag:");
  Serial.println(sizeof(RFIDTag));
  Serial.print("size of tag:");
  Serial.println(sizeof(tags));
  Serial.println("RFID reader is ready!");

  SPI.begin();
  mfrc522.PCD_Init();       // 初始化MFRC522讀卡機模組
  servo.attach(SERVO_PIN);  // 將伺服馬達物件附加在數位2腳
  locker(lockerSwitch);
}

void loop() {
    // 確認是否有新卡片
    if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
      byte *id = mfrc522.uid.uidByte;   // 取得卡片的UID
      byte idSize = mfrc522.uid.size;   // 取得UID的長度
      bool foundTag = false;    // 是否找到紀錄中的標籤,預設為「否」。
      
      for (byte i=0; i<totalTags; i++) {
        if (memcmp(tags[i].uid, id, idSize) == 0) {  // 比對陣列資料值
          Serial.println(tags[i].name);  // 顯示標籤的名稱
          foundTag = true;  // 設定成「找到標籤了!」
          
          lockerSwitch = !lockerSwitch;  // 切換鎖的狀態
          locker(lockerSwitch);          // 開鎖或關鎖
          break;  // 退出for迴圈
        }
      }

      if (!foundTag) {  // 若掃描到紀錄之外的標籤,則顯示"Wrong card!"。
        Serial.println("Wrong card!");

        // 如果鎖是開啟狀態,則關閉它。
        if (lockerSwitch) {
          lockerSwitch = false;
          locker(lockerSwitch);
        }
      }

      mfrc522.PICC_HaltA();  // 讓卡片進入停止模式      
    } 
}

延伸閱讀

Posts created 483

22 thoughts on “Mifare RFID-RC522模組實驗(四):Mifare RFID的門禁系統實驗

  1. 請問需要自行修改RFID識別碼的部份
    為什麼改成自己的卡片之後還是不行呢
    是讀取完識別碼之後將他換算成四進制嗎?

  2. 為什麼我用你第一個《Mifare RFID-RC522模組實驗(一):讀取Mifare RFID卡的UID識別碼》所出現的UID碼 卻不能使用在這個程式上面,而且只要輸入有英文的UID碼就會錯誤

    1. 因為RFIDtag的第一組資料型態是byte,請問你的字元資料有用單引號括起來嗎?

      thanks,
      jeffrey

  3. struct RFIDTag tags[] = { // 初始化結構資料,請自行修改RFID識別碼。
    {{‘A9′,’2B’,’9D’,’1A’}, “Arduino”}, 你說的單引號是這樣? 這個代碼是我們磁扣碼 但感應時顯示wrong card
    {{212,211,192,97}, “Raspberry Pi”},
    {{21,8,10,83}, “Espruino”}
    };

    1. 不是,byte類型代表數字0~255或單一字元,C語言用單引號包圍一個字元,這些基礎知識書本都有說明,請自行參考或者請教專題老師。

      thanks,
      jeffrey

  4. 不好意思 我想請問 為何顯示WRONG CARD時 (已先輸入對應UID卡片) 伺服馬達卻無法回歸0度?

    1. 你可以在判斷為wrong card的條件敘述中,加入轉動servo的敘述試試看。

      thanks,
      jeffrey

    1. 單純就硬體接線來說,不計算消耗電流,每個SPI週邊至少要佔用一條晶片選擇線,因此你可以自行計算總共可以接多少RFID讀卡機。

      have fun!
      jeffrey

  5. 老師~~~我想請問如果我要用同一張RFID卡開啟和關閉那個馬達應該要怎麼做???

  6. 老師您好
    我想把伺服馬達弄成可復歸回0度,所以把開關鎖的地方弄成這樣
    void locker(bool toggle) {
    if (toggle) {
    servo.write(90); // 開鎖
    delay(1000);
    servo.write(0);
    } else {
    servo.write(0); // 關鎖
    }
    delay(15); // 等伺服馬達轉到定位
    }
    可是變成了卡片必須感應到兩次才會動作

    1. 因為根據你的程式,感應第一次時,伺服馬達轉90度後一秒轉回0度;第2次感應時,馬達維持在0度,不動作。
      第3次感應,馬達才又轉90度…以此類推。

      thanks,
      jeffrey

  7. 老師您好
    請問在開鎖後10分鐘內忘了關鎖就有蜂鳴器提醒
    直到用卡鎖了,蜂鳴器才停
    可以如何改寫

  8. 想問問如何控制伺福馬達,因為我照這城市上船玩ARDUINO後伺福馬達一職不受控制

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top