We have a grove gps receiver and it writes all of the data back over a software serial (we're using the sample code found here), but it's writing all of the data. All we need/want is to write the latitude and longitude, simply with a space between them (or some delimiter character). We've found a few code samples that claim to do this, but they all have tons of files to include in the project. Is there an easy way to do this?
Is there an easy way to do this?
Use the TinyGPS++ library.
Hello and welcome ![]()
If you don't want to use that library, you can easily extract data with strtok, as in this example:
http://codepad.org/yNR4kv1G
Note: I've updated this post. Please read the second half of the post again.
Thank you for the replies. I was playing with the TinyGPS sample sketch, but the data that was being written to the Serial Monitor was a line full of asterisks:
Sats HDOP Latitude Longitude Fix Date Time Date Alt Course Speed Card Distance Course Card Chars Sentences Checksum
(deg) (deg) Age Age (m) --- from GPS ---- ---- to London ---- RX RX Fail
-------------------------------------------------------------------------------------------------------------------------------------
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** *** ******* ****** *** 0 0 0
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** *** ******* ****** *** 327 0 52
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** *** ******* ****** *** 597 0 87
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** *** ******* ****** *** 796 0 117
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** *** ******* ****** *** 1131 0 172
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** *** ******* ****** *** 1393 0 206
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** *** ******* ****** *** 1592 0 234
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** *** ******* ****** *** 1876 0 277
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** *** ******* ****** *** 2187 0 319
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** *** ******* ****** *** 2384 0 347
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** *** ******* ****** *** 2692 0 394
**** **** ********* ********** **** ********** ******** **** ****** ****** ***** *** ******* ****** *** 2975 0 430
While limited, I like the simplicity of guix's code (and not having to import a library is always nice), but I'm struggling with integrating it into the Grove GPS Sample Code.
I need to know how to return the full GPS line from the receiver. Right now, the buffer array is not starting with $GPGGA so the code guix provided never makes it into the if statement.
To answer your second question first, guix's nice and concise example isn't using a String. It's just a char array.
Part of your problem is buffering. An NMEA string is about 80 characters but the buffer is only 64 characters. So midway through receiving a string the buffer fills. When you try to process the buffer you probably miss the next character. That's why TinyGPS is reporting checksum errors.
The other thing is that guix's code is assuming the first character is the start of an NMEA string, but the code you have doesn't synchronize with the start. So it could be somewhere in the middle of the buffer.
Below is a sketch for RMC and GGA strings. It works, but it's a pretty nasty piece of coding. Something to start with maybe.
#include <SoftwareSerial.h>
#define RX_PIN 2
#define TX_PIN 3
#define BUFFER_SIZE 100
SoftwareSerial SoftSerial(RX_PIN, TX_PIN);
char str[BUFFER_SIZE]; // buffer array for data recieve over serial port
int count=0; // counter for buffer array
bool foundNMEA, gotNMEA;
bool gotGGA, gotRMC;
void setup()
{
SoftSerial.begin(9600); // the SoftSerial baud rate
Serial.begin(9600); // the Serial port of Arduino baud rate.
}
void loop()
{
foundNMEA = gotNMEA = false;
count = 0;
do {
while (!SoftSerial.available()) {} // wait forever (yeah, I know...)
char c = SoftSerial.read(); // read a char
if (c == '
) // looking for start of NMEA string
foundNMEA = true;
if (foundNMEA) { // once found, begin saving characters
str[count++] = c;
if (c == '\n') // looking for end of NMEA string
gotNMEA = true;
}
} while (!gotNMEA && (count < BUFFER_SIZE));
if (gotNMEA) {
gotGGA = gotRMC = false;
if ( !strncmp(str, "$GPGGA", 6) )
gotGGA = true;
else if ( !strncmp(str, "$GPRMC", 6) )
gotRMC = true;
if (gotGGA || gotRMC)
{
char *lat, *lon;
// skip hour
strtok( str + 6, "," );
if (gotRMC)
// skip 'A'
strtok( NULL, "," );
// store lat
lat = strtok( NULL, "," );
// skip 'N'
strtok( NULL, "," );
// store lon
lon = strtok( NULL, "," );
Serial.print(lat); Serial.print(" "); Serial.println(lon);
}
}
if (Serial.available()) // if data is available on hardwareserial port ==> data is comming from PC or notebook
SoftSerial.write(Serial.read()); // write it to the SoftSerial shield
}
Thank you for the response. I was discovering some of the things that you pointed out and I was trying to update my question, but you have answered the big question I was now facing: structuring the string into full lines instead of just unorganized GPS output. Thanks again for the help.
I'm starting down the same path at the moment, how best to parse GPS data for use in my system. Like you I find TinyGPS does more than I need.
Like you I find TinyGPS does more than I need.
I don't understand this. You have to parse the stream of data, at least as far as the values you want. Parsing the whole stream doesn't take that long. You don't need to read/print/acknowledge the existence of (parsed) values that you don't need.
The core of TinyGPS is more or less exactly what I want. But it performs conversions and organizes the data in a way that is counterproductive for my needs.
I've been trying to decide whether to write my own code or gut TinyGPS and use it's skeleton.
I'd start with TinyGPS rather than writing one from scratch. Mind you, if it's doing more than you need, I'd just ignore that until it was causing me issues with space or performance. At that point, hopefully all you would need would be some judicious commenting out of library code.
Space is a huge issue in the project I'm working on. I've been reworking and rewriting libraries to reduce their code and sram footprints.
I measured TinyGPS by removing references to it in a sketch. It used 4.7K of code and 189 bytes of ram. This isn't a perfect measure but it comes close.
A hastily pared down version of TinyGPS measured in the same way used 2.0K of code and 61 bytes of ram. It still does more than I need. I will make it smaller.
Is there any opportunity to use more capable hardware instead?
There's almost always a hardware solution. But it would cost more and likely be larger physically. Power consumption might also increase. The most expensive piece of the project is only compatible with an Uno or Leonardo so that would have to be replaced. Had I known when I started that space would be such an issue I might have taken a different path. But my beginner error (this is my first experience with Arduino) has turned out to be a good thing in a way as it has forced me to learn much more than I would have had it all snapped together with ease.