In this article, we are going to
learn some basics about RFID technology and use an Arduino MEGA to a
play around with a popular RFID module, the ID12LA.
RFID stands
for Radio Frequency IDentification. If you haven’t noticed yet, it is
found in many places. This technology is near you right now!RFID technology is commonly found in hotels, offices, banks, stores, etc. RFID chips are even implanted in pets to make sure that they can be identified and returned home if lost. It is often compared to a barcode. But even if it has the same use as a barcode, the two differ in a few ways.
In this article, we are going to learn some basics about RFID technology and use an Arduino MEGA to a play around with a popular RFID module, the ID12LA. You will be surprised by how easy it will be to incorporate this technology into your next electronics project!
The ID12LA. Image courtesy of Sparkfun.
BOM
Hardware
- Arduino MEGA
- You don't have to use a MEGA, but this will do!
- ID12LA
- ID12LA Breakout PCB
- The pins to the ID12LA are a bit weird so I suggest the breakout PCB from Sparkfun or any other reputable dealer.
- Small Breadboard
- Some jumper wires
- Solder and soldering iron
Software
- Arduino IDE
Theory
Before we can start any kind of software or hardware planning, it is essential to have an understanding of the very basics of RFID.In any RFID system, there will be a device that will have information, typically called a tag or transponder, and another device that will “look” or “sense” this information, typically called a reader or interrogator. Both components will need to have their own antenna to communicate and, depending on the type of RFID technology, they can exchange information one or both ways.
To understand this better, we need to understand the two distinctly different types of RFID technology: passive and active.
Passive RFID
Let’s start with passive. In a passive system, the tag consists of an antenna and circuitry to house a unique code. But there is no power source (no battery), so how does the circuitry inside get powered?The answer lies in the reader. In a passive RFID system, the reader will have an antenna that will emit RF energy that will induce a current in the tag’s circuitry. So whenever the tag is moving through the reader’s electromagnetic field, it gets powered and then immediately broadcasts its unique code. At the same time, the reader is also listening for this code.
At what range does all this happen? It depends on the reader and tag, but it is largely dependent on the frequency on which the code is broadcasted. The three main frequencies for passive RFID are:
- Low frequency: ~125 kHz. Typically has a range of a few centimeters
- High frequency: 13.56 MHz. Has a range of up to a meter
- Ultra-high frequency: ~865 MHz. Has a range of about 30 meters
Passive RFID may seem like it would have its shortcomings due to its short read range but these systems are generally inexpensive. Also, since the tags have no batteries, they can last a long time without service.
Below is a type of 125 kHz, passive tag that the ID12LA can interrogate:
RFID key tags. Image courtesy of RFIDTEK.
Active RFID
Now for active RFID.As you might have guessed, these tags are always powered and thus have an onboard battery to transmit their code.
Because of this, along with the option of operating at either 433 MHz or 915 MHz, they have a very long read range—up to a couple of hundred meters! And since they have onboard batteries, they can be coupled with other technologies like temperature sensors and GPS tracking modules that can tailor to many different types of applications.
Finally, there are two types of tag styles you can purchase: transponder (like in passive RFID) and beacon.
A transponder tag is similiar to the passive system in terms of the communication protocol. The reader will send a signal to the tag to ask for its code.
A beacon tag will do the opposite and send a signal every so often on its own—but this really cuts down on battery life.
In either passive or active systems, you can have a tag that is read-only or writable. Read-only means just that, you cannot change the tag's data. Writable means that you can choose what data to place within the tag.
Active RFID tags can also get pretty big. Below is one type of form factor; specifically, a ruggedized one:
An active RFID tag. Image courtesy of RFIDinsider.
Communicating with the ID12LA with an Arduino
Phew! Now that we got that out of the way, let’s figure out how to get the ID12LA to communicate with the Arduino.To follow along, I strongly suggest having the ID12LA's datasheet (PDF) handy.
So with our newfound RFID knowledge, we know that a tag will send a code to the reader, but then what happens? Well, if we study the datasheet, page 4 gives us information on the data output:
This means that once a tag is read, information can be sent out of the reader in serial format, at 9600 baud, No Parity Bit, and 1 Stop Bit. This is a pretty common asynchronous serial communication setup and will make connecting to the Arduino a snap.
Once the reader sends out the data to the Arduino, we need a way to know when to start capturing data. Looking at how the reader spits out data, we find that it uses a Start of Text controller character. Basically, when the serial buffer has some data in it, we can first look to see if this control character is in the queue. If so, then we can go ahead and record the next. If not, we will keep reading until we see it or until the serial buffer is empty.
Assuming we read in the Start of Text controller character, we can go and blindly read in the next 10 ASCII characters from the serial buffer. Then, for the next 5 ASCII characters (2 for checksum, 1 for carriage return, 1 for line feed, and 1 for End of Text controller character), we will read them in but not save it anywhere in our program.
However, to ensure that our transmission was correct, we will double check to see that the End of Text controller character is seen. Though it may rarely be the case, the transmission might fail and we should throw everything we did out the window for the sake of system integrity.
Once the tag is read and saved somewhere in our program, we can use this data for whatever we want! A typical application is access control. You take your saved tag and compare it to a database of tags that are considered to be valid (in our case, we only use one saved tag). The problem is, how do we know what the tag’s code is before we save it to a database? It is not like the tag comes with a paper with its code scribbled on it from the manufacturer.
To work around this and begin to make a database for ourselves, we will need to read in the code and spit it out to the serial monitor. In the Arduino code section, I will provide easy-to-follow comments on where this occurs. When this happens, we will need to write this code down and then alter our program to store this code upon compilation. This is rather a manual way of doing it but this is for the sake of learning the basics of RFID.
Once that is achieved, I would encourage experimenting with programming a simple program sequence that could save RFID tag to EEPROM while the code is running, as well as a way to save and validate more than one tag.
Okay, so let us summarize what the Arduino code must do:
- Monitor the serial buffer for available data.
- When data is present, read and save it with some validation ensuring communication integrity.
- Spit out the data to a serial monitor (primarily for initial setup) and compare this tag to our saved tags.
- Perform an action (we will spit out a message to the serial terminal to illustrate this).
Wire it Up
If we turn to page 3 on the datasheet, we see the pinouts to what is essentially a giant IC:The ID12LA has some nice features such as an output (pin 6) that indicates when a tag is in range and a beeper output (pin 10). However, we don’t use these features in our baseline interface.
For our application, we are using ASCII output. For this to happen, the datasheet tells us (on page 6) that we need to set the format selector input (pin 7) to ground. The data pin we will use is D0 (pin 9). For controlling the reader’s status, we will connect RES (pin 2) to +5V that way the reader is always on.
Refer to the schematic below for the complete overview:
You can also refer to the ID12LA’s pin descriptions:
Click to enlarge.
As for getting the ID12LA onto a breadboard, there's a reason that I suggested buying a breakout board from Sparkfun.com or some other reputable shop. The spacing on the ID12LA is not breadboard-friendly, and, unless you have female-to-male jumpers, will be impossible to connect easily.
For an example on how to wire on a breadboard, please take a look at my wiring setup below:
My tip is to try and be as neat as possible as it is easy to get lost while wiring. But whatever you do, please ensure the power and ground pins are where they are supposed to be! Follow the schematic!
The capacitor is not optional—it provides important high-frequency power-supply bypassing for the ID12LA.
Arduino Code
As promised, here is the heavily commented code to guide you through all of the logic. This code shows you how to compare the detected tag to one stored tag. The same general techniques can be used to extend the code to compare the detected tag against a database that includes multiple valid tags.If you have any questions, leave me a comment below or run to the forums and someone will be happy to assist you!
If you are still new at Arduino programming, however, I suggest reading up on some basic syntax to help with this code.
/* ================================================================================ File........... ID12LA RFID Test Code Purpose........ To demonstrate how to interface to a ID12LA RFID module Author......... Joseph Corleto E-mail......... corleto.joseph@gmail.com Started........ 06/28/2016 Finished....... 07/02/2016 Updated........ --/--/---- ================================================================================ Notes ================================================================================ - Please visit www.allaboutcircuits.com to search for complete article! ================================================================================ Updates ================================================================================ */ //=============================================================================== // Header Files //=============================================================================== //=============================================================================== // Constants //=============================================================================== // Here is where we save valid tags. When you see the example video // of this working, I will first show the invalid tag. Then I will comment this // line and uncomment the valid tag. This shows you how to manually set your own // valid tag. Only difference is you will need to manually type this in. I // was able to uncomment because I have done this prior to making the video. // Bogus tag char tag1[10] = {'X','X','X','X','X','X','X','X','X','X'}; // Good tag //char tag1[10] = {'3','6','0','0','6','6','0','0','5','C'}; //=============================================================================== // Variables //=============================================================================== char ourTag[10]; // We will use this to hold the interrogated tag's data. boolean tagDetected; // We can use this to continue program action if our // reading seems like a real tag was detected. //=============================================================================== // Pin Declarations //=============================================================================== //Inputs: // Serial1 (pin 19) will be used to grab serial data from buffer which is given // by the ID12LA //Outputs: // Serial (pin 2) will be used to output serial data as user feedback to see // what is going on //=============================================================================== // Initialization //=============================================================================== void setup() { // Initialize serial port speed for the serial terminal. // We will use Serial1 on our MEGA for RFID data and the Serial for messages // to the terminal. Serial.begin(9600); Serial1.begin(9600); // Initialize data flags tagDetected = false; } //=============================================================================== // Main //=============================================================================== void loop() { // This function call will return the interrogated tag's data in form of a char // array. If there was an error in the integrity of the transmission, it will // return "0000000000". Of course, this only happens unless there is something // in the serial buffer. All the while, we also // set a flag if there was data there. This comes into use later on. if (Serial1.available() > 0) { // Give some time for all data to arrive safe and sound into the buffer. delay(250); // The if statement below ensures that the beginning of a tag is seen. // Remember that a Start of Text is the decimal value of 2. If we do not // see this, all bets are off in even continuing to look further into the // buffer. I use peek simply because I don't like touching data until I // decide to process it. if (Serial1.peek() != 2) { // Log that we did not have a true tag detected. tagDetected = false; // Flush the buffer to bring it back to an initial, known state. flushSerial1Buffer(); } else { // Looks like the serial data starts with a valid Start of Text character, // let mark that we detected a potential tag. tagDetected = true; // Go and process the tag in the serial1 buffer. fetchTagData(ourTag); // NOTE: The fetchTagData function actually alters the ourTag array // declared earlier before. Nothing is returned because if an array's name // pass along into a function, it is actually passing by reference, not by // value. That means we are changing the array's contents in the function // so nothing needs to be returned! There are other spots in this program // where this happens so please keep this in mind. // While we're at it, why not print out the tag's ID. Serial.print("Your tag says it is: "); Serial.flush(); printTag(ourTag); } } else { // We don't flush the buffer here since we know the buffer is zero. tagDetected = false; } // If no tag was detected, then the below code will never execute. But, if // there is a tag, then we will see if it belongs to our database. if (tagDetected) { // Now here is the part where we do the database comparison with our handy // isValidTag function. And this where you may perform an action // if it is or is not valid. if (isValidTag(ourTag)) { Serial.println("Come on in and have some freshly baked cookies!!!\n"); Serial.flush(); } else { Serial.println("No idea who you are but I have released the hounds!!!\n"); Serial.flush(); } } } //=============================================================================== // Functions //=============================================================================== //////////////////////// // flushSerial1Buffer // //////////////////////// void flushSerial1Buffer() { // Now there is a function on the Arduino that is called Serial1.flush // but it does not really flush the incoming buffer in recent versions, please // check arduino.cc for more information on why. So instead, we will just // keep on plucking data off of the serial buffer until it is empty! while (Serial1.available() > 0) { Serial.read(); } } ////////////////// // fetchTagData // ////////////////// void fetchTagData(char tempTag[]) { // First, pluck off the Start of Text character Serial1.read(); // Second, read off the tag's actual ID data for (int counter = 0; counter < 10; counter++) { tempTag[counter] = Serial1.read(); } // Third, pluck off two checksum, one CR, and one LF characters Serial1.read(); Serial1.read(); Serial1.read(); Serial1.read(); // Fourth, pluck off what should be the End of Text character. And // while we are plucking, why not throw in a sanity check (mentioned in // the article) if (Serial1.read() != 3) { // If for some odd reason the transmission was faulty and we only read // in partial information, just throw in dummy data for the tag for (int counter = 0; counter < 10; counter++) { tempTag[counter] = '0'; } } else { // But if it all looks good, flush the buffer and keep the previously // acquired data flushSerial1Buffer(); } } //////////////// // isValidTag // //////////////// boolean isValidTag(char tempTag[]) { boolean result; // Compare all of the tags by OR-ing all of the compared tag results. If at // least one matches, then it is a valid tag. result = compareTags(tempTag, tag1); return result; } ///////////////// // compareTags // ///////////////// boolean compareTags(char tagA[], char tagB[]) { boolean result = true; // Basically, we will just compare each character in corresponding array // cells until we hit something that does not match. But if it does all // match, then our initial state of result will be true. for (int counter = 0; counter < 10; counter++) { if (tagA[counter] != tagB[counter]) { result = false; break; } } return result; } ///////////////// // printTag // ///////////////// void printTag(char tag[]) { // This function just helps identify what the tag ID is so that you // may initially read this in, hard code into your program, compile, // and then run to have a valid tag in your database. for (int counter = 0; counter < 10; counter++) { Serial.print(tag[counter]); } Serial.println(""); }
If you've followed all of these steps successfully, you should have your own working passive RFID system. Here's mine in action:
RFID Applications
RFID with access control is a pretty natural and straightforward application— but with some imagination, you can tailor it to different ideas.For example, if you are familiar with Geocaching, you can hide RFID tags that can open to give clues to other treasures. Or maybe try something like what pet owners do and use an RFID to track your dog.
If you want to go even further, I highly encourage trying out active RFID to broaden the horizon. One application that sticks in my head is someone tagging all of their food and creating a database that gives recipes on what to make for dinner depending on what tags were in the fridge; overkill, but definitely cool!
No comments:
Post a Comment