[SOLVED] Extract the date and time from GNSS GPS and display in 16x2 LCD

Status
Not open for further replies.

john2053

Newbie level 4
Joined
Jan 12, 2022
Messages
6
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
92
I am currently displaying the data in the format of $GPGGA,044840.00,3401.21044,N,11824.67722,W,2,07,1.34,29.5,M,−32.9,M,,0000⋅56$GPGGA,044840.00,3401.21044,N,11824.67722,W,2,07,1.34,29.5,M,-32.9,M,,0000⋅56 in the LCD using 8085 microcontroller. The GPS module I am using currently is the MAXM8W0-GNSS module. I just want to show the date and time from this data? How can I extract that from this unsorted data stored in the array buffer received from GPS using UART serial communication and print in LCD?

Code:
void display_gps_data()
{
    unsigned char n;
    unsigned char title[24] = "GPS  DATA DISPLAY ";
    unsigned char data[24] = "00,00,00,11,30,45.00";   

    for (n=0 ;n<20 ;n++){                                       
        buffer1[n] = title[n];
        buffer2[n] = data[n];
    }
    for (n=0; n<20; n++){
        buffer2[n] = serial_data_buffer[n];                         //data from GPS and stored in buffer using UART serial communication
    }
     buffer_display();                                                    //Display title[] and data[] in  the lcd
}
 

Solution
Hello!

can I get a small example of how I can split the string, please? Thank you.

Splitting a string like an NMEA string is easy: there are no spaces, so you can do it by just
replacing commas by 0s.

Here is your string:

$GPGGA,044840.00,3401.21044,N,11824.67722,W,2,07,1.34,29.5,M,-32.9,M,,0000⋅56

You could for instance define an enum in order to index your fields. Skip $GPGGA which is useless.

Code:
enum {
    NMEA_TIME, NMEA_LAT, NMEA_LON .... etc .... NUM_FIELDS
};

You can define an array of strings:

char * nmea_fields[NUM_FIELDS];

Then when doing your iteration, supposing your string is name nmea_str:

Code:
uint8 i;
uint8 f = 0;
for(i = 0 ; i < NUM_FIELDS ; ++i) {
    if(str[i] == ',') {
        str[i] = 0...
where are the data concerning date & time in this sentence ?
$GPGGA,044840.00,3401.21044,N,11824.67722,W,2,07,1.34,29.5,M,−32.9,M,,0000⋅56

can you use "strtok" string function ? easy to separate field with coma separator ...
example :
here ,not concerned by a GPS and separator is ';' to extract each item

Code:
UART1_Write_Text(Buffer1);CRLF1();
    // Codage;1287;1113;2224;3335;4446;5555;Config;0;0;0;0;1;End
    // check Entete et Queue de la commande
    p0=strstr(Buffer1,"End");
    if (p0>0)
    {
       p0=strstr(Buffer1,"Codage");
       if (p0>0)
       {
          p0 = strtok(p0, ";");
          strcpy(CRam1, p0);
          Print(CRam1);CRLF1();
          while (p0 != 0)
          {
            UART1_Write(i+48);UART1_Write(' ');
            p0 = strtok(0, ";");
            strcpy(CRam1, p0);
            Print(CRam1);CRLF1();
            switch (i)
            {
                case 0:
                case 1:
                case 2:
                case 3:
                case 4: strncpy(Mcd[i],CRam1,4);break;
                case 5: break;
                case 6:
                case 7:
                case 8:
                case 9:
                case 10 :Config_Mode_Cde_Relais[i-6]=*(CRam1)-48 ;break   ;
                default : break;
            }
            i++;
          }
        // check back
       CPrint (" New Config Codage \r\n");
       for (i=0;i<5;i++)
       {
       UART1_Write(i+48);
       UART1_Write(' ');
       Print(Mcd[i]);
       CRLF1();
        }
       CPrint (" New Config cdes Relais\r\n");
       for (i=6;i<11;i++)
       {
       ByteToStr(i,CRam1); Print(CRam1);
       UART1_Write(' ');
       UART1_Write(Config_Mode_Cde_Relais[i-6]+48);
       CRLF1();
       }
     }

give this result
Code:
 // exemple de codage
     /*
     strConstRamCpy(Mcd[0],"1287");
     strConstRamCpy(Mcd[1],"1113");
     strConstRamCpy(Mcd[2],"2224");
     strConstRamCpy(Mcd[3],"3335");
     strConstRamCpy(Mcd[4],"4446");
     // Config cde Relais
     Config_Mode_Cde_Relais[0]=0;  //null
     Config_Mode_Cde_Relais[1]=0;  // relais 1 toggle ON/OFF
     Config_Mode_Cde_Relais[2]=0;   // relais 2 toggle ON/OFF
     Config_Mode_Cde_Relais[3]=0;   // relais 3 toggle ON/OFF
     Config_Mode_Cde_Relais[4]=1;    // relais 4 Monostable
     */

or you can use a state machine, to decode online

example
Code:
//Trame_GPGGA.txt  décodé via machine d'etat
int  Decode_Trame_GPS_GPGGA(void)  // GPGGA
  {
   int i, j,k,Pas;
   j = 0;
   Pas=1;
   k=strlen(Trame_GGA) ;
   for (i=7;i<k;i++)
    {
         switch (Pas)
         {
           case 1:
                #ifdef DSM    // Debug State Machine
                 UART1_Write(Pas+48); UART1_Write(',');
                #endif
                      if(Trame_GGA[i]==',')
                      {
                        Utc[j]=0;
                        j=0;
                        Pas=2;
                        break;
                      }
                        else
                      {
                          Utc[j]=Trame_GGA[i];
                          j++;
                       }
                      break;
            case 2 :
                  #ifdef DSM
                  UART1_Write(Pas+48); UART1_Write(',');
                  #endif
                     if(Trame_GGA[i]==',')
                     {
                       Latitude[j]=0;
                       j=0;
                       Pas=3;
                       break;
                       }
                      else
                       {
                          Latitude[j]=Trame_GGA[i];
                          j++;
                       }
                       break;
               case 3 :           //  Nord ou Sud
                  #ifdef DSM
                  UART1_Write(Pas+48);UART1_Write(',');
                  #endif
                     if(Trame_GGA[i]==',')
                     {
                       j=0;
                       Pas=4;
                       break;
                       }
                      else
                       {
                          NSid=Trame_GGA[i];
                          j++;
                       }
                       break;
              case 4 :           //  longitude
                  #ifdef DSM
                  UART1_Write(Pas+48);UART1_Write(',');
                  #endif
                     if(Trame_GGA[i]==',')
                     {
                       Longitude[j]=0;
                       j=0;
                       Pas=5;
                       break;
                       }
                      else
                       {
                          Longitude[j]=Trame_GGA[i];
                          j++;
                       }
                       break;
                case 5 :           //  EAST ou WEST
                  #ifdef DSM
                  UART1_Write(Pas+48);UART1_Write(',');
                  #endif
                     if(Trame_GGA[i]==',')
                     {
                       j=0;
                       Pas=6;
                       break;
                       }
                      else
                       {
                          EWid=Trame_GGA[i];
                          j++;
                       }
                       break;
                case 6 :           // Fix OK ?
                  #ifdef DSM
                  UART1_Write(Pas+48);UART1_Write(',');
                  #endif
                     if(Trame_GGA[i]==',')
                     {
                       j=0;
                       Pas=7;
                       break;
                       }
                      else
                       {
                          GPSFIX=Trame_GGA[i];
                          j++;
                       }
                       break;
                case 7 :           //  Satellites
                     #ifdef DSM
                     UART1_Write(Pas+48); UART1_Write(',');
                     #endif
                     if(Trame_GGA[i]==',')
                     {
                       Satellites[j]=0;
                       j=0;
                       Pas=8;
                       break;
                       }
                      else
                       {
                         Satellites[j]=Trame_GGA[i];
                         j++;
                       }
                       break;
              case 8 :            //  HDOP
                  #ifdef DSM
                  UART1_Write(Pas+48); UART1_Write(',');
                  #endif
                     if(Trame_GGA[i]==',')
                     {

                       HDOP[j]=0;
                       j=0;
                       Pas=9;
                       break;
                       }
                      else
                       {
                          HDOP[j]=Trame_GGA[i];
                          j++;
                       }
                       break;



             case 9 :            //  Altitude
                  #ifdef DSM
                  UART1_Write(Pas+48); UART1_Write(',');
                  #endif
                     if(Trame_GGA[i]==',')
                     {

                       Altitude[j]=0;
                        j=0;
                        Pas=10;
                       break;
                       }
                      else
                       {
                          Altitude[j]=Trame_GGA[i];
                          j++;

                       }
                       break;
                case 10:
                       #ifdef DSM
                       UART1_Write_CText("\r\nDecodage Trame GPGGA .. OK\r\n");
                       #endif
                      i=k; // to go out of FOR loop
                     break;

            default:
                    #ifdef DSM
                     if (Pas==10)
                     UART1_Write_CText(" Decodage OK\r\n");
                     else
                     {
                       UART1_Write('?'); CRLF1();
                       }
                     #endif
                     i=k; // to go out of FOR loop
                     break;
           } // switch
       } //for i
         return Pas;
   }
 
Last edited:
Hello!

The time is directly after the GPGGA string, therefore 044840.00 in your case 04:48:40.00.
By the way, you say "unsorted array", but the GPGGA string is perfectly sorted.
Beside this, there is always the same number of elements in a GPS standard string.
Therefore, instead of doing this the hard way, by endless cases, you can first split the original
string with "," as a separator. You will get an array of strings, and then time wil be
str[1]. str[0] is the $GPGGA header, str[2] is the lattitude, etc. And you can write the above code
with less effort and maybe 1/3 of the code.

Dora.
 
As far as I'm aware of, NMEA GGA sentence includes UTC time (the first field, as already stated) but not date. You have to request another NMEA sentence to get the date.

As for the decoding, I would always suggest to follow the respective NMEA specification and extract the fields between delimiters instead of relying on an arbitrary format used by a specific GPS receiver.
 
str[1]. str[0] is the $GPGGA header, str[2] is the lattitude, etc. A
can I get a small example of how I can split the string, please? Thank you.
 

Hello!

can I get a small example of how I can split the string, please? Thank you.

Splitting a string like an NMEA string is easy: there are no spaces, so you can do it by just
replacing commas by 0s.

Here is your string:

$GPGGA,044840.00,3401.21044,N,11824.67722,W,2,07,1.34,29.5,M,-32.9,M,,0000⋅56

You could for instance define an enum in order to index your fields. Skip $GPGGA which is useless.

Code:
enum {
    NMEA_TIME, NMEA_LAT, NMEA_LON .... etc .... NUM_FIELDS
};

You can define an array of strings:

char * nmea_fields[NUM_FIELDS];

Then when doing your iteration, supposing your string is name nmea_str:

Code:
uint8 i;
uint8 f = 0;
for(i = 0 ; i < NUM_FIELDS ; ++i) {
    if(str[i] == ',') {
        str[i] = 0;                   // Terminate the current string
        nmea_fields[f] = str+i+1;     //    Set the pointer after the comma
        f++;                          // Increase the field index
    }
    if(str[i] == 0) break;            //    Leave when you reach the end of str
}

Then you're done, without complicated and endless case statements. You can
access all the fields by index. Time for instance will be nmea_fields[NMEA_TIME];

Dora
 
Last edited:
Solution
Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…