Hello all!
My summer has been filled with a bunch of projects that I’ll be offloading here soon! The first one I’ll be talking about is my RFID Cloner I built. Making the code work took a lot longer than I expected because I haven’t used C++ in around 5 years and Arduino is based off C++, so for some reason, I forgot how to do simple things, but I eventually got it working. The basis of the project will be the MFRC522 module and an Arduino Mega 2560. The goal here was to create a system that could scan and duplicate High-Frequency RFID cards.
Before I begin I think it’s necessary to talk about some basic RFID details. There are 3 main types of RFID; Low-Frequency, High-Frequency, and Ultra-High-Frequency. These different types determine the radio frequency at which the RFID Card or Tag will ‘excite’ and turn on to let the reader access the information on the card. Low-Frequency RFID systems operate usually at 125 kHz, which allows them to stand up well against interference, but has the downside of having a low range. High-Frequency RFID is what the MFRC522 reads and usually operates at 13.56 MHz, which gives it better range but makes it more vulnerable to interference. And lastly there is Ultra-High-Frequency RFID which operates from 300 MHz to 1 GHz, allowing an insane range up to around 100 meters. I will be using a passive HF system, meaning that there is no battery powering my card and instead the reader emits an electromagnetic resonance that is used to power the card wirelessly.
Onto the actual project! My first task was verifying that all my components worked and getting the proper setups for the pieces I was using. I settled upon 3 libraries that I needed to get everything running smoothly. The first is SPI.h, which is used for the serial interface to communicate to the MFRC522. This library was also massively useful for debugging because I could control the MFRC522 directly and monitor what I was doing, allowing me to get the main code working before my display even arrived. I also used the official MFRC522.h library for controlling the reader and the standard LiquidCrystal.h library for controlling the display. Importing libraries with Arduino is super easy; if you’re using the standard Arduino IDE just install the library through the library manager and then use the #include <>
command. I also needed to declare the objects so that my components know what pins on the Arduino I’m routing them through, so the beginning of my code looks like this.
#include <SPI.h> // Import Serial Peripheral Interface library for RC522 #include <MFRC522.h> // Import library for RC522 RFID Module #include <LiquidCrystal.h> // Import library for LCD Display #define RST_PIN 5 // Reset pin for MFRC522 #define SS_PIN 53 // Serial pin for MFRC522 #define READ_PIN 2 // Pullup resistor pin for read button #define WRITE_PIN 3 // Pullup resistor pin for write button MFRC522 mfrc522(SS_PIN, RST_PIN); // Define MFRC522 instance LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // Define lcd instance byte NEW_UID[4]; // Create a 4 piece list for the UID to be stored in when reading
Next up we need to talk about how C handles functions. When you start a program in C++ you get 2 main functions, setup() and loop(). The setup() function runs only once and is obviously used for setup of variables, pinmodes, etc. And loop() runs infinitely over and over again so you generally use that for anything else unless you want to make a custom function for something, but for this project I didn’t have much of a need for that. During my setup function I needed to do a few key things, the most important of which were to initialize the serial bus and the LCD library for its resolution. After that I also defined my pins using pinMode(), pinMode() takes in some pin and sets it up as either input, input_pullup, or output. For this code I defined READ_PIN and WRITE_PIN as input_pullup, what this means is that there is a resistor running on the line the button is on and if the voltage line gets sent to ground, by the button being pushed, then the resistor line won’t get any voltage and will read as low, when this happens the Arduino knows the button has been pushed.
void setup() { Serial.begin(9600); SPI.begin(); lcd.begin(16, 2); mfrc522.PCD_Init(); // Init MFRC522 card pinMode(READ_PIN, INPUT_PULLUP); pinMode(WRITE_PIN, INPUT_PULLUP); }
Next up we get into the fun part… the loop! This has 3 parts, the initial precursor stuff, then the read function and the write function. Properly I should have put them into their own functions, but instead I placed them into if statements because it was easier. So in the beginning of the loop function I clear the LCD and print “Standby.” on it, then wait until the reader detects a new card in its range.
void loop() { lcd.clear(); lcd.print("Standby"); // Wait until new card is present if ( ! mfrc522.PICC_IsNewCardPresent() || ! mfrc522.PICC_ReadCardSerial() ) { delay(50); return; }
Once this section has run and the Arduino detects a new card it’ll jump into either the read or the write loop depending on which button is pressed. If the read button is pressed then the LCD will display “READING…” while a for loop grabs the UID from the card and prints it to the display, also placing the UID into the NEW_UID list we created earlier.
// Read function if (digitalRead(READ_PIN) == LOW) { lcd.clear(); lcd.setCursor(0, 0); lcd.print("READING..."); delay(500); lcd.setCursor(0, 1); lcd.print("UID:"); for (byte i = 0; i < mfrc522.uid.size; i++) { lcd.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "); lcd.print(mfrc522.uid.uidByte[i], HEX); NEW_UID[i] = (mfrc522.uid.uidByte[i]); } lcd.setCursor(0, 0); delay(1000); }
On the other hand when the write button is pressed the program will take the UID previously stored in NEW_UID and it will write it to the card. If it succeeds in writing the new UID then it declares “Written!” to the screen and reads the UID to display it on the screen again just as a sanity check.
//Write function if (digitalRead(WRITE_PIN) == LOW) { lcd.clear(); lcd.print("WRITING"); delay(500); lcd.setCursor(0, 0); if ( mfrc522.MIFARE_SetUid(NEW_UID, (byte)4, true) ) { lcd.print("Written!"); } lcd.setCursor(0, 1); for (byte i = 0; i < mfrc522.uid.size; i++) { lcd.print(NEW_UID[i], HEX); } delay(1000); } lcd.setCursor(0, 0); }
And bam, we have a functioning RFID Cloner! By creating this I did learn quite a bit about RFID itself, as well as how to manipulate it. I hope you enjoyed the quick overview of current RFID tech and my attempt at a cloner.
Thanks for reading and have a wonderful day!
~ Corbin