在本教程中,我们将学习什么是RFID,它如何工作,以及如何制作基于Arduino的RFIDbetway门锁。你可以观看下面的视频或阅读下面的书面教程了解更多细节。
概述
RFID代表无线电频率识别它是一种非接触式技术,广泛应用于许多行业,如人员跟踪、访问控制、供应链管理、图书馆图书跟踪、收费站系统等。
RFID的工作原理
射频识别系统由两个主要部件组成,一个位于我们想要被识别的物体上的应答器或标签,以及一个收发器或读卡器。
该RFID阅读器由射频模块、控制单元和产生高频电磁场的天线线圈组成。另一方面,标签通常是被动组件,由天线和电子芯片,所以当它附近的电磁场的收发器,由于感应电压产生的天线线圈这芯片的电压作为功率。
现在,当标签启动后,它可以从阅读器中提取传输的消息,为了将消息发送回阅读器,它使用了一种称为负载操作的技术。标签天线上的负载开关会影响阅读器天线的功耗,功耗可以通过电压降来测量。电压的变化将被捕获为1和0,这就是数据从标签传输到阅读器的方式。
在读取器和标签之间还有另一种数据传输方式,叫做反向散射耦合。在这种情况下,标签使用接收到的部分能量产生另一个电磁场,该电磁场将被读取器的天线接收到。
RFID和Arduino
这就是基本的工作原理,现在让我们看看如何将射频识别与Arduino结合来制作我们自己的射频识别门锁。我们将使用基于MIFARE协议和MFRC522 RFID阅读器的标签,这只需要几美元。
这些标签有1kb的内存和一个可以做算术运算的微芯片。它们的工作频率为13.56 MHz,根据天线的几何形状,工作距离可达10厘米。如果我们把其中一个标签放在光源前,我们可以注意到天线和我们之前提到的微芯片。
RFID读写器模块使用SPI协议与Arduino板进行通信,下面是我们需要如何连接它们。请注意,我们必须将模块的VCC连接到3.3V,至于其他引脚,我们不必担心,因为它们是5V容限。
连接模块之后,我们需要下载MFRC522图书馆从GitHub。该库提供了几个很好的示例,我们可以从中学习如何使用该模块。
首先,我们可以上传“DumpInfo”示例并测试我们的系统是否正常工作。现在,如果我们运行Serial Monitor并将标记放在模块附近,读取器将开始读取标记,标记中的所有信息将显示在串行监视器上。
在这里我们可以看到标签的UID号以及1kb的内存,它实际上被分成16个扇区,每个扇区分成4个块,每个块可以存储2字节的数据。在本教程中,我们不会使用任何标签的内存,我们只使用标签的UID号。
Arduino RFID门锁门禁项目
在我们讨论射频识别门锁项目的代码之前,让我们先看看这个项目的组件和电路原理图。
除了RFID模块,我们还将使用一个接近传感器来检查门是否关闭或打开,一个伺服电机用于锁机构和一个字符显示。
你可以从下面的链接获得这个Arduino教程所需的组件:
- MFRC522 RFID模块.........................亚马逊/Banggood/阿里巴巴全球速卖通
- 伺服电机 ............................................亚马逊/Banggood/阿里巴巴全球速卖通
- 液晶显示器 .............................................亚马逊/Banggood/阿里巴巴全球速卖通
- Arduino电路板 ........................................亚马逊/Banggood/阿里巴巴全球速卖通
- 面包板和跳线.................亚马逊/Banggood/阿里巴巴全球速卖通
- 接近传感器CNY70 ........................亚马逊/阿里巴巴全球速卖通
必威外围提钱披露:这些是联盟链接。作为亚马逊助理,我从合格购买中获得。
该项目有以下工作流程:首先,我们必须设置一个主标签,然后系统进入正常模式。如果我们扫描一个未知的标签,访问将被拒绝,但如果我们扫描主,我们将进入一个程序模式,从那里我们可以添加和授权未知的标签。现在如果我们再扫描一次标签就可以打开门了。
我们关门后,门会自动锁上。如果我们想从系统中删除一个标签,我们只需要再次进入程序模式,扫描know标签,它就会被删除。
源代码
现在让我们看一下代码。因此,首先我们需要包括射频识别模块的库,显示和伺服电机,定义一些变量所需的程序,以及创建库的实例。
#include#include #include #include < servi .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;//创建实例MFRC522 MFRC522 (SS_PIN, RST_PIN);液晶显示器(2,3,4,5,6,7); //Parameters: (rs, enable, d4, d5, d6, d7) Servo myServo; // Servo motor
在设置部分,首先对模块进行初始化,将伺服电机的初始值设置为锁定位置。然后,我们将初始消息打印到显示器上,并使用下面的“while”循环,等待主标记被扫描。getID()自定义函数获取标签UID,并将其放入myTags[0]数组的第一个位置。
void setup(){//初始化SPI.begin();// SPI总线mfrc522.PCD_Init();// mfrc522 lcd.begin(16,2);// LCD屏幕myServo.attach(8);//伺服电机myServo.write(10);//伺服电机的初始锁定位置//打印初始消息lcd.print(“ - 没有主标记! - ”);lcd.setcursor(0,1);lcd.print(“立即扫描”);//等待master card被扫描,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(){//准备读取PICCs if (!mfrc522.PICC_IsNewCardPresent()){//如果一个新的PICC放置到RFID阅读器继续返回0;}如果(!mfrc522.picc_readcardserial()){//由于picc放置了串行并继续返回0;} tagID = "";for(uint8_t i = 0; i <4; i ++){//我们使用的mifare piccs有4个字节uid readcard [i] = mfrc522.uid.uidbyte [i];tagid.concat(string(mfrc522.uid.uidbyte [i],hex));//在一个字符串变量中添加4个字节}tagID.toUpperCase();mfrc522.PICC_HaltA ();//停止读取}
在进入主循环之前,在设置部分的末尾,我们还调用了printNormalModeMessage()自定义函数,该函数在显示器上打印“Access Control”消息。
void printNormalModeMessage(){延迟(1500);lcd.clear ();lcd.print(“ - Access Control-”);lcd.setcursor(0,1);lcd.print(“扫描你的标签!”);}
在主回路中,我们从读取接近传感器的值开始,它告诉我们门是否关闭。
int proximitySensor = analogRead(A0);
因此,如果门关闭,使用与我们在getID()自定义函数中描述的相同的行,我们将扫描并获取新标记的UID。我们可以在这里注意到,由于“if”语句中的“return”行,代码在扫描标记之前不会继续执行。
一旦我们扫描了这个标签,我们就会检查这个标签是否是我们之前注册的master,如果是这样,我们就会进入程序模式。在这种模式下,如果我们扫描一个已经授权的标签,它将从系统中删除,或者如果标签是未知的,它将作为授权添加到系统中。
//检查扫描的标签是否是主标签if (tagID == myTags[0]) {lcd.clear();lcd.print(“计划模式:”);lcd.setcursor(0,1);lcd.print(“添加/删除标签”);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(“删除标签!”);printNormalModeMessage (); return; } } myTags[tagsCount] = strdup(tagID.c_str()); lcd.clear(); lcd.setCursor(0, 0); lcd.print(" Tag Added!"); printNormalModeMessage(); tagsCount++; return; } } }
在程序模式之外,通过下一个“for”循环,我们检查扫描的标签是否等于任何挂号标签,我们要么解锁门或保持访问拒绝。最后在“别的”声明中我们等到门关闭,然后我们锁定了门并再次打印了正常模式消息。
//检查扫描的标签是否被授权(int i = 0; i <100; i ++){if(tagid == mytags [i]){lcd.clear();lcd.setCursor(0,0);lcd.print(“获得授予的!”);myServo.write (170);//打开门printNormalModeMessage();correctTag = true;}} if (correctTag == false) {lcd.clear();lcd.setCursor(0,0);lcd.print(“拒绝访问!”);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.www.mfxpo.com * *图书馆:bet188官方网站MFRC522,https://github.com/miguelbalboa/rfid * / #include#include #include #include #define rst_pin 9 #define ss_pin 10字节readcard [4];char* myTags[100] = {};int tagsCount = 0;String tagID = "; ";boolean successRead = false;boolean correctTag = false;int proximitySensor;boolean doorOpened = false;//创建实例MFRC522 MFRC522 (SS_PIN, RST_PIN);液晶显示器(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!"); }
我希望你喜欢本教程,请在下方的评论部分提出任何问题。
谢谢!非常好的教程和项目。
谢谢!
先生,请同时使用esp8266_01和PIC微控制器,您的解释对每个人都很有帮助
谢谢!我正在制作智能锁,作为一名机械工程师,我从你们不同的视频中得到了很多帮助。太棒了!
/可
很高兴听到你这么说,谢谢!
HC-SR501模块将具有与CNY70?
不是真的,HC-SR501是一个PIR传感器,而CNY70是距离测量传感器。
先生,我不能让它工作。我检查了所有的电线,都没问题。
液晶显示仍然空白!
我该如何解决这个问题?
LCD的问题是对比。尝试调整LCD对比度引脚的电压,尝试使用电位器或不同的分压器,以及使用带有Arduino的LCD显示屏查看我的详细教程。
你好,我已经参考了你的LCD教程,但我没有电位器。请问电阻器的调整是在地面上还是在对比度引脚的5v上进行?我在5v上使用220欧姆,在gnd上使用1000欧姆,正如图片颜色代码所示。是我使用了错误的电阻还是有什么问题。因为我用的是和你一样的LCD和连接,所以应该不会有任何错误?谢谢你! !I need this for a mini project of mine hope you can help me with the LCD contrast issue Thanks!!
尽量使用不同的电阻来获得不同的分压器,从而在LCD上获得对比度。
啊. .谢谢!我已经尝试移除一个对比引脚电阻,并将其直接连接到地面。它工作!
谢谢,这是我读过的最好的教程!!
标签id是否存储在EEPROM中,以便在断电后记住先前存储的标签?
谢谢,
李。
你好,这个我用arduino uno代替arduino nano有什么区别吗?
不会有任何区别。
我可以用螺线管12v代替伺服电机吗?如果我想增加led指示灯?我必须做什么(编码)?
请帮助。
你当然能做到。代码不需要太大的改动,可能只是用一个数字引脚来激活电磁阀。
我做到了,
增加电磁阀,按钮从另一边接入,LED RGB,电池和LCD I2c适配器。所有的工作都很完美,除了一个想法,当失去动力程序重新开始。现在我试着用我的EEPROM,你有什么建议吗?
还有一个小问题,当我试图在printNormalModeMessage()上做滚动文本时,程序卡住了,不能扫描卡和运行系统,只是在LCD上出现滚动文本,请帮助。谢谢你,先生。
是啊,为了解决电源损耗的问题,你应该想办法把数据存储在EEPROM里。
感谢本教程,它是优秀的解释和工作完美。
问候,Tobo。
伟大的项目,但我如何存储uid ?另外,在腐蚀标签上存储一个名称也是很好的。
马克
即使断电,您也可以使用Arduino的EEPROM存储uid。
你用的是哪个Arduino,为什么。也有一种方法来记录什么卡被扫描和它被扫描的时间,并能够保存为显示。
当然,您可以编写一个程序来存储时间,您可以使用DS3231实时时钟模块来实现这一目的。
这个项目对我帮助很大。许多谢谢。
能否将thé伺服电机更换为一个电动槽
当然,任何修改都是可能的。
神奇的教程!谢谢
你好,伟大的文章。我需要大约2英尺的射程,这可能吗?
谢谢,汤姆
是的,一些RFID阅读器可以在两英尺远的地方激活被动标签。然而,它们并不紧凑,需要比这个项目多得多的电力,只能在商业上使用,而且可能相对昂贵。在这种情况下,接近传感器可能不实用,超声波传感器可能也不够。如果有意义,可以考虑一个可中断的光束,如红外或激光,物体触发RFID阅读器激活。另一种可能是将RFID阅读器打开,并在标签经过跟踪型应用程序时进行投票。
你好!
关于这个项目,我有一个问题要问你:
这个项目在没有接近传感器的情况下也可以工作吗?或者我需要一个接近传感器才能正常工作吗?
谢谢
嘿,它会起作用,但它需要在代码中进行一些修改。如果您没有那个,您也可以使用不同的接近传感器。
出于某种原因,getID()在我的上面不起作用。有什么办法能解决这个问题吗?谢谢。
PS:我试图复制和粘贴的代码在网站上,这也不起作用。
你会得到什么样的错误?确保您已经安装了MFRC522库,上面的文章中包含了它的链接。
它说:getID()在这个作用域中没有声明。
谢谢,伟大的文章。
你可能错过了第143 - 168行。
尝试再次复制代码。
你好,请问如何连接70元的光学传感器?
我已经炸了3次了,我按照原理图。
只是为了确保你使用的电阻是220和10k对光学传感器?
如何连接传感器接地和电源?
好吧谢谢
我们将使用你连接适当的引脚到适当的电阻,以及接地和5V。电路图显示了正确的连接方式。
嘿,谢谢你的项目。我想知道我们是否可以用超声波传感器而不是接近传感器人民币70元?
是的,你可以用超声波传感器。当然,您必须适当地修改代码。我用70元,因为它更小。