Monday, November 25, 2013

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

3 comments:

  1. hello i used this code but no output came.

    ReplyDelete
    Replies
    1. Hi Bipin -

      Did you set the baud rate correctly? Your GPS unit may be set to 9600 baud or some other rate. If you have trouble figuring it out, you might want to try using Trimble Studio to determine the unit's current settings. It looks like the link to the software on the Sparkfun page is old, but you can also get Trimble Studio (for Windows) at http://trl.trimble.com/dscgi/ds.py/Get/File-674264/TrimbleStudio.exe.
      --Brad

      Delete
    2. Hi Bipin -

      This might be a better link for getting Trimble GPS Studio: http://trl.trimble.com/dscgi/ds.py/Get/File-484972/TrimbleStudio.exe

      Delete