Permalink
Browse files

Parsing works with RMC & GGA with a nice example as well

  • Loading branch information...
1 parent ad4df7f commit b8ce3c6a4d7405fd1fe41b73d57c0a181afd30c1 @ladyada ladyada committed Mar 28, 2012
Showing with 199 additions and 46 deletions.
  1. +44 −39 Adafruit_GPS.cpp
  2. +5 −7 Adafruit_GPS.h
  3. +150 −0 examples/parsing/parsing.pde
View
@@ -12,6 +12,8 @@ All text above must be included in any redistribution
#include <Adafruit_GPS.h>
+// how long are max NMEA lines to parse?
+#define MAXLINELENGTH 120
// we double buffer: read one line in and leave one for the main program
volatile char line1[MAXLINELENGTH];
@@ -25,13 +27,27 @@ volatile boolean recvdflag;
boolean Adafruit_GPS::parse(char *nmea) {
+ // do checksum check
- // look for a few common sentences
+ // first look if we even have one
+ if (nmea[strlen(nmea)-4] == '*') {
+ uint16_t sum = parseHex(nmea[strlen(nmea)-3]) * 16;
+ sum += parseHex(nmea[strlen(nmea)-2]);
+
+ // check checksum
+ for (uint8_t i=1; i < (strlen(nmea)-4); i++) {
+ sum ^= nmea[i];
+ }
+ if (sum != 0) {
+ // bad checksum :(
+ //return false;
+ }
+ }
+ // look for a few common sentences
if (strstr(nmea, "$GPGGA")) {
// found GGA
char *p = nmea;
-
// get time
p = strchr(p, ',')+1;
float timef = atof(p);
@@ -41,7 +57,6 @@ boolean Adafruit_GPS::parse(char *nmea) {
seconds = (time % 100);
milliseconds = fmod(timef, 1.0) * 1000;
- p = strchr(p, ',')+1;
// parse out latitude
p = strchr(p, ',')+1;
@@ -80,7 +95,7 @@ boolean Adafruit_GPS::parse(char *nmea) {
return true;
}
if (strstr(nmea, "$GPRMC")) {
- // found RMC
+ // found RMC
char *p = nmea;
// get time
@@ -94,6 +109,7 @@ boolean Adafruit_GPS::parse(char *nmea) {
milliseconds = fmod(timef, 1.0) * 1000;
p = strchr(p, ',')+1;
+ // Serial.println(p);
if (p[0] == 'A')
fix = true;
else if (p[0] == 'V')
@@ -142,13 +158,15 @@ boolean Adafruit_GPS::parse(char *nmea) {
return false;
}
-void Adafruit_GPS::read(void) {
+char Adafruit_GPS::read(void) {
+ char c = 0;
+
if (paused)
- return;
+ return c;
if (gpsSwSerial->available()) {
- char c = gpsSwSerial->read();
+ c = gpsSwSerial->read();
//Serial.print(c);
@@ -166,37 +184,32 @@ void Adafruit_GPS::read(void) {
currentline = line1;
lastline = line2;
}
- /*
- Serial.println("----");
- Serial.println((char *)lastline);
- Serial.println("----");
- */
- // do checksum check
-
- // first look if we even have one
- if (lastline[lineidx-4] == '*') {
- uint16_t sum = parseHex(lastline[lineidx-3]) * 16;
- sum += parseHex(lastline[lineidx-2]);
-
- // check checksum
- for (uint8_t i=1; i < (lineidx-4); i++) {
- sum ^= lastline[i];
- }
- if (sum == 0) {
- recvdflag = true;
- }
- }
+
+
+ //Serial.println("----");
+ //Serial.println((char *)lastline);
+ //Serial.println("----");
lineidx = 0;
-
+ recvdflag = true;
}
+
currentline[lineidx++] = c;
if (lineidx >= MAXLINELENGTH)
lineidx = MAXLINELENGTH-1;
}
+ return c;
}
-Adafruit_GPS::Adafruit_GPS(void) {
+// Constructor when using SoftwareSerial or NewSoftSerial
+#if ARDUINO >= 100
+Adafruit_GPS::Adafruit_GPS(SoftwareSerial *ser) {
+#else
+ Adafruit_GPS::Adafruit_GPS(NewSoftSerial *ser) {
+#endif
+
common_init(); // Set everything to common state, then...
+ gpsSwSerial = ser; // ...override swSerial with value passed.
+
recvdflag = false;
paused = false;
lineidx = 0;
@@ -211,17 +224,9 @@ Adafruit_GPS::Adafruit_GPS(void) {
fixquality = satellites = 0;
}
-// Constructor when using SoftwareSerial or NewSoftSerial
-#if ARDUINO >= 100
-void Adafruit_GPS::begin(SoftwareSerial *ser, uint16_t baud)
-#else
-void Adafruit_GPS::begin(NewSoftSerial *ser, uint16_t baud)
-#endif
-{
- gpsSwSerial = ser; // ...override swSerial with value passed.
-
- // 9600 NMEA is the default baud rate
+void Adafruit_GPS::begin(uint16_t baud)
+{
gpsSwSerial->begin(baud);
}
View
@@ -40,19 +40,17 @@ All text above must be included in any redistribution
#include "NewSoftSerial.h"
#endif
-// how long are max NMEA lines to parse?
-#define MAXLINELENGTH 100
class Adafruit_GPS {
public:
- Adafruit_GPS(void); // Constructor when using SoftwareSerial
+ void begin(uint16_t baud);
#if ARDUINO >= 100
- void begin(SoftwareSerial *ser, uint16_t baud); // Constructor when using SoftwareSerial
+ Adafruit_GPS(SoftwareSerial *ser); // Constructor when using SoftwareSerial
#else
- void begin(NewSoftSerial *ser, uint16_t baud); // Constructor when using NewSoftSerial
+ Adafruit_GPS(NewSoftSerial *ser); // Constructor when using NewSoftSerial
#endif
- void begin(HardwareSerial *ser, uint16_t baud); // Constructor when using HardwareSerial
+ Adafruit_GPS(HardwareSerial *ser); // Constructor when using HardwareSerial
char *lastNMEA(void);
boolean newNMEAreceived();
@@ -63,7 +61,7 @@ class Adafruit_GPS {
boolean parseNMEA(char *response);
uint8_t parseHex(char c);
- void read(void);
+ char read(void);
boolean parse(char *);
void interruptReads(boolean r);
@@ -0,0 +1,150 @@
+// Test code for Adafruit GPS modules using MTK3329/MTK3339 driver
+//
+// This code shows how to listen to the GPS module in an interrupt
+// which allows the program to have more 'freedom' - just parse
+// when a new NMEA sentence is available! Then access data when
+// desired.
+//
+// Tested and works great with the Adafruit Ultimate GPS module
+// using MTK33x9 chipset
+// ------> http://www.adafruit.com/products/746
+// Pick one up today at the Adafruit electronics shop
+// and help support open source hardware & software! -ada
+
+#include <Adafruit_GPS.h>
+
+// these are for Arduino 1.0
+#include <SoftwareSerial.h>
+SoftwareSerial mySerial(3, 2);
+
+// if using Arduino v23 or earlier, uncomment these
+// two lines and comment out the above. You will
+// need to install NewSoftSerial
+// #include <NewSoftSerial.h>
+// NewSoftSerial mySerial(3, 2);
+
+// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
+// Set to 'true' if you want to debug and listen to the raw GPS sentences
+#define GPSECHO true
+
+// Connect the GPS Power pin to 5V
+// Connect the GPS Ground pin to ground
+// Connect the GPS TX (transmit) pin to Digital 3
+// Connect the GPS RX (receive) pin to Digital 2
+Adafruit_GPS GPS(&mySerial);
+
+
+// this keeps track of whether we're using the interrupt
+// off by default!
+boolean usingInterrupt = false;
+
+void setup()
+{
+
+ // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
+ // also spit it out
+ Serial.begin(115200);
+ Serial.println("Adafruit GPS library basic test!");
+
+ // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800
+ GPS.begin(9600);
+
+ // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
+ GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
+ // uncomment this line to turn on only the "minimum recommended" data
+ //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
+ // For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since
+ // the parser doesn't care about other sentences at this time
+
+ // Set the update rate
+ GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate
+ // For the parsing code to work nicely and have time to sort thru the data, and
+ // print it out we don't suggest using anything higher than 1 Hz
+
+ // the nice thing about this code is you can have a timer0 interrupt go off
+ // every 1 millisecond, and read data from the GPS for you. that makes the
+ // loop code a heck of a lot easier!
+ useInterrupt(true);
+
+ delay(1000);
+}
+
+
+// Interrupt is called once a millisecond, looks for any new GPS data, and stores it
+SIGNAL(TIMER0_COMPA_vect) {
+ char c = GPS.read();
+ // if you want to debug, this is a good time to do it!
+ if (GPSECHO)
+ if (c) UDR0 = c;
+ // writing direct to UDR0 is much much faster than Serial.print
+ // but only one character can be written at a time.
+}
+
+void useInterrupt(boolean v) {
+ if (v) {
+ // Timer0 is already used for millis() - we'll just interrupt somewhere
+ // in the middle and call the "Compare A" function above
+ OCR0A = 0xAF;
+ TIMSK0 |= _BV(OCIE0A);
+ usingInterrupt = true;
+ } else {
+ // do not call the interrupt function COMPA anymore
+ TIMSK0 &= ~_BV(OCIE0A);
+ usingInterrupt = false;
+ }
+}
+
+uint16_t timer = millis();
+void loop() // run over and over again
+{
+ // in case you are not using the interrupt above, you'll
+ // need to 'hand query' the GPS, not suggested :(
+ if (! usingInterrupt) {
+ // read data from the GPS in the 'main loop'
+ char c = GPS.read();
+ // if you want to debug, this is a good time to do it!
+ if (GPSECHO)
+ if (c) UDR0 = c;
+ // writing direct to UDR0 is much much faster than Serial.print
+ // but only one character can be written at a time.
+ }
+
+ // if a sentence is received, we can check the checksum, parse it...
+ if (GPS.newNMEAreceived()) {
+ // a tricky thing here is if we print the NMEA sentence, or data
+ // we end up not listening and catching other sentences!
+ // so be very wary if using OUTPUT_ALLDATA and trytng to print out data
+ //Serial.println(GPS.lastNMEA()); // this also sets the newNMEAreceived() flag to false
+
+ if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false
+ return; // we can fail to parse a sentence in which case we should just wait for another
+ }
+
+ // approximately every 2 seconds or so, print out the current stats
+ if (millis() - timer > 2000) {
+ timer = millis(); // reset the timer
+
+ Serial.print("\nTime: ");
+ Serial.print(GPS.hour, DEC); Serial.print(':');
+ Serial.print(GPS.minute, DEC); Serial.print(':');
+ Serial.print(GPS.seconds, DEC); Serial.print('.');
+ Serial.println(GPS.milliseconds);
+ Serial.print("Date: ");
+ Serial.print(GPS.day, DEC); Serial.print('/');
+ Serial.print(GPS.month, DEC); Serial.print("/20");
+ Serial.println(GPS.year, DEC);
+ Serial.print("Fix: "); Serial.print(GPS.fix);
+ Serial.print(" quality: "); Serial.println(GPS.fixquality);
+ if (GPS.fix) {
+ Serial.print("Location: ");
+ Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
+ Serial.print(", ");
+ Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);
+
+ Serial.print("Speed (knots): "); Serial.println(GPS.speed);
+ Serial.print("Angle: "); Serial.println(GPS.angle);
+ Serial.print("Altitude: "); Serial.println(GPS.altitude);
+ Serial.print("Satellites: "); Serial.println(GPS.satellites);
+ }
+ }
+}

0 comments on commit b8ce3c6

Please sign in to comment.