Channels ▼

Al Williams

Dr. Dobb's Bloggers

RFID Connections from the Top

July 01, 2014

Last time I talked about decomposing moderately complicated programs into simpler blocks and drilling down to smaller blocks with more complexity.

A few years back I was approached to redesign a piece of gear. The exact details aren't important, so I'm going to change the details to protect the guilty. The basic idea was the machine could produce one of several objects like a 3D printer. The user would take an existing object and put it in a slot. The machine would recognize which part it was and print a copy of that part.

Simple, right? Apparently the people who designed the complex machine thought so. They had wired reed switches to a conventional PC keyboard and put magnets on the model objects. If the user put the object in just right, the machine would see a keypress on the keyboard and get to work. The chances of that, however, were pretty slim and the machine was often surrounded by angry users.

When I first saw this, I thought about using RFID, which was a pretty new thing at the time. I was afraid it might be cost prohibitive, but I found a line of very neat sensors from a company called Phidgets. The inexpensive boards connect via USB and one of them provides an RFID sensor.

You've probably seen RFID tag systems in stores. The tags can be in a credit card form or in a little button about the size of a quarter. The simple tags supported by the Phidget board have to be close to the receiver and they each have a unique number that identifies them. If the tag gets close to the reader, the reader will detect it and report is unique number.

The API to read the RFID isn't very difficult to use, but it is a bit baroque. In other words, it isn't as simple as just calling get_rfid_tag(). You have to open the device and connect to it. There are a variety of callbacks (but you don't have to use them) and a little logic to determine if you have a new tag or you are still reading a previous tag.

This is a good example of how you can get a program rolling by using the top down method I discussed last time. Here's a simple program that meets the requirements:

#include "auto3dp.h"

int main(int argc, char *argv[])
  {
   init();
   while (1)
      {
        int tag=read_rfid();
        if (tag) do_3d_print_job(get_obj_id(tag));
      }
   return 0; // not reached
  }

That's easy, right? Well, if you already have the get_rfid and do_3d_print_job functions, it is. I'm going to leave the do_3d_print_job function as an exercise for the reader (although, it is easy enough to stream G-Code to the printer or call an external program to do it). That's another advantage of this technique. For debugging purposes, it is very easy to replace the simple function with a debugging stub. For example:

#include <stdio.h>

char *objects[]=
  {
   "None",
   "Robot",
   "Cup",
   "Ring",
   "Money Clip"
   };


void do_3d_print_job(int id)
   {
      assert(id<sizeof(objects)/sizeof(objects[0]));
      printf("Printing object %s\n",objects[id]);
   }

This lets me put that function off until I'm ready to work on it for real.

The Phidgets RFID reader API requires you to do the following steps:

  1. Create a handle to the device
  2. Connect callbacks for various events (optional)
  3. Open the device
  4. Connect the device
  5. Turn on the antenna
  6. Either wait for events or wait for callbacks

The events can be that a tag was acquired or lost, an interface board being inserted or removed, or some sort of error.

For this simple program I decided to do the simplest thing and just wait for a tag to appear. Without the callbacks, the easiest way to do that seems to be to make a call to see if the reader is currently in contact with an RFID tag. If so, you can read the "last" tag (which is, of course, the one it is contact with). The program stores the tag number so that it doesn't report the same tag repeatedly. It will, however, report the same tag if the readers sees the tag, loses contact with the tag, and then the tag is placed next to the reader again.

The only other complication is that the tag is long enough to need a 64-bit integer. In the code, you’ll see the use of long long data types and the rarely used strtoull function (the two l's at the end are not a typo).

Here's my actual implementation of the RFID code:

#include "auto3dp.h"
#include <stdlib.h>

static CPhidgetRFIDHandle rfid=0;
static unsigned long long lastid=0;






static int open_rfid()
{
  int result;
  if (!rfid)
    {
      CPhidgetRFID_create(&rfid);
      CPhidget_open((CPhidgetHandle)rfid,-1);
      return 1;
      
    }
  return rfid!=0;
}

static void close_rfid()
{
  lastid=0;
  if (rfid)
    {
      CPhidget_close((CPhidgetHandle)rfid);
      CPhidget_delete((CPhidgetHandle)rfid);
      rfid=0;
    }

}

unsigned long long read_rfid(void)
{
  unsigned long long rv=0;
  int stat=0;
  char *tag;
  CPhidgetRFID_Protocol proto;
  open_rfid();  // does nothing if already open
  CPhidgetRFID_setAntennaOn(rfid,PTRUE);
  // check to see if tag active
  CPhidgetRFID_getTagStatus(rfid,&stat);
  if (stat!=1) 
    {
      lastid=0;
      return rv;
    }
  

  CPhidgetRFID_getLastTag2(rfid,&tag,&proto);
   rv=strtoull(tag,NULL,16);
   if (rv==lastid) return 0;
   lastid=rv;
  return rv;
}

You can find all the code online if you want to try it for yourself. You'll also need the Phidgets C API from their web site to compile and run the program. Or, you can replace the RFID module with a debugging stub, if you prefer.

I used C because the Phidgets API is C-oriented (although they have other APIs for many other languages, and there are some third-party C++ wrappers on the Internet). However, the general idea is applicable to just about any language.

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 


Video