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

Revision:
3:43cb067ecd00
Child:
4:28cc0cf01570
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gps_mod.cpp	Mon Jul 27 08:44:59 2020 +0000
@@ -0,0 +1,265 @@
+#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
+//$                                   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