Introduction
The MiFare reader is capable of reading and writing into RFID cards. Each card has about 1k of memory.
Project
In this project, we will write 2 different names in 2 RFID cards. Then use one card to provide access and another card to deny access. The code below has highlighted lines that are currently commented which need to be enabled. The corresponding blockcontent array should be enabled.
Pin Configuration
Arduino | Sensor |
3.3V | 3.3V |
GND | GND |
Pin 12 | MISO |
Pin 11 | MOSI |
Pin 13 | SCK |
Pin 10 | SDA |
Pin 5 | RST |
Circuit Connections
Library
[wpdm_package id=’691′]
Download the library, unzip and place it in Documents/Arduino/Libraries
Code
[wpdm_package id=’695′]
#include <SPI.h>//include the SPI bus library #include <MFRC522.h>//include the RFID reader library #define SS_PIN 10 //slave select pin #define RST_PIN 5 //reset pin MFRC522 mfrc522(SS_PIN, RST_PIN); // instatiate a MFRC522 reader object. MFRC522::MIFARE_Key key;//create a MIFARE_Key struct named 'key', which will hold the card information void setup() { Serial.begin(9600); // Initialize serial communications with the PC SPI.begin(); // Init SPI bus mfrc522.PCD_Init(); // Init MFRC522 card (in case you wonder what PCD means: proximity coupling device) Serial.println("Scan a MIFARE Classic card"); // Prepare the security key for the read and write functions - all six key bytes are set to 0xFF at chip delivery from the factory. // Since the cards in the kit are new and the keys were never defined, they are 0xFF for (byte i = 0; i < 6; i++) { key.keyByte[i] = 0xFF;//keyByte is defined in the "MIFARE_Key" 'struct' definition in the .h file of the library } } int block=2;//this is the block number we will write into and then read. Do not write into 'sector trailer' block, since this can make the block unusable. //byte blockcontent[16] = {"DR.KAYARVIZHY.."};//an array with 16 bytes to be written into one of the 64 card blocks is defined byte blockcontent[16] = {"MR.YOUKNOWWHO.."};//an array with 16 bytes to be written into one of the 64 card blocks is defined //byte blockcontent[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//all zeros. This can be used to delete a block. byte readbackblock[18];//This array is used for reading out a block. The MIFARE_Read method requires a buffer that is at least 18 bytes to hold the 16 bytes of a block. void loop() { // Look for new cards (in case you wonder what PICC means: proximity integrated circuit card) if (mfrc522.PICC_IsNewCardPresent()) {//if PICC_IsNewCardPresent returns 1, a new card has been found and we continue if (mfrc522.PICC_ReadCardSerial()) {//if PICC_ReadCardSerial returns 1, the "uid" struct (see MFRC522.h lines 238-45)) contains the ID of the read card. Serial.println("..Card Selected.."); // Kayarvizhy commented the write below... When you want to write enable the code below... //writeBlock(block, blockcontent);//the blockcontent array is written into the card block char name[20]; readBlock(block, readbackblock);//read the block back int j; for (j=0 ; j<16 ; j++) { name[j]=readbackblock[j]; } name[j]='\0'; if (strcmp(name,"DR.KAYARVIZHY..")==0) { Serial.print ("Access Provided for : "); Serial.println (name); } else { Serial.print ("Access DENIED for : "); Serial.println (name); } mfrc522.PCD_Init(); Serial.println("\n\nScan a MIFARE Classic card"); delay(5000); } } } int writeBlock(int blockNumber, byte arrayAddress[]) { //this makes sure that we only write into data blocks. Every 4th block is a trailer block for the access/security info. int largestModulo4Number=blockNumber/4*4; int trailerBlock=largestModulo4Number+3;//determine trailer block for the sector if (blockNumber > 2 && (blockNumber+1)%4 == 0){Serial.print(blockNumber);Serial.println(" is a trailer block:");return 2;}//block number is a trailer block (modulo 4); quit and send error code 2 Serial.print(blockNumber); Serial.println(" is a data block:"); /*****************************************authentication of the desired block for access***********************************************************/ MFRC522::StatusCode 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 3;//return "3" as error message } //it appears the authentication needs to be made before every block read/write within a specific sector. //If a different sector is being authenticated access to the previous one is lost. /*****************************************writing the block***********************************************************/ status = mfrc522.MIFARE_Write(blockNumber, arrayAddress, 16);//valueBlockA is the block number, MIFARE_Write(block number (0-15), byte array containing 16 values, number of bytes in block (=16)) //status = mfrc522.MIFARE_Write(9, value1Block, 16); if (status != MFRC522::STATUS_OK) { Serial.print("MIFARE_Write() failed: "); Serial.println(mfrc522.GetStatusCodeName(status)); return 4;//return "4" as error message } Serial.println("block was written"); } int readBlock(int blockNumber, byte arrayAddress[]) { int largestModulo4Number=blockNumber/4*4; int trailerBlock=largestModulo4Number+3;//determine trailer block for the sector /*****************************************authentication of the desired block for access***********************************************************/ MFRC522::StatusCode status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid)); //byte PCD_Authenticate(byte command, byte blockAddr, MIFARE_Key *key, Uid *uid); //this method is used to authenticate a certain block for writing or reading //command: See enumerations above -> PICC_CMD_MF_AUTH_KEY_A = 0x60 (=1100000), // this command performs authentication with Key A //blockAddr is the number of the block from 0 to 15. //MIFARE_Key *key is a pointer to the MIFARE_Key struct defined above, this struct needs to be defined for each block. New cards have all A/B= FF FF FF FF FF FF //Uid *uid is a pointer to the UID struct that contains the user ID of the card. if (status != MFRC522::STATUS_OK) { Serial.print("PCD_Authenticate() failed (read): "); Serial.println(mfrc522.GetStatusCodeName(status)); return 3;//return "3" as error message } //it appears the authentication needs to be made before every block read/write within a specific sector. //If a different sector is being authenticated access to the previous one is lost. /*****************************************reading a block***********************************************************/ byte buffersize = 18;//we need to define a variable with the read buffer size, since the MIFARE_Read method below needs a pointer to the variable that contains the size... status = mfrc522.MIFARE_Read(blockNumber, arrayAddress, &buffersize);//&buffersize is a pointer to the buffersize variable; MIFARE_Read requires a pointer instead of just a number if (status != MFRC522::STATUS_OK) { Serial.print("MIFARE_read() failed: "); Serial.println(mfrc522.GetStatusCodeName(status)); return 4;//return "4" as error message } Serial.println("block was read"); }
Output
Scan a MIFARE Classic card ..Card Selected.. block was read Access Provided for : DR.KAYARVIZHY.. Scan a MIFARE Classic card ..Card Selected.. block was read Access DENIED for : MR.YOUKNOWWHO.. Scan a MIFARE Classic card ..Card Selected.. block was read Access Provided for : DR.KAYARVIZHY.. Scan a MIFARE Classic card ..Card Selected.. block was read Access Provided for : DR.KAYARVIZHY.. Scan a MIFARE Classic card ..Card Selected.. block was read Access DENIED for : MR.YOUKNOWWHO.. Scan a MIFARE Classic card ..Card Selected.. block was read Access Provided for : DR.KAYARVIZHY.. Scan a MIFARE Classic card ..Card Selected.. block was read Access DENIED for : MR.YOUKNOWWHO.. Scan a MIFARE Classic card