ماژول RFID-RC522

ماژول RFID-RC522

سلام به همگی . تو این پست میخوایم اول به شما یاد بدیم که RFID چی هست و بعدا بریم سراغ راه اندازی ماژول RFID با آردوینو .

RFID چیست؟

کلمه RFID مخفف  Radio Frequency Identification یعنی شناسایی بوسیله امواج رادیویی هست . که درواقع یک سامانهٔ شناسایی بی‌سیم قادر به تبادل داده‌ها به‌وسیلهٔ برقراری اطلاعات بین یک Reader (بازخوان یا تگخوان) و یک Tag (شناسه یا تگ) که به یک کالا، شی، کارت و… متصل شده‌است می‌باشد.به عبارت دیگه سامانه‌های RFID از سیگنال‌های الکترونیکی و الکترومغناطیسی برای خواندن و نوشتن داده‌ها بدون تماس استفاده میکنن.

تگ RFID چیست و چگونه کار میکند؟

تگ های RFID متشکل از یک چیپ سیلیکونی ، یک سیم پیچ مسی و یک خازن هست که میتونه داخل یک کارت ، کیف پول، جاسوئیچی و حتی دست شما باشه! تگ های RFID چند سالی هست که داخل دست کاشت میشن و میشه اطلاعاتی رو از جمله کارت های پرداخت و اطلاعات بیماری فرد رو در اونها ذخیره کرد . نمونش رومیتونید داخل عکس پایین ببینید:

این چیپ ا داخل مچ دست قرار میگیرن و میتونن اطلاعات مثلا بیمار رو ذخیره کنن . در نتیجه اگر مثلا فرد تصادف کنه یا با سطح هوشیاری پایین مراجعه کنه، پزشک با اسکن این تگ داخل دست فرد میتونه سابقه بیماری های زمینه ای و داروهاییکه فرد به اونا حساسه رو ببینه. یا فرد در مترو و اتوبوس با جلو بردن دستش جلوی RFID READER میتونه پول سفر رو پرداخت کنه . در کل خیلی کاربردی هست . جنس بدنه این تگ ها هم بوروسیلیکات هست تا توی دست باعث عفونت نشه . ولی خب یکم اذیت میکنه شما همش یه چیپ داخل دستت باشه . بهرحال با این تگ آشنا شدید .

ماژول RC522

این ماژول رو که میخرید ممکنه به شکل زیر براتون ارسال بشه:

یک ماژول و دو عدد تگ RFID و دو عدد پین هدر برای ما ارسال شد که پین هدر رو باید خودتون لحیم کنید روش.

ماژول های زیادی توی بازار برای خواندن و نوشتن کارت RFID توی بازار وجود دارن و ما کاربردی ترینشون رو انتخاب کردیم. ولتاژ این ماژول 3.3 ولت هست و از سه روش SPI و I2C و UART قابل راه اندازیه . این ماژولی که میبینید منحصرا برای روش SPIساخته شده و بطور فیزیکی نمیشه از روش دیگه یعنی I2C و UART راه اندازیش کرد. باید تغییری در سیم کشی برد انجام بدیم ولی هنوز کتابخونه درست درمونی واسه این کار پیدا نکردیم و اگر تونستیم حلش کنیم این پست به روزرسانی میشه. طبق تست ما این ماژول تا 2 سانتی متر تگ رو میخونه . میریم سراغ روش SPI:

اتصال پین ها:

نام پین روی ماژول نام پین روی آردوینو
SDADIGITAL 10
SCKDIGITAL 13
MOSIDIGITAL 11
MISODIGITAL 12
RQمتصل نیست
GNDGND
RSTDIGITAL 9
3.33.3V

حالا که سیم کشی رو انجام دادید میریم سراغ کد. قبلش باید کتابخونه MFRC522 رو نصب کنید که از منوی sketch>>include library>>manage libraries قابل نصب هست.حالا کد رو آپلود کنید و سریال مانیتور رو باز کنید و باودریت رو روی 9600 تنظیم کنید.

 
#include <SPI.h>
#include <MFRC522.h>
 
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.

void setup() 
{
  Serial.begin(9600);   // Initiate a serial communication
  SPI.begin();      // Initiate  SPI bus
  mfrc522.PCD_Init();   // Initiate MFRC522
  Serial.println("Approximate your card to the reader...");
  Serial.println();

}
void loop() 
{
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent()) 
  {
    return;
  }
  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) 
  {
    return;
  }
  //Show UID on serial monitor
  Serial.print("UID tag :");
  String content= "";
  byte letter;
  for (byte i = 0; i < mfrc522.uid.size; i++) 
  {
     Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
     Serial.print(mfrc522.uid.uidByte[i], HEX);
     content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  Serial.println();
  Serial.print("Message : ");
  content.toUpperCase();
  if (content.substring(1) == "D0 48 18 32") //change here the UID of the card/cards that you want to give access
  {
    Serial.println("Authorized access");
    Serial.println();
    delay(3000);
  
  }
 
 else   {
    Serial.println(" Access denied");
    delay(3000);
  }
}

اگر همه چی درست پیش رفته باشه با نزدیک کردن تگ به ماژول همچین چیزی میبینید:

حالا بریم سراغ قسمت های مهم کد که نیازه بدونید:

اول کتابخونه های موردنیاز رو معرفی میکنیم:

#include <SPI.h>
#include <MFRC522.h>

معرفی پایه های SDAو RST:

#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.

ایجاد ارتباط سریال و تنظیم باودریت:

  Serial.begin(9600); 

راه اندازی ارتباط SPI:

 SPI.begin(); 

اینجا هم میتونید UID کد رو تغییر بدید و UIDکارت خودتون رو وارد کنید . چندین تا UIDهم میتونید تعریف کنید براش:

  if (content.substring(1) == "D0 48 18 32") 

خب این کد فقط کارت رو میخونه و UID کارت رو به شما میگه . حالا اگر نیاز باشه اطلاعات داخل کارت روببینیم چی؟ اینجا کد زیر به کمک ما میاد:

این کد از منوی File>>examples>>MFRC522>>Dumpinfo در دسترسه .

/*
 * --------------------------------------------------------------------------------------------------------------------
 * Example sketch/program showing how to read data from a PICC to serial.
 * --------------------------------------------------------------------------------------------------------------------
 * This is a MFRC522 library example; for further details and other examples see: https://github.com/miguelbalboa/rfid
 * 
 * Example sketch/program showing how to read data from a PICC (that is: a RFID Tag or Card) using a MFRC522 based RFID
 * Reader on the Arduino SPI interface.
 * 
 * When the Arduino and the MFRC522 module are connected (see the pin layout below), load this sketch into Arduino IDE
 * then verify/compile and upload it. To see the output: use Tools, Serial Monitor of the IDE (hit Ctrl+Shft+M). When
 * you present a PICC (that is: a RFID Tag or Card) at reading distance of the MFRC522 Reader/PCD, the serial output
 * will show the ID/UID, type and any data blocks it can read. Note: you may see "Timeout in communication" messages
 * when removing the PICC from reading distance too early.
 * 
 * If your reader supports it, this sketch/program will read all the PICCs presented (that is: multiple tag reading).
 * So if you stack two or more PICCs on top of each other and present them to the reader, it will first output all
 * details of the first and then the next PICC. Note that this may take some time as all data blocks are dumped, so
 * keep the PICCs at reading distance until complete.
 * 
 * @license Released into the public domain.
 * 
 * Typical pin layout used:
 * -----------------------------------------------------------------------------------------
 *             MFRC522      Arduino       Arduino   Arduino    Arduino          Arduino
 *             Reader/PCD   Uno/101       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 <SPI.h>
#include <MFRC522.h>

#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

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
	delay(4);				// Optional delay. Some board do need more time after init to be ready, see Readme
	mfrc522.PCD_DumpVersionToSerial();	// Show details of PCD - MFRC522 Card Reader details
	Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks..."));
}

void loop() {
	// Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
	if ( ! mfrc522.PICC_IsNewCardPresent()) {
		return;
	}

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

	// Dump debug info about the card; PICC_HaltA() is automatically called
	mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
}

کد رو که آپلود کردید سریال مانیتور رو باز کنید و باودریت 9600 رو انتخاب کنید و اگر همه چی درست باشه میتونید تصویری مشابه تصویر زیر رو بعد از نزدیک کردن کارت به ماژول ببینید:

حتما یادتون باشه کارت رو باید تا زمانیکه عدد سمت چپ به صفر میرسه نزدیک ماژول نگه دارید وگرنه تمام اطلاعات داخل کارت خونده نمیشه. حالا این جدول ها به چه معنا هستن؟

تگ های RFID در واقع 1KB حافظه دارن.این حافظه به 16 بخش تقسیم شده ( بخشهای 0 تا 15) و هر بخش دوباره خودش به 4 بلوک تقسیم شده ( بلوک 0 تا 3) و هرکدوم از این بلوک ها 16 بایت دیتا رو میتونن تو خودشون ذخیره کنن(از 0 تا 16 ).و اگر 16 بخش رو در 4 بلوک و 16 واحد حافظه ضرب کنیم عدد 1024 بایت که معادل 1 کیلوبایت هست بدست میاد .توی تصویر زیر میتونید بخشهای حافظه رو که رنگی مشخص شدن ببینید:

بلوک سوم هر بخش هم SECTOR TRAILER نام داره و داخلش اطلاعات دسترسی یا Access Bits قرار داره و قابلیت دسترسی نوشتن روی هر بلوک رو ایجاد میکنه(قسمت سبز رنگ عکس پایین) . یعنی فقط سه بلوک از هر بخش قابل ذخیره سازی دیتا هست (بلوک های 0و1و2). بلوک 0 بخش 0 هم اطلاعات شرکت سازنده و ایدی کارت رو ذخیره میکنه (قسمت قرمز رنگ توی عکس زیر):

بوسیله کد زیر هم میتونید نوشته های داخل تگ رو تغییر بدید . البته دقت کنید که این کار خیلی ریسک داره و ممکنه تگ کلا بسته بشه و دیگه نتونید بخونیدش.یادتون نره تا زمانیکه عملیات خوندن و یا نوشتن انجام میشه کارت رو نزدیک ماژول نگه دارید.

#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
 
//this is the block number we will write into and then read.
int block=2;  
 
byte blockcontent[16] = {"clooner.ir"};  //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.
 
//This array is used for reading out a block.
byte readbackblock[18];
 
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.
  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
  }
}
 
void loop()
{  
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return;
  }
   
  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) 
  {
    return;
  }
    Serial.println("card selected");
          
   //the blockcontent array is written into the card block
   writeBlock(block, blockcontent);
    
   //read the block back
   readBlock(block, readbackblock);
   //uncomment below line if you want to see the entire 1k memory with the block written into it.
   //mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
    
   //print the block contents
   Serial.print("read block: ");
   for (int j=0 ; j<16 ; j++)
   {
     Serial.write (readbackblock[j]);
   }
   Serial.println("");
}
 
 
 
//Write specific block    
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;}
  Serial.print(blockNumber);
  Serial.println(" is a data block:");
   
  //authentication of the desired block for access
  byte 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
  }
   
  //writing the block 
  status = mfrc522.MIFARE_Write(blockNumber, arrayAddress, 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");
}
 
 
 
//Read specific block
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
  byte 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 (read): ");
         Serial.println(mfrc522.GetStatusCodeName(status));
         return 3;//return "3" as error message
  }
 
//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");
}

توی کد زیر بلوکی که میخواید اطلاعات در اون وارد بشه رو انتخاب میکنید.یادتون باشه به هیچ وجه داخل بلوک 3 چیزی ننویسید چون کلا این بخش رو غیر قابل استفاده میکنه .

//this is the block number we will write into and then read.
int block=2;

اینجا یه آرایه 16 بیتی میسازیم تا اطلاعاتی که میخوایم رو تگ بنویسه. اگر داخل آرایه صفر قرار بدیم اون بلوک رو پاک میکنه:

byte blockcontent[16] = {"clooner.ir"}; 
//byte blockcontent[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

بعد یک آرایه 18 بیتی برای نوشتن و خواندن دیتا تعریف میکنیم . چرا 18 مگه نباید 16 باشه؟ خب بخاطر این 18 استفاده میکنیم چون توی روش MIFARE_Read در کتابخانه  MFRC522 به یک بافر حداقل 18 بیتی برای ذخیره 16 بایت یک بلوک نیاز داریم:

byte readbackblock[18];

اگر کارتتون نو هست باید رمز عبور براش تعریف کنید که 0xFF تعیین شده. حتما خودتون رمز بزارید براش مخصوصا اگر پروژه مهمی دارید.اگر هم کارتی که قبلا پروگرام شده رو در اختیار دارید باید رمزش رو بدونید و داخل key قرارش بدید.

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
}

به اینصورت شما تونستید دیتایی داخل تگ بنویسید.

امیدوارم از خوندن این پست لذت برده باشید . اگر سوالی داشتید از قسمت نظرات بپرسید .

موفق باشید.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *