Posted by automatik on February 16, 2009 at 2:32am
Hi all,below is my attempt at basis for NMEA parser - actually code below just reads desired NMEA sentences...I am not trying too reinvent the wheel, as I know many others have already done this - and I used Jordi's and Michal B.'s code for learning and reference. I just wanted to write my own, as to really understand the problem and what is needed (if I have to solve it I need to understand it :) ). I might , or might not use this for my future plans.From what I can tell, IF I understood Jordi's and Michal's code, major difference is that while reading data from gps, I only "fill" gps data buffer if I am reading NMEA sentance I want - RMC and GGA; ther is no buffering of data for GLL, GSA, GSV, etc.This is accomplished by, once start buffer flag is received, I scan buffer while it's being filled when it has only 5 entries. If protocol header is not RMC or GGA, buffer filling stops - thought behind this is potential performance as array (buffer) is not manipulated. Any array manipulation is done only when wanted protocol headers are being received, or for a short time while protocol header is being checked; otherwise code goes only through very short checking to see if received data is preamble $ (still no array manipulation). Switch / case statement is and 'break' option utilized ....I am looking for critique on the method - and please be brutally honest; also is there any merit to this approach, etc. (just remember this is skeleton and not full parser, and some other stuff missing as not to complicate things now (such as buffer overflow check, etc.))P.S. formatting got messed up once posted ..it was easier to read before in dev environmentcode://gps GPS reader attempt by automatikchar gps_raw_data; // incoming data from gpschar gps_buffer[90]; // buffer for gps datachar head_rmc[]="GPRMC"; //GPS NMEA header to look forchar head_gga[]="GPGGA"; //GPS NMEA header to look forbyte gps_counter=0; //counter for gps bufferbyte gps_data_into_buf_ok=1; //flag for gps buffervoid setup(){Serial.begin(4800); // opens serial port, in future will set to higher rate}void loop(){gps_data2();//also do some other stuff in future}void gps_data2(void){while(Serial.available() > 0){gps_raw_data = Serial.read();switch (gps_data_into_buf_ok){case 0: //gps buffer closed (not opened for filling) - should we open it?if (gps_raw_data == '$') //if eq to '$' it's start of NMEA sentence{ // sogps_data_into_buf_ok=1; // set flag to strat filling gps buffer}else{//Serial.println("Buffer closed - nothing written");//do nothing - buffer not open and it's not start of NMEA sentence//nothing written to buffer array}break; //let's exit as there is no need to evaluate furthercase 1: //buffer opened for filling - what shold we do with it?gps_buffer[gps_counter] = gps_raw_data;if (gps_counter == 4) //buffer is not full yet// but let's test to see if we are getting NMEA sentence we want//if we are we keep filling, if not we'll close buffer{ //see if we are getting RMC or GGA sentencesif ((strncmp (gps_buffer,head_rmc,5) == 0) || (strncmp (gps_buffer,head_gga,5) == 0)){//everything fine - we sre reading NMEA sentences we wantgps_counter++; //so let's increase counterbreak; //and exit and advance to another data read since//since this is not end of sentence - it will not be only 5 char long}else{ //not NEMA sentence we want sogps_data_into_buf_ok=0; //let's close buffergps_counter = 0; //reset counter; not really necessary here but just for claritybreak; //and get out of here}}//so gps counter is less then 4 and will be evaluated later//or we are filling the bufferif (gps_buffer[gps_counter] == 0x0A) // if data received is line feed (end of NMEA sentance){//----------let's process buffer-------//--print buffer---just for visualization ---//uncomment next line to see ------//Serial.print(gps_buffer);//------------------------------------------------------// here to be implemented - checksum, parsing out, etc//--------------------------------------------------------------------------// buffer processed let's do some cleanupfor(int a=0; a<=gps_counter; a++) // reinitializing gps buffer{gps_buffer[a]=0;}gps_counter=0; // Restarting the countergps_data_into_buf_ok=0; // close buffer as we are done processing//and should be looking for start of new one// found end of the gps NMEA sentence}else{ // either valid buffer or still to be evaluated for desired NMEA sentence//so advance countergps_counter++;}}}}
You need to be a member of diydrones to add comments!
automatik: good approach, but it won't be any faster to only selectively "fill line buffer". You probably can't measure speed difference.
Rather concentrate on code size, this is what matters more on system with 14KB usable RAM. And you can measure code size.
By the way, you'll probably notice that it is a good idea to configure the GPS to spit only the needed sentences. It's what Chris proposed to do here with the Locosys GPS chip.
Replies
Rather concentrate on code size, this is what matters more on system with 14KB usable RAM. And you can measure code size.