2016年3月30日 星期三

[Arduino] RFID 與 MIFARE






   RFID 以無線電波傳遞訊息,只要在電波範圍內,即可傳送訊號,不會有傳輸屏障之問題。這種設備的運作為一個讀卡設備會發出一個電磁場,而感應卡內部有線圈,當線圈靠近磁場時,會產生感應電流,就可以做為電力傳輸資訊。另外,感應卡平常沒有靠近電場時,內部晶片根本沒有電力可以工作,不用擔心卡片放在一起資料不見。

  不過,因RFID的運作是由無線電波傳送,所以在遇到金屬或是液體時,訊號的傳導會產生干擾與衰減,進而影響到資料讀取的可靠性與準確度(每個頻率間的干擾程度不同)。

  RFID設備所使用的頻段分為低頻(LF,125KHz)、高頻(HF,13.56MHz)、 超高頻(UHF,868~915MHz)、微波(Microwave,2.45 & 5.814GHz)各個頻 段的設備有不同的物理特性,如讀取的距離與讀取的速度,因此在不同應用情境中會採用不同頻段的設備。

  其中,現有門禁卡中的EM卡跟MIFARE卡長得很類似,常常會被搞混,悠遊卡為MIFARE卡。em卡無識別讀卡機的能力,當讀卡機感應時,感應卡就會回覆一組卡號,所以當得知卡號以後就可以在另一張可寫式em卡把卡號寫入,即能複製一張em卡;MIfare卡的卡片序號是在卡片產生時就已經寫死了,所以不會有複製相同卡片的問題,除非製造商刻意製造相同卡號的卡片,而mifare卡又具備加密與驗證機制,所以通常可以拿來做小額的消費,像是悠遊卡、一卡通或i-cASH。



  EM卡因不具防衝突的功能,所以當兩張同時感應時,無法感應,而MIFARE卡因為有防衝突功能,則是兩張都會感應到,不過這項特點如果沒注意到可能會造成困擾。之前曾經有民眾在捷運感應時,因為兩張卡放在一起,結果被重複扣款。



  我們今天要介紹的RFID感應器是頻率為13.56MHz的 RFID-RC522,而他的感應卡為MIFARE卡,MIFARE卡又有分不同儲存容量的卡。MIFARE S50 內部儲存容量1KbyteMIFARE S70 內部儲存容量 4Kbytes,各劃分為 16 區與 64 區,每區都有獨立的 A / B 兩層存取控制密碼,每區有4個BLOCK,每個BLOCK有16個字節。


  通常,以一個SECTOR為一組,前三個BLOCK為數據區,第四個BLOCK為驗證區,驗證區含有A/B兩組密碼,A做為讀取的密碼,B為修改資料的密碼,要比對成功才能做資料上的讀寫,比較特別的是BLOCK0為卡片與商業之資料,是不能更改的,而卡號寫在BLOCK0的前四個字結。

  RFID與ARDUINO UNO的腳位接法為: RST→9、SDA(SS)→10、MOSI→11、MISO→12、SCK→13,需要注意的是電源(VCC)要接3.3V不是5V
  範例碼中,卡片靠近感應時,只要進入感應範圍內,就會不停的作讀取,在程式設計上可能會因為他不停在讀取,所以感應速度太快,沒辦法好好去做判斷的動作,在門禁實作上也會造成重複感應。可以利用程式碼中的 mfrc522.PICC_HaltA(); 函式,來使得卡片靠近時只讀取一次,而不是在卡片靠近的範圍中一直讀取,再利用DELAY來讓讀取間隔時間久一點,來避免感應卡片時放下跟拿起的兩次重複感應,RFID的讀取就完成囉。

/**
 * ----------------------------------------------------------------------------
 * This is a MFRC522 library example; see https://github.com/miguelbalboa/rfid
 * for further details and other examples.
 * 
 * NOTE: The library file MFRC522.h has a lot of useful info. Please read it.
 * 
 * Released into the public domain.
 * ----------------------------------------------------------------------------
 * This sample shows how to read and write data blocks on a MIFARE Classic PICC
 * (= card/tag).
 * 
 * BEWARE: Data will be written to the PICC, in sector #1 (blocks #4 to #7).
 * 
 * 
 * Typical pin layout used:
 * -----------------------------------------------------------------------------------------
 *             MFRC522      Arduino       Arduino   Arduino    Arduino          Arduino
 *             Reader/PCD   Uno           Mega      Nano v3    Leonardo/Micro   Pro Micro
 * Signal      Pin          Pin           Pin       Pin        Pin              Pin
 * -----------------------------------------------------------------------------------------
 * RST/Reset   RST          9             5         D9         RESET/ICSP-5     RST
 * SPI SS      SDA(SS)      10            53        D10        10               10
 * SPI MOSI    MOSI         11 / ICSP-4   51        D11        ICSP-4           16
 * SPI MISO    MISO         12 / ICSP-1   50        D12        ICSP-1           14
 * SPI SCK     SCK          13 / ICSP-3   52        D13        ICSP-3           15
 * 
 */

#include 
#include 

#define RST_PIN         9           // Configurable, see typical pin layout above
#define SS_PIN          10          // Configurable, see typical pin layout above

MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.

MFRC522::MIFARE_Key key;
/**
 * Initialize.
 */
void setup() {
    Serial.begin(9600); // Initialize serial communications with the PC
    while (!Serial);    // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
    SPI.begin();        // Init SPI bus
    mfrc522.PCD_Init(); // Init MFRC522 card

    // Prepare the key (used both as key A and as key B)
    // using FFFFFFFFFFFFh which is the default at chip delivery from the factory
    for (byte i = 0; i < 6; i++) {
        key.keyByte[i] = 0xFF;
    }

    Serial.println(F("Scan a MIFARE Classic PICC to demonstrate read and write."));
    Serial.print(F("Using key (for A and B):"));
    dump_byte_array(key.keyByte, MFRC522::MF_KEY_SIZE);
    Serial.println();
    
    Serial.println(F("BEWARE: Data will be written to the PICC, in sector #1"));
}

/**
 * Main loop.
 */
void loop() {
    // Look for new cards
    if ( ! mfrc522.PICC_IsNewCardPresent())
        return;

    // Select one of the cards
    if ( ! mfrc522.PICC_ReadCardSerial())
        return;

    // Show some details of the PICC (that is: the tag/card)
    //Serial.print(F("Card UID:"));
    dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
    Serial.println();
    //mfrc522.PICC_HaltA();放到 dump_byte_array 函式內
    delay(1000);
}

/**
 * Helper routine to dump a byte array as hex values to Serial.
 */
void dump_byte_array(byte *buffer, byte bufferSize) {
  mfrc522.PICC_HaltA();
    for (byte i = 0; i < bufferSize; i++) {
        Serial.print(buffer[i] < 0x10 ? "0" : "");
        Serial.print(buffer[i], HEX);
    }
}



  以上程式碼,只用簡單的卡號讀取來做展示,範例碼中還有其他的讀寫範例。

參考: http://blog.davidou.org/archives/988

沒有留言:

張貼留言