Microcontroller and GPS

ericgibbs

Joined Jan 29, 2010
21,439
hi R,
This is a simple program for an Arduino.
E

C-like:
// ESP/57 GPS extract coordinates
// Arduino

String strID ="";
String strTime="";
String strLat="";
String strLong="";
String GPSmessage = ""; // message buffer
bool msgEOL = false;  // EOL flag

void setup() {
  // initialize serial:
Serial.begin(9600); // user local
Serial1.begin(9600); // gps sensor port

  // reserve 100 bytes for the GPSmessage:
  GPSmessage.reserve(100);
}

void loop() {
  // print the GPS message when a Fix arrives:
  // if all GPS message types are being received, select 'GG' type
if (msgEOL) {
// Serial.println(GPSmessage); // Use to Check raw message
    strID=(GPSmessage.substring(4,6)); 
      if (strID == "GG"){
     Serial.print("$"); 
     Serial.print(GPSmessage.substring(8,14));
     Serial.print(",N");
     Serial.print(GPSmessage.substring(18,28));
     Serial.print(",E");
     Serial.println(GPSmessage.substring(31,42));
    }
    //clear the smessage:
    GPSmessage = "";
    strID="";
    msgEOL = false;
  }
}

//  SerialEvent#1 occurs new GPS RXD message.
void serialEvent1() {
  while (Serial1.available()) {
    // get the new byte:
    char gpsChar = (char)Serial1.read();
    // add it to the GPSmessage:
    GPSmessage += gpsChar;
    // if the incoming character is a newline, set a EOL true
    if (gpsChar == '\r') { // return code , no LF!
      msgEOL = true;
    }
  }
}
 
Last edited:

djsfantasi

Joined Apr 11, 2010
9,237
NMEA).

I am getting confused between the message and the sentence. I think there may many sentence in one message
The output from the Receiver is a stream of characters and not sent in neat “messages”. You have to parse the stream into messages and then parse out the desired values. By the way, both parsing operations can be done at the same time. That is, you don’t need to parse out the message from the serial stream and then parse out the values. Look for the $GPGGA and after it’s found, parse the values looking for a comma and save the appropriate value based on a count of the commas found.
 

djsfantasi

Joined Apr 11, 2010
9,237
hi R,
This is a simple program for an Arduino.
E

C-like:
// ESP/57 GPS extract coordinates
// Arduino

String strID ="";
String strTime="";
String strLat="";
String strLong="";
String GPSmessage = ""; // message buffer
bool msgEOL = false;  // EOL flag

void setup() {
  // initialize serial:
Serial.begin(9600); // user local
Serial1.begin(9600); // gps sensor port

  // reserve 100 bytes for the GPSmessage:
  GPSmessage.reserve(100);
}

void loop() {
  // print the GPS message when a Fix arrives:
  // if all GPS message types are being received, select 'GG' type
if (msgEOL) {
// Serial.println(GPSmessage); // Use to Check raw message
    strID=(GPSmessage.substring(4,6));
      if (strID == "GG"){
     Serial.print("$");
     Serial.print(GPSmessage.substring(8,14));
     Serial.print(",N");
     Serial.print(GPSmessage.substring(18,28));
     Serial.print(",E");
     Serial.println(GPSmessage.substring(31,42));
    }
    //clear the smessage:
    GPSmessage = "";
    strID="";
    msgEOL = false;
  }
}

//  SerialEvent#1 occurs new GPS RXD message.
void serialEvent1() {
  while (Serial1.available()) {
    // get the new byte:
    char gpsChar = (char)Serial1.read();
    // add it to the GPSmessage:
    GPSmessage += gpsChar;
    // if the incoming character is a newline, set a EOL true
    if (gpsChar == '\r') { // return code , no LF!
      msgEOL = true;
    }
  }
}
Note this program is only valid if all values take a fixed length. I think they’re not because there would not be a need for commas if they were.
 

WBahn

Joined Mar 31, 2012
32,823
Note this program is only valid if all values take a fixed length. I think they’re not because there would not be a need for commas if they were.
Some of the fields are variable length, but even if they weren't, the comma separators would likely still be there, especially since the width of all of fields are not the same length. Relying on character count alone would make software/firmware development more error prone and less maintainable.

https://www.gpsworld.com/what-exactly-is-gps-nmea-data/
 

djsfantasi

Joined Apr 11, 2010
9,237
Some of the fields are variable length, but even if they weren't, the comma separators would likely still be there, especially since the width of all of fields are not the same length. Relying on character count alone would make software/firmware development more error prone and less maintainable.

https://www.gpsworld.com/what-exactly-is-gps-nmea-data/
Exactly what I was referring to. The Arduino code posted depends on fixed-length values. I was noting that it wouldn’t work in all cases.
 

WBahn

Joined Mar 31, 2012
32,823
Exactly what I was referring to. The Arduino code posted depends on fixed-length values. I was noting that it wouldn’t work in all cases.
I was merely confirming what you are thinking, as well as commenting that the tie between the presence of separators and the variable width of the fields is not absolute. Fixed length fields often still use separators to make parsing easier. Even with variable fields lengths, it would be possible to structure the data so that it is separable without explicit separators - for instance, by alternating between fields containing numbers and letters or including polarity signs on values.
 

ericgibbs

Joined Jan 29, 2010
21,439
hi dj,
My header does say simple.
I have stripped out all the pre-parsing statements in order to show the TS the basics of the message string.

I have written countless numbers of commercial surveying programs, using different coding techniques, for my surveying products.

If the TS gets a handle on the GPS basics, I will help him with the final full program.
E
 

Thread Starter

Ronda123

Joined Feb 3, 2023
8
I am writing some steps which are necessary, please correct me if I am wrong.

  1. Receive the character.
  2. check if it is '$' if it is not '$' then Keep reading and checking character until we get a '$'
  3. if we get '$' then keep reading and checking until we get the sentence type GPGGA.
  4. If it is NOT the one we want, we just keep reading and checking characters until the next '$'
  5. if we get the sentence type then store the data in array
 

MrChips

Joined Oct 2, 2009
34,809
$GPRMC,092750.000,A,5321.6802,N,00630.3372,W,0.02,31.66,280511,,,A*43
$GPGGA,092751.000,5321.6802,N,00630.3371,W,1,8,1.03,61.7,M,55.3,M,,*75

1. Keep reading until $ is encountered.
2. Check if the next five characters are GPGGA.
3. If not, go back to 1.
4. Parse the line.
 

ericgibbs

Joined Jan 29, 2010
21,439
hi,
While seeking a 'good' lock and in adverse conditions, the following type of 'error' message can be received
$GPGGA,164803,,,,,1,04,1.80,,,47.7,M,,*77?
ie: Time value but no Lat Long data, but the 'commas' will be as normal in the message.
One test is to get the length of the message string, which should be greater than 50.

Always use the $ character as the start of the received message, store all the message in a buffer before attempting any message processing, use the EOL as the stop character/s

For a 'good' message, use the comma count location to get the value of the desired value.

E
 

Thread Starter

Ronda123

Joined Feb 3, 2023
8
store all the message in a buffer before attempting any message processing, use the EOL as the stop character/s
This description is confusing me a bit. Do you mean after getting character we should store in array first and then should check the character

Microcontroller receive one character at a time via UART.

I can't figure out how and when to store and check each character to get location.
 

camerart

Joined Feb 25, 2013
3,830
I am a mechanical engineer but I have interest in electronics.




https://en.m.wikipedia.org/wiki/NMEA_0183#:~:text=NMEA 0183 is a combined,Marine Electronics Association (NMEA).

I am getting confused between the message and the sentence. I think there may many sentence in one message

Code:
$GPGGA,092750.000,5321.6802,N,00630.3372,W,1,8,1.03,61.7,M,55.2,M,,*76
$GPGSA,A,3,10,07,05,02,29,04,08,13,,,,,1.72,1.03,1.38*0A
$GPGSV,3,1,11,10,63,137,17,07,61,098,15,05,59,290,20,08,54,157,30*70
$GPGSV,3,2,11,02,39,223,19,13,28,070,17,26,23,252,,04,14,186,14*79
$GPGSV,3,3,11,29,09,301,24,16,09,020,,36,,,*76
$GPRMC,092750.000,A,5321.6802,N,00630.3372,W,0.02,31.66,280511,,,A*43
$GPGGA,092751.000,5321.6802,N,00630.3371,W,1,8,1.03,61.7,M,55.3,M,,*75
$GPGSA,A,3,10,07,05,02,29,04,08,13,,,,,1.72,1.03,1.38*0A
$GPGSV,3,1,11,10,63,137,17,07,61,098,15,05,59,290,20,08,54,157,30*70
$GPGSV,3,2,11,02,39,223,16,13,28,070,17,26,23,252,,04,14,186,15*77
$GPGSV,3,3,11,29,09,301,24,16,09,020,,36,,,*76
$GPRMC,092751.000,A,5321.6802,N,00630.3371,W,0.06,31.66,280511,,,A*45
Does the micro controller store all the sentences or store the specific sentence that is needed
Hi R,
If you follow the link, it uses sentence, but message is fine.
Some GPS modules, can be set to only send the message that you choose, e,g, $GPGGA. to save time.
C.
 

Reloadron

Joined Jan 15, 2015
7,889
You may find this webpage useful. Much of it is just a rehash of everything covered here but some additional and informative information also.

Ron
 

WBahn

Joined Mar 31, 2012
32,823
This description is confusing me a bit. Do you mean after getting character we should store in array first and then should check the character

Microcontroller receive one character at a time via UART.

I can't figure out how and when to store and check each character to get location.
He's not saying that you have to do it that way, just that it might be a good place to start.

The key is to look for the $GPGGA header and, if you don't see it, go back to looking for it. When you do see it, copy everything that follows it to the buffer up until the next $. Then go back to looking for another header. If the only sentences you are capturing are the GPGGA sentences, there's no need to copy the header to the buffer. But if you decide to capture multiple types of sentences, then you need to flag each type differently in the buffer, but you can do that however you want, including tacking on a sentence-type character at the end, if that makes your logic cleaner.
 

ericgibbs

Joined Jan 29, 2010
21,439
hi Ronda,
The method I use is this one.
I assume you know the basics of programming a MCU.?

Set the GPS module to transmit at 9600 and send only the $GPGGA sentence.

Dim a buffer array of 80 Bytes long , say rxd(80)
Dim cntr as Byte

Write, an Interrupt routine, which is Called when the UART receives a data Byte.

ISR:
cntr=0

Test the Byte for the '$' start of sentence/message ASCII data string.
If NOT $, error flag Set, then Return
Save the $ in rxd(0)
inc cntr+1

GetNext Byte:
Save the Char in rxd(cntr), increment the cntr+1
Test the Byte for the LF ( 0x0A)...[End of Line]
If Byte is LF then
'check
Return
else
'check
goto GetNext Byte
'check
Return

Note: this is NOT the complete code for the ISR, it is rough outline.
A timer would be started when ISR starts, if the timer exceeds a set limit, the ISR will return with a Time out Error flag Set.
also
the cntr value will be checked for the correct sentence length

If you can follow this general idea I maybe able to help with final program, which MCU and programming language do you use.?
E
 

ericgibbs

Joined Jan 29, 2010
21,439
hi Ronda,
This is a clip from an actual GPS data log using a NEO GPS and Arduino.
I have blocked out my location, I don't want an Iranian drone or an off course Chinese weather balloon dropping into my back garden. :rolleyes:

Note the Sentences that are output when the satellite lock is poor, check the comma's.
E
 

Attachments

Thread Starter

Ronda123

Joined Feb 3, 2023
8
hi Ronda,
This is a c
Note the Sentences that are output when the satellite lock is poor, check the comma's.
E
.

According to your idea what happens in a main routine and interrupt service routine.

Do you read the character and store in a array and then leave the interrupt service routine.

Please tell when you enter into interrupt service routine and when you leave the interrupt service routine
 

ericgibbs

Joined Jan 29, 2010
21,439
hi Ronda,
Usually you enable the UART receive interrupt, so when a character is received, the program will call the ISR.
If a Valid sentence, get all the sentence into the buffer and return to the main program with a Valid data flag set.
If sentence invalid, the Flag is not set.

Which programming language and MCU are you using.?
E

The reception time period is approx 10mSec for a 80 byte sentence, at every 1 second of GPS data, so you have lots of time to post process the sentence after the ISR flag is set.
 
Last edited:
Top