Example code for reading from a serial GPS unit & parsing an RMC GPS string to a struct.

Dependencies:   mbed

Fork of mbed_blinky by Mbed

Files at this revision

API Documentation at this revision

Comitter:
HackerLabATTKit01
Date:
Thu Mar 09 21:21:17 2017 +0000
Parent:
15:165ecc5f4280
Child:
17:15322357429b
Commit message:
Example code for reading from a serial GPS unit & parsing an RMC GPS string into a struct.

Changed in this revision

GPRMCSentence.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GPRMCSentence.h	Thu Mar 09 21:21:17 2017 +0000
@@ -0,0 +1,161 @@
+#define TIMEMAX     6
+#define LATMAX      20
+#define LONGMAX     20
+#define SPEEDMAX    6
+#define TRACKMAX    6
+#define DATEMAX     6
+#define MAGVARMAX   6
+#define CHECKSUMMAX 10
+#define DEVNULMAX   20
+
+#define CRLF2 "\n\r"
+
+/** Tfile provides a means for parsing serially received GPRMC sentences into a location struct **/
+
+typedef struct {
+    char time[TIMEMAX+1];
+    char status;
+    char latitude[LATMAX+1];
+    double dlatitude;
+    char latdir;
+    char longitude[LONGMAX+1];
+    double dlongitude;
+    char longdir;
+    char speed[SPEEDMAX+1];
+    char trackangle[TRACKMAX+1];
+    char date[DATEMAX+1];
+    char magvar[MAGVARMAX+1];
+    char magvardir;
+    //char checksum[CHECKSUMMAX+1];
+} GPRMCSentence;
+
+double charStrToDouble(char* str) {
+    uint16_t decpos = 0;
+    double num = 0.0;
+    while((str[decpos]!='.')&&(str[decpos]!='\0')) decpos++;
+    double multiplier = 1.0;
+    for(uint16_t i = 1;(decpos-i)>=0;i++) {
+        num += (multiplier*(str[decpos-i]-48));
+        multiplier *= 10.0;
+    }
+    multiplier = (1.0/10.0);
+    for(uint16_t i = 1;str[decpos+i]!='\0';i++) {
+        num += (multiplier*(str[decpos+i]-48));
+        multiplier /= 10.0;
+    }
+    return num;
+}
+
+uint16_t parseStringToGPRMCStructEntry(char* gprmcstr, char* gprmcentry, uint16_t start, uint16_t length) {
+    int16_t i=0;
+    while((gprmcstr[start] != ',')  &&
+          (gprmcstr[start] != '\0') &&
+          (gprmcstr[start] != '\n') &&
+          (i < length)) {
+        gprmcentry[i] = gprmcstr[start];
+        start++;i++;
+    }
+    while(i<=length) {
+        gprmcentry[i] = '\0';
+        i++;
+    }
+    return start + 1;
+}
+
+void moveDecimalLeft(char* num, uint16_t places) {
+    if (places == 0) return;
+    else places--;
+    uint16_t i = 0;
+    while(num[i] != '\0') {
+        if ((i >= places) && (num[i] == '.')) {
+            uint16_t j;
+            for(j=i;j>(i-places);j--) num[j] = num[j-1];
+            num[j] = num[j-1];
+            num[j-1] = '.';
+            break;
+        }
+        else i++;
+    }
+}
+
+void negateCharStrNumber(char* num, uint16_t len) {
+    for(uint16_t i=(len-1); i>0;i--) num[i] = num[i-1];
+    num[0] = '-';
+}
+
+/************************
+parseGPRMCStrToStruct:
+
+In: gprmcstr: raw char array string of gprmc sentence
+In: GPRMCSentece: struct object representing gprmc sentence to parse to
+
+Out: integer:    < 0 : not a gprmc sentence
+                 = 0 : not valid
+                 > 0 : valid
+
+*/
+int8_t parseGPRMCStrToStruct(char* gprmcstr, GPRMCSentence* gprmstruct) {
+    uint16_t pos = 7;
+    char devnull[DEVNULMAX+1];
+    if ((gprmcstr[0] == '$') &&
+        (gprmcstr[1] == 'G') &&
+        (gprmcstr[2] == 'P') &&
+        (gprmcstr[3] == 'R') &&
+        (gprmcstr[4] == 'M') &&
+        (gprmcstr[5] == 'C') &&
+        (gprmcstr[6] == ',')) {
+        pos = parseStringToGPRMCStructEntry(gprmcstr,gprmstruct->time,pos,TIMEMAX);
+        //pos = parseStringToGPRMCStructEntry(gprmcstr,devnull,pos,DEVNULMAX); // to get rid of time decimal, needed for some gps modules
+        if (gprmcstr[pos] != ',') {gprmstruct->status = gprmcstr[pos];pos++;}
+        else gprmstruct->status = '\0';
+        pos++;
+
+        pos = parseStringToGPRMCStructEntry(gprmcstr,gprmstruct->latitude,pos,LATMAX);
+        moveDecimalLeft(gprmstruct->latitude,2);
+        gprmstruct->dlatitude = charStrToDouble(gprmstruct->latitude);
+        if (gprmcstr[pos] != ',') {gprmstruct->latdir = gprmcstr[pos];pos++;}
+        else gprmstruct->latdir = '\0';
+        if(gprmstruct->latdir == 'S') {
+            negateCharStrNumber(gprmstruct->latitude, LATMAX);
+            gprmstruct->dlatitude *= -1;
+        }
+        pos++;
+
+        pos = parseStringToGPRMCStructEntry(gprmcstr,gprmstruct->longitude,pos,LONGMAX);
+        moveDecimalLeft(gprmstruct->longitude,2);
+        gprmstruct->dlongitude = charStrToDouble(gprmstruct->longitude);
+        if (gprmcstr[pos] != ',') {gprmstruct->longdir = gprmcstr[pos];pos++;}
+        else gprmstruct->longdir = '\0';
+        if(gprmstruct->longdir == 'W') {
+            negateCharStrNumber(gprmstruct->longitude, LONGMAX);
+            gprmstruct->dlongitude *= -1;
+        }
+        pos++;
+
+        pos = parseStringToGPRMCStructEntry(gprmcstr,gprmstruct->speed,pos,SPEEDMAX);
+        pos = parseStringToGPRMCStructEntry(gprmcstr,gprmstruct->trackangle,pos,TRACKMAX);
+        pos = parseStringToGPRMCStructEntry(gprmcstr,gprmstruct->date,pos,DATEMAX);
+        pos = parseStringToGPRMCStructEntry(gprmcstr,gprmstruct->magvar,pos,MAGVARMAX);
+        if (gprmcstr[pos] != ',') {gprmstruct->magvardir = gprmcstr[pos];pos++;}
+        else gprmstruct->magvardir = '\0';
+        pos++;
+        //pos = parseStringToGPRMCStructEntry(gprmcstr,gprmstruct->checksum,pos,CHECKSUMMAX);
+        if (gprmstruct->status == 'A') return 1;
+        else return 0;
+    }
+    else return -1;
+}
+
+void printGPRMCSentence(GPRMCSentence* gprmcstruct, Serial *serial) {
+    serial->printf("Time:    %s" CRLF2,gprmcstruct->time);
+    serial->printf("Status:  %c" CRLF2,gprmcstruct->status);
+    serial->printf("Lat:     %s" CRLF2,gprmcstruct->latitude);
+    serial->printf("LatDir:  %c" CRLF2,gprmcstruct->latdir);
+    serial->printf("Long:    %s" CRLF2,gprmcstruct->longitude);
+    serial->printf("LongDir: %c" CRLF2,gprmcstruct->longdir);
+    serial->printf("Speed:   %s" CRLF2,gprmcstruct->speed);
+    serial->printf("Angle:   %s" CRLF2,gprmcstruct->trackangle);
+    serial->printf("Date:    %s" CRLF2,gprmcstruct->date);
+    serial->printf("MagVar:  %s" CRLF2,gprmcstruct->magvar);
+    serial->printf("MagDir:  %c" CRLF2,gprmcstruct->magvardir);
+}
--- a/main.cpp	Wed Jan 18 13:46:04 2017 +0000
+++ b/main.cpp	Thu Mar 09 21:21:17 2017 +0000
@@ -1,12 +1,80 @@
 #include "mbed.h"
+#include "GPRMCSentence.h"
+
+#define GPSBUFFSIZE 256
+
+Serial pc(USBTX, USBRX); // tx, rx
+Serial xgps(PTC15, PTC14);
+
+unsigned gpsSentenceIndex = 0;
+char gpsSentence[GPSBUFFSIZE];
+volatile bool newline_detected = false;
+GPRMCSentence lastPosition;
 
-DigitalOut myled(LED1);
+void clearGpsSentence() {
+    for(int i=0;i<GPSBUFFSIZE;i++) gpsSentence[i] = '\0';
+    gpsSentenceIndex = 0;
+}
+ 
+int main() {
+    pc.printf("Where am I? ----------- \n");
+    clearGpsSentence();
+    while(1) {
+        gpsSentence[gpsSentenceIndex] = xgps.getc();
+        pc.putc(gpsSentence[gpsSentenceIndex]);
+        gpsSentenceIndex++;
+        if(gpsSentence[gpsSentenceIndex - 1] == '\n') {
+            gpsSentence[gpsSentenceIndex] = '\0';
+            if (parseGPRMCStrToStruct(gpsSentence, &lastPosition) >= 0) {
+                pc.printf("time: %s Status: %c \n\r" , lastPosition.time, lastPosition.status);
+                pc.printf("Lat : %s %c \n\r" , lastPosition.latitude, lastPosition.latdir);
+                pc.printf("Long: %s %c \n\r" , lastPosition.longitude, lastPosition.longdir);
+            }
+            clearGpsSentence();
+        }
+    }
+}
+
+
+/*include "mbed.h"
+
+DigitalOut rled(LED_RED);
+DigitalOut gled(LED_GREEN);
+DigitalOut bled(LED_BLUE);
 
 int main() {
     while(1) {
-        myled = 1;
+        rled = 0;
+        gled = 0;
+        bled = 0;
+        wait(0.2);
+        rled = 0;
+        gled = 0;
+        bled = 1;
+        wait(0.2);
+        rled = 0;
+        gled = 1;
+        bled = 0;
+        wait(0.2);
+        rled = 0;
+        gled = 1;
+        bled = 1;
         wait(0.2);
-        myled = 0;
+        rled = 1;
+        gled = 0;
+        bled = 0;
+        wait(0.2);
+        rled = 1;
+        gled = 0;
+        bled = 1;
+        wait(0.2);
+        rled = 1;
+        gled = 1;
+        bled = 0;
+        wait(0.2);
+        rled = 1;
+        gled = 1;
+        bled = 1;
         wait(0.2);
     }
-}
+}*/
--- a/mbed.bld	Wed Jan 18 13:46:04 2017 +0000
+++ b/mbed.bld	Thu Mar 09 21:21:17 2017 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/ad3be0349dc5
\ No newline at end of file
+http://mbed.org/users/mbed_official/code/mbed/builds/e1686b8d5b90
\ No newline at end of file