K mému Arduinu jsem si sehnal GPS modul Ublox Neo-6M. Bohužel, s knihovnou TinyGPS ani TinyGPSPlus si nerozumí (knihovna nedokáže dekódovat data z modulu). Proto jsem si napsal vlastní obslužný kód, který zobrazuje všechny dostupné informace.
Zeměpisná šířka a délka přicházejí ve formátu „DDMM.MMMMM“. Parsování provádím tak, že načtu část před desetinnou tečkou. Stupně získám celočíselným dělením DDMM / 100. Minuty jsou zbytek po celočíselném dělení DDMM % 100. K celým minutám přičtu část za desetinnou tečkou převedenou na „0.MMMMM“ (MMMMM / 100000).
Pro převod stupňového formátu do decimálního slouží vzorec DEC = DEGREE + MINUTES / 60 + SECONDS / 3600. Minuty máme v desetinném tvaru, takže je stačí vydělit 60 a přičíst ke stupňům.
Protože funkce Serial.print() zobrazuje pouze 2 desetinná místa, rozhodl jsem se výsledek vynásobit 1000. Pokud se zobrazí číslo 49163.69, víme, že se ve skutečnosti jedná o 49.16369.
#include "SoftwareSerial.h" #define GPS_RX_PIN 7 #define GPS_TX_PIN 6 #define BUFFSIZ 90 char buffer[BUFFSIZ]; char buffidx; char *parseptr; uint32_t latitude, longitude; SoftwareSerial gpsSerial(GPS_RX_PIN, GPS_TX_PIN); void setup() { Serial.begin(9600); gpsSerial.begin(9600); } void loop() { uint32_t tmp; if (gpsSerial.available() > 0) { readline(); if (strncmp(buffer, "$GPRMC", 6) == 0) { // Time parseptr = buffer + 7; tmp = parsedecimal(parseptr); Serial.print(tmp / 10000); Serial.print(":"); Serial.print((tmp / 100) % 100); Serial.print(":"); Serial.print(tmp % 100); // Status parseptr = strchr(parseptr, ',') + 1; Serial.print(" "); Serial.print(parseptr[0]); Serial.print(" "); // Latitude parseptr += 2; latitude = parsedecimal(parseptr); if (latitude != 0) { parseptr = strchr(parseptr, '.') + 1; Serial.print(((latitude / 100) + (((latitude % 100) + (parsedecimal(parseptr) / 100000.0)) / 60.0)) * 1000); } parseptr = strchr(parseptr, ',') + 1; if (parseptr[0] != ',') { // Serial.print(parseptr[0]); } Serial.print("x10^3 "); // Longitude parseptr = strchr(parseptr, ',') + 1; longitude = parsedecimal(parseptr); if (longitude != 0) { parseptr = strchr(parseptr, '.') + 1; Serial.print(((longitude / 100) + (((longitude % 100) + (parsedecimal(parseptr) / 100000.0)) / 60.0)) * 1000); } parseptr = strchr(parseptr, ',') + 1; if (parseptr[0] != ',') { // Serial.print(parseptr[0]); } Serial.print("x10^3 "); // Groundspeed parseptr = strchr(parseptr, ',') + 1; Serial.print(parsedecimal(parseptr)); Serial.print(" "); // Track angle parseptr = strchr(parseptr, ',') + 1; Serial.print(parsedecimal(parseptr)); Serial.print(" "); // Date parseptr = strchr(parseptr, ',') + 1; tmp = parsedecimal(parseptr); Serial.print(tmp / 10000); Serial.print("/"); Serial.print((tmp / 100) % 100); Serial.print("/"); Serial.print(tmp % 100); Serial.println(); } else { // Serial.println("waiting..."); } } else { Serial.println("unavaliable"); } } uint32_t parsedecimal(char *str) { uint32_t d = 0; while (str[0] != 0) { if ((str[0] > '9') || (str[0] < '0')) { return d; } d *= 10; d += str[0] - '0'; str++; } return d; } void readline(void) { char c; buffidx = 0; while (1) { c = gpsSerial.read(); if (c == -1) { continue; } if (c == '\n') { continue; } if ((buffidx == BUFFSIZ-1) || (c == '\r')) { buffer[buffidx] = 0; return; } buffer[buffidx++]= c; } }
Inspirace na webu http://forum.arduino.cc/.