Sunday, April 27, 2014

Inventek GPS


We used the Inventek GPS for our onboard GPS.  This device was able to transmit its coordinates through the Laird Comm system as well as store its coordinates on the onboard SD card.

The GPS could not simply be connected to the Arduino's TX and RX pins.  We used these pins for the Laird Comm system, and had to define other pins of the Arduino as TX and RX.  Following the instructions on the data sheet found here http://inventeksys.com/specs/ISM300F2_Functional_Spec.pdf  we were able to connect the GPS to our Arduino.

To set pins as TX and RX we used these lines of code.
#define RXPIN 3
#define TXPIN 2

void setup(){
  pinMode(RXPIN,INPUT);
  pinMode(TXPIN,OUTPUT);
}

This set digital pin 3 as RX and digital pin 2 as TX.

The GPS printed out an NMEA sentence of the type GPGGA.  Using the site http://aprs.gids.nl/nmea/ we were able to find which portions of the sentence carried the information we needed.  For this project we used latitude, longitude, altitude, and the number of satellites locked on to the GPS.

The following code was used to parse out the wanted information.

#include <SoftwareSerial.h>
#include <stdlib.h>

#define RXPIN 3
#define TXPIN 2
SoftwareSerial nss(RXPIN, TXPIN);

#define BUFFSIZ 90 // plenty big
char buffer[BUFFSIZ];
char buffer2[BUFFSIZ];
char *parseptr;
char buffidx;
uint8_t hour, minute, second, year, month, date;
uint32_t latitude, longitude, Satellites, altitude;

uint8_t groundspeed, trackangle;
char latdir, longdir;
char status;

float lat, lon;
unsigned long fix_age, time, speedvar, coursevar;

unsigned long chars;
unsigned short sentences, failed_checksum;
float flat, flon;

 
void setup() {
  Serial.begin(9600);
  nss.begin(4800);
 
  pinMode(RXPIN,INPUT);
  pinMode(TXPIN,OUTPUT);  
}

void loop()
{

uint32_t tmp;
 
  //Serial.print("\n\rread: ");
 int found = 0;
 int tries = 20;
 int itry = 0;



 while ((found != 1) || itry > tries){
  readline();
  if (buffer[0] != '$'){
    buffer2[0]='$';
    char nextchar;
    int i = 0;
    while(buffer[i+1] != '\0')
      {
        nextchar = buffer[i];
        buffer2[i+1] = nextchar;
       
       
        i++;
      }
  }
    // Serial.println(buffer);
   if ((strncmp(buffer, "$GPGGA",6) == 0)){
     found = 1;
   }
   itry = itry + 1;
 }
 
 Serial.print("\nbuffer: ");
 //Serial.println(buffer);
  Serial.print(buffer);
 
 
   parseptr = buffer+7;
    tmp = parsedecimal(parseptr);
    hour = tmp / 10000;
    minute = (tmp / 100) % 100;
    second = tmp % 100;
   
    parseptr = strchr(parseptr, ',') + 1;

    // grab latitude & long data
    // latitude
    latitude = parsedecimal(parseptr);
    if (latitude != 0) {
      latitude *= 10000;
      parseptr = strchr(parseptr, '.')+1;
      latitude += parsedecimal(parseptr);
    }
    parseptr = strchr(parseptr, ',') + 1;
    // read latitude N/S data
    if (parseptr[0] != ',') {
      latdir = parseptr[0];
    }
   
    //Serial.println(latdir);
   
    // longitude
    parseptr = strchr(parseptr, ',')+1;
    longitude = parsedecimal(parseptr);
    if (longitude != 0) {
      longitude *= 10000;
      parseptr = strchr(parseptr, '.')+1;
      longitude += parsedecimal(parseptr);
    }
    parseptr = strchr(parseptr, ',')+1;
    // read longitude E/W data
    if (parseptr[0] != ',') {
      longdir = parseptr[0];
    }
   
    //Satelites
    parseptr = strchr(parseptr, ',')+3;
  if (parseptr[0] != ',') {
     Satellites = parsedecimal(parseptr);
  }
   
 parseptr = strchr(parseptr, ',')+5;
 altitude = parsedecimal(parseptr);
  if (parseptr[0] != ',') {  
    altitude *= 100;
     parseptr = strchr(parseptr, '.')+1;
     altitude += parsedecimal(parseptr);
  }

    Serial.print("\nTime: ");
    Serial.print(hour, DEC); Serial.print(':');
    Serial.print(minute, DEC); Serial.print(':');
    Serial.println(second, DEC);

   
    Serial.print("Lat: ");
    if (latdir == 'N')
       Serial.print('+');
    else if (latdir == 'S')
       Serial.print('-');

   Serial.print(latitude/1000000, DEC); Serial.print('\''); Serial.print(' ');
    Serial.print((latitude/10000)%100, DEC); Serial.print('\''); Serial.print(' ');
    Serial.print((latitude%10000)*6/1000, DEC); Serial.print('.');
    Serial.print(((latitude%10000)*6/10)%100, DEC); Serial.println('"');
 
    Serial.print("Long: ");
    if (longdir == 'E')
       Serial.print('+');
    else if (longdir == 'W')
       Serial.print('-');
    Serial.print(longitude/1000000, DEC); Serial.print('\''); Serial.print(' ');
    Serial.print((longitude/10000)%100, DEC); Serial.print('\''); Serial.print(' ');
    Serial.print((longitude%10000)*6/1000, DEC); Serial.print('.');
    Serial.print(((longitude%10000)*6/10)%100, DEC); Serial.println('"');
     Serial.print("Alt: ");
     Serial.println(((float) altitude / 100.),DEC);
     Serial.print("Satellites: ");
     Serial.println(Satellites);
 
 
  delay(5000);
 
}



uint32_t parsedecimal(char *str) {
  uint32_t d = 0;
 
  while (str[0] != 0) {
   if ((str[0] > '9') || (str[0] < '0'))
     return d;
   d *= 10;
   d += str[0] - '0';
   str++;
  }
  return d;
}

void readline(void) {
  char c;
 
  buffidx = 0; //start at begninning
   int started = 0;
  while (1) {
     //int started = 0;
      c=nss.read();
   
      if (c == 'G'){
        started = 1;
      }
      if (started == 1 && c == '$'){
        return;
      }
      if (c == -1)
        continue;
     // Serial.print(c);
      if (c == '\n')
        continue;
      if ((buffidx == BUFFSIZ-1) || (c == '\r')) {
        buffer[buffidx] = 0;
       
        return;
      }
      buffer[buffidx++]= c;
  }
}
Note that the latitude and longitude printed here is in degree form.  Decimal form is much more useful, and can be plugged into google maps, in our final code I used the print statements here to convert the latitude and longitude into decimal form.  It was brought up by another team member that you can simply print the longitude and latitude with no corrections (simply Serial.print(latitude)) and you should get the latitude in decimal form, judging from the GPGGA statement.

Using this setup we were able to get a fix with 5-8 satellites in a few minutes, and were able to get a lock on our location that was fairly close to that given by google maps.

Written by: Iain Rhodes

No comments:

Post a Comment