This below is an RFID module that I’ve bought from eBay for very cheap. If you want one as well, check the link below. I get the RF TAG close enough to the RFID module, it detects it, reads the unique ID that the card has and then you could do any process that you want, in our case later, unlock a door.
by: ELECTRONOOBS on 2026-06-17
1 x Arduino NANO/UNO LINK eBay
1 x RFID LINK eBay
3 x Push buttons LINK eBay
1 x i2c LCD: LINK eBay
1 x Servo: LINK eBay
1 x buzzer: LINK eBay
1 x 12V DC transformer: LINK eBay
Resistors: LINK eBay
Wires LINK eBay
Female PCB pins LINK eBay
Male PCB pins LINK eBay
Drilled PCB LINK eBay
Wire, soldering iron, solder, etc...

If we look close enough we can see that the mdoule has the circuit on one side and on the other we can se a PCB coil antenna. We can easily see 4 windings and also a bunch of capacitors. Now if we look at the RFID card, at first sight it seams just like a random plastic card. But if I place it against light we can see once again a coil antenna but also a tiny microchip. So, these two antennas give us some sort if idea of how this communication will work. Let me explain with a bit of more details.

This below will be our radio module and the ID card. They both have some coil antennas, which you all know, that by passing current through a copper wire, they will create a magnetic field wave. But also, a magnetic flux passing through a coil will induce current in that copper winging and that will result in a voltage drop. That’s how the data is sent through air. A magnetic wave is created in the first antenna, and that magnetic field will reach the ID tag antenna.
The signal that the RF module sends is RF modulated and works at 13.6kHz as you can see below. The module has a 27.12MHz crystal oscillator but the RF signal is sent at 13.6KHz.
Ok, so we know now how basic RF antennas work, but how these specific modules work? Well, an oscillating radio frequency signal is created in the transmitter antenna as you can see below. The receiver, the ID tag antenna in this case will receive the RF signal. But this plastic tag has no battery or any kind of power. The card will have to send back the unique ID data, so how dose that?

Well, the RF signal that arrives at the receiver will first charge up a capacitor through a rectifying bridge so we would get DC voltage. We name this capacitor, power capacitor since this will be the one providing power to the IC for a short amount of time. So now the internal IC of the TAG card has power. At the input we have another capacitor but way smaller and without rectifying circuit. This capacitor, since it is much smaller, will only smooth the radio waves so the control unit could understand the values. So, the output of this capacitor will be the data in, the output of this one, the power in and finally, we add switch connected to the data out pin. This data out will modulate the response signal and it will use the power stored into the power capacitor and send another signal to the RFID module. That signal will carry all the data inside of the ID tag and that’s how we read the information on this plastic RFID card.
I’ve made a small copper wire coil and connected it to my oscilloscope and set a small code that will send data and try to connect on any RFID device. At first look we can’t see anything but if we go close enough we can see an oscillating RF signal of 13,6KHz. I can’t see changing frequency so I suppose this is not FM signal so it must be AM or amplitude modulated. If I trigger the signal right in the communication time, we can see the modulated signal, so, if this is amplitude modulation the low signal must be 0 and high must be a digital one or something like that. Or maybe the lenght of the FM signal oscilating represents the sent data. I’m not entirely sure of the type of modulation but with these two characteristics, I could say it is AM.

So, now we know how the communication works, let’s connect the RFID module to an Arduino and start working with it. Use the basic schematic below, we connect to the Arduino. Be careful, the module works at 3.3V so supply that voltage to the module. The rest of the pins are 5V compatible so no worries. Connect the SPI pins which are clock, MOSI, MISO and a data pin. Now open Arduino IDE and go to library manager. There search for the MFRC 522 library and install it. If you don’t want to use the manager, just download the library zip file from below and go to sketch, include library, add .zip library and select the downloaded .zip file.

Ok, once installed go to examples, MFRC 522 and open the read ID example. Select the Arduino NANO board, select the com and upload. Now open the serial monitor and set a baud rate of 9600. As you can see below, when I place tag card in front of the sensor, I get the unique ID code in decimal and hexadecimal values. Write these codes down in order to remember the code for each of your tags if you want.

Ok, so now we know the ID of these two tags that come with the module. Using bits from this example code, I’ve made my own code that will detect the scanned card, check the ID and if the ID is on the user list it will open a door with a servo motor. The servo motor is a 9g one and it could be supplied directly with 5V from the Arduino since it won’t draw too much current.
This below is the schematic of the final project. I’ve added an LCD in order to send notifications to the user and 3 push buttons. The LCD uses i2C communication so make sure you install the i2c LCD library that you could also find in the description below. One push button is for outside closing the door and the other two are for inside close and open the door. If you are outside the room you could close the door with the button but open it only with the RFID tag. If you are inside you could both open or close the door whenever you want using the buttons. Finally, I’ve also added a buzzer for sound notifications, this will make the project less boring and add little sound.

I’ve designed a small case and 3D printed using PLA material and my ANYCUBIC i3 printer. The link for the 3D case is below if you want to build the same project. It has holes for you to screw it on any surface, place for the LCD screen, the RF module and a push button. Also, this another small case for the other two buttons on the other side.

I screw the LCD in place using M3 screws and nuts. I solder everything and also fit the RF sensor on the front side of the case. I supply 12V to the circuit using a DC transformer. The servo motor is connected to pin D3, the RFID module to SPI port and the LCD to A4 and A5, the i2c port.

This system could store up to 5 users in my case but if you want more, you would have to copy paste some parts of the code and add more users. I have the RF module and one push button on the outside and the other case on the other side. The servo motor on the inside part of the door connected to an opening system.
Let's see how the code works. First inlcude all the libraries that we need and define the LCD and the MFRC module pins and alsodefine the Servo variable for the motor.
/* RFID door lock code example.
* Visit the video: https://www.youtube.com/watch?v=X7hUSqS86DM
* Visit webpage tutorial: http://www.ELECTRONOOBS.com/eng_arduino_tut26.php
*
* Connections: http://www.ELECTRONOOBS.com/eng_arduino_tut26_sch1.php */
#include <SPI.h>
#include <MFRC522.h> //Downlaod the library: http://www.electronoobs.com/eng_arduino_MFRC522.php
#include <Servo.h>
//LCD config
#include <Wire.h>
#include <LiquidCrystal_I2C.h> //Downlaod the library: http://www.electronoobs.com/eng_arduino_liq_crystal.php
LiquidCrystal_I2C lcd(0x3f,20,4); //sometimes the adress is not 0x3f. Change to 0x27 if it dosn't work.
#define RST_PIN 9 //Pin 9 is for the RC522 reset
#define SS_PIN 10 //Pin 10 is the SS (SDA) of RC522 module
MFRC522 mfrc522(SS_PIN, RST_PIN); //Create anew RC522 object
Servo motor_1;
//Variables
boolean door_opened=false;
boolean first_read=false;
boolean normal_mode=true;
boolean countdown = false;
int timer=0;
int user_added=0;
int add_ID_counter = 0;
//I/O
int buzzer_pin=7;
int outside_close = 4; //pin for the button of the outside open
int inside_close = 6; //pin for the button of the inside close
int inside_open = 5; //pin for the button of the inside open
void setup() {
SPI.begin(); //Start a new SPI bus
mfrc522.PCD_Init(); // Startt the MFRC522
motor_1.attach(3); //Set digital pin D3 to be the PWM signal for the servo motor
pinMode(buzzer_pin,OUTPUT); //Set digital pin D7 to be the buzzer OUTPUT
//Config of the i2c LCD screen
lcd.init();
lcd.backlight();
lcd.setCursor(0,0);
lcd.print("Place card here!");
lcd.setCursor(0,1);
lcd.print(" ");
motor_1.writeMicroseconds(1000); //Put the servo in to the close position
}
byte ActualUID[4]; //This will store the ID each time we read a new ID code
byte USER1[4]= {0x09, 0x92, 0x53, 0x28} ; //Master ID code Change it for yor tag. First use the READ exampel and check your ID
byte USER2[4]= {0x00, 0x00, 0x00, 0x00} ; //Empty ID of USER2
byte USER3[4]= {0x00, 0x00, 0x00, 0x00} ; //Empty ID of USER3
byte USER4[4]= {0x00, 0x00, 0x00, 0x00} ; //Empty ID of USER4
byte USER5[4]= {0x00, 0x00, 0x00, 0x00} ; //Empty ID of USER5
void loop() {
if(digitalRead(outside_close)) //If the button is pressed, we close the door
{
door_opened=false;
first_read=false;
countdown = false;
add_ID_counter = 0;
motor_1.writeMicroseconds(1000);
lcd.setCursor(0,0);
lcd.print(" Door closed ");
lcd.setCursor(0,1);
lcd.print(" from OUTSIDE ");
digitalWrite(buzzer_pin,HIGH);
delay(300);
digitalWrite(buzzer_pin,LOW);
delay(4000);
lcd.setCursor(0,0);
lcd.print("Place card here!");
lcd.setCursor(0,1);
lcd.print(" DOOR CLOSED ");
}
if(digitalRead(inside_close)) //If the button is pressed, we close the door
{
door_opened=false;
first_read=false;
countdown = false;
add_ID_counter = 0;
motor_1.writeMicroseconds(1000);
lcd.setCursor(0,0);
lcd.print(" Door closed ");
lcd.setCursor(0,1);
lcd.print(" from INSIDE ");
digitalWrite(buzzer_pin,HIGH);
delay(300);
digitalWrite(buzzer_pin,LOW);
delay(4000);
lcd.setCursor(0,0);
lcd.print("Place card here!");
lcd.setCursor(0,1);
lcd.print(" DOOR CLOSED ");
}
if(digitalRead(inside_open)) //If the button is pressed, we open the door
{
door_opened=true;
first_read=false;
countdown = false;
add_ID_counter = 0;
motor_1.writeMicroseconds(1500);
lcd.setCursor(0,0);
lcd.print(" Door open ");
lcd.setCursor(0,1);
lcd.print(" from INSIDE ");
digitalWrite(buzzer_pin,HIGH);
delay(300);
digitalWrite(buzzer_pin,LOW);
delay(4000);
lcd.setCursor(0,0);
lcd.print("Place card here!");
lcd.setCursor(0,1);
lcd.print(" DOOR OPENED ");
}
if(normal_mode)
{
if(countdown)
{
if(add_ID_counter > 300)
{
countdown = false;
first_read=false;
add_ID_counter = 0;
lcd.setCursor(0,0);
lcd.print("New ID canceled");
lcd.setCursor(0,1);
lcd.print(" ");
digitalWrite(buzzer_pin,HIGH);
delay(1000);
digitalWrite(buzzer_pin,LOW);
delay(4000);
lcd.setCursor(0,0);
lcd.print("Place card here!");
lcd.setCursor(0,1);
lcd.print(" ");
}
if(add_ID_counter == 50)
{
lcd.setCursor(15,1);
lcd.print("5");
digitalWrite(buzzer_pin,HIGH);
delay(100);
digitalWrite(buzzer_pin,LOW);
}
if(add_ID_counter == 100)
{
lcd.setCursor(15,1);
lcd.print("4");
digitalWrite(buzzer_pin,HIGH);
delay(100);
digitalWrite(buzzer_pin,LOW);
}
if(add_ID_counter == 150)
{
lcd.setCursor(15,1);
lcd.print("3");
digitalWrite(buzzer_pin,HIGH);
delay(100);
digitalWrite(buzzer_pin,LOW);
}
if(add_ID_counter == 200)
{
lcd.setCursor(15,1);
lcd.print("2");
digitalWrite(buzzer_pin,HIGH);
delay(100);
digitalWrite(buzzer_pin,LOW);
}
if(add_ID_counter == 250)
{
lcd.setCursor(15,1);
lcd.print("1");
digitalWrite(buzzer_pin,HIGH);
delay(100);
digitalWrite(buzzer_pin,LOW);
}
add_ID_counter = add_ID_counter+1;
delay(10);
}
// Check if there are any new ID card in front of the sensor
if ( mfrc522.PICC_IsNewCardPresent())
{
//Select the found card
if ( mfrc522.PICC_ReadCardSerial())
{
// We store the read ID into 4 bytes with a for loop
for (byte i = 0; i < mfrc522.uid.size; i++) {
ActualUID[i]=mfrc522.uid.uidByte[i];
}
//Compare the UID and check if the new iD is on the user listz
if(first_read)
{
if(compareArray(ActualUID,USER1))
{
countdown=false;
add_ID_counter = 0;
digitalWrite(buzzer_pin,HIGH);
delay(300);
digitalWrite(buzzer_pin,LOW);
normal_mode=false;
lcd.setCursor(0,0);
lcd.print("Place New ID in:");
lcd.setCursor(0,1);
lcd.print(" 3 ");
digitalWrite(buzzer_pin,HIGH);
delay(100);
digitalWrite(buzzer_pin,LOW);
delay(1000);
lcd.setCursor(0,1);
lcd.print(" 2 ");
digitalWrite(buzzer_pin,HIGH);
delay(100);
digitalWrite(buzzer_pin,LOW);
delay(1000);
lcd.setCursor(0,1);
lcd.print(" 1 ");
digitalWrite(buzzer_pin,HIGH);
delay(100);
digitalWrite(buzzer_pin,LOW);
delay(1000);
lcd.setCursor(0,1);
lcd.print(" NOW! ");
digitalWrite(buzzer_pin,HIGH);
delay(500);
digitalWrite(buzzer_pin,LOW);
}
else
{
first_read=false;
}
}
if(!first_read)
{
if(compareArray(ActualUID,USER1))
{
lcd.setCursor(0,0);
lcd.print(" Access granted ");
lcd.setCursor(0,1);
lcd.print(" MASTER USER ");
digitalWrite(buzzer_pin,HIGH); //use analogWrite(buzzer_pin,200); for non active buzzer
delay(300);
digitalWrite(buzzer_pin,LOW); //use analog write for non active buzzer
motor_1.writeMicroseconds(1500);
door_opened=true;
first_read=true;
countdown=true;
delay(3000);
lcd.setCursor(0,0);
lcd.print("Put MASTER card");
lcd.setCursor(0,1);
lcd.print("for new ID 6");
digitalWrite(buzzer_pin,HIGH);
delay(100);
digitalWrite(buzzer_pin,LOW);
}
else if(compareArray(ActualUID,USER2))
{
lcd.setCursor(0,0);
lcd.print(" Access granted ");
lcd.setCursor(0,1);
lcd.print(" USER 2 ");
digitalWrite(buzzer_pin,HIGH); //use analogWrite(buzzer_pin,200); for non active buzzer
delay(300);
digitalWrite(buzzer_pin,LOW); //use analog write for non active buzzer
motor_1.writeMicroseconds(1500);
door_opened=true;
first_read=true;
delay(3000);
lcd.setCursor(0,0);
lcd.print("Last use: USER2");
lcd.setCursor(0,1);
lcd.print(" Door OPENED ");
}
else if(compareArray(ActualUID,USER3))
{
lcd.setCursor(0,0);
lcd.print(" Access granted ");
lcd.setCursor(0,1);
lcd.print(" USER 3 ");
digitalWrite(buzzer_pin,HIGH); //use analogWrite(buzzer_pin,200); for non active buzzer
delay(300);
digitalWrite(buzzer_pin,LOW); //use analog write for non active buzzer
motor_1.writeMicroseconds(1500);
door_opened=true;
first_read=true;
delay(3000);
lcd.setCursor(0,0);
lcd.print("Last use: USER3");
lcd.setCursor(0,1);
lcd.print(" Door OPENED ");
}
else if(compareArray(ActualUID,USER4))
{
lcd.setCursor(0,0);
lcd.print(" Access granted ");
lcd.setCursor(0,1);
lcd.print(" USER 4 ");
digitalWrite(buzzer_pin,HIGH); //use analogWrite(buzzer_pin,200); for non active buzzer
delay(300);
digitalWrite(buzzer_pin,LOW); //use analog write for non active buzzer
motor_1.writeMicroseconds(1500);
door_opened=true;
first_read=true;
delay(3000);
lcd.setCursor(0,0);
lcd.print("Last use: USER4");
lcd.setCursor(0,1);
lcd.print(" Door OPENED ");
}
else if(compareArray(ActualUID,USER5))
{
lcd.setCursor(0,0);
lcd.print(" Access granted ");
lcd.setCursor(0,1);
lcd.print(" USER 5 ");
digitalWrite(buzzer_pin,HIGH); //use analogWrite(buzzer_pin,200); for non active buzzer
delay(300);
digitalWrite(buzzer_pin,LOW); //use analog write for non active buzzer
motor_1.writeMicroseconds(1500);
door_opened=true;
first_read=true;
delay(3000);
lcd.setCursor(0,0);
lcd.print("Last use: USER5");
lcd.setCursor(0,1);
lcd.print(" Door OPENED ");
}
else
{
lcd.setCursor(0,0);
lcd.print(" Access denied ");
lcd.setCursor(0,1);
lcd.print(" UNKNOWN ID ");
analogWrite(buzzer_pin,200); //use analogWrite(buzzer_pin,200); for non active buzzer
delay(1500);
analogWrite(buzzer_pin,LOW); //use analog write for non active buzzer
motor_1.writeMicroseconds(1000);
door_opened=false;
first_read=false;
delay(3000);
lcd.setCursor(0,0);
lcd.print("Place card here!");
lcd.setCursor(0,1);
lcd.print(" Door CLOSED ");
}
}
// Terminamos la lectura de la tarjeta tarjeta actual
mfrc522.PICC_HaltA();
}
}
}//end normal mode
if(!normal_mode)
{
// Revisamos si hay nuevas tarjetas presentes
if ( mfrc522.PICC_IsNewCardPresent())
{
//Seleccionamos una tarjeta
if ( mfrc522.PICC_ReadCardSerial())
{
// Enviamos serialemente su UID
for (byte i = 0; i < mfrc522.uid.size; i++) {
ActualUID[i]=mfrc522.uid.uidByte[i];
}
//Compare the read ID and the stored USERS
if(user_added==4)
{
lcd.setCursor(0,0);
lcd.print(" User list is ");
lcd.setCursor(0,1);
lcd.print(" FULL ");
digitalWrite(buzzer_pin,HIGH); //use analogWrite(buzzer_pin,200); for non active buzzer
delay(3000);
digitalWrite(buzzer_pin,LOW); //use analog write for non active buzzer
lcd.setCursor(0,0);
lcd.print("Place card here!");
lcd.setCursor(0,1);
lcd.print(" ");
}
if(user_added==3)
{
USER5[0] = ActualUID[0];
USER5[1] = ActualUID[1];
USER5[2] = ActualUID[2];
USER5[3] = ActualUID[3];
user_added = user_added+1;
lcd.setCursor(0,0);
lcd.print("New user stored ");
lcd.setCursor(0,1);
lcd.print(" as USER 5 ");
digitalWrite(buzzer_pin,HIGH); //use analogWrite(buzzer_pin,200); for non active buzzer
delay(300);
digitalWrite(buzzer_pin,LOW); //use analog write for non active buzzer
delay(1000);
normal_mode=true;
first_read=false;
delay(3000);
lcd.setCursor(0,0);
lcd.print("Place card here!");
lcd.setCursor(0,1);
lcd.print(" ");
}
if(user_added==2)
{
USER4[0] = ActualUID[0];
USER4[1] = ActualUID[1];
USER4[2] = ActualUID[2];
USER4[3] = ActualUID[3];
user_added = user_added+1;
lcd.setCursor(0,0);
lcd.print("New user stored ");
lcd.setCursor(0,1);
lcd.print(" as USER 4 ");
digitalWrite(buzzer_pin,HIGH); //use analogWrite(buzzer_pin,200); for non active buzzer
delay(300);
digitalWrite(buzzer_pin,LOW); //use analog write for non active buzzer
delay(1000);
normal_mode=true;
first_read=false;
delay(3000);
lcd.setCursor(0,0);
lcd.print("Place card here!");
lcd.setCursor(0,1);
lcd.print(" ");
}
if(user_added==1)
{
USER3[0] = ActualUID[0];
USER3[1] = ActualUID[1];
USER3[2] = ActualUID[2];
USER3[3] = ActualUID[3];
user_added = user_added+1;
lcd.setCursor(0,0);
lcd.print("New user stored ");
lcd.setCursor(0,1);
lcd.print(" as USER 3 ");
digitalWrite(buzzer_pin,HIGH); //use analogWrite(buzzer_pin,200); for non active buzzer
delay(300);
digitalWrite(buzzer_pin,LOW); //use analog write for non active buzzer
delay(1000);
normal_mode=true;
first_read=false;
delay(3000);
lcd.setCursor(0,0);
lcd.print("Place card here!");
lcd.setCursor(0,1);
lcd.print(" ");
}
if(user_added==0)
{
USER2[0] = ActualUID[0];
USER2[1] = ActualUID[1];
USER2[2] = ActualUID[2];
USER2[3] = ActualUID[3];
user_added = user_added+1;
lcd.setCursor(0,0);
lcd.print("New user stored ");
lcd.setCursor(0,1);
lcd.print(" as USER 2 ");
digitalWrite(buzzer_pin,HIGH); //use analogWrite(buzzer_pin,200); for non active buzzer
delay(300);
digitalWrite(buzzer_pin,LOW); //use analog write for non active buzzer
delay(1000);
normal_mode=true;
first_read=false;
delay(3000);
lcd.setCursor(0,0);
lcd.print("Place card here!");
lcd.setCursor(0,1);
lcd.print(" ");
}
}
}
}//end ID add mode
}
//Compare the 4 bytes of the users and the received ID
boolean compareArray(byte array1[],byte array2[])
{
if(array1[0] != array2[0])return(false);
if(array1[1] != array2[1])return(false);
if(array1[2] != array2[2])return(false);
if(array1[3] != array2[3])return(false);
return(true);
}
In the setup loop we start the LCD and RFID module and print something on the LCD screen. We attach the motor at pin D3 and set the buzzer pin as an output. Funally using "motor_1.writeMicroseconds(1000);" we put the servo in the closed position.
In the void loop, using the functions below we read the ID. Then we check if each of the 4 bytes are the same as the ones that we have stored on the program. If yes, we open the door. If not, we give error.
Very important, make sure you add the push buttons and pullup resistors just as in the schematic, otherwise those pins will be in free air and the signal will wamble around and open and close the door like a crazy system.
So, there you go my friends. Now you know the basics of how RFID system works, how we use RF signal and send data, how the non-powered ID tag responds and how to use this module and make a system for door opening. You have the part list, schematics, 3D files and codes on this post so make sure you check those out. If you would like to support my projects, check my Patreon page, I would really appreciate that guys and by the way, thank you very much to all my Patreons.
Leave a comment
Please login in order to comment.