Jump to content
43oh

Unable to retrieve complete NMEA string from serial communication


Recommended Posts

Hi Guys,

I am new to MSP430 micro-controller. i have interfaced MTK3329 GPS module to my MSP430g2553 launchpad. i am trying to parse the data string i am receiving at hardware serial pin1_1 and pin1_2. here is my code:i am unable to read complete string . here is what i am getting at serial monitor

here is the complete format of GPGLL sentence i am trying to read and store-"$GPGLL,1111.1111,a,yyyy.yyyy,a,hhmmss.ss,A,A*hh"
Thanks.

<code>

 char gps[20];

char first;
int i;
void setup() {
  // initialize serial:
  Serial.begin(9600);
  Serial.write("$PMTK314,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29");
 Serial.write(0x0D);
 Serial.write(0x0A);
  delay(100);
  Serial.write("$PMTK251,9600*1F");  // 115200bps
  Serial.write(0x0D);
  Serial.write(0x0A);  
  delay(100); 
  Serial.write("$PMTK300,1000,0,0,0,0*1C");  
  Serial.write(0x0D);
  Serial.write(0x0A);  
  delay(100); 
  // reserve 200 bytes for the inputString:
  
}
 
void loop() {
  // print the string when a newline arrives:
  while(Serial.available()){
  char first = Serial.read();
  if(first=='$')
  {
   gps[0]= first;
   gps[1]=Serial.read();
   gps[2]=Serial.read();
   gps[3]=Serial.read();
   gps[4]=Serial.read();
   gps[5]=Serial.read();
   gps[6]=Serial.read();
   gps[7]=Serial.read();
   gps[8]=Serial.read();
   gps[9]=Serial.read();
   gps[10]=Serial.read();
   gps[11]=Serial.read();
   gps[12]=Serial.read();
   gps[13]=Serial.read();
   gps[14]=Serial.read();
   gps[15]=Serial.read();
   gps[16]=Serial.read();
 gps[17]=Serial.read();
   gps[18]=Serial.read();
   gps[19]=Serial.read();
   gps[20]=Serial.read();
for (i = 0; i <= 20; i = i + 1) {
  Serial.print(gps);
  
}
 
}
  }
Serial.println();
delay(500);
  }
</code>
 

post-35475-0-83057100-1390377792_thumb.png

Link to post
Share on other sites

You have a couple of issues, and you are actually lucky it is working as well as it is.

 

Firstly, your buffer is 20 bytes, but you are putting 21 bytes into it. When you declare your array variable "char gps[20]" you are creating a space big enough to put 20 characters. These 20 characters can be addressed with the subscripts 0 to 19. Your last serial line and also your line where you print the characters, you are accessing gps[20] - this is actually the 21st element of gps, which is 1 more than it has been defined to hold.  You are actually accessing data in RAM beyond your array, which is probably one of Energia's global or private variables. You either need to only read up to gps[19], or you need to declare gps to be 21 characters in size.

 

Now, your main problem is with the logic with your reads.  You first check to see if there is data available by calling Serial.available().  But if there is serial data available, you then proceed to immediately read 21 bytes.  Serial.read() is not blocking - it will return immediately whether there is data available or not. The trouble is, the MSP430 is much faster than the serial port, so by the time it gets part way through the reads it has finished reading all of the data that is available. Serial.read() then starts returning 0xFF because there is nothing to read, and you fill the last few bytes of your gps[] array with 0xFF's which print as the modified y characters you are seeing.

 

You need to amend your logic so that you check if there is data available before every read. Something like the following:

void loop() 
{
  // print the string when a newline arrives:
  while(Serial.available())
  {
    char first = Serial.read();
    if(first=='$')
    {
     gps[0]= first;
     i=1;
     while (i<20)
     {
       if (Serial.available())
       {
         gps[i]=Serial.read();
         i++;
       }
     }
    for (i = 0; i < 20; i++) {
      Serial.print(gps[i]);
    }
    Serial.println();
   }
 }
}

You'll note that I also moved the position of the Serial.println and took out the delay(500) - previously it would output a blank line every half second, by moving it where I did, it only prints the newline after it has successfully received and printed a line of data. The delay was a nasty one - if more data came in during the delay than what Energia's buffer could hold (16 bytes if memory serves correctly), then extra data would be lost.

Link to post
Share on other sites

@@Samanvai

 

Yes it's true that you have to take care of RAM, but I think that would only be a problem if you want to process a lot of GPGSV sentences (and store them temporary). My problem was the flash memory (Binary sketch size: 16.177 bytes (of a 16.384 byte maximum)), because I'm using a pretty large OLED driver lib.

 

Back to GPS: if you only need LON and LAT, I would go with tinyGPS and parse GPGGA and/or GPRMC sentence - both sentences contain LON and LAT and they are already included in the tinyGPS lib. The only things I did on the tinyGPS lib was to delete functions I don't need and modifying the "cardinal"-function for my needs. As far as I can remember, the lib and the arduino sketch worked in Energia without any changes.

 

Now some code:

#include <TinyGPS.h>
TinyGPS gps;

void setup()
{
   ...

  Serial.begin(9600); //Initial baud rate of GPS is 9600
  
  //Serial.println("$PMTK251,57600*2C");
  Serial.println("$PMTK251,115200*1F"); //set to 115200 for 10Hz update rate
  
  Serial.begin(115200); //switch to 115200
  
  Serial.println("$PMTK314,0,1,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*2C"); //only GPGGA and GPRMC sentences, see MTK3329/3339 Data sheet
  
  Serial.println("$PMTK220,100*2F"); //10Hz update rate
  
  ...
}

Simple example for showing the speed:

bool newData = false;

void loop()
{
  
  // Parsing data
  for (unsigned long start = millis(); millis() - start < 85;) //85ms is a good value for 10Hz update rate - may be do some tests to find the optimal timing
  {
    while (Serial.available())
    {
      char c = Serial.read();
      
      if (gps.encode(c))
      { // newData gets "true" when you have a fix and valid data (see GPRMC validity in tinyGPS.cpp)
        newData = true;    
     }
    }
  }
  
  if (newData)
  { 
	oled.set_cursor(0, 3, XL_FONT); oled.write("%3i",(int) gps.f_speed_kmph()); //display speed on OLED - change this to your needs (Serial output / LCD / ...)
  }
  
}

You can get LON and LAT with:

gps.get_position(&lat, &lon, &age);

So I think most of the tinyGPS examples you will find around the web will work without changes.

 

Links:

MTK Command Set

Online Checksum Calculator

Adafruit Tutorial

 

There is also an Adafruit GPS lib here

 

Kind regards

yosh

Link to post
Share on other sites

Another question relative to the OP question:  so, there is no conflict between the UART on the MSP430 Launchpad and the Debug USB Port?  Do they share the same UART?  So, if I connect a serial GPS receiver to Pins P3.4 and P3.3, I can still communicate (upload and debug my program)  to the Launchpad via my computer USB port?

 

Thanks!

Link to post
Share on other sites

Another question relative to the OP question:  so, there is no conflict between the UART on the MSP430 Launchpad and the Debug USB Port?  Do they share the same UART?  So, if I connect a serial GPS receiver to Pins P3.4 and P3.3, I can still communicate (upload and debug my program)  to the Launchpad via my computer USB port?

 

Thanks!

If you connect a GPS receiver to your UART pins, you should disconnect the jumpers that connect the UART to the debugger part. You can then still program and debug your MSP430 (unless you're using BSL mode) but you cannot retrieve printf() or write() debug output anymore; instead this debug output is sent to your GPS receiver.

Link to post
Share on other sites

Another question relative to the OP question:  so, there is no conflict between the UART on the MSP430 Launchpad and the Debug USB Port?  Do they share the same UART?  So, if I connect a serial GPS receiver to Pins P3.4 and P3.3, I can still communicate (upload and debug my program)  to the Launchpad via my computer USB port?

 

Thanks!

 

There are some examples out there (e.g. from Adafruit, see HERE) which use Hardware Serial for debugging and Software Serial for GPS RX/TX. Never tried it myself, because I'm using an I2C OLED Display. But maybe this could be an option for you?

 

Edit: see HERE - nice TX-only example by Rei Vilo which could by used for debugging output.

Link to post
Share on other sites

If you are on the F5529 then you also have Serial1 with Receive Data (RXD) at P3.4 aka pin 3 and Transmit Data (TXD) at P3.3 aka pin 4.

Serial is the debug uart and is routed to the debugger that makes it a USB->Serial. This is the serial port that shows up for the Serial terminal in Energia.

Serial has RXD on P4.5 aka pin 45 and TXD on P4.4 aka pin 46.

 

Also see the pin map here: https://github.com/energia/Energia/blob/master/hardware/msp430/variants/launchpad_f5529/pins_energia.h

And the excellent pin map by Rei Vilo here: http://energia.nu/Guide_MSP430F5529LaunchPad.html

 

Use Serial for the debug output and use Serial1 to talk to the GPS receiver.

Edited by energia
Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...