Skip to content

Instantly share code, notes, and snippets.

@phieber
Last active October 14, 2022 18:55
Show Gist options
  • Save phieber/93cd5e736769e7dd2b83 to your computer and use it in GitHub Desktop.
Save phieber/93cd5e736769e7dd2b83 to your computer and use it in GitHub Desktop.
based on the GPS module from adafruit, TeensyLC and the SD adapter for the Teensy
#include <Adafruit_GPS.h>
#include <SD.h>
#include <SPI.h>
#include <XMLWriter.h>
Adafruit_GPS GPS(&Serial3);
// 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
// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// Teensy audio board: pin 10
// Wiz820+SD board: pin 4
// Teensy 2.0: pin 0
// Teensy++ 2.0: pin 20
const int chipSelect = 4;
uint8_t last_hh = 0, last_mm = 0, last_ss = 0;
uint16_t last_ms = 0;
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!");
Serial3.begin(9600);
pinMode(0, OUTPUT);
digitalWrite(0, HIGH);
pinMode(1, OUTPUT);
digitalWrite(1, HIGH);
// 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
//GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_ALLDATA);
// Set the update rate
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_5HZ);
GPS.sendCommand(PMTK_API_SET_FIX_CTL_5HZ);
// 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
// Request updates on antenna status, comment out to keep quiet
GPS.sendCommand(PGCMD_ANTENNA);
delay(1000);
Serial.print("Initializing SD card...");
// make sure that the default chip select pin is set to
// output, even if you don't use it:
pinMode(10, OUTPUT);
SPI.setMOSI(11);
SPI.setMISO(12);
SPI.setSCK(13);
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
}
Serial.println("card initialized.");
// Ask for firmware version
Serial1.println(PMTK_Q_RELEASE);
}
String append0ifNeeded(uint8_t value) {
if ( value < 10 ) {
return String("0") + String(value);
} else {
return String(value);
}
}
/**
* This function returns a properly formatted ISO 8601 string
*/
String getISO8601string(uint8_t y = 0, uint8_t m = 1, uint8_t d = 1, uint8_t h = 0, uint8_t mm = 0, uint8_t ss = 0, uint8_t ms = 0) {
return String("20" + append0ifNeeded(y) +
"-" +
append0ifNeeded(m) +
"-" +
append0ifNeeded(d) +
"T" +
append0ifNeeded(h) +
":" +
append0ifNeeded(mm) +
":" +
append0ifNeeded(ss) +
"." +
append0ifNeeded(ms) +
"Z"
);
}
void loop() // run over and over again
{
GPS.read();
// 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
Serial.println("cannot parse NMEA");
}
if (GPS.fix) {
if (GPS.hour != last_hh || GPS.minute != last_mm || GPS.seconds != last_ss || GPS.milliseconds != last_ms) { // different measurement
// update values
last_hh = GPS.hour;
last_mm = GPS.minute;
last_ss = GPS.seconds;
last_ms = GPS.milliseconds;
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((int)GPS.fix);
Serial.print(" quality: "); Serial.println((int)GPS.fixquality);
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("Location (in degrees, works with Google Maps): ");
Serial.print(GPS.latitudeDegrees, 4);
Serial.print(", ");
Serial.println(GPS.longitudeDegrees, 4);
Serial.print("Speed (knots): "); Serial.println(GPS.speed);
Serial.print("Angle: "); Serial.println(GPS.angle);
Serial.print("Altitude: "); Serial.println((int)floor(GPS.altitude + .5));
Serial.print("Satellites: "); Serial.println((int)GPS.satellites);
String filename = append0ifNeeded(GPS.year) + append0ifNeeded(GPS.month) + append0ifNeeded(GPS.day) + ".xml";
char buff[filename.length() + 1];
filename.toCharArray(buff, filename.length() + 1);
File dataFile = SD.open(buff, FILE_WRITE);
if (dataFile) { // file exists or created successfuly
XMLWriter XML(&dataFile);
XML.setIndentSize(2);
String timestring = getISO8601string(GPS.year, GPS.month, GPS.day, GPS.hour, GPS.minute, GPS.seconds, GPS.milliseconds);
char timeArray[timestring.length() + 1];
timestring.toCharArray(timeArray, timestring.length() + 1);
if (dataFile.size() == 0) { //include header
XML.header();
XML.tagStart("gpx");
XML.tagField("version", "1.1");
XML.tagField("creator", "Patrick Hieber");
XML.tagField("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
XML.tagField("xmlns", "http://www.topografix.com/GPX/1/1");
XML.tagField("xsi:schemaLocation", "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd");
XML.tagEnd(NEWLINE, NOSLASH);
XML.tagOpen("metadata");
XML.writeNode("name", "GPS recording");
XML.writeNode("time", timeArray);
XML.tagClose();
}
XML.tagStart("wpt");
XML.tagField("lat", GPS.latitudeDegrees, 4);
XML.tagField("lon", GPS.longitudeDegrees, 4);
XML.tagEnd(NEWLINE, NOSLASH);
XML.writeNode("ele", GPS.altitude + .5, 0);
XML.writeNode("time", timeArray);
XML.writeNode("magvar", GPS.magvariation);
XML.writeNode("geoidheight", GPS.geoidheight + .5, 0);
XML.writeNode("sat", (uint8_t)GPS.satellites);
XML.tagStart("/wpt");
XML.tagEnd(NEWLINE, NOSLASH);
dataFile.close();
// problem: XSD will always fail due to missing </gpx>
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment