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/.