Notes About Working with Various Arduino & Netduino Microcontroller Boards

Saturday, October 26, 2013

RFID Using the Innovations ID-20LA & Arduino Yún

On October 24, 2013, Zoe Romano posted on the Arduino Blog about using an RFID reader and an Arduino Yún.  I've posted before about using Innovations RFID readers with the Arduino (connected via the Sparkfun RFID Reader breakout board).  Since the Yún combines a compact Linux machine with the basic Arduino, it allows the inclusion of a small database to track cards and log access.

The stripped down example I present here uses an Innovations ID-20LA RFID module, the Sparkfun breakout board, and an Arduino Yún.  This example uses the light-weight Sqlite3 database, which can be installed on the Yún quite easily.  When an RFID card is in range of the reader, the card's code is checked agains a database table of valid card numbers.  If the card is in the DB table, access is granted.  To keep things simple for this example, messages are sent to the serial monitor rather than a physical access mechanism.

Software installation, Sqlite3 DB setup, and Python programming are done via SSH.  The Arduino sketch is uploaded and the serial monitor is accessed via the latest Arduino IDE.

Installing Sqlite


At the Yún's command prompt, run the following opkg commands to install Sqlite3 and the Python module for accessing it:

opkg install sqlite3-cli

opkg install python-sqlite3

I could not find these modules in the list of available modules in the browser-based software installation page for Yún administration, but they show up in the list of installed packages after running opkg from the command line.

Using the Sqlite3 command line interface at the command prompt, I created the database (rfid.db) and the tables to hold the valid card numbers (rfid_card) and successful access (rfid_access).  I won't go into the details here.  See the Sqlite3 documentation for more information.


Connections


Sparkfun RFID Board   Arduino Yún
VCC                   3.3V                          
GND                   GND
TX                    Digital 10 (using SoftwareSerial)

Arduino Code


The Arduino C sketch used the SoftwareSerial library for communication with the RFID module and the Bridge library for communication between the Arduino and Linux sides of the Yún.

The Arduino sketch reads the number from the RFID tag and sends it to the Python script via the Bridge library for verification and logging.

#include <Bridge.h>
#include <Process.h>
#include <SoftwareSerial.h>


SoftwareSerial rfidSerial(10, 11); // RX, TX (TX not used)
String card = "";

void setup()  
{
  Serial.begin(9600);
  rfidSerial.begin(9600);
  Bridge.begin();  
  while(!Serial);
}

void loop() 
{
  while(rfidSerial.available()) {
    char c = rfidSerial.read();
    if(c == '\n') {
      card.trim();
      // Remove 2 control chars at start of card data
      card = card.substring(2);
      if(card.length() == 12) {
        checkCard(card);
        break;
      }
      else {
        Serial.println("Error");
        card = "";
      }
    }
    else {
      card = card + c;
    }  
  }
}

void checkCard(String cardID) {
  Process p;
  String cmd = "/usr/bin/python";
  p.begin(cmd);
  // Adjust path to Python script as needed
  p.addParameter("/mnt/sda1/lookup_rfid.py");
  p.addParameter(cardID);
  p.run();
  while(p.available() > 0) {
    char result = p.read();
    if(result == '1') {
      Serial.println("OK");
      card = "";
      break;
    }
    else {
      Serial.println("Denied");
      card = "";
      break;
    }
  }
}

Python Code


The following code is saved in file called lookup_rfid.py.

import sys
import sqlite3

# Change path to DB file as required
conn = sqlite3.connect('/mnt/sda1/rfid.db')
cur = conn.cursor()
# Note space between ' and ''' in 2nd line    
lookup_sql = '''select count(*) from rfid_card  
where card = '%s' ''' % sys.argv[1]
result = cur.execute(lookup_sql)
data = cur.fetchone()           
# if 1, access allowed. Log access
if data[0] == 1:                                             
print 1                                                  
log_sql = '''insert into rfid_access(card, date_time)    
values('%s', date('now', 'localtime') || ' ' ||
time('now', 'localtime'))''' % sys.argv[1]
cur.execute(log_sql)
conn.commit()     
# if 0, access denied     
elif data[0] == 0: print 0
# Other errors
else: print 3
conn.close()

Note: For some reason, I always get an error when I scan the first card after starting the application, but subsequent scans work as expected.

1 comment: