Monday, November 25, 2013

C Code to Read RFID Data from an Innovations ID-20LA Using the SparkfunRFID USB Reader Board

This example shows a C program that reads RFID data from an Innovations 20-LA reader using the Sparkfun RFID USB reader board.  This RFID reader board makes it easy to connect the Innovations 20-LA to the Raspberry Pi using a USB cable.

This code is based on sample serial port code by Gary Frerking that I found at the Linux Documentation Project.

This very basic program reads an RFID card and prints the card's unique number to the terminal window.  The program runs continuously until interrupted by the user (ctrl-c).

C Code


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

#define BAUDRATE B9600
#define MODEMDEVICE "/dev/ttyUSB0"
#define TRUE 1

main()
{
        int fd, c, res;
        struct termios newtio;
        char buf[13];
        fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
        if (fd < 0) { perror(MODEMDEVICE); exit(-1); }
        bzero(&newtio, sizeof(newtio)); /* clear struct for new port settings */
        /* BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
           CRTSCTS : output hardware flow control (only used if the cable has
                     all necessary lines. See sect. 7 of Serial-HOWTO)
           CS8     : 8n1 (8bit,no parity,1 stopbit)
           CLOCAL  : local connection, no modem contol
           CREAD   : enable receiving characters */
        newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
        /* IGNPAR  : ignore bytes with parity errors
                     otherwise make device raw (no other input processing) */
        newtio.c_iflag = IGNPAR;

        /*  Raw output  */
        newtio.c_oflag = 0;

        /* ICANON  : enable canonical input
                     disable all echo functionality, and don't send signals to calling
                     program */
        newtio.c_lflag = ICANON;
        /* now clean the modem line and activate the settings for the port */
        tcflush(fd, TCIFLUSH);
        tcsetattr(fd,TCSANOW,&newtio);
        while (TRUE) { /* loop continuously */
                res = read(fd, buf, 13);
                buf[res] = 0;
                printf("%s", buf, res);
        }
}

C Program to Read Copernicus II GPS Data via Serial on a Raspberry Pi

I've already posted a couple examples of using Java to read GPS data from a Copernicus II GPS module connected to a Raspberry Pi ("Sample Java Code to Read GPS Data from a Sparkfun Copernicus II DIP Module on a Raspberry Pi" & "Java Program to Read GPS Data from a Sparkfun Copernicus II GPS & Store it in a MySQL Database on a Raspberry Pi").

The following example is written in C.  It shows how to send an NMEA command over the serial port to the GPS module to configure the output and then reads the GPS data from the module and prints it to the terminal window. The program runs until the user presses ctrl-c.

This code is based on sample serial port code by Gary Frerking that I found at the Linux Documentation Project.  I also posted a version of this code for Beaglebone Black on my Brad's µC Blog.

For more information about the commands to configure the Copernicus II, see Appendix C of the Copernicus II manual.  Each command must include a 2-digit checksum after the asterisk.  See this page for an online tool to calculate the checksum.


If you need a way to test your GPS module or adjust its settings, you may find Trimble GPS Studio helpful. You can download a free copy for Windows here.

Connections


Copernicus II Raspberry Pi
VCC           3.3V 
GND           GND 
TX-B          GPIO15 (RXD) (P1-10)
RX-B          GPIO14 (TXD) (P1-08)


C Code


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

/* baudrate settings are defined in <asm/termbits.h>, which is
   included by <termios.h> */
#define BAUDRATE B19200   // Change as needed, keep B

/* change this definition for the correct port */
#define MODEMDEVICE "/dev/ttyAMA0" 

#define _POSIX_SOURCE 1 /* POSIX compliant source */

#define FALSE 0
#define TRUE 1

main()
{
    int fd, c, res;
    struct termios oldtio, newtio;
    char buf[255]; 
    /* Open modem device for reading and writing and not as controlling tty
       because we don't want to get killed if linenoise sends CTRL-C. */
    fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
    if (fd < 0) { perror(MODEMDEVICE); exit(-1); }

    bzero(&newtio, sizeof(newtio)); /* clear struct for new port settings */

    /* BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
       CRTSCTS : output hardware flow control (only used if the cable has
                 all necessary lines. See sect. 7 of Serial-HOWTO)
       CS8     : 8n1 (8bit,no parity,1 stopbit)
       CLOCAL  : local connection, no modem contol
       CREAD   : enable receiving characters */
    newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;

    /* IGNPAR  : ignore bytes with parity errors
       otherwise make device raw (no other input processing) */
    newtio.c_iflag = IGNPAR;

    /*  Raw output  */
    newtio.c_oflag = 0;

    /* ICANON  : enable canonical input
       disable all echo functionality, and don't send signals to calling program */
    newtio.c_lflag = ICANON;
    /* now clean the modem line and activate the settings for the port */
    tcflush(fd, TCIFLUSH);
    tcsetattr(fd,TCSANOW,&newtio);
    // NMEA command to ouput all sentences
    // Note that this code & format values in manual are hexadecimal
    write(fd, "$PTNLSNM,273F,01*27\r\n", 21);
    /* terminal settings done, now handle input*/
    while (TRUE) {     /* loop continuously */
        /*  read blocks program execution until a line terminating character is
            input, even if more than 255 chars are input. If the number
            of characters read is smaller than the number of chars available,
            subsequent reads will return the remaining chars. res will be set
            to the actual number of characters actually read */
        res = read(fd, buf, 255);
        buf[res] = 0;             /* set end of string, so we can printf */
        printf("%s", buf, res);
    }
}


Compiling & Running the Code


Compiling the code at the command line is very easy.   Assuming that the source code is saved in a file called gps.c -

gcc gps.c -o gps

And the following will run the new program until the user presses control-c -

./gps