Simply store coordinates from Adafruit Ultimate GPS Breakout

Hi,

I having quite a problem to simply store the coordinates my new Adafruit Ultimate GPS Breakout is sending. Even the tutorial is giving me no clue on how to do so, neither the examples. All I want is to write both coordinates latitude and longitude into variables or as a String.

As I figured so far out the breakout is constantly sending stuff, so I would need to catch one of these and process them?

Best,

Dennis

All I want is to write both coordinates latitude and longitude into variables or as a String.

WHERE do you intend to store this data? The Arduino has 3 kinds of memory - SRAM, Flash, and EEPROM.

Storing data in SRAM is easy, but there is a (very) limited amount of it, and it is not persistent.

Storing data in EEPROM is relatively easy, but there is even less of it than SRAM, but it is persistent.

There is lots of Flash, but it is read-only at run-time.

I just need them temporarily in order to process and write them into a json file on my attached sd-card. My problem is that I don't know and cannot figure out how the Adafruit GPS library is working in detail so I can just define a variable like double lat = GPS.lat(); But regrettably it's not that straightforward :/

My problem is that I don't know and cannot figure out how the Adafruit GPS library is working in detail so I can just define a variable like double lat = GPS.lat(); But regrettably it's not that straightforward :/

It probably is. But, we need a link to the library AND we need to see your code, to tell you where to add the code to get/use/store the latitude and longitude data.

I use the GPS from Adafruit. Here is the test code I used to test it. Maybe you can get some useful stuff from it. The GPS_init function shows how to change some of the setup stuff that you may want to try. I left a lot of debugging stuff in it, but commented out. I use a Mega 2560, so I use Serial1 (hardware), but I have tested it with software serial, and it works almost as well with it.

One of the other members of the forum (/dev) has a library that will parse the stuff for you, but I haven’t tried it yet. He should be along soon.

int charCount = 0;
char gpsBuf[255];
byte tIndex[16];
char latDegrees[4];
char latMinutes[8];
char latSeconds[6];
char longDegrees[5];
char longMinutes[8];
char longSeconds[6];
char gpsSpeed[8];
char gpsHeading[8];
boolean gpsLock = false;
boolean readLock = false;

void setup() {
  Serial.begin(115200);

  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);
  
  GPS_init();
}

void loop() {
  checkGPS();
}

void computeSeconds(char* minuteBuf,char* secondBuf)
{
  for(int i = 0; i < 8; i++)
  {
    if(minuteBuf[i] == '.')
    {
      minuteBuf[i] = 0;
      unsigned int secondInt = atoi(&minuteBuf[i+1]);
      secondInt = (secondInt * 6)/100;
      itoa(secondInt,secondBuf,10);      
      secondBuf[strlen(secondBuf) + 1] = 0;
      secondBuf[strlen(secondBuf)] = secondBuf[strlen(secondBuf) -1];
      secondBuf[strlen(secondBuf) -2] = '.';
    }
  }
}

void GPS_init() {
  Serial1.begin(9600);

// warm start
  Serial1.println("$PMTK102*31");
  delay(500);

  Serial1.println("$PMTK251,19200*22");
  delay(500);

  Serial1.end();
  delay(1000);
  Serial1.begin(19200);
  delay(500);
  
// update 500ms
//  Serial1.println("$PMTK220,500*2B");
//  delay(100);
    
// position only
  Serial1.println("$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29");
}

void checkGPS() {
  while(Serial1.available()) {
    char ch = Serial1.read();
    
    if(charCount < 254 && ch != '\r' && ch != '\n') {
      gpsBuf[charCount] = ch;
      charCount++;      
      gpsBuf[charCount] = 0;
    }

    if(ch == '\n') {

      if(strncmp(gpsBuf,"$GPRMC",6) == 0) {
        digitalWrite(13,HIGH);

//        Serial.println(gpsBuf);
        int commaCount = 0;
                
        for(int i = 0; i < 254; i++) {
          if(gpsBuf[i] == ',') {
            tIndex[commaCount] = i + 1;
            gpsBuf[i] = 0;
            commaCount++;              
          }
          else if(gpsBuf[i] == '*') {
            gpsBuf[i] = 0;
            break;            
          }
        }

        Serial.print("Time: ");
        Serial.print(&gpsBuf[tIndex[0]]);

//        Serial.print(" Status: ");
        Serial.println(&gpsBuf[tIndex[1]]);

        if(gpsBuf[tIndex[1]] == 'A')
        {
          readLock = true;
          gpsLock = true;
          delay(10);
          
//          Serial.print(" ");
//          Serial.print(&gpsBuf[tIndex[3]]);
//          Serial.print(&gpsBuf[tIndex[2]]);

          strcpy(latDegrees,&gpsBuf[tIndex[3]]);
          strncat(latDegrees,&gpsBuf[tIndex[2]],2);
          strcpy(latMinutes,&gpsBuf[tIndex[2] + 2]);
          computeSeconds(latMinutes,latSeconds);

          Serial.print(latDegrees);
          Serial.print(" ");
          Serial.print(latMinutes);
          Serial.print("' ");
          Serial.print(latSeconds);
          Serial.print("\" ");
//          Serial.print(&gpsBuf[tIndex[5]]);
//          Serial.print(&gpsBuf[tIndex[4]]);

          strcpy(longDegrees,&gpsBuf[tIndex[5]]);
          strncat(longDegrees,&gpsBuf[tIndex[4]],3);
          strcpy(longMinutes,&gpsBuf[tIndex[4] + 3]);
          computeSeconds(longMinutes,longSeconds);
          
          Serial.print(longDegrees);
          Serial.print(" ");
          Serial.print(longMinutes);
          Serial.print("' ");
          Serial.print(longSeconds);
          Serial.println("\" ");

/*
          Serial.print(" Speed: ");
          Serial.print(&gpsBuf[tIndex[6]]);
*/

          int thisSpeed = atoi(&gpsBuf[tIndex[6]]);
          itoa(thisSpeed,gpsSpeed,10);
          strcpy(gpsSpeed,&gpsBuf[tIndex[6]]);
                 
//          Serial.print(" Hdg: ");
//          Serial.println(&gpsBuf[tIndex[7]]);

          int thisHdg = atoi(&gpsBuf[tIndex[7]]);
          itoa(thisHdg,gpsHeading,10);

          strcpy(gpsHeading,&gpsBuf[tIndex[7]]);
          readLock = false;

          digitalWrite(13,LOW);
        }
        else {
          Serial.println(" No lock");
          gpsLock = false;
        }
      }
      else Serial.println("No position");
            
      charCount = 0;
      gpsBuf[0] = 0;
    }
  }
}

Thanks SurferTim, I'll try later! I was testing the Adafruit GPS Library and the parsing example.

I haven't tried that library. What is the problem you are having with it?

edit: I see what you posted above. I don't use float. I use int data types parsed into character arrays. BTW, there are a ton of example sketches for that library. Take a look at the "parsing" example.

As said I was trying the parsing example ;-)

One of the other members of the forum (/dev) has a library that will parse the stuff for you, but I haven’t tried it yet. He should be along soon.

:smiley:

Yes, I wrote a GPS library called NeoGPS. It is faster and smaller than all other libraries combined, able to leap tall buildings, etc., etc.

It is not easier to understand than other libraries, but I do think the examples are easier to understand:

#include <Arduino.h>
#include "NMEAGPS.h"
#include <NeoSWSerial.h>

NeoSWSerial gps_port( 2, 3 ); // connected to GPS TX, GPS RX pins
NMEAGPS  gps; // This parses the GPS characters

void setup()
{
  Serial.begin(9600);
  while (!Serial)
    ;

  Serial.println( F("Looking for GPS device...") );

  gps_port.begin(9600);
}

//--------------------------

void loop()
{
  while (gps.available( gps_port ))
    doSomeWork( gps.read() );
}

//--------------------------

void doSomeWork( const gps_fix & fix )
{
  //  This is the best place to do your time-consuming work, right after
  //    the RMC sentence was received.  If you do too many other things
  //    in "loop()", you could cause GPS characters to be lost, and you 
  //    will not get a good lat/lon.
  //  If you print too much data here, this routine will not get back 
  //    to "loop()" in time to process the next set of GPS data.

  if (fix.valid.location) {

    if ( fix.dateTime.seconds < 10 )
      Serial.print( '0' );
    Serial.print( fix.dateTime.seconds );
    Serial.print( ',' );

    Serial.print( fix.latitude(), 6 ); // floating-point display
    Serial.print( ',' );
    Serial.print( fix.longitude(), 6 ); // floating-point display

    Serial.print( ',' );
    if (fix.valid.satellites)
      Serial.print( fix.satellites );

    Serial.print( ',' );
    Serial.print( fix.speed(), 2 );
    Serial.print( F(" kn = ") );
    Serial.print( fix.speed_mph(), 2 );
    Serial.print( F(" mph") );

  } else {
    // No valid location data yet!
    Serial.print( '?' );
  }

  Serial.println();

} // doSomeWork

But beginners usually have trouble figuring out how to get the GPS fields they want.

In a nutshell, the gps.read() function returns a whole structure, not just one character. That structure has been populated with all the parsed GPS data. So if you want the latitude, you would access that member of the structure:

  Serial.print( fix.latitude(), 6 ); // prints latitude with 6 digits after the decimal point

That line is in the example above, in doSomeWork(). The fix structure was passed in from loop():

    doSomeWork( gps.read() );

All the fields you can access are described here.

BTW, there is also a NeoGPS example for logging data to the SD card, but it’s more advanced. If you want to try it, be sure to follow the Installation instructions and work through the examples: NMEA.ino, NMEAorder.ino, NMEA_isr.ino and finally NMEASDlog.ino. You will also need one of the Neo__Serial libraries for that. Many people have trouble logging to an SD card with other GPS libraries.

What Arduino do you have? Use one of the HardwareSerial ports if you have a Mega or Leo:

HardwareSerial & gps_port = Serial1;

If you have an UNO, connect the GPS to pins 8&9 and use AltSoftSerial for best results:

AltSoftSerial gps_port;

If those pins aren’t available (are you sure?), use NeoSWSerial on any other pair of pins (see example sketch above). NeoSWSerial is much more efficient than SoftwareSerial, and it won’t interfere with other parts of your program like SoftwareSerial.

Cheers,
/dev

Thanks for that! Works like a charm :slight_smile: