Friday, 8 November 2013

Interfacing Serial Devices - Part 2 - Working with a Serial RFID Reader

The RFID Basics

What is RFID?
RFID stands for Radio Frequency IDentification. RFID is a basic technology that allows  the identification of a device (read tag / sticker / label)  to be read wirelessly by a Reader(RFID reader) using Radio Frequnecy.

How does it work?
The Tag contains a small IC containing the Identity Information. The IC is attached to an antenna and transmits its identity to a Reader when it detects a Reader. It detects a Reader by detecting the electromagnetic energy produced by the Reader. The Identity information is transmitted as Radio Frequencies. The Reader then converts the received Radio Frequencies into the Identity Data.

Types of Tags
There are 2 major types of tags available - Active & Passive.

Active Tags
Active tags have an embedded power source and use it to transmit data. Owing to this reason they are expensive and are not viable for large scale deployments. 

Passive Tags
Passive Tags on the other hand get their power from the electromagnetic energy produced by the Reader (Electromagnetic Induction). These are cheap and are the most commonly used RFID tags (ID Cards, etc).


Interfacing an RFID reader with Induino R3 / Arduino

Most RFID readers provide with a Serial Interface for connecting to a microcontroller. Some of the readers also provide another interface called the Weigand Intreface. However for the scope of our tutorial we will stick to the Serial Interface. We shall also use the EM 18 RFID Reader Module available on our site as the reference. This is a 125Khz module and comes with both Serial and Weigand interfaces. 



Since there is only 1 way communication (Reader to Microcontroller) the reader has only a Tx Pin. Connect the Reader as follows
  1. Connect the +5V of the Reader to the +5V pin on the Induino R3
  2. Connect the GND of the Reader to the GND pin on the Induino R3
  3. Connect the Tx pin of the Reader to the Rx pin on the Induino R3 - Make this connection after uploading the program otherwise you will not be able to upload to the Induino R3 / Arduino board as the Rx / Tx pins are used for Programming the Induino R3 / Arduino. Remember to take this connection out every time you re-program your Induino R3 / Arduino
  4. Leave alone the DET pin for now, we will connect this later

Reading a TAG

Lets first write a Simple Program that would read the value of a Tag and display it on the Serial monitor. Make a note of the value as we would use this in our next program.

Here's the Program
/*  Induino R3 User Guide - Program 16.0 - Reading a TAG Value using the RFID reader
 This sketch Reads the Value of a RFID Tag and displays it on the Serial Monitor   
 */

int count = 0; // A variable to count the length of the Tag DATA

void setup()
{
  Serial.begin(9600); // Initialize Serial Communication - Both with the RFID reader & the Serial Monitor

}

void loop()
{
  
  if(Serial.available()) // Check if there is Incoming Data in the Serial Buffer. This is data coming from the RFID reader
  {
    count = 0; // Reset count to zero
    while(Serial.available()) // Keep reading Byte by Byte from the Buffer till the Buffer is empty
    {
      char input = Serial.read(); // Read 1 Byte of data and store it in a character variable
      Serial.print(input); // Print the Byte
      count++; // Increment the Byte count after every Byte Read
      delay(5); // A small delay - Removing this might make the Program run faster and not respond properly as data from the reader could be slow
    }
    // Print Tag Length
    Serial.println();
    Serial.print("Tag Length : ");
    Serial.print(count);
    Serial.println(" Bytes");
  }
}

Now open the Serial Monitor and Show the TAG onto the RFID reader (You have to hold it very close to the Central part of the Reader) and you will get the value of the TAG displayed. Note this value down. Later, We shall do some additional programs to identify a Tag and do specific tasks. 


Software Serial
Its pretty annoying to remove the connection every time you have to upload a new program. This is required as the same pins are used both by our computer (for programming) and the RFID reader. We can overcome this by using Software Serial - The ability to use any 2 pins on an Arduino for Serial communication. This is made possible by the SoftwareSerial library in Arduino which programatically simulates Serial Communication. Now Lets change our connections and experiment with this.
  1. Connect the Tx pin of the Reader to the digital pin 7 on the Induino R3 - We will use this as our Rx Pin for Software Serial. We can use Pin 1 for Tx as we are not going to connect anything 

Here's the modified Program
/*  Induino R3 User Guide - Program 16.1 - Reading a TAG Value using the RFID reader using Software Serial
 This sketch Reads the Value of a RFID Tag and displays it on the Serial Monitor   
 */
 
#include <SoftwareSerial.h> // include the Software Serial Library

SoftwareSerial rfid_reader(7,1); // Creat a Software Serial Object Mapping it to 7th pin as Rx and 1st Pin as Tx

int count = 0; // A variable to count the length of the Tag DATA


void setup()
{
  rfid_reader.begin(9600); // Initialise Serial Communication with the RFID reader
  Serial.begin(9600); // Initialise Serial Communication with the Serial Monitor
}

void loop()
{
  
  if(rfid_reader.available()) // Check if there is Incoming Data in the RFID Reader Serial Buffer. 
  {
    count = 0; // Reset count to zero
    while(rfid_reader.available()) // Keep reading Byte by Byte from the Buffer till the RFID Reader Buffer is empty
    {
      char input = rfid_reader.read(); // Read 1 Byte of data and store it in a character variable
      Serial.print(input); // Print the Byte
      count++; // Increment the Byte count after every Byte Read
      delay(5); // A small delay - Removing this might make the Program run faster and not respond properly as data from the reader could be slow
    }
    // Print Tag Length
    Serial.println();
    Serial.print("Tag Length : ");
    Serial.print(count);
    Serial.println(" Bytes");
  }
}

Now open the Serial Monitor and Show the TAG onto the RFID reader (You have to hold it very close to the Central part of the Reader) and you will get the value of the TAG displayed.  

Read More on Software Serial Here -> http://arduino.cc/en/Reference/SoftwareSerial


Matching Tags

To Match a Tag with a specific action, we need to get the Tag ID using the above program (16.0 / 16.1) Once we have the ID, we can use it in our program and compare it to the ID of any tag being presented.  So, Lets try to toggle the state of a LED using a specific Tag ID.

Here's the Program
/*  Induino R3 User Guide - Program 16.2 - Toggling a LED based on a RFID Tag
 This sketch toggles the state of a led everytime the correct tag is presented.
 */

#include <SoftwareSerial.h> // include the Software Serial Library
SoftwareSerial rfid_reader(7,1); // Creat a Software Serial Object Mapping it to 7th pin as Rx and 1st Pin as Tx

char tag[] ="4F006DD86A90"; // The Tag ID which we got from Program 16.0
char input[12]; // A Variable to store the ID of the Tag being presented
int count = 0; // A counter variable to navigate through the input[] character array
boolean flag = 0; // A variable to store the Tag match status
boolean state = 0; // A variable to store the state of the Led to be toggled
void setup()
{
  rfid_reader.begin(9600); // Initialise Serial Communication with the RFID reader
  Serial.begin(9600); // Initialise Serial Communication with the Serial Monitor
  pinMode(13,OUTPUT); // LED output
}

void loop()
{
  
  if(rfid_reader.available())// Check if there is Incoming Data in the RFID Reader Serial Buffer. 
  {
    count = 0; // Reset the counter to zero
    while(rfid_reader.available() && count < 12) // Keep reading Byte by Byte from the Buffer till the RFID Reader Buffer is empty or till 12 Bytes (the ID size of our Tag) is read
    {
      input[count] = rfid_reader.read(); // Read 1 Byte of data and store it in the input[] variable
      count++; // increment counter
      delay(5);
    }
    if(count == 12) // When the counter reaches 12 (the size of the ID) we stop and compare each value of the input[] to the corresponding stored value
    {
      count =0; // reset counter varibale to 0
      flag = 1;
      while(count<12 && flag !=0) // Iterate through each value and compare till either the 12 values are all matching or till the first mistmatch occurs
      {
        if(input[count]==tag[count])
        flag = 1; // everytime the values match, we set the flag variable to 1
        else
        flag=0; // if the ID values don't match, set flag variable to 0 and stop comparing by exiting the while loop
        count++; // increment i
      }
    }
    if(flag == 1) // If flag variable is 1, then it means the tags match
    {
      Serial.println("Matched!");
      state = !state; // Toggle state
      digitalWrite(13,state); // Apply the new state to the LED
    }
    else
    {
      Serial.println("Wrong Tag"); // Incorrect Tag Message
    }
   
    for(count=0; count<12; count++) // Fill the input variable array with a fixed value 'F' to overwrite all values getting it empty for the next read cycle
      {
        input[count]= 'F';
      }
     count = 0; // Reset counter variable  
  }
}

Now this should control the state of the 13th pin LED on the Induino R3 everytime you show the correct tag to it.

Using Interrupts
Now we have managed to identify a tag and control accordingly. However, our program has a small drawback. We keep checking for the tag all the time. If we can optimize this to check only when a tag is being present, we should be done. The DET pin on the RFID Reader outputs a constant high signal and gives a short LOW pulse when a Tag is presented. We can use this signal as an interrupt trigger and check the RFID readers serial line only when an interrupt is triggered. To make it more interesting, we will let a simple blink program run and get interrupted by the RFID reader.

Make the following additional connection
  1. Connect the DET line of the RFID reader to the digital pin 2 (Interrupt 0)

Here's the Program
/*  Induino R3 User Guide - Program 16.3 - Toggling a LED based on a RFID Tag using Interrupts
 This sketch is a simple blink that uses interrupts to toggle the state of a led everytime the correct tag is presented 
 */
 
#include <SoftwareSerial.h> // include the Software Serial Library
SoftwareSerial rfid_reader(7,1); // Creat a Software Serial Object Mapping it to 7th pin as Rx and 1st Pin as Tx

char tag[] ="4F006DD86A90"; // The Tag ID which we got from Program 16.0
char input[12]; // A Variable to store the ID of the Tag being presented
int count = 0; // A counter variable to navigate through the input[] character array
boolean flag = 0; // A variable to store the Tag match status
boolean state = 0; // A variable to store the state of the Led to be toggled
boolean tag_ready=0; // A variable that is set by the ISR when an interrupt occurs

void setup()
{
  rfid_reader.begin(9600); // Initialise Serial Communication with the RFID reader
  Serial.begin(9600); // Initialise Serial Communication with the Serial Monitor
  pinMode(13,OUTPUT); // LED output
  pinMode(12,OUTPUT); // A Normal LED output for LED Blink
  pinMode(2,INPUT); // Interrupt Pin defined as Input
  attachInterrupt(0, check, FALLING); // Enable the Interrupt to call the ISR check when a Falling Interrupt occurs
}

void check() // The Interrupt Service Routine
{
 
  tag_ready = 1; // Set the tag_ready variable
  
}

void loop()
{
  if(tag_ready) // Check if the variable is set 
  {
    process_tag(); // if the variable is set, call the process_tag() function
  }
  // Regular Blink Operation
  digitalWrite(12,HIGH); 
  delay(500);
  digitalWrite(12,LOW);
  delay(500);
  
}

/* Function to Process the TAG and Act */

void process_tag()
{
  if(rfid_reader.available())// Check if there is Incoming Data in the RFID Reader Serial Buffer. 
  {
    count = 0; // Reset the counter to zero
    while(rfid_reader.available() && count < 12) // Keep reading Byte by Byte from the Buffer till the RFID Reader Buffer is empty or till 12 Bytes (the ID size of our Tag) is read
    {
      input[count] = rfid_reader.read(); // Read 1 Byte of data and store it in the input[] variable
      count++; // increment counter
      delay(5);
    }
    if(count == 12) // When the counter reaches 12 (the size of the ID) we stop and compare each value of the input[] to the corresponding stored value
    {
      count =0; // reset counter varibale to 0
      flag = 1;
      while(count<12 && flag !=0) // Iterate through each value and compare till either the 12 values are all matching or till the first mistmatch occurs
      {
        if(input[count]==tag[count])
        flag = 1; // everytime the values match, we set the flag variable to 1
        else
        flag=0; // if the ID values don't match, set flag variable to 0 and stop comparing by exiting the while loop
        count++; // increment i
      }
    }
    if(flag == 1) // If flag variable is 1, then it means the tags match
    {
      Serial.println("Matched!");
      state = !state; // Toggle state
      digitalWrite(13,state); // Apply the new state to the LED
    }
    else
    {
      Serial.println("Wrong Tag"); // Incorrect Tag Message
    }
   
    for(count=0; count<12; count++) // Fill the input variable array with a fixed value 'F' to overwrite all values getting it empty for the next read cycle
      {
        input[count]= 'F';
      }
     count = 0; // Reset counter variable  
  }
  tag_ready=0;
}

Now this should control the state of the 13th pin LED on the Induino R3 everytime you show the correct tag to it. The LED on the 12th pin should be blinking all the while

Thats It For This Part! Enjoy... and feel free to drop us an email with questions you might have -> info@simplelabs.co.in

 Visit www.simplelabs.co.in for more interesting products

23 comments:

  1. Do different RFID card have different ID ?? If so can multiple Tasks can be done using multiple cards...

    ReplyDelete
    Replies
    1. yes. they all have unique ids and can be used for different tasks

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
  3. Nice article. If i want to make use of my android phone with nfc, Is it possible to make my android phone to be treated like a rfid reader? or do i need to get a nfc reader?

    ReplyDelete
    Replies
    1. You can use your android phone as a reader however that would require a lot of android skills + arduino skills... easier would be to buy a separate reader

      Delete
  4. Sir,
    My EM-18 has no ttl outputs. so i used rs232 to ttl converter. Reader module has a dc supply option. so is there any change in connection? ttl pinouts are tx,rx,5v,gnd. Should i use 5v adapter to power EM-18

    ReplyDelete
    Replies
    1. well you can use your arduino / induino for the 5V supply. There should be a ttl output somewhere on the reader... try tracing it.. if not the converter should work as well...

      Delete
  5. Hi prakash,

    I need to receive the string continuously which ends by '\0'
    How can i do it can u help me ...............?

    ReplyDelete
  6. what is the read range? and what is the write range?

    ReplyDelete
    Replies
    1. range as in distance? Well its very short - 1 to 4 cms.

      Delete
  7. This comment has been removed by the author.

    ReplyDelete
  8. Can i use Active RFID tags with EM-18 RFID Reader module?

    ReplyDelete
    Replies
    1. Well if you have the tag try it. We don't have any active tags around and are unable to test this.

      Delete
  9. Hey, thanks for the wonderful tutorial. I tried to implement the same interrupt driven concept in my project. But for some reason, my input array ends up empty, even though a tag is detected. Can you please let me know why.

    The link to my code:
    https://db.tt/NXcRjLgv

    ReplyDelete
    Replies
    1. You are trying to use string comparsion on a character array... Thats the clue... now find out the difference between a character array and a string :) and change your program accordingly.

      Delete
  10. hey
    i have written the same code as in your software serial but im not getting anything being shown on the serial monitor.any help?

    my code:

    #include
    SoftwareSerial rfid(7,1);

    void setup()
    {
    Serial.begin(9600);
    rfid.begin(9600);
    Serial.println("scanning");
    }
    void loop()
    {
    if(Serial.available())
    {

    while(rfid.available())
    {
    char input=rfid.read();
    Serial.print(input);
    }
    }
    }

    ReplyDelete
    Replies
    1. #include what?
      Can you post a clear photo of your connections? Does the RFID reader blinks an led or sounds a buzzer when the card is detected?

      Delete
  11. hey, i am using ATK_RF_ID EM-18 Reader Module, USB to RS232 Converter for RFID setup... and using HyperTerminal for receiving the RFID tags...
    So i wanna know is there any API in any programming language, or any application that i can use to receive the tags in plain format and send them to mysql database...

    Also, i dont have to use Arduino, MicroController, ATMEGA... or anything like that..

    ReplyDelete
  12. You may found EM-18 datasheet at

    http://www.nrdcentre.com/image/data/RFID/EM-18 Datasheett.jpg

    ReplyDelete
  13. Hi Prakash,

    I am using this EM-18 Reader Module and it seems to work fine with the Induino R3 board. But i haven't been able to get it to deliver the RFID tag data using any other Arduino board. I have tried Arduino Yun, Genuino MKR1000 and RedBear Duo. I also tried Raspberry Pi 3 but don't get any data on UART Pin

    Any ideas why this would be happening.

    ReplyDelete
  14. Thank you for your excellent tutorial! Best yet. However, I have wired an Arduino Uno R3 to the Itead PN532 RFID Module, as described using Arduino Pin 1 (Rx) and Pin 1 (Tx) to appropriate Itead pins but nothing shows on the Arduino serial monitor. RFID module Mode is set to UART. No errors in code. Please advise. Thanks!

    ReplyDelete
  15. These are photos of my wiring. See Itead for pin layout.
    White is Tx. Purple is Rx. Mode pins set to UART (L/L).
    Thanks.

    https://1drv.ms/i/s!AuwYVXTmJ7BBjKcdb2DV_CXzm7xN9Q
    https://1drv.ms/i/s!AuwYVXTmJ7BBjKccj-dLfUfwpeabtA

    ReplyDelete