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

Committer:
JonFreeman
Date:
Sat Dec 05 12:40:17 2020 +0000
Revision:
5:6ca3e7ffc553
Parent:
4:28cc0cf01570
Code for 'Smart Regulator' to August 2020, published as is. Basic low-level functions all thoroughly tested and debugged, top level algorithms have scope for further development - over to you! For help contact jon @ jons-workshop[.com

Who changed what in which revision?

UserRevisionLine numberNew contents of line
JonFreeman 3:43cb067ecd00 1 #include "mbed.h"
JonFreeman 3:43cb067ecd00 2
JonFreeman 4:28cc0cf01570 3 //#ifdef GPS_
JonFreeman 3:43cb067ecd00 4
JonFreeman 3:43cb067ecd00 5 #include "mbed.h"
JonFreeman 3:43cb067ecd00 6 #include "gps_mod.h"
JonFreeman 3:43cb067ecd00 7 using namespace std;
JonFreeman 3:43cb067ecd00 8 #if defined (TARGET_NUCLEO_L476RG) // Computer is low power ARM Cortex development system
JonFreeman 3:43cb067ecd00 9 #include "BufferedSerial.h"
JonFreeman 3:43cb067ecd00 10 BufferedSerial gps_module (A0, A1);
JonFreeman 3:43cb067ecd00 11 #endif
JonFreeman 3:43cb067ecd00 12 #if defined (TARGET_DISCO_F746NG) // Computer is high-end ARM Cortex development system with touch lcd
JonFreeman 3:43cb067ecd00 13 #include "BufferedSoftSerial.h"
JonFreeman 3:43cb067ecd00 14 BufferedSoftSerial gps_module (A4, A5);
JonFreeman 3:43cb067ecd00 15 #endif
JonFreeman 3:43cb067ecd00 16 #ifdef TARGET_NUCLEO_L432KC
JonFreeman 3:43cb067ecd00 17 #include "BufferedSerial.h"
JonFreeman 3:43cb067ecd00 18 extern BufferedSerial gps_module;
JonFreeman 3:43cb067ecd00 19 #endif
JonFreeman 3:43cb067ecd00 20 gps_mod::gps_mod() // Constructor
JonFreeman 3:43cb067ecd00 21 {
JonFreeman 3:43cb067ecd00 22 //BufferedSoftSerial gps_module (_pinTx : A0, _pinRx : A1);
JonFreeman 3:43cb067ecd00 23 state = WAITING4DOLLAR;
JonFreeman 3:43cb067ecd00 24 destptr = dest;
JonFreeman 3:43cb067ecd00 25 strcpy (latstr, "Invalid\0");
JonFreeman 3:43cb067ecd00 26 strcpy (longstr, "Invalid\0");
JonFreeman 3:43cb067ecd00 27 strcpy (altistr, "Invalid\0");
JonFreeman 3:43cb067ecd00 28 strcpy (timestr, "??:??:??\0");
JonFreeman 3:43cb067ecd00 29 chcnt = 0;
JonFreeman 3:43cb067ecd00 30 inmsg = false;
JonFreeman 3:43cb067ecd00 31 newdata = false;
JonFreeman 3:43cb067ecd00 32 posfix[0] = 'x';
JonFreeman 3:43cb067ecd00 33 posfix[1] = 0;
JonFreeman 3:43cb067ecd00 34 return;
JonFreeman 3:43cb067ecd00 35 }
JonFreeman 3:43cb067ecd00 36
JonFreeman 3:43cb067ecd00 37 bool gps_mod::new_data() {
JonFreeman 3:43cb067ecd00 38 bool r;
JonFreeman 3:43cb067ecd00 39 r = newdata;
JonFreeman 3:43cb067ecd00 40 newdata = false;
JonFreeman 3:43cb067ecd00 41 return r;
JonFreeman 3:43cb067ecd00 42 }
JonFreeman 3:43cb067ecd00 43
JonFreeman 3:43cb067ecd00 44 bool gps_mod::fix_valid()
JonFreeman 3:43cb067ecd00 45 {
JonFreeman 3:43cb067ecd00 46 if (posfix[0] < '1' || posfix[0] > '3') return false;
JonFreeman 3:43cb067ecd00 47 return true;
JonFreeman 3:43cb067ecd00 48 }
JonFreeman 3:43cb067ecd00 49
JonFreeman 3:43cb067ecd00 50 char * gps_mod::date () {
JonFreeman 3:43cb067ecd00 51 return datestr;
JonFreeman 3:43cb067ecd00 52 }
JonFreeman 3:43cb067ecd00 53
JonFreeman 3:43cb067ecd00 54 char * gps_mod::heading () {
JonFreeman 3:43cb067ecd00 55 return headingstr;
JonFreeman 3:43cb067ecd00 56 }
JonFreeman 3:43cb067ecd00 57
JonFreeman 3:43cb067ecd00 58 char * gps_mod::mph () {
JonFreeman 3:43cb067ecd00 59 return speed_mphourstr;
JonFreeman 3:43cb067ecd00 60 }
JonFreeman 3:43cb067ecd00 61
JonFreeman 3:43cb067ecd00 62 char * gps_mod::position_fix_indicator ()
JonFreeman 3:43cb067ecd00 63 {
JonFreeman 3:43cb067ecd00 64 return posfix;
JonFreeman 3:43cb067ecd00 65 }
JonFreeman 3:43cb067ecd00 66
JonFreeman 3:43cb067ecd00 67 char * gps_mod::latitude()
JonFreeman 3:43cb067ecd00 68 {
JonFreeman 3:43cb067ecd00 69 if (fix_valid()) return latstr;
JonFreeman 3:43cb067ecd00 70 return "No Fix ";
JonFreeman 3:43cb067ecd00 71 }
JonFreeman 3:43cb067ecd00 72
JonFreeman 3:43cb067ecd00 73 char * gps_mod::longitude()
JonFreeman 3:43cb067ecd00 74 {
JonFreeman 3:43cb067ecd00 75 if (fix_valid()) return longstr;
JonFreeman 3:43cb067ecd00 76 return "No Fix ";
JonFreeman 3:43cb067ecd00 77 }
JonFreeman 3:43cb067ecd00 78
JonFreeman 3:43cb067ecd00 79 char * gps_mod::altitude()
JonFreeman 3:43cb067ecd00 80 {
JonFreeman 3:43cb067ecd00 81 if (fix_valid()) return altistr;
JonFreeman 3:43cb067ecd00 82 return "No Fix ";
JonFreeman 3:43cb067ecd00 83 }
JonFreeman 3:43cb067ecd00 84
JonFreeman 3:43cb067ecd00 85 char * gps_mod::sat_count ()
JonFreeman 3:43cb067ecd00 86 {
JonFreeman 3:43cb067ecd00 87 return numofsats;
JonFreeman 3:43cb067ecd00 88 }
JonFreeman 3:43cb067ecd00 89
JonFreeman 3:43cb067ecd00 90 char * gps_mod::message(int mess_num)
JonFreeman 3:43cb067ecd00 91 {
JonFreeman 3:43cb067ecd00 92 if (mess_num < 0 || mess_num > 5)
JonFreeman 3:43cb067ecd00 93 return NULL;
JonFreeman 3:43cb067ecd00 94 return dest + mess_num * (MAXMSGLEN + 4);
JonFreeman 3:43cb067ecd00 95 }
JonFreeman 3:43cb067ecd00 96
JonFreeman 3:43cb067ecd00 97 char * gps_mod::time ()
JonFreeman 3:43cb067ecd00 98 {
JonFreeman 3:43cb067ecd00 99 // char * t = message(0);
JonFreeman 3:43cb067ecd00 100 return timestr;
JonFreeman 3:43cb067ecd00 101 }
JonFreeman 3:43cb067ecd00 102
JonFreeman 3:43cb067ecd00 103 double gps_mod::lat_merged ()
JonFreeman 3:43cb067ecd00 104 {
JonFreeman 3:43cb067ecd00 105 double result = strtod (latstr, NULL);
JonFreeman 3:43cb067ecd00 106 return result + (strtod (latstr + 3, NULL) / 60.0);
JonFreeman 3:43cb067ecd00 107 }
JonFreeman 3:43cb067ecd00 108
JonFreeman 3:43cb067ecd00 109 double gps_mod::lon_merged ()
JonFreeman 3:43cb067ecd00 110 {
JonFreeman 3:43cb067ecd00 111 double result = strtod (longstr, NULL);
JonFreeman 3:43cb067ecd00 112 return result + (strtod (longstr + 4, NULL) / 60.0);
JonFreeman 3:43cb067ecd00 113 }
JonFreeman 3:43cb067ecd00 114
JonFreeman 3:43cb067ecd00 115 int gps_mod::update()
JonFreeman 3:43cb067ecd00 116 {
JonFreeman 3:43cb067ecd00 117 static const char month_tab[] = "---\0Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec\0";
JonFreeman 3:43cb067ecd00 118 const int MAX_COMMAS_IN_MSG = 24;
JonFreeman 3:43cb067ecd00 119 int date, month;
JonFreeman 3:43cb067ecd00 120 while (gps_module.readable()) {
JonFreeman 3:43cb067ecd00 121 ch = gps_module.getc();
JonFreeman 3:43cb067ecd00 122 switch (state) {
JonFreeman 3:43cb067ecd00 123 case WAITING4DOLLAR:
JonFreeman 3:43cb067ecd00 124 i = 0;
JonFreeman 3:43cb067ecd00 125 if (ch == '$') state = GOTDOLLAR;
JonFreeman 3:43cb067ecd00 126 break;
JonFreeman 3:43cb067ecd00 127 case GOTDOLLAR: // accumulate 5 chars after '$'
JonFreeman 3:43cb067ecd00 128 hdracc[i++] = ch;
JonFreeman 3:43cb067ecd00 129 hdracc[i] = 0;
JonFreeman 3:43cb067ecd00 130 if (i > 4) {
JonFreeman 3:43cb067ecd00 131 i = -1;
JonFreeman 3:43cb067ecd00 132 state = GOTHDR;
JonFreeman 3:43cb067ecd00 133 }
JonFreeman 3:43cb067ecd00 134 break;
JonFreeman 3:43cb067ecd00 135 case GOTHDR: // have read "$GP???" to get here
JonFreeman 3:43cb067ecd00 136 // if (ch != ',') pc.printf ("Oops, comma missing\r\n");
JonFreeman 3:43cb067ecd00 137 if (strncmp(hdracc,"GPGGA",5) == 0) i = 0;
JonFreeman 3:43cb067ecd00 138 else if (strncmp(hdracc,"GPGLL",5) == 0) i = 1;
JonFreeman 3:43cb067ecd00 139 else if (strncmp(hdracc,"GPGSA",5) == 0) i = 2;
JonFreeman 3:43cb067ecd00 140 else if (strncmp(hdracc,"GPGSV",5) == 0) i = 3;
JonFreeman 3:43cb067ecd00 141 else if (strncmp(hdracc,"GPRMC",5) == 0) i = 4;//161229.487,A,3723.24756, N,12158.34162,W, 0.13, 309.62, 120598,,*10
JonFreeman 3:43cb067ecd00 142 // time ? lat lon ground speed knots|heading|date
JonFreeman 3:43cb067ecd00 143 else if (strncmp(hdracc,"GPVTG",5) == 0) i = 5;
JonFreeman 3:43cb067ecd00 144 if (i < 0) state = WAITING4DOLLAR; // Found invalid header info
JonFreeman 3:43cb067ecd00 145 else { // Validated header info
JonFreeman 3:43cb067ecd00 146 destptr = message(i);
JonFreeman 3:43cb067ecd00 147 chcnt = 0;
JonFreeman 3:43cb067ecd00 148 state = WAITING4CR;
JonFreeman 3:43cb067ecd00 149 }
JonFreeman 3:43cb067ecd00 150 break;
JonFreeman 3:43cb067ecd00 151 case WAITING4CR:
JonFreeman 3:43cb067ecd00 152 if (ch == '\r') {
JonFreeman 3:43cb067ecd00 153 state = WAITING4LF; // process new string data here
JonFreeman 3:43cb067ecd00 154 int comma_count = 0, comma_positions[MAX_COMMAS_IN_MSG + 2];
JonFreeman 3:43cb067ecd00 155 for (int j = 0; j < strlen(destptr) && j < MAXMSGLEN && comma_count < MAX_COMMAS_IN_MSG; j++) {
JonFreeman 3:43cb067ecd00 156 if (destptr[j] == ',') {
JonFreeman 3:43cb067ecd00 157 comma_positions[comma_count++] = j;
JonFreeman 3:43cb067ecd00 158 comma_positions[comma_count] = 0;
JonFreeman 3:43cb067ecd00 159 }
JonFreeman 3:43cb067ecd00 160 }
JonFreeman 3:43cb067ecd00 161 switch (i) {
JonFreeman 3:43cb067ecd00 162 case 0: // GGA 183655.00,5110.25620,N,00320.09926,W,1,11,0.80,59.9,M,49.5,M,,*74
JonFreeman 3:43cb067ecd00 163 if (comma_positions[0] == 9) { // time data seems to exist
JonFreeman 3:43cb067ecd00 164 timestr[0] = dest[0];
JonFreeman 3:43cb067ecd00 165 timestr[1] = dest[1];
JonFreeman 3:43cb067ecd00 166 timestr[2] = ':';
JonFreeman 3:43cb067ecd00 167 timestr[3] = dest[2];
JonFreeman 3:43cb067ecd00 168 timestr[4] = dest[3];
JonFreeman 3:43cb067ecd00 169 timestr[5] = ':';
JonFreeman 3:43cb067ecd00 170 timestr[6] = dest[4];
JonFreeman 3:43cb067ecd00 171 timestr[7] = dest[5];
JonFreeman 3:43cb067ecd00 172 timestr[8] = 0;
JonFreeman 3:43cb067ecd00 173 } else {
JonFreeman 3:43cb067ecd00 174 strcpy (timestr, "Invalid");
JonFreeman 3:43cb067ecd00 175 }
JonFreeman 3:43cb067ecd00 176 posfix[0] = dest[comma_positions[4] + 1];
JonFreeman 3:43cb067ecd00 177 if (fix_valid()) {
JonFreeman 3:43cb067ecd00 178 int a = 0, b = comma_positions[5] + 1; // get numof sats
JonFreeman 3:43cb067ecd00 179 if (dest[b] == ',') {
JonFreeman 3:43cb067ecd00 180 numofsats[0] = '-';
JonFreeman 3:43cb067ecd00 181 numofsats[1] = '-';
JonFreeman 3:43cb067ecd00 182 }
JonFreeman 3:43cb067ecd00 183 else {
JonFreeman 3:43cb067ecd00 184 numofsats[0] = dest[b++];
JonFreeman 3:43cb067ecd00 185 numofsats[1] = dest[b++];
JonFreeman 3:43cb067ecd00 186 }
JonFreeman 3:43cb067ecd00 187 b = comma_positions[7] + 1; // get altitude
JonFreeman 3:43cb067ecd00 188 char c;
JonFreeman 3:43cb067ecd00 189 while ((c = dest[b++]) != ',' && a < 7)
JonFreeman 3:43cb067ecd00 190 altistr[a++] = c;
JonFreeman 3:43cb067ecd00 191 altistr[a] = 0;
JonFreeman 3:43cb067ecd00 192 }
JonFreeman 3:43cb067ecd00 193 numofsats[2] = 0;
JonFreeman 3:43cb067ecd00 194 break;
JonFreeman 3:43cb067ecd00 195 case 1: // GLL 5110.25606,N,00320.10001,W,183752.00,A,A*72
JonFreeman 3:43cb067ecd00 196 latstr[0] = destptr[0];
JonFreeman 3:43cb067ecd00 197 latstr[1] = destptr[1];
JonFreeman 3:43cb067ecd00 198 latstr[2] = '~';
JonFreeman 3:43cb067ecd00 199 latstr[3] = destptr[2];
JonFreeman 3:43cb067ecd00 200 latstr[4] = destptr[3];
JonFreeman 3:43cb067ecd00 201 latstr[5] = '.';
JonFreeman 3:43cb067ecd00 202 for (int k = 5; k < 10; k++)
JonFreeman 3:43cb067ecd00 203 latstr[k + 1] = destptr[k];
JonFreeman 3:43cb067ecd00 204 latstr[11] = ' ';
JonFreeman 3:43cb067ecd00 205 latstr[12] = destptr[11]; // N or S
JonFreeman 3:43cb067ecd00 206 latstr[13] = 0;
JonFreeman 3:43cb067ecd00 207 for (int k = 0; k < 3; k++)
JonFreeman 3:43cb067ecd00 208 longstr[k] = destptr[k + 13];
JonFreeman 3:43cb067ecd00 209 longstr[3] = '~';
JonFreeman 3:43cb067ecd00 210 longstr[4] = destptr[16];
JonFreeman 3:43cb067ecd00 211 longstr[5] = destptr[17];
JonFreeman 3:43cb067ecd00 212 longstr[6] = '.';
JonFreeman 3:43cb067ecd00 213 for (int k = 7; k < 12; k++)
JonFreeman 3:43cb067ecd00 214 longstr[k] = destptr[k + 12];
JonFreeman 3:43cb067ecd00 215 longstr[12] = ' ';
JonFreeman 3:43cb067ecd00 216 longstr[13] = destptr[25]; // E or W
JonFreeman 3:43cb067ecd00 217 longstr[14] = 0;
JonFreeman 3:43cb067ecd00 218 break;
JonFreeman 3:43cb067ecd00 219 case 2: // GSA A,3,11,22,01,03,17,23,19,14,09,,,,1.72,0.97,1.42*0E
JonFreeman 3:43cb067ecd00 220 break;
JonFreeman 3:43cb067ecd00 221 case 3: // GSV complex multiple
JonFreeman 3:43cb067ecd00 222 break; // 0 1 2 3 4 5 67
JonFreeman 3:43cb067ecd00 223 case 4: // RMC 184111.00, A,5110.25663, N,00320.10076,W, 0.223, , 090816,,,A*6B
JonFreeman 3:43cb067ecd00 224 // // 161229.487,A,3723.24756, N,12158.34162,W, 0.13, 309.62, 120598,,*10
JonFreeman 3:43cb067ecd00 225 // time ? lat lon ground speed knots|heading|date
JonFreeman 3:43cb067ecd00 226 if (comma_positions[6] + 1 == comma_positions[7]) // no heading data exists
JonFreeman 3:43cb067ecd00 227 strcpy (headingstr, "-/-");
JonFreeman 3:43cb067ecd00 228 else
JonFreeman 3:43cb067ecd00 229 sprintf(headingstr, "%.1f", strtod(destptr + comma_positions[6] + 1, NULL));
JonFreeman 3:43cb067ecd00 230 // pc.printf("%s ^%s^", destptr, headingstr);
JonFreeman 3:43cb067ecd00 231 date = (destptr[comma_positions[7] + 1] - '0') * 10 + (destptr[comma_positions[7] + 2] - '0');
JonFreeman 3:43cb067ecd00 232 month = (destptr[comma_positions[7] + 3] - '0') * 10 + (destptr[comma_positions[7] + 4] - '0');
JonFreeman 3:43cb067ecd00 233 if (month > 12 || month < 1)
JonFreeman 3:43cb067ecd00 234 month = 0;
JonFreeman 3:43cb067ecd00 235 month *= 4;
JonFreeman 3:43cb067ecd00 236 sprintf (datestr, "%d %s 20%d", date, &month_tab[month], strtol(&destptr[comma_positions[7] + 5], NULL, 10));
JonFreeman 3:43cb067ecd00 237 break;
JonFreeman 3:43cb067ecd00 238 case 5: // VTG ,T , ,M,0.098,N,0.181,K,A*2A course over ground and ground speed
JonFreeman 4:28cc0cf01570 239 //Adafruit $GPVTG,165.48,T,,M,0.03,N,0.06,K,A*37
JonFreeman 3:43cb067ecd00 240 //$ GPVTG 309.62,T , ,M,0.13, N,0.2, K*6E
JonFreeman 3:43cb067ecd00 241 sprintf (speed_mphourstr, "%.1fmph", km2miles * strtod(destptr + comma_positions[5] + 1, NULL));
JonFreeman 3:43cb067ecd00 242 newdata = true;
JonFreeman 3:43cb067ecd00 243 break; // course true|course magnetic|knots|km/hour
JonFreeman 3:43cb067ecd00 244 default:
JonFreeman 3:43cb067ecd00 245 // pc.printf ("Naf i = %d\r\n", i);
JonFreeman 3:43cb067ecd00 246 break;
JonFreeman 3:43cb067ecd00 247 }
JonFreeman 3:43cb067ecd00 248 } else { // char is not CR
JonFreeman 3:43cb067ecd00 249 if (chcnt > MAXMSGLEN) chcnt = MAXMSGLEN;
JonFreeman 3:43cb067ecd00 250 destptr[chcnt++] = ch;
JonFreeman 3:43cb067ecd00 251 destptr[chcnt] = 0;
JonFreeman 3:43cb067ecd00 252 }
JonFreeman 3:43cb067ecd00 253 break;
JonFreeman 3:43cb067ecd00 254 case WAITING4LF:
JonFreeman 3:43cb067ecd00 255 // if (ch != '\n')
JonFreeman 3:43cb067ecd00 256 // pc.printf ("Oops, no LF\r\n");
JonFreeman 3:43cb067ecd00 257 state = WAITING4DOLLAR;
JonFreeman 3:43cb067ecd00 258 break;
JonFreeman 3:43cb067ecd00 259 default:
JonFreeman 3:43cb067ecd00 260 break;
JonFreeman 3:43cb067ecd00 261 }
JonFreeman 3:43cb067ecd00 262 }
JonFreeman 3:43cb067ecd00 263 return 0;
JonFreeman 3:43cb067ecd00 264 } // end of int gps_mod::update()
JonFreeman 3:43cb067ecd00 265
JonFreeman 4:28cc0cf01570 266 //#endif