logo-site-sefid
Search
Close this search box.
آر-اف-ای-دی-چیست

آر اف ای دی چیست ؟

نحوه‌ی کار آر اف آی دی و چگونگی ساخت قفل درب آر اف آی دی بر اساس آردوینو

در این آموزش قصد داریم به مواردی چون: آر اف ای دی چیست ؟، چگونه کار می‌کند و چگونه یک قفل درب RFID بر اساس آردوینو بسازم، بپردازیم.

بررسی اجمالی: آر اف ای دی چیست ؟

RFID مخفف عبارت Radio Frequency Identification به معنای شناسایی از طریق امواج رادیویی است و یک فناوری غیر تماسی است که به طور گسترده در صنایع برای مواردی چون ردیابی پرسنل، کنترل دسترسی، مدیریت زنجیره تأمین، ردیابی کتاب‌ها در کتابخانه، سیستم‌های پرداخت عوارض (tollgate) و غیره استفاده می‌گردد.

آر اف ای دی چیست
آر اف ای دی چیست

نحوه‌ی عملکرد RFID

یک سیستم RFID شامل دو عنصر اصلی است، یک فرستنده یا برچسبی قرار گیرنده روی جسمی که می‌خواهیم شناخته شود و یک گیرنده یا تجهیزاتی برای خواندن برچسب.

اجزای تشکیل دهنده‌ی RFID
اجزای تشکیل دهنده‌ی RFID

برچسب خوان RFID خود از اجزای مقابل تشکیل شده است. یک ماژول فرکانس رادیویی، یک بخش کنترلی و یک سیم پیچ آنتن که میدان الکترومغناطیسی فرکانس بالا تولید می‌کند. از سوی دیگر، برچسب معمولاً یک عنصر پسیو (Passive) است که تنها از یک آنتن و یک میکرو چیپ تشکیل شده است؛ بنابراین، هنگامی که به میدان الکترومغناطیسی گیرنده نزدیک می‌شود، به دلیل ایجاد القای مغناطیسی، ولتاژی در سیم پیچ آنتن تولید می‌شود و این ولتاژ، به عنوان ورودی توسط میکرو چیپ مورد بهره برداری قرار می‌گیرد.

میدان الکترومغناطیسی برچسب و برچسب خوان
میدان الکترومغناطیسی برچسب و برچسب خوان

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

همچنین راه دیگری برای انتقال داده‌ها بین برچسب و برچسب خوان وجود دارد که تزویج پس پراکنده (backscattered coupling) نام دارد. در این حالت، برچسب از بخشی از توان دریافت شده برای تشکیل میدان الکترومغناطیسی دیگری استفاده می‌کند که توسط آنتن برچسب خوان انتخاب می‌شود.

RFID و آردوینو

تا اینجا اصول پایه‌ای نحوه‌ی کار تشریح شد و حال می‌توانیم به بررسی نحوه‌ی استفاده از RFID در کنار آردوینو بپردازیم و قفل درب RFID خودمان را بسازیم. ما از برچسب‌هایی بر پایه‌ی پروتکل MIFARE و برچسب خوان MFRC522 RFID که قیمت نسبتاً پایینی دارند استفاده می‌کنیم. همچنین از یک آردوینو نانو استفاده میکنیم که در پروژه های آموزش رباتیک کاربرد زیادی خواهد داشت.

برچسب‌های بر پایه‌ی پروتکل MIFARE و برچسب خوان MFRC522 RFID
برچسب‌های بر پایه‌ی پروتکل MIFARE و برچسب خوان MFRC522 RFID

این برچسب‌ها حافظه‌ای 1 کیلو بایتی دارند و از میکرو چیپی با قابلیت محاسبه‌ی عملگرهای حسابی بهره می‌برند. فرکانس کاری آن‌ها 13.56 مگاهرتز و فاصله‌ای که در آن قادر به عملکرد صحیح هستند بیش از 10 سانتی متر بسته به هندسه‌ی آنتن است. اگر یکی از این برچسب‌ها را در مقابل نور قرار دهیم، می‌توانیم آنتن و میکرو چیپی که در قبل در مورد آن‌ها صحبت کردیم ببینیم.

قرارگرفتن برچسب در معرض نور و مشخص شدن اجزای مداری آن
قرارگرفتن برچسب در معرض نور و مشخص شدن اجزای مداری آن

ذکر این نکته در مورد ماژول برچسب خوان RFID که از پروتکل SPI برای برقراری ارتباط با برد آردوینو استفاده می‌کند و موارد مربوط به نحوه‌ی اتصال آن‌ها ضروری به نظر می‌رسد. توجه داشته باشید که باید Vcc ماژول را به 3.3 ولت متصل کنیم. در مورد سایر پین‌ها، نیازی به نگرانی نیست چرا که تا 5 ولت، قابلیت تحمل دارند.

ارتباط برد آردوینو و مدار RFID-RC522
ارتباط برد آردوینو و مدار RFID-RC522

در صورت نیاز، برای اتصال ماژول، می‌توانیم کتابخانه‌ی MFRC522 را از GitHub دانلود کنیم. این کتابخانه شامل چندین مثال خوب برای درک بیشتر نحوه‌ی استفاده از ماژول است. در ابتدا، می‌توانیم از بارگذاری مثال “DumpInfo” استفاده کنیم و این موضوع که آیا سیستم ما درست کار می‌کند یا خیر را بررسی کنیم. حال اگر مانیتور سریال را اجرا کنیم و برچسب را نزدیک ماژول کنیم، برچسب خوان شروع به خواندن برچسب می‌کند و تمام اطلاعات از برچسب روی مانیتور سریال به نمایش گذاشته خواهد شد.

شماره‌های UID برچسب
شماره‌های UID برچسب

در اینجا باید به این نکته توجه داشت که شماره UID برچسب و تقسیم حافظه‌ی 1 کیلوبایتی به 16 بخش از اهمیت بالایی برخوردار است. این 16 بخش هرکدام به 4 بلوک تقسیم می‌شوند که هر بلوک می‌تواند 2 بایت داده در خود ذخیره کند. برای این آموزش ما از هیچ یک از حافظه‌های برچسب استفاده نخواهیم کرد و تنها به استفاده از شماره‌ی UID برچسب بسنده خواهیم کرد.

پروژه‌ی کنترل دسترسی قفل درب RFID با آردوینو

قبل از اینکه کد پروژه‌ی قفل درب RFID را مرور کنیم، نگاهی به اجزا و نمودارهای مدار این پروژه خواهیم داشت.

شماتیک مداری پروژه‌ی کنترل دسترسی قفل درب RFID با آردوینو
شماتیک مداری پروژه‌ی کنترل دسترسی قفل درب RFID با آردوینو

علاوه بر ماژول RFID، از یک حسگر مجاورت برای بررسی بسته یا باز بودن درب، یک سروو موتور برای ساز و کار قفل درب و یک نمایشگر کاراکتر بهره می‌بریم.

این پروژه به طور کلی مقابل روال زیر دنبال خواهد شد: در ابتدا، یک برچسب اصلی را تنظیم خواهیم کرد و پس از آن سیستم وارد حالت عادی خواهد شد. اگر یک برچسب ناشناخته را اسکن کنیم، دسترسی محدود خواهد شد اما اگر برچسب اصلی را اسکن کنیم وارد حالت برنامه می‌شویم و می‌توانیم در این حالت برچسب ناشناخته را اضافه و مجاز کنیم؛ بنابراین اگر دوباره برچسب را اسکن کنیم، امکان دسترسی فراهم می‌شود تا بتوانیم درب را باز کنیم.

نمونه‌ی ساخته شده
نمونه‌ی ساخته شده

پس از بسته شدن درب، به صورت خودکار اقدام به قفل شدن می‌کند. اگر بخواهیم برچسبی را از سیستم حذف کنیم، کافی است مجدداً به حالت برنامه برویم و برچسب شناخته شده را اسکن کنیم.

کد منبع

حال زمان آن رسیده است که نگاهی به کد بیندازیم؛ بنابراین در اولین گام، باید کتابخانه‌هایی برای ماژول RFID، نمایشگر و سروو موتور بیابیم که متغیرهای مورد نیاز را برای برنامه‌ی زیر تعریف کند و همچنین نمونه‌های کتابخانه‌ها را ایجاد کند.

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

#define RST_PIN   9
#define SS_PIN    10

byte readCard[4];
char* myTags[100] = {};
int tagsCount = 0;
String tagID = "";
boolean successRead = false;
boolean correctTag = false;
int proximitySensor;
boolean doorOpened = false;

// Create instances
MFRC522 mfrc522(SS_PIN, RST_PIN);
LiquidCrystal lcd(2, 3, 4, 5, 6, 7); //Parameters: (rs, enable, d4, d5, d6, d7)
Servo myServo; // Servo motor

در بخش تنظیمات، ابتدا ماژول‌ها را مقداردهی اولیه می‌کنیم و مقدار اولیه سروو موتور را در موقعیت قفل تنظیم می‌کنیم. سپس، پیام اولیه را بر روی صفحه نمایش چاپ می‌کنیم و با حلقه “while” زیر منتظر می‌مانیم تا یک برچسب اصلی اسکن شود. تابع سفارشی getID برچسب UID را دریافت می‌کند و ما آن را در اولین مکان آرایه [0] myTags قرار می‌دهیم.

void setup() {
  // Initiating
  SPI.begin();        // SPI bus
  mfrc522.PCD_Init(); //  MFRC522
  lcd.begin(16, 2);   // LCD screen
  myServo.attach(8);  // Servo motor

  myServo.write(10); // Initial lock position of the servo motor
  // Prints the initial message
  lcd.print("-No Master Tag!-");
  lcd.setCursor(0, 1);
  lcd.print("    SCAN NOW");
  // Waits until a master card is scanned
  while (!successRead) {
    successRead = getID();
    if ( successRead == true) {
      myTags[tagsCount] = strdup(tagID.c_str()); // Sets the master tag into position 0 in the array
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Master Tag Set!");
      tagsCount++;
    }
  }
  successRead = false;
  printNormalModeMessage();
}

در ادامه به بررسی تابع getID() خواهیم پرداخت. این تابع، این موضوع را بررسی می‌کند که آیا برچسب جدیدی در کنار برچسب خوان قرار گرفته است یا خیر و در این صورت، به حلقه‌ی “for” که UID برچسب را در اختیار می‌گذارد، ادامه می‌دهیم. برچسب‌هایی که از آن ها استفاده می‌کنیم، شماره‌ی UID 4 بایتی دارند که دقیقاً به همین دلیل هم هست که ما به چهار تکرار در این حلقه نیاز داریم و از یک تابع concat() استفاده می‌کنیم که 4 بایت را در یک متغیر رشته جداگانه قرار می‌دهد. همچنین، همة کاراکترهای رشته را با حروف بزرگ انگلیسی تنظیم می‌کنیم و در پایان عملیات خواندن را متوقف می‌کنیم.

uint8_t getID() {
  // Getting ready for Reading PICCs
  if ( ! mfrc522.PICC_IsNewCardPresent()) { //If a new PICC placed to RFID reader continue
    return 0;
  }
  if ( ! mfrc522.PICC_ReadCardSerial()) {   //Since a PICC placed get Serial and continue
    return 0;
  }
  tagID = "";
  for ( uint8_t i = 0; i < 4; i++) {  // The MIFARE PICCs that we use have 4 byte UID
    readCard[i] = mfrc522.uid.uidByte[i];
    tagID.concat(String(mfrc522.uid.uidByte[i], HEX)); // Adds the 4 bytes in a single String variable
  }
  tagID.toUpperCase();
  mfrc522.PICC_HaltA(); // Stop reading
  return 1;
}

قبل از اینکه وارد حلقة اصلی شویم، در پایان‌ بخش تنظیمات، تابع   printNormalModeMessage() را نیز فراخوانی می‌کنیم که پیام “Access Control” را روی نمایشگر نشان می‌دهد.

void printNormalModeMessage() {
  delay(1500);
  lcd.clear();
  lcd.print("-Access Control-");
  lcd.setCursor(0, 1);
  lcd.print(" Scan Your Tag!");
}

در حلقة اصلی، با خواندن مقادیر حسگر مجاورت کار را آغاز می‌کنیم که به ما اطلاع می‌دهد که آیا در بسته است یا خیر.

int proximitySensor = analogRead(A0);

بنابراین اگر در بسته باشد، با استفاده از همین خطوط که در تابع getID() تشریح شد، فرایند اسکن کردن آغاز خواهد شد و UID را از برچسب جدید دریافت می‌کنیم. باید توجه داشته باشید که در اینجا، کد اقدام جدیدی انجام نمی‌دهد مگر اینکه یک برچسب اسکن شود و این به دلیل قرار گرفتن “return” در عبارت “if” است.

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

// Checks whether the scanned tag is the master tag
    if (tagID == myTags[0]) {
      lcd.clear();
      lcd.print("Program mode:");
      lcd.setCursor(0, 1);
      lcd.print("Add/Remove Tag");
      while (!successRead) {
        successRead = getID();
        if ( successRead == true) {
          for (int i = 0; i < 100; i++) {
            if (tagID == myTags[i]) {
              myTags[i] = "";
              lcd.clear();
              lcd.setCursor(0, 0);
              lcd.print("  Tag Removed!");
              printNormalModeMessage();
              return;
            }
          }
          myTags[tagsCount] = strdup(tagID.c_str());
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("   Tag Added!");
          printNormalModeMessage();
          tagsCount++;
          return;
        }
      }
    }

 در خارج از حالت برنامه، با حلقه بعدی “for” بررسی می‌کنیم که آیا برچسب اسکن شده برابر با هر یک از برچسب‌های ثبت شده است یا اینکه در را باز می‌کنیم یا دسترسی را محروم می‌کنیم. در انتهای عبارت “else” منتظر می‌مانیم تا در بسته شود، سپس در را قفل می‌کنیم و پیام حالت عادی را دوباره چاپ می‌کنیم.

// Checks whether the scanned tag is authorized
    for (int i = 0; i < 100; i++) {
      if (tagID == myTags[i]) {
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print(" Access Granted!");
        myServo.write(170); // Unlocks the door
        printNormalModeMessage();
        correctTag = true;
      }
    }
    if (correctTag == false) {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(" Access Denied!");
      printNormalModeMessage();
    }
  }
  // If door is open...
  else {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print(" Door Opened!");
    while (!doorOpened) {
      proximitySensor = analogRead(A0);
      if (proximitySensor > 200) {
        doorOpened = true;
      }
    }
    doorOpened = false;
    delay(500);
    myServo.write(10); // Locks the door
    printNormalModeMessage();
  }

بنابراین تقریباً پروژه به اتمام رسید و کد کامل آن مطابق زیر است:

/*
* Arduino Door Lock Access Control Project
* 
* Library: MFRC522, https://github.com/miguelbalboa/rfid
*/

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

#define RST_PIN   9
#define SS_PIN    10

byte readCard[4];
char* myTags[100] = {};
int tagsCount = 0;
String tagID = "";
boolean successRead = false;
boolean correctTag = false;
int proximitySensor;
boolean doorOpened = false;

// Create instances
MFRC522 mfrc522(SS_PIN, RST_PIN);
LiquidCrystal lcd(2, 3, 4, 5, 6, 7); //Parameters: (rs, enable, d4, d5, d6, d7)
Servo myServo; // Servo motor

void setup() {
  // Initiating
  SPI.begin();        // SPI bus
  mfrc522.PCD_Init(); //  MFRC522
  lcd.begin(16, 2);   // LCD screen
  myServo.attach(8);  // Servo motor

  myServo.write(10); // Initial lock position of the servo motor
  // Prints the initial message
  lcd.print("-No Master Tag!-");
  lcd.setCursor(0, 1);
  lcd.print("    SCAN NOW");
  // Waits until a master card is scanned
  while (!successRead) {
    successRead = getID();
    if ( successRead == true) {
      myTags[tagsCount] = strdup(tagID.c_str()); // Sets the master tag into position 0 in the array
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Master Tag Set!");
      tagsCount++;
    }
  }
  successRead = false;
  printNormalModeMessage();
}

void loop() {
  int proximitySensor = analogRead(A0);
  // If door is closed...
  if (proximitySensor > 200) {
    if ( ! mfrc522.PICC_IsNewCardPresent()) { //If a new PICC placed to RFID reader continue
      return;
    }
    if ( ! mfrc522.PICC_ReadCardSerial()) {   //Since a PICC placed get Serial and continue
      return;
    }
    tagID = "";
    // The MIFARE PICCs that we use have 4 byte UID
    for ( uint8_t i = 0; i < 4; i++) {  //
      readCard[i] = mfrc522.uid.uidByte[i];
      tagID.concat(String(mfrc522.uid.uidByte[i], HEX)); // Adds the 4 bytes in a single String variable
    }
    tagID.toUpperCase();
    mfrc522.PICC_HaltA(); // Stop reading

    correctTag = false;
    // Checks whether the scanned tag is the master tag
    if (tagID == myTags[0]) {
      lcd.clear();
      lcd.print("Program mode:");
      lcd.setCursor(0, 1);
      lcd.print("Add/Remove Tag");
      while (!successRead) {
        successRead = getID();
        if ( successRead == true) {
          for (int i = 0; i < 100; i++) {
            if (tagID == myTags[i]) {
              myTags[i] = "";
              lcd.clear();
              lcd.setCursor(0, 0);
              lcd.print("  Tag Removed!");
              printNormalModeMessage();
              return;
            }
          }
          myTags[tagsCount] = strdup(tagID.c_str());
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("   Tag Added!");
          printNormalModeMessage();
          tagsCount++;
          return;
        }
      }
    }
    successRead = false;
    // Checks whether the scanned tag is authorized
    for (int i = 0; i < 100; i++) {
      if (tagID == myTags[i]) {
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print(" Access Granted!");
        myServo.write(170); // Unlocks the door
        printNormalModeMessage();
        correctTag = true;
      }
    }
    if (correctTag == false) {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(" Access Denied!");
      printNormalModeMessage();
    }
  }
  // If door is open...
  else {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print(" Door Opened!");
    while (!doorOpened) {
      proximitySensor = analogRead(A0);
      if (proximitySensor > 200) {
        doorOpened = true;
      }
    }
    doorOpened = false;
    delay(500);
    myServo.write(10); // Locks the door
    printNormalModeMessage();
  }
}

uint8_t getID() {
  // Getting ready for Reading PICCs
  if ( ! mfrc522.PICC_IsNewCardPresent()) { //If a new PICC placed to RFID reader continue
    return 0;
  }
  if ( ! mfrc522.PICC_ReadCardSerial()) {   //Since a PICC placed get Serial and continue
    return 0;
  }
  tagID = "";
  for ( uint8_t i = 0; i < 4; i++) {  // The MIFARE PICCs that we use have 4 byte UID
    readCard[i] = mfrc522.uid.uidByte[i];
    tagID.concat(String(mfrc522.uid.uidByte[i], HEX)); // Adds the 4 bytes in a single String variable
  }
  tagID.toUpperCase();
  mfrc522.PICC_HaltA(); // Stop reading
  return 1;
}

void printNormalModeMessage() {
  delay(1500);
  lcd.clear();
  lcd.print("-Access Control-");
  lcd.setCursor(0, 1);
  lcd.print(" Scan Your Tag!");
}

 

رضا قنبری
متخصص آموزش رباتیک

رضا قنبری هستم متخصص آموزش رباتیک با بیش از 10 سال سابقه فعالیت در ایران

این مطلب را به اشتراک بگذارید

ماژول کاهنده

ماژول كاهنده قبل از خواندن مقاله ماژول كاهنده بهتر است در نظر داشته باشید مقالاتی که با عنوان ماژول در سایت قرار گرفته اند از

ماژول تشخیص دود و گاز

ماژول تشخیص دود و گاز قبل از خواندن این مقاله بهتر است در نظر داشته باشید مقالاتی که با عنوان ماژول در سایت قرار گرفته

دیدگاه‌ خود را بنویسید

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