When I say two sentences I mean from a single GPS unit
Doh! My misunderstanding.
So you really are just copying 3 sentences to the USB and onto the SD card. That is a different kettle of fish.
The goal of NeoGPS is to provide the parsed information as quickly as possible, using as little RAM/flash as possible. It's really targeted to 'copters and other real-time navigational apps, or to resource-constrained location-aware apps, like geo-caching. If you were doing Kalman filtering with or without IMU/compass, those calculations would require the parsed fields.
In your case, you only need the bytes between the '$' and the CR/LF. This is really a line-buffering problem, not a parsing problem. You don't need any kind of GPS library.
Here's one way you could do it:
(DO NOT USE THIS CODE! Corrected version by longjohn119 below)
static void check_gps();
static void check_sdd();
void loop()
{
check_gps();
check_sdd();
}
//----------------
enum NMEA_state_t { WAITING_FOR_$, RECEIVING };
static NMEA_state_t gps_state, sdd_state;
static char start_of_gps[8]; // temporary place until first 6 chars received
static char start_of_sdd[8];
static char rmc[120] = "$GPRMC";
static char gga[120] = "$GPGGA";
static char dpt[120] = "$SDDPT";
static bool got_rmc;
static bool got_gga;
static bool got_dpt;
static char *gps_line;
static uint8_t gps_count;
static uint32_t last_rx = 0UL; // to remember when we last received a char
//............
static void check_gps()
{
bool got_something = false;
while (Serial1.available()) {
c = Serial1.Read();
got_something = true;
switch (gps_state) {
case WAITING_FOR_$:
if (c == '
(DO NOT USE THIS CODE! Corrected version by longjohn119 below)
There might be few things missing... I'll give it a try later, and edit the post if there's a major problem.
Notice how all sentences are saved until they can be written during the GPS quiet time. This will avoid any possibility of losing GPS chars because the SD and Serial writes take too long.
I imagine that you can see a pattern in the two check routines... there are techniques for reducing the copied sections, but this is perhaps better for your level of coding.
You should probably send a $PUBX configuration command to the GPS during setup() to turn off the other sentence types.
Cheers,
/dev) {
// Start of sentence!
gps_count = 0;
gps_line = &start_of_gps[0];
*gps_line++ = c;
gps_count++;
gps_state = RECEIVING;
}
break;
case RECEIVING:
if (c == '\r') {
*gps_line++ = c;
gps_count++;
} else if (c == '\n')) {
*gps_line++ = c;
gps_count++;
*gps_line++ = 0; // NUL-terminate
gps_state = WAITING_FOR_$; // get next sentence
} else if (gps_count == 6) {
// check the sentence type
*gps_line++ = c;
gps_count++;
if (strncmp( start_of_gps, rmc, 6 ) == 0) {
got_rmc = true;
gps_line = &rmc[6];
} else if (strncmp( start_of_rmc, gga, 6 ) == 0)) {
got_gga = true;
gps_line = &gga[6];
} else
gps_state = WAITING_FOR_$; // ignore the rest
} else if (gps_count < sizeof(rmc)-3) {
// save chars if there's room
*gps_line++ = c;
gps_count++;
}
break;
}
}
if (got_something)
last_rx = millis();
else if (millis() - last_rx > 10UL) {
if (gps_state == WAITING_FOR_$) {
// Quiet time, write the GPS sentences...
if (got_rmc) {
sd_file->write( rmc );
Serial->write( rmc );
got_rmc = false;
}
if (got_gga) {
sd_file->write( gga );
Serial->write( gga );
got_gga = false;
}
// ... and the SDDPT sentence, when/if it shows up during the quiet time.
if (got_dpt) {
sd_file->write( dpt );
Serial->write( dpt );
got_dpt = false;
}
}
}
}
//...............
static char *sdd_line;
static uint8_t sdd_count;
static void check_sdd()
{
while (Serial2.available()) {
c = Serial2.Read();
switch (sdd_state) {
case WAITING_FOR_$:
if (c == '
(DO NOT USE THIS CODE! Corrected version by **longjohn119** below)
There might be few things missing... ;) I'll give it a try later, and edit the post if there's a major problem.
Notice how all sentences are saved until they can be written during the GPS quiet time. This will avoid any possibility of losing GPS chars because the SD and Serial writes take too long.
I imagine that you can see a pattern in the two check routines... there are techniques for reducing the copied sections, but this is perhaps better for your level of coding.
You should probably send a $PUBX configuration command to the GPS during **setup()** to turn off the other sentence types.
Cheers,
/dev) {
// Start of sentence!
sdd_count = 0;
sdd_line = &start_of_sdd[0];
*sdd_line++ = c;
sdd_count++;
sdd_state = RECEIVING;
}
break;
case RECEIVING:
if (c == '\r') {
*sdd_line++ = c;
sdd_count++;
} else if (c == '\n')) {
// SDDPT complete
*sdd_line++ = c;
sdd_count++;
*sdd_line = 0; // NUL-terminate
got_dpt = true;
sdd_state = WAITING_FOR_$;
} else if (sdd_count == 6) {
// check the sentence type
*sdd_line++ = c;
sdd_count++;
if (strncmp( start_of_sdd, dpt, 6 ) == 0) {
sdd_line = &dpt[6];
got_dpt = false;
} else
sdd_state = WAITING_FOR_$; // ignore the rest
} else if (sdd_count < sizeof(dpt)-3) {
// save chars if there's room
*sdd_line++ = c;
sdd_count++;
}
break;
}
}
}
(DO NOT USE THIS CODE! Corrected version by longjohn119 below)
There might be few things missing... I'll give it a try later, and edit the post if there's a major problem.
Notice how all sentences are saved until they can be written during the GPS quiet time. This will avoid any possibility of losing GPS chars because the SD and Serial writes take too long.
I imagine that you can see a pattern in the two check routines... there are techniques for reducing the copied sections, but this is perhaps better for your level of coding.
You should probably send a $PUBX configuration command to the GPS during setup() to turn off the other sentence types.
Cheers,
/dev