PDA

View Full Version : C++ or C code for serial access to RFID Reader



markjoh
02-18-2007, 08:42 AM
Does anyone have an example of the POSIX C or C++ code to get and manipulate RFID Reader serial output?

MarkJ

PLJack
02-20-2007, 08:20 AM
Are you asking how to interface with the computer serial port or how to interface with a RFID reader?

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
- - - PLJack - - -

-----------------------------------------------------------------------------
Perfection in design is not achieved when there is nothing left to add.
It is achieved when there is nothing left to take away.

markjoh
02-20-2007, 12:35 PM
Basically my setup is an RFID reader hooked up to a Mac running OSX using a Keyspan serial adapter. The project is in C/C++ (using Cocoa). I have the RFID reader antennae always "on" by shorting /ENABLE with the ground (the red light is lit).

I am able to properly open and set the attributes of the port (I think at least) using code like this:

//
struct termios theTermios;
#define BUFSIZE 4096
u_char theBuff[BUFSIZE];

fd = open("/dev/cu.USA28Xb2P1.1", O_RDWR | O_NONBLOCK);

tcgetattr(fd, &theTermios);
cfsetspeed(&theTermios, 2400);
theTermios.c_cflag &= (CLOCAL | CREAD);
theTermios.c_cflag &= ~PARENB;
theTermios.c_cflag &= ~CSTOPB;
theTermios.c_cflag &= ~CSIZE;
theTermios.c_cflag |=CS8;
theTermios.c_iflag = 0;
theTermios.c_oflag |= 0;
tcsetattr(fd, TCSAFLUSH, &theTermios);
//

and then read it like this:

k = read(fd, theBuff, n);

However, the data from the port is all garbled like this:

2007-02-19 20:02:24.917 Serial Test[23478] Characters in buffer: 12
2007-02-19 20:02:24.917 Serial Test[23478] Bytes in port buffer: 604
2007-02-19 20:02:24.917 Serial Test[23478] Size of theBuff: 4096
2007-02-19 20:02:24.917 Serial Test[23478] read 12 bytes
2007-02-19 20:02:24.917 Serial Test[23478] theBuff[0]: Ω
2007-02-19 20:02:24.917 Serial Test[23478] theBuff: v
2007-02-19 20:02:24.917 Serial Test[23478] theBuff:
2007-02-19 20:02:24.917 Serial Test[23478] theBuff: V
2007-02-19 20:02:24.917 Serial Test[23478] theBuff:
2007-02-19 20:02:24.917 Serial Test[23478] theBuff:
2007-02-19 20:02:24.917 Serial Test[23478] theBuff[6]: E
2007-02-19 20:02:24.917 Serial Test[23478] theBuff[7]:
2007-02-19 20:02:24.917 Serial Test[23478] theBuff[8]:
2007-02-19 20:02:24.917 Serial Test[23478] theBuff[9]:
2007-02-19 20:02:24.918 Serial Test[23478] theBuff[10]: V
2007-02-19 20:02:24.918 Serial Test[23478] theBuff[11]:

I can't seem to get the tag IDs out of this (12 bits with a LF start and CR stop bit). I have the BASIC code per the RFID docs, but I don't know BASIC and can't figure out how to do this all in C/C++. Thus, I was looking for sample C code to access the serial port and read the RFID reader data, and then to be able to validate the tags.

Does this help explain my problem?

Mark

Harrison.
02-20-2007, 01:38 PM
How are you connecting the reader to your serial port? Did you use a serial level shifter / inverting driver? (something like a MAX232)

Harrison

markjoh
02-20-2007, 09:36 PM
Harrison:

The RFID reader is connected to RS232 to TTL cable (http://www.superdroidrobots.com/shop/item.asp?itemid=104&catid=42), which I believe has a MAX232 inside. That is then connected to a RS232 to RS422 converter (http://www.usconverters.com/rs422.html). I then have the RS232 to RS422 converter connected to the Mac serial port using Cat5 to a DIN8 plug after figuring out which pins were which (only 4 Cat5 wires are used: Rx+, Rx-, Tx+ and Tx-). The reason I went to RS422 is 1) that is what the Mac serial port takes and 2) I will need the RFID reader to be about 1000' from the CPU for my application (an identification reader at an outside gate).

If it helps, when I use another serial program (PortTerm), I have a similar issue. When I put the tag next to the reader and have the output set to "read as string" I get this type of thing (three passes of the tag to the reader - hopefully the garbage characters will make it into this reply):

markjoh
02-20-2007, 09:39 PM
Harrison:

The garbage characters appear to have cut off my reply. Here is the rest of the message:

[continuing]

When I put the tag next to the reader and have the output set to "read as string" I get this type of thing (three passes of the tag to the reader - hopefully the garbage characters will make it into this reply):

markjoh
02-20-2007, 09:43 PM
Harrison:

Well, this forum doesn't seem to like those garbage characters. Anyway, when I use PortTerm and 'read as hex", I get output like this (three passes of the tag to the reader)

B0 00 9F 97 9D 95 7D 7B 91 91 93 9D E5 00 00 00

BD 76 D6 56 D6 ED 45 8B 00 9B D6 56 00 0F 60 EF 76 D6 56 D6 ED 45 8B 9B 00 D6 56 00 0F

EB 9F 97 9D 95 7D 7B 91 91 93 9D E5

Can't seem to find anything that resembles a 12 bit response from the reader.

Mark J

Mike Green
02-20-2007, 11:17 PM
Clearly you're getting garbage. Look in the Parallax reader documentation for the exact format, but it should start with LF, then 10 ASCII digits, then CR. Are you supplying power to the TTL to RS232 converter? Do you have a Stamp or another (different) TTL to Serial or TTL to USB adapter that you could use for testing?

Just as an aside, the Mac serial ports, although they're described as RS422, are compatible with RS232. It's just a matter of using the right cable connections and any Mac mini-DIN to Serial-9 cable will be set up that way. It should work fine for 1000' if you've got a good cable (twisted pairs, shielded).

markjoh
02-20-2007, 11:38 PM
> Look in the Parallax reader documentation for the exact format,
> but it should start with LF, then 10 ASCII digits, then CR.

I was looking for both in the hex output using PortTerm: LF is 0A (hex) and 10 (dec), and CR is 0D (hex), 13 (dec). I can't get any of this in the hex serial stream and definitely not in the string garbage.

> Are you supplying power to the TTL to RS232 converter?

Yes - 5v to the RFID reader, as well as to the TTL to RS232 converter and to the RS232 to RS422 converter, all using the same 9 volt wall wart into a LM7805 or equivalent (tested it - it's 5v).

> Do you have a Stamp or another (different) TTL to
> Serial or TTL to USB adapter that you could use for testing?

No - Is there a suggestion for an inexpensive TTL to USB adapter? For me that probably isn't a permanent solution - I'm having enough trouble learning serial communications with this project and don't want to get into USB communication complexities at this point. I don't have a stamp as I am not sure of Mac compatability and I would need to get a copy of BASIC somewhere (and then learn BASIC - which I thunk I learnt 30 years ago :)

> Just as an aside, the Mac serial ports, although they're described as RS422,
> are compatible with RS232. It's just a matter of using the right cable
> connections and any Mac mini-DIN to Serial-9 cable will be set up that way.
> It should work fine for 1000' if you've got a good cable (twisted pairs, shielded).

Agreed, I've read this. But I set up the RS422 just in case to have it ready. I know they are using RS422 for warehouse and other industrial long-runs of serial.

Mark J

Mike Green
02-21-2007, 01:57 AM
I'm not sure what to suggest other than to simplify the setup until you have a handle on it. If you look on Parallax's Propeller web page (www.parallax.com/dl/docs/prod/prop/SerialtoPropeller.pdf (http://www.parallax.com/dl/docs/prod/prop/SerialtoPropeller.pdf)), there's a TTL to Serial converter. The points marked "3.3V" could just as well be connected to +5V. The reset circuit attached to DTR can be left out for this purpose.

It may be that the RS422 converter is connected backwards or doesn't work as you expect.

PLJack
02-21-2007, 09:28 AM
markjoh said...


u_char theBuff[BUFSIZE];

and then read it like this:

k = read(fd, theBuff, n);



Just some shots in the dark. Not familiar with your compiler.

Most stream functions, especially buffer functions, require a pointer to a character array, u_char in your case.
You seem to be passing a direct reference to the array instead of a pointer to the starting address of the array contents.
Both legal in C++. In other words theBuff should be declared u_char *theBuff[BUFSIZE];, note the * in front of theBuff.
Or, k = read(fd, *theBuff, n);
Hard to tell from a small clippit.
You are dealing with a character array. That means pointers. Garbage out from an array is almost always a pointer issue.

You don't show the declaration fd or n, I assume the are integers.

Like I said, shots in the dark, not much code to go by.
I think it was stated before, but at this point you need to break down your problem into smaller components.

By pass the serial code for now. Create an array and fill it with known values. Then try to read it with your code.
If you get garbage, then you can assume its not the serial code.
You should be filling that buffer with 0's a least, before you use it. A freshly assigned character array will contain whatever happens to reside in that segment of RAM. This is C++, not basic.

Can you read the output with Hyper Terminal?
Does your buffer read contain the same data.
I doubt a RFID tag returns digestible data. Do you need to combine some of those bytes together before you interpret a value?

I'm just rambling now.
Just trying to jog you imagination.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
- - - PLJack - - -

-----------------------------------------------------------------------------
Perfection in design is not achieved when there is nothing left to add.
It is achieved when there is nothing left to take away.

markjoh
02-22-2007, 10:16 PM
Without changing the physical setup, I did do the following per your advice:

#define BUFSIZE 4096
u_char *theBuff[BUFSIZE];

Now, I get the following when I pass the tag near the reader (sorry about the length of this but you can see how the reader output is being handled):

------------

2007-02-21 21:28:38.278 Serial Test 2[26165] Read 1 bytes, Data read (theBuff): 56d6ed45
2007-02-21 21:28:38.282 Serial Test 2[26165] Read 3 bytes, Data read (theBuff): 56d6ed45
2007-02-21 21:28:38.286 Serial Test 2[26165] Read 2 bytes, Data read (theBuff): 56d6ed45
2007-02-21 21:28:38.290 Serial Test 2[26165] Read 2 bytes, Data read (theBuff): 56d6ed45
2007-02-21 21:28:38.321 Serial Test 2[26165] Read 8 bytes, Data read (theBuff): d6ed4500
2007-02-21 21:28:38.325 Serial Test 2[26165] Read 2 bytes, Data read (theBuff): d6ed4500
2007-02-21 21:28:38.329 Serial Test 2[26165] Read 2 bytes, Data read (theBuff): d6ed4500
2007-02-21 21:28:38.338 Serial Test 2[26165] Read 1 bytes, Data read (theBuff): d6ed4500
2007-02-21 21:28:38.341 Serial Test 2[26165] Read 3 bytes, Data read (theBuff): d6ed4500
2007-02-21 21:28:38.348 Serial Test 2[26165] Read 2 bytes, Data read (theBuff): d6ed4500
2007-02-21 21:28:38.349 Serial Test 2[26165] Read 2 bytes, Data read (theBuff): d6ed4500
2007-02-21 21:28:38.356 Serial Test 2[26165] Read 2 bytes, Data read (theBuff): d6ed4500
2007-02-21 21:28:38.365 Serial Test 2[26165] Read 5 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.368 Serial Test 2[26165] Read 2 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.373 Serial Test 2[26165] Read 2 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.376 Serial Test 2[26165] Read 2 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.382 Serial Test 2[26165] Read 2 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.391 Serial Test 2[26165] Read 1 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.392 Serial Test 2[26165] Read 3 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.398 Serial Test 2[26165] Read 2 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.400 Serial Test 2[26165] Read 2 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.409 Serial Test 2[26165] Read 1 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.416 Serial Test 2[26165] Read 1 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.417 Serial Test 2[26165] Read 1 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.422 Serial Test 2[26165] Read 3 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.431 Serial Test 2[26165] Read 1 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.432 Serial Test 2[26165] Read 1 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.436 Serial Test 2[26165] Read 1 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.440 Serial Test 2[26165] Read 1 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.444 Serial Test 2[26165] Read 3 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.450 Serial Test 2[26165] Read 2 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.456 Serial Test 2[26165] Read 1 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.462 Serial Test 2[26165] Read 1 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.464 Serial Test 2[26165] Read 3 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.471 Serial Test 2[26165] Read 1 bytes, Data read (theBuff): ed4500
2007-02-21 21:28:38.527 Serial Test 2[26165] Read 12 bytes, Data read (theBuff): 9d957d7b
2007-02-21 21:28:38.527 Serial Test 2[26165] Read 4 bytes, Data read (theBuff): 9d957d7b
2007-02-21 21:28:46.551 Serial Test 2[26165] Read 6 bytes, Data read (theBuff): d6ed7d7b
2007-02-21 21:28:46.555 Serial Test 2[26165] Read 1 bytes, Data read (theBuff): d6ed7d7b
2007-02-21 21:28:46.564 Serial Test 2[26165] Read 2 bytes, Data read (theBuff): d6ed7d7b
2007-02-21 21:28:46.573 Serial Test 2[26165] Read 2 bytes, Data read (theBuff): d6ed7d7b
2007-02-21 21:28:46.666 Serial Test 2[26165] Read 9 bytes, Data read (theBuff): 56d6ed4d
2007-02-21 21:28:46.670 Serial Test 2[26165] Read 2 bytes, Data read (theBuff): 56d6ed4d
2007-02-21 21:28:46.679 Serial Test 2[26165] Read 3 bytes, Data read (theBuff): 56d6ed4d
2007-02-21 21:28:46.688 Serial Test 2[26165] Read 4 bytes, Data read (theBuff): 56d6ed4d
2007-02-21 21:28:46.908 Serial Test 2[26165] Read 8

------------

From this, it looks like there are two pieces of usable data: 56d6ed4d and 56d6ed45. Those are only 8 characters and I need 10 per the RFID docs. However, if those are viewed as hex characters, then those pieces now look like 8621423777 and 8621423769 in dec, which are now 10 characters and likely candidates for the unique 10 digit IDs for the tags.

Now, what I need to do is find a way to capture the hex series and compare that to a list of known tags (again using a hex series), and I should be good to go to the next step. What is confusing to me though is that the RFID docs say the reader outputs a 12-byte ASCII string. So I guess that could include a 10 byte ASCII hex string, which is what I think I am seeing.

FYI, below this message I've attached the code I'm using to do this testing, which is fairly short. The above output was using the startRead() method that uses a thread rather than the readNonThreaded() method which simply gets a fetch from the buffer rather than starting a thread.

Mark J

============ CODE ==============
#import "serial_test_2.h"

#define DEVICENAME "/dev/cu.USA28Xb2P1.1"

#define BUFSIZE 4096
u_char *theBuff[BUFSIZE];

typedef void *(*__pthreadStart_t)(void *);
pthread_t theReadThread;

int readArmed = 0, fd = 0;

void readThreadCleanup(void *thing),
startRead(),
readThread(void *thing),
stopRead();

struct termios theTermios;

int i, k, n, done = 0;

@implementation serial_test_2

-(void)awakeFromNib
{
}

- (IBAction)configureAndOpen:(id)sender
{
// if port open, close it
if (fd)
{
close(fd);
fd = 0;
//tcflush(fd, &theTermios);
NSLog(@"port closed\n");
} else {
NSLog(@"port already closed\n");
}
// open the port
fd = open(DEVICENAME, O_RDWR | O_NONBLOCK);
NSLog(@"open (%s) returned %d\n", DEVICENAME, fd);

tcgetattr(fd, &theTermios);
cfsetspeed(&theTermios, 2400);
theTermios.c_cflag &= (CLOCAL | CREAD);
theTermios.c_cflag &= ~PARENB;
theTermios.c_cflag &= ~CSTOPB;
theTermios.c_cflag &= ~CSIZE;
theTermios.c_cflag |=CS8;
theTermios.c_iflag = 0;
theTermios.c_oflag |= 0;

tcsetattr(fd, TCSAFLUSH, &theTermios);
NSLog(@"Serial port configured.");
}

- (IBAction)readNonThreaded:(id)sender
{
if (fd)
{
n = 12;
k = read(fd, theBuff, n);
if (k==-1)
{
NSLog(@"read returned errno %d\n", errno);
}
else if (k==0)
{
NSLog(@"read returned 0\n");
}
else
{
NSLog(@"Characters in buffer: %d", k);
int bytes;
//ioctl(fd, FIONREAD, &bytes);
NSLog(@"Bytes in port buffer: %d", bytes);
NSLog(@"Size of theBuff: %d", sizeof(theBuff));
NSLog(@"read %d bytes\n", k);
for (i=0; i<k; i++)
{
NSLog(@"theBuff[%d]: %c", i, theBuff);
}
NSLog(@"\n");
}
}
}

-(IBAction)readThreaded:(id)sender
{
if (readArmed)
{
stopRead();
NSLog(@"Read stopped\n");
}
else
{
NSLog(@"Read started ...\n");
startRead();
}
}

void startRead()
{
if (fd == 0 || readArmed)
return;
readArmed = 1;

// creates a new thread using readThread()
pthread_create(&theReadThread, NULL, (__pthreadStart_t)readThread, NULL);
}

void stopRead()
{
readArmed = 0;
pthread_cancel(theReadThread);
}

void readThreadCleanup(void *thing)
{

}

void readThread(void *thing)
{
pthread_cleanup_push(readThreadCleanup, thing);

while (readArmed)
{
n = 12;
k = read(fd, theBuff, n);
if (k != -1){
NSLog(@"Read %d bytes, Data read (theBuff[%d]): %x\n", k, 1, theBuff);
}
}
pthread_cleanup_pop(thing);
}

@end

markjoh
02-26-2007, 02:21 AM
I been able to capture what appears to be the tag IDs using the code below. Here is what I captured using two tags:

bd 76 d6 56 d6 ed 4d 7b cb 4d 2b 0
bd 76 d6 56 d6 ed 45 8b 9b d6 56 f

These are in hex. According to the RFID reader docs, the RFID reader should send out a 12-byte ASCII string, beginning with a line feed (0x0A) and ending with a carriage return (0x0D). In between these should be 10 digits which should be the unique tag ID. I don't see a line feed to start the string, but "bd" (which is 189 in dec, not a line feed which should be 10). The ending character ("0" and "f") are not CRs (which also are not hex, and a CR in dec should be 13). If I convert the hex charaters to dec, I get way more that 10 digits for the unique ID.

Can anyone provide insight as to how these characters I am capturing relate to the 12 byte ASCII string the RFID reader is putting out?

Mark J

====== the code ==========

#import "serial_test_2.h"

#define DEVICENAME "/dev/cu.USA28Xb2P1.1"

#define BUFSIZE 4096
u_char theBuff[BUFSIZE];

typedef void *(*__pthreadStart_t)(void *);
pthread_t theReadThread;

int readArmed = 0, fd = 0;

void readThreadCleanup(void *thing),
startRead(),
readThread(void *thing),
stopRead();

struct termios theTermios;

int i, k, n, done = 0;

@implementation serial_test_2

-(void)awakeFromNib
{
//[messages setStringValue:@"Messages Initialized ..."];
}

- (IBAction)configureAndOpen:(id)sender
{
// if port open, close it first
if (fd)
{
close(fd);
fd = 0;
NSLog(@"port closed\n");
} else {
NSLog(@"port already closed\n");
}
// open the port
fd = open(DEVICENAME, O_RDWR | O_NOCTTY | O_NONBLOCK);
NSLog(@"open (%s) returned %d\n", DEVICENAME, fd);

// configure the port
tcgetattr(fd, &theTermios);

cfsetspeed(&theTermios, 2400);
theTermios.c_cflag &= (CLOCAL | CREAD);
theTermios.c_cflag &= ~PARENB;
theTermios.c_cflag &= ~CSTOPB;
theTermios.c_cflag &= ~CSIZE;
theTermios.c_cflag |= CS8;
theTermios.c_iflag = IGNPAR;
theTermios.c_iflag &= ~(ICRNL);
theTermios.c_oflag |= 0;
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &theTermios);
NSLog(@"Serial port configured.");
}

- (IBAction)readNonThreaded:(id)sender
{
if (fd)
{
int buffToRead = 20;
k = read(fd, theBuff, buffToRead);
if (k==-1)
{
NSLog(@"read returned errno %d\n", errno);
}
else if (k==0)
{
NSLog(@"read returned 0\n");
}
else
{
//if(*theBuff[0] == '\n'){
//NSLog(@"Found new line character\n");
//}
NSLog(@"Characters in buffer: %d", k);
int bytes;
ioctl(fd, FIONREAD, &bytes);
//fcntl(fd, F_SETFL, FNDELAY);
NSLog(@"Bytes in port buffer: %d", bytes);
NSLog(@"Size of theBuff: %d", sizeof(theBuff));
NSLog(@"read %d bytes\n", k);
for (i=0; i<25; i++)
{
NSLog(@"theBuff[%d]: %x", i, theBuff);
}
NSLog(@"\n");
}
close(fd);
char theTag = theBuff[0] & theBuff;
NSLog(@"theTag: %c\n", theTag);
if (theBuff[0] == 0xbd & theBuff[6] == 0x4d){
NSLog(@"Got it\n");
theBuff[0] = 0x00;
theBuff[6] = 0x00;
}
}
}

-(IBAction)readThreaded:(id)sender
{
if (readArmed)
{
stopRead();
NSLog(@"Read stopped\n");
}
else
{
NSLog(@"Read started ...\n");
startRead();
}
}

void startRead()
{
if (fd == 0 || readArmed)
return;
readArmed = 1;

// creates a new thread using readThread()
pthread_create(&theReadThread, NULL, (__pthreadStart_t)readThread, NULL);
}

void stopRead()
{
readArmed = 0;
pthread_cancel(theReadThread);
}

void readThreadCleanup(void *thing)
{

}

void readThread(void *thing)
{
pthread_cleanup_push(readThreadCleanup, thing);

while (readArmed)
{
n = 12;
k = read(fd, theBuff, n);
if (k != -1){
if (theBuff != 0){
NSLog(@"Read %d bytes, Data read (theBuff[%d]): %x\n", k, 1, theBuff);
}
}
}
pthread_cleanup_pop(thing);
}

@end