Improved, thread compatible. Adds new features
Fork of GroveGPS by
GroveGPS.h@2:073674e3f5bf, 2018-04-19 (annotated)
- Committer:
- JimCarver
- Date:
- Thu Apr 19 17:54:31 2018 +0000
- Revision:
- 2:073674e3f5bf
- Parent:
- 1:403eb5e9e994
- Child:
- 4:4615d6e99bb4
Updated to reflect cloud example
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
michaelray | 0:56d6407653a7 | 1 | #ifndef _GROVE_GPS_H_ |
michaelray | 0:56d6407653a7 | 2 | #define _GROVE_GPS_H_ |
michaelray | 0:56d6407653a7 | 3 | |
michaelray | 0:56d6407653a7 | 4 | #include "mbed.h" |
michaelray | 0:56d6407653a7 | 5 | #include <stdlib.h> |
michaelray | 0:56d6407653a7 | 6 | #include <string> |
michaelray | 0:56d6407653a7 | 7 | |
michaelray | 0:56d6407653a7 | 8 | class GroveGPS { |
michaelray | 0:56d6407653a7 | 9 | |
michaelray | 0:56d6407653a7 | 10 | public: |
michaelray | 0:56d6407653a7 | 11 | |
michaelray | 0:56d6407653a7 | 12 | GroveGPS() : _last_line("") {} |
michaelray | 0:56d6407653a7 | 13 | |
michaelray | 0:56d6407653a7 | 14 | void readCharacter(char newCharacter) { |
michaelray | 0:56d6407653a7 | 15 | if (newCharacter == '\n') { |
michaelray | 0:56d6407653a7 | 16 | parseLine(); |
michaelray | 0:56d6407653a7 | 17 | _last_line = ""; |
michaelray | 0:56d6407653a7 | 18 | } else { |
michaelray | 0:56d6407653a7 | 19 | _last_line += newCharacter; |
michaelray | 0:56d6407653a7 | 20 | } |
michaelray | 0:56d6407653a7 | 21 | } |
michaelray | 0:56d6407653a7 | 22 | |
michaelray | 0:56d6407653a7 | 23 | struct GGA { |
michaelray | 0:56d6407653a7 | 24 | double utc_time; // Format: hhmmss.sss |
michaelray | 0:56d6407653a7 | 25 | double latitude; // Format: ddmm.mmmm |
michaelray | 0:56d6407653a7 | 26 | char ns_indicator; // Format: N=north or S=south |
michaelray | 0:56d6407653a7 | 27 | double longitude; // Format: dddmm.mmmm |
michaelray | 0:56d6407653a7 | 28 | char ew_indicator; // Format: E=east or W=west |
michaelray | 0:56d6407653a7 | 29 | int position_fix; // Options: [0=not available, 1=GPS SPS mode, 2=Differential GPS, 6=dead reckoning] |
michaelray | 0:56d6407653a7 | 30 | int sats_used; // Range: 0-12 |
michaelray | 0:56d6407653a7 | 31 | double hdop; // Horizontal Dilution of Precision |
michaelray | 0:56d6407653a7 | 32 | double msl_altitude; |
michaelray | 0:56d6407653a7 | 33 | char msl_altitude_units; |
michaelray | 0:56d6407653a7 | 34 | double geoid_separation; |
michaelray | 0:56d6407653a7 | 35 | char geoid_separation_units; |
michaelray | 0:56d6407653a7 | 36 | long age_of_diff; |
michaelray | 0:56d6407653a7 | 37 | long diff_ref_station_id; |
JimCarver | 1:403eb5e9e994 | 38 | int new_flag; |
michaelray | 0:56d6407653a7 | 39 | std::string checksum; |
michaelray | 0:56d6407653a7 | 40 | } gps_gga; |
JimCarver | 1:403eb5e9e994 | 41 | |
JimCarver | 1:403eb5e9e994 | 42 | struct ZDA { |
JimCarver | 1:403eb5e9e994 | 43 | double utc_time; // Format: hhmmss.sss |
JimCarver | 1:403eb5e9e994 | 44 | int day; |
JimCarver | 1:403eb5e9e994 | 45 | int month; |
JimCarver | 1:403eb5e9e994 | 46 | int year; |
JimCarver | 1:403eb5e9e994 | 47 | int new_flag; |
JimCarver | 1:403eb5e9e994 | 48 | std::string checksum; |
JimCarver | 1:403eb5e9e994 | 49 | } gps_zda; |
michaelray | 0:56d6407653a7 | 50 | |
JimCarver | 1:403eb5e9e994 | 51 | struct VTG { |
JimCarver | 1:403eb5e9e994 | 52 | double course1; |
JimCarver | 1:403eb5e9e994 | 53 | int truec; |
JimCarver | 1:403eb5e9e994 | 54 | double course2; |
JimCarver | 1:403eb5e9e994 | 55 | int magnetic; |
JimCarver | 1:403eb5e9e994 | 56 | double speed1; |
JimCarver | 1:403eb5e9e994 | 57 | int knots; |
JimCarver | 1:403eb5e9e994 | 58 | double speed2; |
JimCarver | 1:403eb5e9e994 | 59 | int kmh; |
JimCarver | 1:403eb5e9e994 | 60 | int new_flag; |
JimCarver | 1:403eb5e9e994 | 61 | std::string checksum; |
JimCarver | 1:403eb5e9e994 | 62 | } gps_vtg; |
JimCarver | 1:403eb5e9e994 | 63 | |
JimCarver | 2:073674e3f5bf | 64 | void getTimestamp(char* buffer) { |
JimCarver | 2:073674e3f5bf | 65 | if (gps_gga.position_fix==0) |
JimCarver | 2:073674e3f5bf | 66 | sprintf(buffer, "N/A"); |
JimCarver | 2:073674e3f5bf | 67 | else |
JimCarver | 2:073674e3f5bf | 68 | sprintf(buffer, "%f", gps_gga.utc_time); |
JimCarver | 2:073674e3f5bf | 69 | } |
JimCarver | 1:403eb5e9e994 | 70 | |
JimCarver | 1:403eb5e9e994 | 71 | void getAltitude(char* buffer) { |
JimCarver | 1:403eb5e9e994 | 72 | if (gps_gga.position_fix==0) |
JimCarver | 1:403eb5e9e994 | 73 | sprintf(buffer, "N/A"); |
JimCarver | 1:403eb5e9e994 | 74 | else |
JimCarver | 1:403eb5e9e994 | 75 | sprintf(buffer, "%f", gps_gga.msl_altitude); |
JimCarver | 1:403eb5e9e994 | 76 | } |
JimCarver | 1:403eb5e9e994 | 77 | |
JimCarver | 1:403eb5e9e994 | 78 | void getCourse(char* buffer) { |
JimCarver | 1:403eb5e9e994 | 79 | if (gps_gga.position_fix==0) |
JimCarver | 1:403eb5e9e994 | 80 | sprintf(buffer, "N/A"); |
JimCarver | 1:403eb5e9e994 | 81 | else |
JimCarver | 1:403eb5e9e994 | 82 | sprintf(buffer, "%f", gps_vtg.course1); |
JimCarver | 1:403eb5e9e994 | 83 | } |
JimCarver | 1:403eb5e9e994 | 84 | |
JimCarver | 1:403eb5e9e994 | 85 | void getSpeed(char* buffer) { |
JimCarver | 1:403eb5e9e994 | 86 | if (gps_gga.position_fix==0) |
JimCarver | 1:403eb5e9e994 | 87 | sprintf(buffer, "N/A"); |
JimCarver | 1:403eb5e9e994 | 88 | else |
JimCarver | 1:403eb5e9e994 | 89 | sprintf(buffer, "%f", gps_vtg.speed1); |
JimCarver | 1:403eb5e9e994 | 90 | } |
JimCarver | 2:073674e3f5bf | 91 | |
JimCarver | 2:073674e3f5bf | 92 | |
JimCarver | 2:073674e3f5bf | 93 | void getUncertanty(char* buffer) { |
JimCarver | 1:403eb5e9e994 | 94 | if (gps_gga.position_fix==0) |
JimCarver | 1:403eb5e9e994 | 95 | sprintf(buffer, "N/A"); |
JimCarver | 1:403eb5e9e994 | 96 | else |
JimCarver | 2:073674e3f5bf | 97 | sprintf(buffer, "%f", gps_gga.hdop); |
michaelray | 0:56d6407653a7 | 98 | } |
JimCarver | 2:073674e3f5bf | 99 | |
michaelray | 0:56d6407653a7 | 100 | void getLatitude(char* buffer) { |
michaelray | 0:56d6407653a7 | 101 | double coordinate = convertGPSToDecimal(gps_gga.latitude); |
JimCarver | 2:073674e3f5bf | 102 | if (gps_gga.position_fix==0) { |
michaelray | 0:56d6407653a7 | 103 | sprintf(buffer, "N/A"); |
JimCarver | 2:073674e3f5bf | 104 | } else { |
JimCarver | 2:073674e3f5bf | 105 | sprintf(buffer, "%c%f", (gps_gga.ns_indicator == 'N') ? '0' : '-', coordinate); |
JimCarver | 2:073674e3f5bf | 106 | } |
michaelray | 0:56d6407653a7 | 107 | } |
michaelray | 0:56d6407653a7 | 108 | |
michaelray | 0:56d6407653a7 | 109 | void getLongitude(char* buffer) { |
michaelray | 0:56d6407653a7 | 110 | double coordinate = convertGPSToDecimal(gps_gga.longitude); |
michaelray | 0:56d6407653a7 | 111 | if (gps_gga.position_fix==0) |
michaelray | 0:56d6407653a7 | 112 | sprintf(buffer, "N/A"); |
michaelray | 0:56d6407653a7 | 113 | else |
michaelray | 0:56d6407653a7 | 114 | sprintf(buffer, "%c%f", (gps_gga.ew_indicator == 'E') ? '0' : '-', coordinate); |
michaelray | 0:56d6407653a7 | 115 | } |
michaelray | 0:56d6407653a7 | 116 | |
michaelray | 0:56d6407653a7 | 117 | private: |
michaelray | 0:56d6407653a7 | 118 | std::string _last_line; |
michaelray | 0:56d6407653a7 | 119 | |
JimCarver | 1:403eb5e9e994 | 120 | |
michaelray | 0:56d6407653a7 | 121 | double convertGPSToDecimal(double coordinate) { |
michaelray | 0:56d6407653a7 | 122 | int degrees = coordinate/100.0; |
michaelray | 0:56d6407653a7 | 123 | int minutes = ((int)coordinate) % 100; |
michaelray | 0:56d6407653a7 | 124 | double seconds = coordinate - ((int)coordinate); |
michaelray | 0:56d6407653a7 | 125 | return degrees + (minutes+seconds)/60; |
michaelray | 0:56d6407653a7 | 126 | |
michaelray | 0:56d6407653a7 | 127 | } |
michaelray | 0:56d6407653a7 | 128 | |
michaelray | 0:56d6407653a7 | 129 | void parseLine() { |
michaelray | 0:56d6407653a7 | 130 | if (_last_line.find("GPGGA") != std::string::npos) { |
michaelray | 0:56d6407653a7 | 131 | parseGGA(); |
michaelray | 0:56d6407653a7 | 132 | } |
JimCarver | 1:403eb5e9e994 | 133 | if (_last_line.find("GPZDA") != std::string::npos) { |
JimCarver | 1:403eb5e9e994 | 134 | parseZDA(); |
JimCarver | 1:403eb5e9e994 | 135 | } |
JimCarver | 1:403eb5e9e994 | 136 | if (_last_line.find("GPVTG") != std::string::npos) { |
JimCarver | 1:403eb5e9e994 | 137 | parseVTG(); |
JimCarver | 1:403eb5e9e994 | 138 | } |
JimCarver | 1:403eb5e9e994 | 139 | } |
JimCarver | 1:403eb5e9e994 | 140 | |
JimCarver | 1:403eb5e9e994 | 141 | void parseVTG() { |
JimCarver | 1:403eb5e9e994 | 142 | char* pEnd; |
JimCarver | 1:403eb5e9e994 | 143 | for (int i=0; i<5; i++) { |
JimCarver | 1:403eb5e9e994 | 144 | std::string current_item = _last_line.substr(0,_last_line.find(",")); |
JimCarver | 1:403eb5e9e994 | 145 | _last_line = _last_line.substr(_last_line.find(",")+1); |
JimCarver | 1:403eb5e9e994 | 146 | if (i==0) { // NMEA Tag |
JimCarver | 1:403eb5e9e994 | 147 | } else if (i==1) { // UTC time |
JimCarver | 1:403eb5e9e994 | 148 | gps_vtg.course1 = strtod(current_item.c_str(), &pEnd); |
JimCarver | 1:403eb5e9e994 | 149 | } else if (i==3) { |
JimCarver | 1:403eb5e9e994 | 150 | gps_vtg.course2 = strtod(current_item.c_str(), &pEnd); |
JimCarver | 1:403eb5e9e994 | 151 | } else if (i==5) { |
JimCarver | 1:403eb5e9e994 | 152 | gps_vtg.speed1 = strtod(current_item.c_str(), &pEnd); |
JimCarver | 1:403eb5e9e994 | 153 | } else if (i==7) { |
JimCarver | 1:403eb5e9e994 | 154 | gps_vtg.speed2 = strtod(current_item.c_str(), &pEnd); |
JimCarver | 1:403eb5e9e994 | 155 | } |
JimCarver | 2:073674e3f5bf | 156 | if(gps_vtg.course2 > gps_vtg.course1) gps_vtg.course1 = gps_vtg.course2; |
JimCarver | 2:073674e3f5bf | 157 | if(gps_vtg.speed2 > gps_vtg.speed1) gps_vtg.speed1 = gps_vtg.speed2; |
JimCarver | 1:403eb5e9e994 | 158 | } |
JimCarver | 1:403eb5e9e994 | 159 | gps_vtg.new_flag = 1; |
JimCarver | 1:403eb5e9e994 | 160 | } |
JimCarver | 1:403eb5e9e994 | 161 | |
JimCarver | 1:403eb5e9e994 | 162 | void parseZDA() { |
JimCarver | 1:403eb5e9e994 | 163 | char* pEnd; |
JimCarver | 1:403eb5e9e994 | 164 | for (int i=0; i<5; i++) { |
JimCarver | 1:403eb5e9e994 | 165 | std::string current_item = _last_line.substr(0,_last_line.find(",")); |
JimCarver | 1:403eb5e9e994 | 166 | _last_line = _last_line.substr(_last_line.find(",")+1); |
JimCarver | 1:403eb5e9e994 | 167 | if (i==0) { // NMEA Tag |
JimCarver | 1:403eb5e9e994 | 168 | } else if (i==1) { // UTC time |
JimCarver | 1:403eb5e9e994 | 169 | gps_zda.utc_time = strtod(current_item.c_str(), &pEnd); |
JimCarver | 1:403eb5e9e994 | 170 | } else if (i==2) { |
JimCarver | 1:403eb5e9e994 | 171 | gps_zda.day = strtod(current_item.c_str(), &pEnd); |
JimCarver | 1:403eb5e9e994 | 172 | } else if (i==3) { |
JimCarver | 1:403eb5e9e994 | 173 | gps_zda.month = strtod(current_item.c_str(), &pEnd); |
JimCarver | 1:403eb5e9e994 | 174 | } else if (i==4) { |
JimCarver | 1:403eb5e9e994 | 175 | gps_zda.year = strtod(current_item.c_str(), &pEnd); |
JimCarver | 1:403eb5e9e994 | 176 | } |
JimCarver | 1:403eb5e9e994 | 177 | } |
JimCarver | 1:403eb5e9e994 | 178 | gps_zda.new_flag = 1; |
michaelray | 0:56d6407653a7 | 179 | } |
michaelray | 0:56d6407653a7 | 180 | |
michaelray | 0:56d6407653a7 | 181 | void parseGGA() { |
michaelray | 0:56d6407653a7 | 182 | char* pEnd; |
michaelray | 0:56d6407653a7 | 183 | for (int i=0; i<14; i++) { |
michaelray | 0:56d6407653a7 | 184 | std::string current_item = _last_line.substr(0,_last_line.find(",")); |
michaelray | 0:56d6407653a7 | 185 | _last_line = _last_line.substr(_last_line.find(",")+1); |
michaelray | 0:56d6407653a7 | 186 | if (i==0) { // NMEA Tag |
michaelray | 0:56d6407653a7 | 187 | } else if (i==1) { // UTC time |
michaelray | 0:56d6407653a7 | 188 | gps_gga.utc_time = strtod(current_item.c_str(), &pEnd); |
michaelray | 0:56d6407653a7 | 189 | } else if (i==2) { // Latitude |
michaelray | 0:56d6407653a7 | 190 | gps_gga.latitude = strtod(current_item.c_str(), &pEnd); |
michaelray | 0:56d6407653a7 | 191 | } else if (i==3) { // Latitude North/South indicator |
michaelray | 0:56d6407653a7 | 192 | gps_gga.ns_indicator = current_item[0]; |
michaelray | 0:56d6407653a7 | 193 | } else if (i==4) { // Longitude |
michaelray | 0:56d6407653a7 | 194 | gps_gga.longitude = strtod(current_item.c_str(), &pEnd); |
michaelray | 0:56d6407653a7 | 195 | } else if (i==5) { // Longitude indicator |
michaelray | 0:56d6407653a7 | 196 | gps_gga.ew_indicator = current_item[0]; |
michaelray | 0:56d6407653a7 | 197 | } else if (i==6) { |
michaelray | 0:56d6407653a7 | 198 | gps_gga.position_fix = strtod(current_item.c_str(), &pEnd); |
JimCarver | 1:403eb5e9e994 | 199 | }else if (i==7) { |
JimCarver | 1:403eb5e9e994 | 200 | gps_gga.sats_used = strtod(current_item.c_str(), &pEnd); |
JimCarver | 2:073674e3f5bf | 201 | } else if (i==8) { // Uncertanty |
JimCarver | 1:403eb5e9e994 | 202 | gps_gga.hdop = strtod(current_item.c_str(), &pEnd); |
JimCarver | 2:073674e3f5bf | 203 | } else if (i==9) { // Altitude mean sea level |
JimCarver | 1:403eb5e9e994 | 204 | gps_gga.msl_altitude = strtod(current_item.c_str(), &pEnd); |
JimCarver | 2:073674e3f5bf | 205 | } else if (i==11) { |
JimCarver | 2:073674e3f5bf | 206 | gps_gga.geoid_separation = strtod(current_item.c_str(), &pEnd); |
JimCarver | 2:073674e3f5bf | 207 | gps_gga.msl_altitude += gps_gga.geoid_separation; |
michaelray | 0:56d6407653a7 | 208 | } |
michaelray | 0:56d6407653a7 | 209 | } |
JimCarver | 1:403eb5e9e994 | 210 | gps_gga.new_flag = 1; |
michaelray | 0:56d6407653a7 | 211 | } |
JimCarver | 1:403eb5e9e994 | 212 | |
michaelray | 0:56d6407653a7 | 213 | }; |
michaelray | 0:56d6407653a7 | 214 | |
michaelray | 0:56d6407653a7 | 215 | #endif |