Interfacing RFID reader with ZKit-ARM-1769

RFID reader is a radio frequency (RF) transmitter and receiver controlled by a microprocessor. In this article, we will show how to interface an RFID reader from rhydoLABZ (RFID-1320) with the ZKit-ARM-1769.

RFID reader specifications

When the RFID tags are brought in proximity to the reader, the RFID reader transmits the unique ID through the serial port at 9600 bps. The reader output is 12 byte including one start, stop byte and 10 unique data byte. The start byte and stop byte are used to easily identify that a correct string has been received from the reader. The middle ten bytes are the actual tag’s unique ID.

The serial port parameters: 8 data bits, no parity and 1 stop bit.

Hardware setup

The RFID reader is connected to the target board using UART (P2) port.

/static/images/zkit-arm-1769-rfid.jpg
Figure 1. RFID Reader Connected to ZKit-ARM-1769

Software

The application program to read and authenticate RFIDs is shown in the following list. The following program requires termios enabled in NuttX. The NuttX library provided by Zilogic does not have termios enabled by default. Hence NuttX has to be rebuilt with termios enabled. Procedure to build NuttX is available in Building NuttX for ZKit-ARM-1769.

  • Modify the NSH configuration available in nuttx/configs/zkit-arm-1769/nsh/defconfig and enable the CONFIG_SERIAL_TERMIOS option.

  • Build NuttX for the NSH application.

  • Add the following program as a new application, as indicated in Writing NuttX Applications

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <stdio.h>

/* UART(P2) device path by default - RFID reader is connected to this port */
#define PORT "/dev/ttyS1"

#define RFID_START_CHAR '\n'
#define RFID_STOP_CHAR  '\r'
#define RFID_SIZE       10
/**
 * rfid_init - initialize RFID reader
 *
 * Initializes the RFID reader serial interface and returns the
 * serial port file descriptor.
 *
 * Returns:
 *   serial port fd on success.
 *   -1 on failure, errno is set accordingly.
 */
static int rfid_init(void)
{
        struct termios options;
        speed_t speed;
        int fd;
        int ret;
        fd = open(PORT, O_RDWR | O_NOCTTY);
        if (fd == -1)
                return -1;
         /* get serial port attributes*/
        ret = tcgetattr(fd, &options);
         /* clear the attributes*/
        bzero(&options, sizeof(options));
         /* setting baud rate as required by the RFID reader */
        speed = B9600;
        cfsetospeed(&options, speed);
        cfsetispeed(&options, speed);
         /*
          * c_flag, control mode flag costants => ignore modem control lines,
          * enable receiver, character size mask respectively
          */
        options.c_cflag |= (CLOCAL | CREAD |  CS8);
         /*
          * c-iflag, input mode flag constants => ignore framming errors and
          * parity errors, ignore break condition on input respectively
          */
        options.c_iflag |= (IGNPAR | IGNBRK );
        options.c_cc[VTIME] = 10;
        options.c_cc[VMIN] = 0;
         /* TCSANOW => set sttributes now*/
        tcsetattr(fd, TCSANOW, &options);
        return fd;
}

/*
 * Wait for a character on the serial port.
 */
static void wait_for(int fd, char ch)
{
        char read_ch;
        int ret;

        while (1) {
                ret = read(fd, &read_ch, 1);
                if (ret == 1 && read_ch == ch)
                        break;
        }
}

/**
 * read_rfid - read an RFID
 * @fd: the RFID serial port file descriptor
 * @string: buffer to store the RFID, should be atleast 11 characters
 *
 * Returns:
 *    0 - on success
 *   -1 - if read fails, errno is set accordingly.
 *   -2 - if stop byte is not seen, or if short RFID is read
 */
static int rfid_read(int fd, char *string)
{
        int nbytes;
        int ret;

        wait_for(fd, '\n');
        nbytes = 0;
        while (nbytes < (RFID_SIZE + 1)) {
                ret = read(fd, &string[nbytes], 1);
                if (ret < 0)
                        return ret;

                if (ret == 1) {
                        if (string[nbytes] == RFID_STOP_CHAR) {
                                if (nbytes != RFID_SIZE)
                                        return -2;

                                string[nbytes] = 0;
                                return 0;
                        }
                        nbytes++;
                }
        }
        return -2;
}

/*
 * List of permitted RFIDs.
 */
static char *permit_list[] = {
        "660093E2BA",
        "660093DD86",
        "2345678901"
};

/*
 * Check if the specified ID is in the permitted list.
 */
static int authenticate_id(char *buf)
{
        int index;
        int count = sizeof(permit_list) / sizeof(char *);

        for (index = 0; index < count; index++) {
                if (strcmp(buf, permit_list[index]) == 0)
                        return 0;
        }
        return 1;
}

int app_main(int argc, char *argv[])
{
        int fd, ret, flag;
        char buf[RFID_SIZE + 1];  /* RFID size, plus 1 byte for '\0' */

        fd = rfid_init();
        if (fd == -1) {
                perror("error initializing RFID reader\n");
                return -1;
        }

        printf("RFID ready\n");

        while (1) {
                ret = rfid_read(fd, buf);
                if (ret == -2)
                        continue;

                if (ret == -1) {
                        perror("error reading data\n");
                        return -1;
                }

                printf("Read ID: %s\n", buf);

                flag = authenticate_id(buf);
                if (!flag)
                        printf("Authentication success\n");
                else
                        printf("Authentication failure\n");
        }

        return 0;
}

The source code of this project can be downloaded from /static/code/nuttx-rfid.c[here].