Code for 'Smart Regulator' featured in 'Model Engineer', November 2020 on. Contains all work to August 2020 including all code described. Top level algorithm development is quite spares, leaving some work for you! Any questions - jon@jons-workshop.com
Dependencies: mbed BufferedSerial Servo2 PCT2075 I2CEeprom FastPWM
gps_mod.cpp
- Committer:
- JonFreeman
- Date:
- 2020-12-05
- Revision:
- 5:6ca3e7ffc553
- Parent:
- 4:28cc0cf01570
File content as of revision 5:6ca3e7ffc553:
#include "mbed.h" //#ifdef GPS_ #include "mbed.h" #include "gps_mod.h" using namespace std; #if defined (TARGET_NUCLEO_L476RG) // Computer is low power ARM Cortex development system #include "BufferedSerial.h" BufferedSerial gps_module (A0, A1); #endif #if defined (TARGET_DISCO_F746NG) // Computer is high-end ARM Cortex development system with touch lcd #include "BufferedSoftSerial.h" BufferedSoftSerial gps_module (A4, A5); #endif #ifdef TARGET_NUCLEO_L432KC #include "BufferedSerial.h" extern BufferedSerial gps_module; #endif gps_mod::gps_mod() // Constructor { //BufferedSoftSerial gps_module (_pinTx : A0, _pinRx : A1); state = WAITING4DOLLAR; destptr = dest; strcpy (latstr, "Invalid\0"); strcpy (longstr, "Invalid\0"); strcpy (altistr, "Invalid\0"); strcpy (timestr, "??:??:??\0"); chcnt = 0; inmsg = false; newdata = false; posfix[0] = 'x'; posfix[1] = 0; return; } bool gps_mod::new_data() { bool r; r = newdata; newdata = false; return r; } bool gps_mod::fix_valid() { if (posfix[0] < '1' || posfix[0] > '3') return false; return true; } char * gps_mod::date () { return datestr; } char * gps_mod::heading () { return headingstr; } char * gps_mod::mph () { return speed_mphourstr; } char * gps_mod::position_fix_indicator () { return posfix; } char * gps_mod::latitude() { if (fix_valid()) return latstr; return "No Fix "; } char * gps_mod::longitude() { if (fix_valid()) return longstr; return "No Fix "; } char * gps_mod::altitude() { if (fix_valid()) return altistr; return "No Fix "; } char * gps_mod::sat_count () { return numofsats; } char * gps_mod::message(int mess_num) { if (mess_num < 0 || mess_num > 5) return NULL; return dest + mess_num * (MAXMSGLEN + 4); } char * gps_mod::time () { // char * t = message(0); return timestr; } double gps_mod::lat_merged () { double result = strtod (latstr, NULL); return result + (strtod (latstr + 3, NULL) / 60.0); } double gps_mod::lon_merged () { double result = strtod (longstr, NULL); return result + (strtod (longstr + 4, NULL) / 60.0); } int gps_mod::update() { static const char month_tab[] = "---\0Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec\0"; const int MAX_COMMAS_IN_MSG = 24; int date, month; while (gps_module.readable()) { ch = gps_module.getc(); switch (state) { case WAITING4DOLLAR: i = 0; if (ch == '$') state = GOTDOLLAR; break; case GOTDOLLAR: // accumulate 5 chars after '$' hdracc[i++] = ch; hdracc[i] = 0; if (i > 4) { i = -1; state = GOTHDR; } break; case GOTHDR: // have read "$GP???" to get here // if (ch != ',') pc.printf ("Oops, comma missing\r\n"); if (strncmp(hdracc,"GPGGA",5) == 0) i = 0; else if (strncmp(hdracc,"GPGLL",5) == 0) i = 1; else if (strncmp(hdracc,"GPGSA",5) == 0) i = 2; else if (strncmp(hdracc,"GPGSV",5) == 0) i = 3; else if (strncmp(hdracc,"GPRMC",5) == 0) i = 4;//161229.487,A,3723.24756, N,12158.34162,W, 0.13, 309.62, 120598,,*10 // time ? lat lon ground speed knots|heading|date else if (strncmp(hdracc,"GPVTG",5) == 0) i = 5; if (i < 0) state = WAITING4DOLLAR; // Found invalid header info else { // Validated header info destptr = message(i); chcnt = 0; state = WAITING4CR; } break; case WAITING4CR: if (ch == '\r') { state = WAITING4LF; // process new string data here int comma_count = 0, comma_positions[MAX_COMMAS_IN_MSG + 2]; for (int j = 0; j < strlen(destptr) && j < MAXMSGLEN && comma_count < MAX_COMMAS_IN_MSG; j++) { if (destptr[j] == ',') { comma_positions[comma_count++] = j; comma_positions[comma_count] = 0; } } switch (i) { case 0: // GGA 183655.00,5110.25620,N,00320.09926,W,1,11,0.80,59.9,M,49.5,M,,*74 if (comma_positions[0] == 9) { // time data seems to exist timestr[0] = dest[0]; timestr[1] = dest[1]; timestr[2] = ':'; timestr[3] = dest[2]; timestr[4] = dest[3]; timestr[5] = ':'; timestr[6] = dest[4]; timestr[7] = dest[5]; timestr[8] = 0; } else { strcpy (timestr, "Invalid"); } posfix[0] = dest[comma_positions[4] + 1]; if (fix_valid()) { int a = 0, b = comma_positions[5] + 1; // get numof sats if (dest[b] == ',') { numofsats[0] = '-'; numofsats[1] = '-'; } else { numofsats[0] = dest[b++]; numofsats[1] = dest[b++]; } b = comma_positions[7] + 1; // get altitude char c; while ((c = dest[b++]) != ',' && a < 7) altistr[a++] = c; altistr[a] = 0; } numofsats[2] = 0; break; case 1: // GLL 5110.25606,N,00320.10001,W,183752.00,A,A*72 latstr[0] = destptr[0]; latstr[1] = destptr[1]; latstr[2] = '~'; latstr[3] = destptr[2]; latstr[4] = destptr[3]; latstr[5] = '.'; for (int k = 5; k < 10; k++) latstr[k + 1] = destptr[k]; latstr[11] = ' '; latstr[12] = destptr[11]; // N or S latstr[13] = 0; for (int k = 0; k < 3; k++) longstr[k] = destptr[k + 13]; longstr[3] = '~'; longstr[4] = destptr[16]; longstr[5] = destptr[17]; longstr[6] = '.'; for (int k = 7; k < 12; k++) longstr[k] = destptr[k + 12]; longstr[12] = ' '; longstr[13] = destptr[25]; // E or W longstr[14] = 0; break; case 2: // GSA A,3,11,22,01,03,17,23,19,14,09,,,,1.72,0.97,1.42*0E break; case 3: // GSV complex multiple break; // 0 1 2 3 4 5 67 case 4: // RMC 184111.00, A,5110.25663, N,00320.10076,W, 0.223, , 090816,,,A*6B // // 161229.487,A,3723.24756, N,12158.34162,W, 0.13, 309.62, 120598,,*10 // time ? lat lon ground speed knots|heading|date if (comma_positions[6] + 1 == comma_positions[7]) // no heading data exists strcpy (headingstr, "-/-"); else sprintf(headingstr, "%.1f", strtod(destptr + comma_positions[6] + 1, NULL)); // pc.printf("%s ^%s^", destptr, headingstr); date = (destptr[comma_positions[7] + 1] - '0') * 10 + (destptr[comma_positions[7] + 2] - '0'); month = (destptr[comma_positions[7] + 3] - '0') * 10 + (destptr[comma_positions[7] + 4] - '0'); if (month > 12 || month < 1) month = 0; month *= 4; sprintf (datestr, "%d %s 20%d", date, &month_tab[month], strtol(&destptr[comma_positions[7] + 5], NULL, 10)); break; case 5: // VTG ,T , ,M,0.098,N,0.181,K,A*2A course over ground and ground speed //Adafruit $GPVTG,165.48,T,,M,0.03,N,0.06,K,A*37 //$ GPVTG 309.62,T , ,M,0.13, N,0.2, K*6E sprintf (speed_mphourstr, "%.1fmph", km2miles * strtod(destptr + comma_positions[5] + 1, NULL)); newdata = true; break; // course true|course magnetic|knots|km/hour default: // pc.printf ("Naf i = %d\r\n", i); break; } } else { // char is not CR if (chcnt > MAXMSGLEN) chcnt = MAXMSGLEN; destptr[chcnt++] = ch; destptr[chcnt] = 0; } break; case WAITING4LF: // if (ch != '\n') // pc.printf ("Oops, no LF\r\n"); state = WAITING4DOLLAR; break; default: break; } } return 0; } // end of int gps_mod::update() //#endif