四时宝库

程序员的知识宝库

Arduino 的 RFID 门锁制作-原理,接线图,代码

在本教程中,我们将了解什么是 RFID、它是如何工作的以及如何制作基于 Arduino 的 RFID 门锁。您可以观看以下视频或阅读下面的书面教程以了解更多详细信息。

概述


RFID 代表射频识别(Radio Frequency Identification),它是一种非接触式技术,广泛应用于许多行业,用于人员跟踪、访问控制、供应链管理、图书馆书籍跟踪、收费站系统等任务。


RFID 的工作原理


RFID 系统由两个主要组件组成,一个是位于我们想要识别的对象上的标签,另一个是阅读器。

RFID阅读器由射频模块、控制单元和产生高频电磁场的天线线圈组成。另一方面,标签通常是无源元件,仅由天线和电子微芯片组成,因此当它靠近收发器的电磁场时,由于感应,在其天线线圈中产生电压,这电压作为微芯片的电源。

现在,当标签通电时,它可以从阅读器中提取传输的消息,并将消息发送回阅读器,它使用一种称为负载操作的技术。打开和关闭标签天线上的负载会影响阅读器天线的功耗,这可以用电压降来衡量。电压的这种变化将被捕获为 1 和 0,这就是数据从标签传输到阅读器的方式。

阅读器和标签之间还有另一种数据传输方式,称为反向散射耦合。在这种情况下,标签使用部分接收功率来生成另一个电磁场,该电磁场将被阅读器的天线接收。

RFID 和 Arduino


这就是基本的工作原理,现在让我们看看如何将 RFID 与 Arduino 结合使用并构建我们自己的 RFID 门锁。我们将使用基于 MIFARE 协议和 MFRC522 RFID 阅读器的标签,它们的成本仅为几元。

这些标签有 1kb 的内存,并有一个可以进行算术运算的微芯片。它们的工作频率为 13.56 MHz,工作距离可达 10 cm,具体取决于天线的几何形状。如果我们将这些标签中的一个放在光源前面,我们可以注意到我们之前谈到的天线和微芯片。

至于 RFID 阅读器模块,它使用 SPI 协议与 Arduino 板进行通信,以下是我们需要如何连接它们。请注意,我们必须将模块的 VCC 连接到 3.3V,至于其他引脚,我们不必担心,因为它们可以承受 5V。

连接模块后,我们需要 从 GitHub下载 MFRC522库。该库附带了几个很好的示例,我们可以从中学习如何使用该模块。

首先我们可以上传“DumpInfo”示例并测试我们的系统是否正常工作。现在,如果我们运行串行监视器并将标签放在模块附近,阅读器将开始读取标签,并且来自标签的所有信息都将显示在串行监视器上。

这里我们可以看到标签的UID号以及1KB的内存,实际分成16个扇区,每个扇区分成4个块,每个块可以存储2个字节的数据。在本教程中,我们不会使用任何标签的内存,我们将只使用标签的 UID 号。

Arduino RFID 门锁门禁控制项目


在我们介绍我们的 RFID 门锁项目的代码之前,让我们先来看看这个项目的组件和电路原理图。

除了 RFID 模块外,我们还将使用接近传感器来检查门是关闭还是打开,伺服电机用于锁定机构和字符显示器。

本 Arduino 教程所需的组件:

· MFRC522 RFID模块

· 伺服电机

· LCD 显示屏

· Arduino 板

· 面包板和跳线

· 接近传感器 CNY70

该项目有以下工作流程:

首先我们必须设置一个主标签,然后系统进入正常模式。如果我们扫描未知标签,访问将被拒绝,但如果我们扫描主服务器,我们将进入一个程序模式,我们可以从中添加和授权未知标签。所以现在如果我们再次扫描标签,将被授予访问权限,因此我们可以打开门。

我们关上门后,门会自动锁上。如果我们想从系统中删除一个标签,我们只需要再次进入程序模式,扫描已知标签,它将被删除。

源代码解释


现在让我们来看看代码。 首先我们需要包含 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

setup部分,我们初始化模块,并将伺服电机的初始值设置为锁定位置。然后我们将初始消息打印到显示器上,并通过以下“while”循环等待主标签被扫描。getID() 自定义函数获取标签 UID 并将其放入 myTags[0] 数组的第一个位置。

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。我们使用的标签有 4 个字节的 UID 号,这就是为什么我们需要对这个循环进行 4 次迭代,并使用 concat() 函数将 4 个字节添加到单个 String 变量中。我们还将字符串的所有字符设置为大写,最后我们停止阅读。

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;
}
Before we enter the main loop, at the end of the setup section, we also call the printNormalModeMessage() custom function which prints the “Access Control” message on the display.
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。我们在这里可以注意到,由于“if”语句中的“return”行,在我们扫描标签之前,代码不会继续进行。

一旦我们扫描了标签,我们就会检查该标签是否是我们之前注册的主,如果是,我们将进入程序模式。在这种模式下,如果我们扫描一个已经授权的标签,它将从系统中删除,或者如果标签未知,它将作为授权添加到系统中。

// 检查扫描到的标签是否是主标签
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”语句的最后,我们等到门关闭,然后锁上门并再次打印正常模式消息。

// 检查扫描的标签是否被授权
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 门锁门禁控制项目
*
* 作者:Dejan Nedelkovski,www.HowToMechatronics.com
*
* 库: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!");
}

让我们一起动手试试吧!

如果您喜欢本教程,欢迎收藏,点赞加关注喔!这将为我后续文章提供更大的动力。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接