CP180 NMEA specification needed for parsing

Joined
20 Jun 2007
Messages
16,234
Location
Live in Kent, boat in Canary Islands
www.bavariayacht.info
I'm working on a microcontroller device to parse the NMEA sentence RMC outputted from my CP180. I believe there is some flexibility in how NMEA is formatted, in particular the final field before the checksum, and the terminator.

Can anyone confirm what the terminator is on a CP180? Is it <CR><LF> or just <CR> or something else?

The new field I refer to is in NMEA 2.3 see below, does the original CP180 have this?
http://www.gpsinformation.org/dale/nmea.htm#RMC

In addition, does anyone have some sample sentences from a CP180?
 
Are you writing the parser in assembler? In C/C++ you shouldn't need to know as the use of sscanf with a valid format string should do it automatically. I use the type of statement shown here:

Code:
// $GPRMC,115807,A,5214.116,N,00008.293,E,000.0,360.0,020704,003.2,W*6F
  char gps_format_string[] = "$GPRMC,%d,%1c,%f,%1c,%f,%1c,%*f,%*f,%d,%*[^*]*%x";

 sscanf(buffer, gps_format_string, &time, fix_status, &latitude, latside, &longitude, longside, &date, &checksum);

PS: I think that it's LF
 
Arg. never try and edit a post on a phone with sweat dripping into your eyes. Last message deleted in error. To repeat it...

I'd suggest you have a look what it's outputting by connecting it up to a serial to usb thingy but seeing as it's you I'm guessing that's not an option because you're somewhere where the chart plotter isn't and you want to write the software and bring the microcontroller to the boat to test, yes?

No inside info on this device but whilst not being an "expert" (i.e. being in possession of legitimate copies all versions of the -0183 specs) I'm not aware of any version of the spec which *doesn't* have <CR><LF> as the terminator. Having said that <CR> is not a valid character within a sentence so you shouldn't run into problems if you just terminate on <CR> and ignore everything after until a ! or $ signals the start of a new sentence.

Personally regardless of the format this device is outputting I'd be inclined to code to accommodate both versions of the sentence (with/without the extra field). But then I do have a habit of making life hard for myself in the name of correctness:
https://xkcd.com/974/
 
Connect the output of the CP180 to the serial input to a PC running any ascii terminal emulator and if the NMEA message lines appear under each other the terminator is <CR><LF> if the message lines overight one another along the same line the terminator is just <CR>

I once wrote a terminal emulator that could display the incoming text in ascii hex when I was ripping ascii comms apart from all kind of hardware including baudot or EBCIDC.
 
Last edited by a moderator:
I once wrote a terminator that could display the incoming text in ascii hex when I was ripping ascii comms apart from all kind of hardware including baudot or EBCIDC.

Bet it was hilarious sending it strings such as "I need your clothes, your boots and your motorcycle."
 
Last edited:
... seeing as it's you I'm guessing that's not an option because you're somewhere where the chart plotter isn't and you want to write the software and bring the microcontroller to the boat to test, yes?
Yes.

I was also sure it was <CR><LF> but I came across a forum where just <CR> was being discussed. I can read a line at a time, but the function needs to know the terminator. I guess I could just look for <CR> then wait before resetting the terminal ready flag. Luckily I've found a library with functions to parse the sentence, this will help a lot.
 
I can read a line at a time, but the function needs to know the terminator.

I'm sure you won't, but don't fall into the trap of treating the character after the terminator as the "beginning" of the next sentence. Not only will you throw away any valid sentences which happen to have line noise in between you'll have problems when you encounter anything putting out NMEA-0183v4 sentences preceded by TAG blocks. Just chuck away everything between terminator and a "$" or !". Doing that terminating on <CR> alone is not quite "correct" but easy and avoids your question about what the CP180 does being an issue (because the <LF> is just part of what you skip over).
 
Last edited:
... Doing that terminating on <CR> alone is not quite "correct" but easy and avoids your question about what the CP180 does being an issue (because the <LF> is just part of what you skip over).

I agree, but I don't know how I can skip a <LF> using the UARTx_Read_Text() function, this is the info on it:

void UARTx_Read_Text(char *Output, char *Delimiter, char Attempts);
Reads characters received via UART until the delimiter sequence is detected. The read sequence is stored in the parameter output; delimiter sequence is stored in the parameter delimiter.
This is a blocking call: the delimiter sequence is expected, otherwise the procedure exits (if the delimiter is not found).

Parameters :
Output: received text
Delimiter: sequence of characters that identifies the end of a received string
Attempts: defines number of received characters in which Delimiter sequence is expected. If Attempts is set to 255, this routine will continuously try to detect the Delimiter sequence.

Code:
// Example 
// Read text until the sequence “OK” is received, and send back what’s been received:

UART1_Init(4800);                         // initialize UART1 module
Delay_ms(100);

while (1) {
  if (UART1_Data_Ready() == 1) {          // if data is received 
    UART1_Read_Text(output, "OK", 10);    // reads text until 'OK' is found
    UART1_Write_Text(output);             // sends back text 
 }
}
 
Last edited:
Don't bother about the CR/LF

Start parsing from the $ and read fields according to the sentence format. As the NMEA sentences are not variable in content if you did get something beyond the defined fields you'd simply drop the sentence anyway. Read the checksum at the end, validate and extract your variables. Then start waiting for the next $

If you are only interested in the GPRMC sentence you can drop back into wait mode after discovering that the sentence header is not RMC.

BTDT many, many, many times! :)
 
I'm working on a microcontroller device to parse the NMEA sentence RMC outputted from my CP180. I believe there is some flexibility in how NMEA is formatted, in particular the final field before the checksum, and the terminator.

Can anyone confirm what the terminator is on a CP180? Is it <CR><LF> or just <CR> or something else?

The new field I refer to is in NMEA 2.3 see below, does the original CP180 have this?
http://www.gpsinformation.org/dale/nmea.htm#RMC

In addition, does anyone have some sample sentences from a CP180?

According to my spec it is <CR><LF>
 
RMC Recommended Minimum Navigation Information
12
1 2 3 4 5 6 7 8 9 10 11|
| | | | | | | | | | | |
$--RMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,xxxx,x.x,a*hh
1) Time (UTC)
2) Status, V = Navigation receiver warning
3) Latitude
4) N or S
5) Longitude
6) E or W
7) Speed over ground, knots
8) Track made good, degrees true
9) Date, ddmmyy
 
Are you writing the parser in assembler? In C/C++ you shouldn't need to know as the use of sscanf with a valid format string should do it automatically. I use the type of statement shown here:

Code:
// $GPRMC,115807,A,5214.116,N,00008.293,E,000.0,360.0,020704,003.2,W*6F
  char gps_format_string[] = "$GPRMC,%d,%1c,%f,%1c,%f,%1c,%*f,%*f,%d,%*[^*]*%x";

 sscanf(buffer, gps_format_string, &time, fix_status, &latitude, latside, &longitude, longside, &date, &checksum);

I think you need to be much more flexible in parsing in order to accomodate potentially old devices which have not read/implemented the current spec.
PS: I think that it's LF

It is <cr><lf> at the end of each sentence.

Note that you need to be much more flexible in parsing in order to accommodate potentially old devices which have not read/implemented the current spec.

Also sometimes you will find that a certain device simply omits some fields. If they are at the end, then you might not get the field separators (i.e. the commas) either. I think the last W towards the end of your example message would not be output by any of the GPS units on my boat and the preceding comma would be missing as well. This would cause your sscanf to fail to match
Code:
 ,%*[^*]*%x
and as a result it would not store the checksum field.
 
Top