Example code for reading from a serial GPS unit & parsing an RMC GPS string to a struct.
Fork of mbed_blinky by
Revision 16:1bf12f0bb4b9, committed 2017-03-09
- 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
--- /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