RFID Reader 모듈 (RC522 chip, 13.56MHz)
1. RFID 모듈
RFID 모듈입니다. 이것만 있으면 뭔가 대단한걸 만들 수 있을것만 같습니다. 그런데 사용하는 방법이 좀 까다롭네요.
Ebay를 뒤져보니 RC522 chip, 13.56MHz 를 지원하는 RFID 모듈들이 대세네요. 가격도 저렴하고. SPI 인터페이스를 지원하기 때문에 연결도 그다지 어렵지 않습니다. 반면에 (늘 그렇듯이…) 모듈에 대한 자세한 tutorial 이나 라이브러리가 소개되어 있질 않아서 인터넷을 뒤지고 다녀야 합니다. 싼게 장땡인지라 여기서는 이 모듈을 기준으로 자료를 정리했습니다.
Operating current of 13-26mA / DC 3.3V
Idle Current :10-13mA / DC 3.3V
Sleep current: <80uA
Peak current: <30mA
Operating Frequency: 13.56MHz
Supported card types: mifare1 S50, the mifare1 S70, Mifare UltraLight, Mifare Pro, mifare DESFire
Product physical properties: size: 40mm x 60mm
Environmental Operating temperature: -20-80 degrees Celsius
Environment Storage temperature: -40-85 degrees Celsius
Ambient Relative Humidity: 5% -95%
Reader에서 지원하는 card type 을 확인하고 원하는 카드/태그를 추가하세요.
IC Card:
Capacity: 8KB EEPROM;
Divided into 16 sectors, each sector is 4 blocks, each block is 16 bytes, each block as 1 unit;
Each sector has a separate set of passwords and access control;
Each card has a unique 32-bit serial number;
Have anti-collision mechanism, support for multi-card operations;
No power, with an antenna, embedded encryption control logic and communication logic circuit;
Data retention period of 10 years, can be rewritten 100,000 times, reading limitless;
Operating Temperature -20 ℃ ~ 50 ℃ ; Humidity is 90% ;
Operating frequency is 13.56MHz;
RF protocol : ISO14443A;
Communication speed : 106KBPS;
Read and write distance : ≤ 10cm (regardless of reader);
NFC TAG Keychain:
Main Chip: Philips Mifare 1 S50;
Storage capacity: 8Kbit, 16 partitions, each partition with 2 grounp passwords;
Operating Frequency: 13.56 MHz;
Communication speed: 106K Boud;
Read and write distance: 2.5 ~ 10cm;
Read and write time: 1 ~ 2ms;
Operating Temperature: -20 °C ~ 85°C;
Endurance:> 100,000 times;
아두이노 공식 사이트인 arduino.cc 에서 Parallax RFID 모듈에 대한 예제를 소개하고 있는데 판매처에서 확인해보니 가격 차이가 너무 납니다. Parallax RFID 모듈은 reader, reader/writer 버전이 별도로 있습니다. 자세한 내용은 링크를 참고하세요.
이외에도 다양한 제품이 있을 수 있기 때문에 본 문서의 자료와 호환 되는지 주의하셔야 합니다.
2. 연결 방법
SPI 인터페이스를 지원합니다.
3. 소스 코드 (스케치)
링크, 링크로 가시면 아마도 중국 제조사에서 제작한 듯 한 소스코드를 영어로 번역한 코드가 있습니다. 좀 복잡해 보이는 코드라 이대로 사용하기보다는 RFID 라이브러리를 사용하는 것이 적절해 보입니다. 아래 링크로 가시면 RFID 라이브러리가 있습니다. 라이브러리를 설치하고 예제코드 중 ReadAndWrite 를 불러와서 테스트 해보시기 바랍니다.
Arduino RFID Library for MFRC522
/* * MFRC522 - Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI W AND R BY COOQROBOT. * The library file MFRC522.h has a wealth of useful info. Please read it. * The functions are documented in MFRC522.cpp. * * Based on code Dr.Leong ( WWW.B2CQSHOP.COM ) * Created by Miguel Balboa (circuitito.com), Jan, 2012. * Rewritten by Søren Thing Andersen (access.thing.dk), fall of 2013 (Translation to English, refactored, comments, anti collision, cascade levels.) * * Released into the public domain. * * This sample shows how to setup a block on a MIFARE Classic PICC to be in "Value Block" mode. * In Value Block mode the operations Increment/Decrement/Restore and Transfer can be used. * ----------------------------------------------------------------------------- empty_skull - Aggiunti pin per arduino Mega - Scritto semplice codice per la scrittura e lettura - add pin configuration for arduino mega - write simple read/write Code for new entry user http://mac86project.altervista.org/ ----------------------------------------------------------------------------- Nicola Coppola * Pin layout should be as follows: * Signal Pin Pin Pin * Arduino Uno Arduino Mega MFRC522 board * ------------------------------------------------------------ * Reset 9 5 RST * SPI SS 10 53 SDA * SPI MOSI 11 52 MOSI * SPI MISO 12 51 MISO * SPI SCK 13 50 SCK * * The reader can be found on eBay for around 5 dollars. Search for "mf-rc522" on ebay.com. */ #include <SPI.h> #include <MFRC522.h> #define SS_PIN 53 #define RST_PIN 5 MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance. void setup() { Serial.begin(9600); // Initialize serial communications with the PC SPI.begin(); // Init SPI bus mfrc522.PCD_Init(); // Init MFRC522 card //Serial.println("Scan a MIFARE Classic PICC to demonstrate Value Blocks."); } void loop() { // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory. MFRC522::MIFARE_Key key; for (byte i = 0; i < 6; i++) { key.keyByte[i] = 0xFF; } // Look for new cards if ( ! mfrc522.PICC_IsNewCardPresent()) { return; } // Select one of the cards if ( ! mfrc522.PICC_ReadCardSerial()) { return; } // Now a card is selected. The UID and SAK is in mfrc522.uid. // Dump UID Serial.print("Card UID:"); for (byte i = 0; i < mfrc522.uid.size; i++) { Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "); Serial.print(mfrc522.uid.uidByte[i], HEX); } Serial.println(); // Dump PICC type byte piccType = mfrc522.PICC_GetType(mfrc522.uid.sak); Serial.print("PICC type: "); Serial.println(mfrc522.PICC_GetTypeName(piccType)); if ( piccType != MFRC522::PICC_TYPE_MIFARE_MINI && piccType != MFRC522::PICC_TYPE_MIFARE_1K && piccType != MFRC522::PICC_TYPE_MIFARE_4K) { //Serial.println("This sample only works with MIFARE Classic cards."); return; } // In this sample we use the second sector (ie block 4-7). the first sector is = 0 // scegliere settore di lettura da 0 = primo settore byte sector = 1; // block sector 0-3(sector0) 4-7(sector1) 8-11(sector2) // blocchi di scrittura da 0-3(sector0) 4-7(sector1) 8-11(sector2) byte valueBlockA = 4; byte valueBlockB = 5; byte valueBlockC = 6; byte trailerBlock = 7; byte status; // Authenticate using key A. // avvio l'autentificazione A //Serial.println("Authenticating using key A..."); status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid)); if (status != MFRC522::STATUS_OK) { Serial.print("PCD_Authenticate() failed: "); Serial.println(mfrc522.GetStatusCodeName(status)); return; } // Authenticate using key B. // avvio l'autentificazione B //Serial.println("Authenticating again using key B..."); status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, trailerBlock, &key, &(mfrc522.uid)); if (status != MFRC522::STATUS_OK) { Serial.print("PCD_Authenticate() failed: "); Serial.println(mfrc522.GetStatusCodeName(status)); return; } // Writing new value block A // Scrivo i valori per il settore A Serial.println("Writing new value block A(4) : the first of the sector TWO "); byte value1Block[] = { 1,2,3,4, 5,6,7,8, 9,10,255,12, 13,14,15,16, valueBlockA,~valueBlockA,valueBlockA,~valueBlockA }; status = mfrc522.MIFARE_Write(valueBlockA, value1Block, 16); if (status != MFRC522::STATUS_OK) { Serial.print("MIFARE_Write() failed: "); Serial.println(mfrc522.GetStatusCodeName(status)); } /* // Writing new value block B // Scrivo i valori per il settore B Serial.println("Writing new value block B"); byte value2Block[] = { 255,255,255,255, 0,0,0,0, 0,0,0,0, 255,255,255,255, valueBlockB,~valueBlockB,valueBlockB,~valueBlockB }; status = mfrc522.MIFARE_Write(valueBlockB, value2Block, 16); if (status != MFRC522::STATUS_OK) { Serial.print("MIFARE_Write() failed: "); Serial.println(mfrc522.GetStatusCodeName(status)); } // Writing new value block D // Scrivo i valori per il settore C Serial.println("Writing new value block C"); byte value3Block[] = { 255,255,255,255, 0,0,0,0, 0,0,0,0, 255,255,255,255, valueBlockC,~valueBlockC,valueBlockC,~valueBlockC }; status = mfrc522.MIFARE_Write(valueBlockC, value3Block, 16); if (status != MFRC522::STATUS_OK) { Serial.print("MIFARE_Write() failed: "); Serial.println(mfrc522.GetStatusCodeName(status)); } */ Serial.println("Read block A(4) : the first of the sector TWO"); byte buffer[18]; byte size = sizeof(buffer); // change this: valueBlockA , for read anather block // cambiate valueBlockA per leggere un altro blocco status = mfrc522.MIFARE_Read(valueBlockA, buffer, &size); Serial.print("Settore : 0 Valore :"); Serial.println(buffer[0]); Serial.print("Settore : 1 Valore :"); Serial.println(buffer[1]); Serial.print("Settore : 2 Valore :"); Serial.println(buffer[2]); Serial.print("Settore : 3 Valore :"); Serial.println(buffer[3]); Serial.print("Settore : 4 Valore :"); Serial.println(buffer[4]); Serial.print("Settore : 5 Valore :"); Serial.println(buffer[5]); Serial.print("Settore : 6 Valore :"); Serial.println(buffer[6]); Serial.print("Settore : 7 Valore :"); Serial.println(buffer[7]); Serial.print("Settore : 8 Valore :"); Serial.println(buffer[8]); Serial.print("Settore : 9 Valore :"); Serial.println(buffer[9]); Serial.print("Settore :10 Valore :"); Serial.println(buffer[10]); Serial.print("Settore :11 Valore :"); Serial.println(buffer[11]); Serial.print("Settore :12 Valore :"); Serial.println(buffer[12]); Serial.print("Settore :13 Valore :"); Serial.println(buffer[13]); Serial.print("Settore :14 Valore :"); Serial.println(buffer[14]); Serial.print("Settore :15 Valore :"); Serial.println(buffer[15]); //byte value1Block[] = { 1,2,3,4, 5,6,7,8, 9,10,255,12, 13,14,15,16, valueBlockA,~valueBlockA,valueBlockA,~valueBlockA }; if ( buffer[0] == 1 && buffer[1] == 2 && buffer[2] == 3 && buffer[3] == 4 && buffer[4] == 5 && buffer[5] == 6 && buffer[6] == 7 && buffer[7] == 8 && buffer[8] == 9 && buffer[9] == 10 && buffer[10] == 255 && buffer[11] == 12 && buffer[12] == 13 && buffer[13] == 14 && buffer[14] == 15 && buffer[15] == 16 ){ // sel a scrittura è uguale alla lettura allora e stato un successo !! Serial.println("Read block A(4) : the first of the sector TWO : success"); Serial.println(":-)"); }else{ // scrittura Fallita Serial.println("Read block A(4) : the first of the sector TWO : no match - write don't work fine "); Serial.println(":-( "); } // risponde successo //Serial.println(mfrc522.GetStatusCodeName(status)); // Dump the result //mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector); // Halt PICC mfrc522.PICC_HaltA(); // Stop encryption on PCD mfrc522.PCD_StopCrypto1(); }