GPS module and NMEA sentence's

Thread Starter

Parth786

Joined Jun 19, 2017
642
I'm trying to understand the basic behind a GPS NMEA sentence. I saw one datasheet for further reading https://www.sparkfun.com/datasheets/GPS/Modules/LS20030~3_datasheet_v1.0.pdf

GPS send NMEA sentence's or data to microcontroller and microcontroller receive data and decode the relevant NMEA sentence

I don't understand what is meaning of this

Code:
GSV---GNSS Satellites in View
Table 5.1-8 contains the values for the following example:
$GPGSV,3,1,12,28,81,285,42,24,67,302,46,31,54,354,,20,51,077,46*73
$GPGSV,3,2,12,17,41,328,45,07,32,315,45,04,31,250,40,11,25,046,41*75
$GPGSV,3,3,12,08,22,214,38,27,08,190,16,19,05,092,33,23,04,127,*7B
When we connect GPS receiver to microcontroller then GPS receiver can send data to uart. Data can be send serially to microcontroller. How does microcontroller identify and decode data ?
 

ericgibbs

Joined Jan 29, 2010
18,766
hi Path,
You may find the GGA message easier to follow.
The values are always in the same order separated by commas.
You can parse out the values of interest by storing the message string in an array buffer, then count the commas to point to the value you want to extract.

E
 

Thread Starter

Parth786

Joined Jun 19, 2017
642
hi Path,
You may find the GGA message easier to follow.
I am trying to understand basic between GPS and MCU

This is NMEA sentence
Code:
$GPGGA,053740.000,2503.6319,N,12136.0099,E,1,08,1.1,63.8,M,15.2,M,0000*64
unsigned char string = {$GPGGA,053740.000,2503.6319,N,12136.0099,E,1,08,1.1,63.8,M,15.2,M,0000*64 };

unsigned char character = {'$GPGGA','053740.000','2503.6319','N','12136.0099','E','1','08','1.1','63.8','M','15.2','M','0000*64' };

What happen when GPS send this NMEA sentence to microcontroler.

What does the microcontroller do with this NMEA sentence ?

Does MCU read string or single character one by one?

What does MCU do after reading string or character ?
 
Last edited:

Mark Hughes

Joined Jun 14, 2016
409
@Parth786 The GPS communicates with the MCU via something called UART. The GPS Tx Pin connects to the Arduino's Rx pin, the Tx pin changes voltages in a particular timed pattern, and the patterns represent characters. The Rx pin on the MCU detects the changes on the line

In this particular setup, the GPS sends the data out continuously, whether the MCU is ready or not. As long as the GPS has power, it's going to stream out data on its TX line as a series of times voltage changes

MCUs are multipurpose, and a single pin can have many functions, so you have to configure it with software. Somewhere, a long time ago, an engineer sat down and wrote all of the code necessary to monitor the Rx line, and convert those voltage changes into characters on the MCU and then store them for use. Memory on a MCU is a finite resource, so only a certain number of the most recent characters are stored, and as more come in, the old data is overwritten.

So while the data that you're looking for is in the memory -- you've got to look for it and do something with it.

There quite a bit more to it than that -- hardware vs. software serial, buffer length, interrupts, etc... take a look at that article I posted above -- it has code that can read the GPS sentence that you're looking for.

Hope this helps. Perhaps some other users can explain it a bit better than I.

Mark
 

ericgibbs

Joined Jan 29, 2010
18,766
Does MCU read string or single character one by one?
hi Parth,
The GPS module sends out message Strings at one second intervals. [ Note: more than one String type is sent out from GPS module]

There are number of different message Strings, each String has its own Header ID, ie: $GPGGA or $GPGSV etc ...
All the Strings start with the dollar sign $ and end with Cr Lf codes ie: Carriage Return 0x0D , Line Feed 0x0A.

All the message characters are transmitted sequentially from the GPS module one character at a time.

So the program in the MCU has to recognise the $ sign character and start saving the characters in a MCU buffer as they are received,
In my project I am only interested in the $GPGGA message, so if the 5th character I receive is a 'G' I continue saving the characters until the LF [ 0x0A] is detected.
If the 5th character is not a 'G' , the program stops buffering the message String and resumes waiting for the next '$' character.

The reason the message String is buffered is so that program has a complete valid message from which it can extract the values of interest.

This is easily done by using the comma positions in the String to pick out the required values.

E
 
Last edited:

Thread Starter

Parth786

Joined Jun 19, 2017
642
So the program in the MCU has to recognise the $ sign character and start saving the characters in a MCU buffer as they are received,
In my project I am only interested in the $GPGGA message, so if the 5th character I receive is a 'G' I continue saving the characters until the LF [ 0x0A] is detected.
If the 5th character is not a 'G' , the program stops buffering the message String and resumes waiting for the next '$' character.

E
Hi ericgibbs

GPS module sends each character one by one and MCU get each character one by one

$ G P G G A

Here is six characters.

GPS send character $ then MCU get this $ character

GPS send character G then MCU get this G character

GPS send character P then MCU get this P character

GPS send character G then MCU get this G character

GPS send character G then MCU get this G character

GPS send character A then MCU get this A character

Get the character from GPS if it is $ then get the next character G, if it is G then get next character P, If it is P then get next character G, if it is G then get the next character, if it is G then get the next character A

Here is my hand program I know we don't write real program like this but I hope It will be happen something like this
C:
 Void getdata (void)
{
 
    for ( variable inilitize, test, incement )
    {     
        If (  character = )
        {
         character match ;
                          }
        Else
        {
           waiting for data
        }
    }
 
}
For loop will test whole character and if else statement will check character
 

ericgibbs

Joined Jan 29, 2010
18,766
hi P,
I do not use the 'C' programming language, so I cannot advise on your program.

Have you checked Mark's article for a C program .?
E
If no one else steps forward to help, I can post a Oshonsoft Basic version of a program, from which you could convert C.
 

miniwinwm

Joined Feb 2, 2018
68
Code:
GSV---GNSS Satellites in View
Table 5.1-8 contains the values for the following example:
$GPGSV,3,1,12,28,81,285,42,24,67,302,46,31,54,354,,20,51,077,46*73
$GPGSV,3,2,12,17,41,328,45,07,32,315,45,04,31,250,40,11,25,046,41*75
$GPGSV,3,3,12,08,22,214,38,27,08,190,16,19,05,092,33,23,04,127,*7B
Don't bother with the GSV message. It contains a table of satellites in view, and I doubt you need that. You need to look at the message that contains the position data, like GLL or RMC. These contain a data valid field that is an A (data ok) or a V (data not ok). Ignore messages until this field goes to A.

Having a quick scoot through some old code of mine that parsed NMEA0183 messages on a PIC, you need something like this...

Code:
        case NMEA_GLL:
           util_get_field(6, (char *)(nmea_message), next_message_field, ',');
           if(*next_message_field!='A')
           {
             break;
           }  
          
           if(util_get_field(1, (char *)(nmea_message), next_message_field, ',')>0)
           {
             sscanf(next_message_field, "%f", &coord);
             nmea_latitude_degrees=(signed int)(coord/100.0f);
             nmea_latitude_minutes=100.0f*frac(coord/100.0f);
            
             util_get_field(2, (char *)(nmea_message), next_message_field, ',');
             if(*next_message_field=='N' || *next_message_field=='S')
             {
               if(*next_message_field=='S')
               {
                 nmea_latitude_degrees=-nmea_latitude_degrees;
                 nmea_latitude_minutes=-nmea_latitude_minutes;
               }  
             }  
           }
          
           if(util_get_field(3, (char *)(nmea_message), next_message_field, ',')>0)
           {
             sscanf(next_message_field, "%f", &coord);
             nmea_longitude_degrees=(signed int)(coord/100.0f);
             nmea_longitude_minutes=100.0f*frac(coord/100.0f);
            
             util_get_field(4, (char *)(nmea_message), next_message_field, ',');
             if(*next_message_field=='E' || *next_message_field=='W')
             {
               if(*next_message_field=='W')
               {
                 nmea_longitude_degrees=-nmea_longitude_degrees;
                 nmea_longitude_minutes=-nmea_longitude_minutes;
               }  
             }  
           }
 
Last edited:

Thread Starter

Parth786

Joined Jun 19, 2017
642
I visited on the some pages. I am little bit confused with GPS NMEA sentence's and GPS NMEA strings.

I think GPS NMEA sentence's would have this
Code:
$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A
GPS NMEA strings would have this
Code:
$GPRMC
I know the GPS send data continuously to mcu but I don't understand what the data mcu receives. Is it receive NMEA sentence's or NMEA strings?

Does MCU get data (the $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A) or just get $GPRMC?
 

miniwinwm

Joined Feb 2, 2018
68
I know the GPS send data continuously to mcu but I don't understand what the data mcu receives. Is it receive NMEA sentence's or NMEA strings?

Does MCU get data (the $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A) or just get $GPRMC?
It gets the whole thing. A GPS string is something of your imagination. While we're at it, to confuse you more, ignore the two characters after the $ (GP in your example). They are manufacturer specific and do not identify the sentence. You can see a variety of characters there in real life (marine navigation systems often use II, for example). Just look for the $ and then the RMC.
 

Thread Starter

Parth786

Joined Jun 19, 2017
642
Just look for the $ and then the RMC.
So far I understood that if I have to send data from GPS to MCU then I have to use uart.
I am writing function to receive data from GPS. I have stored GPS data in to array
C:
void UART_Init()
{
    TMOD = 0x20;        /* Timer 1, 8-bit auto reload mode */
    TH1  = 0xFD;        /* Load value for 9600 baud rate */
    SCON = 0x50;        /* Mode 1, reception enable */
    TR1  = 1;           /* Start timer 1 */
}

unsigned char Receive_Data(void)
{
    while(RI == 0);     // Wait till the data is received
    RI = 0;              // Clear Receive Interrupt Flag for next cycle
    return(SBUF);       // return the received char
}
    char GPS_Data[6] = {"$GPRMC"};
Now How to extract GPS data. What program logic need to extract GPS data

Note : Code is not complete. this is just one part of code
 
Last edited:

ericgibbs

Joined Jan 29, 2010
18,766
hi Parth,
The GPS module will automatically output the data messages at one second intervals.
Your program could use an Interrupt to detect the start of a message.
The messages always start with a dollar sign $ and end with CR LF codes
E
 

be80be

Joined Jul 5, 2008
2,072
Parth Look at post #12 that's what your MCU will get from the GPS that's the data sent out of it's serial port after ait locked and got where I was at I ran it on a web app that then used google maps to show where I was at the red line pointed to the building I'm in really cool.

If you look at what I posted the data is no good the gps had to lock first.

Look at the links in post #2 and post #4 You need to know what the wheel is before you try to make one.
 

Thread Starter

Parth786

Joined Jun 19, 2017
642
I was at I ran it on a web app that then used google maps to show where I was at the red line pointed to the building I'm in really cool..
I saw post #12 I don't see any red line in code. How do you know your location when you see output data
 

Thread Starter

Parth786

Joined Jun 19, 2017
642
Your program could use an Interrupt to detect the start of a message.
I have to set interrupt for 1 second right but i am stuck how to calculate TH0 TL0 for 1 second interrupt

C:
void UART_Init()
{
    TMOD = 0x20;        /* Timer 1, 8-bit auto reload mode */
    TH1  = 0xFD;        /* Load value for 9600 baud rate */
    SCON = 0x50;        /* Mode 1, reception enable */
    TR1  = 1;           /* Start timer 1 */
}
unsigned char Receive_Data(void)
{
    while(RI == 0);     // Wait till the data is received
    RI = 0;              // Clear Receive Interrupt Flag for next cycle
    return(SBUF);       // return the received char
}
    char GPS_Data[6] = {"$GPRMC"};

void main(void)
{
   TR0 = 0;        /* Stop Timer 0   */
   TF0 = 0;        /*Clear the interrupt flag */
   TMOD = 0x01;    /*Set timer0 in mode 1*/
   TH0 = 0x27;     /* 60 ms reloading time */
   TL0 = 0xFD;
   ET0 = 1;         /* Enable Timer0 interrupts */
   EA  = 1;          /* Global interrupt enable */
   TR0 = 1;         /* Start Timer 0 */

   while (1)
    {
      /* Do Nothing */
    }

/* It is called after every 60ms */
void timer(void) interrupt 1
    {
  
     /*Code */
    }
 
Top