Friday 24 January 2014

GPS Version 3

Here's an update to the code:

// GPS v3 module and LCD display
// display is limited to 16 x 2, so some data truncated
// Antony Watts 2014

/* GPS Pin connections
Module - Arduino
GND    -     GND
RX     -  Pin 11 TXPIN
TX     -  Pin 10 RXPIN
VCC    -    3.3V !!!!!
*/

// libraries
#include "SoftwareSerial.h"
#include "LiquidCrystal.h"

// GPS connections
#define RXPIN 10
#define TXPIN 11
#define BAUD 9600

// $GPRMC field positions in NMEA stream
#define RMCUTC 1
#define RMCLAT 3
#define RMCNS 4
#define RMCLON 5
#define RMCEW 6
#define RMCSOG 7
#define RMCCOG 8
#define RMCDATE 9

// LCD connections
#define RS 2
#define EN 3
#define D4 4
#define D5 5
#define D6 6
#define D7 7

// set up serial comms for GPS
SoftwareSerial gps(RXPIN, TXPIN); // serial comms to GPS UART

// Create LCD object
LiquidCrystal lcd(RS, EN, D4, D5, D6, D7);

void setup()
{
  gps.begin(BAUD); // start GPS serial
  lcd.begin(16, 2); // start LCD 16 col x 2 row
}

void loop()
{
  // main data buffers, NMEA read and field extract
  char gpsbuf[200];
  char ebuf[20];
  
  readgps(gpsbuf); // read each $GPxxx NMEAstrings+CRLF into gpsbuf
  
  // use $GPRMC string
  if(strncmp(gpsbuf, "$GPRMC", 6) == 0)
  { 
    extract(RMCUTC, gpsbuf, ebuf); // get utc
    lcdrpt(ebuf, 9, 0, "**:**"); // display lcd at col 9, row 0, in format hh:mm
      
    extract(RMCLAT, gpsbuf, ebuf); // get lat
    lcdrpt(ebuf, 0, 1, "** ****"); // display lcd at col 0 row 1, in format dd mmmm
    
    extract(RMCNS, gpsbuf, ebuf); // get N|S
    lcdrpt(ebuf, 7, 1, "* ");
    
    extract(RMCLON, gpsbuf, ebuf); // get lon
    lcdrpt(ebuf, 9, 1, "*** **");
    
    extract(RMCEW, gpsbuf, ebuf); // get E|W
    lcdrpt(ebuf, 15, 1, "* ");
    
//    extract(RMCSOG, gpsbuf, ebuf); // get SOG
    
//    extract(RMCCOG, gpsbuf, ebuf); // get COG
    
    extract(RMCDATE, gpsbuf, ebuf); // get date
    lcdrpt(ebuf, 0, 0, "**-**-**");
  }
}

// read GPxxx NMEA string into buffer
void readgps(char *buffer) 
{
  int bp;
  char c;
  
  bp = 0;
  do
  {
    c = gps.read();
    if(c == -1) continue; // gps sends -1 when idle
    buffer[bp++] = c;
  } while(c != '\n'); // ends with LF
  buffer[bp] = '\0'; // add '\0'
}

// extract string from field 0-10 from inbuf to outbuf
void extract(int field, char *inbuf, char *outbuf)
{
  int fcount; // field counter
  int ip; // inbuf pointer
  int op; // outbuf ptr

  fcount = 0;
  ip = 0;
  op = 0;
  
  while(fcount != field) // find field
  {
    while(inbuf[ip++] != ',');
    fcount++;
  }
  
  while(inbuf[ip] != ',') // copy inbuf to outbuf
  {
    outbuf[op++] = inbuf[ip++];
  }
  outbuf[op] = '\0'; // mark end of string
}

// display inbuf at col row in fmtbuf format
// display: * = use inbuf character, otherwise use fmtbuf character
int lcdrpt(char *inbuf, int col, int row, char *fmtbuf)
{
 int inp; // pointers to inbuf and format
 int fmtp;
 
 inp = 0; // start at buffers beginning
 fmtp = 0;
 
 lcd.setCursor(col, row);// start writing here
 
 while(fmtbuf[fmtp] != '\0') // continue until '\0' of format
 {
   if(fmtbuf[fmtp] == '*') // use inbuf character
   {
     lcd.write(inbuf[inp++]); // write inbuf char to lcd
   }
   else
   {
     lcd.write(fmtbuf[fmtp]); // format character
   }
   fmtp++;
 }
}


No comments: