Variances with Vessel GPS Co-Ordinates across devices and Apps

Discussion and support for the Nmea4Wifi multiplexer - a 4-input Nmea 0183 wifi multiplexer.
Post Reply
Mark Lee
Posts: 3
Joined: Sat Mar 20, 2021 8:43 pm

Variances with Vessel GPS Co-Ordinates across devices and Apps

Post by Mark Lee » Sat Mar 27, 2021 6:59 pm

I have just received my NMEA4WIFI. It is running firmware 4.1.

I am using the P4 input configured to Seatalk.

I am using the wifi UDP setting to link into a number of Apps on various devices, all of which are Android.
The Apps I am using are Navionics Boating, OPENCPN and NKE Display.

The P5 port is being used with NMEA0183 hard wired to a Simrad RS82 VHF radio and a Raymarine SL70C, this will eventually incorporate the ST5000 Plus Autopilot.

I have not set any filtering.

My problem is that the vessel location is different across these devices and Apps.

My actual vessel location is

59 Degrees 26.553 Minutes North
000 Degrees 49.128 Minutes West

The OPENCPN and Navionics Boating Apps are illustrating this location correctly, however the NKE Display, RS82 VHF and the SL70C are illustrating the vessel location at:-

59 Degrees 26.55 Minutes North
049 Degrees 00.13 Minutes West

It appears that the Seatalk conversion of the RMC sentence is being done with errors which can be handled by the Navionics and OPENCPN Apps but cannot be handled by the nke App, RS82 and the SL70C.

The actual RMC sentence captured through the NMEA4WIFI tool is

$GPRMC,285752,A,5326.552,N,049.130,W,0.0,148,210321,17,W*4E

It appears that there are insufficient characters in the W parameter. Perhaps the 049.130 should be 0049.130.

There are no other location sentences visible on the network.

For information all other Seatalk Sentences appear correctly on all devices and Apps
E.g. Depth, Speed Heading etc
although at this point I am only in the infancy of integrating the systems.

I have also run the simulation file which exists within the Firmware of the NMEA4WIFI and that displays information correctly on all Apps and Devices. Obviously here there will be no Seatalk to NMEA conversions taking place.

I have tried to install older versions of the Firmware to see if that fixes the problem but unfortunately I am unable to to do this, a technical issue I am currently facing into.

Has anybody has this problem with the Seatalk translation and how did you fix it.

Luis Sa
Site Admin
Posts: 846
Joined: Thu May 04, 2017 4:12 am

Re: Variances with Vessel GPS Co-Ordinates across devices and Apps

Post by Luis Sa » Sat Mar 27, 2021 9:24 pm

Hello Mark,

Thank you for your informative posting about the ST datagram conversion to Longitude. During the last weeks I have been working very hard on the development of ST1<>NMEA0183 bridge. In the direction ST1>NMEA0183 this bridge uses exactly the same code as both the NMEA2WIFI and NMEA4WIFI multiplexers. In the NMEA0183>ST1 direction I have coded several sentences. I hope to create a specific topic on this bridge and publish the source code that I am using. The hardware is a simple ESP32 module and a transistor and a couple of resistors. If you know how to compile and flash an ESP32 using the Arduino IDE, I could add you to a private forum where I am posting all my progress on that task.

2 days ago I coded the conversion of GLL and RMC to ST datagrams. I ask you to wait a couple of days so that I can complete and publish the bridge software and I will look to the ST > NMEA conversion. Despite of that It looks like you are right on the Longitude field. Here is the (partial) code that I use to convert RMC to SeaTalk1

Code: Select all

boolean ParseNmea42() { // this is for RMC
  /*
  RMC - Recommended Minimum Navigation Information
  This is one of the sentences commonly emitted by GPS units.
                                                            12
         1         2 3       4 5        6  7   8   9    10 11|  13
         |         | |       | |        |  |   |   |    |  | |   |
  $--RMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,xxxx,x.x,a,m,*hh<CR><LF>
   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
  10) Magnetic Variation, degrees
  11) E or W
  12) FAA mode indicator (NMEA 2.3 and later)
  13) Checksum
  Example: $GPRMC,120004.03,A,3905.84900,N,02633.42800,E,0000.0,330.0,011019,0.0,W,A,S*64
  */  
  // first thing to do is to check if there is space in the buffer
  int nextBuf = inBuf + 1; 
  if (nextBuf == 8) { nextBuf = 0; }
  if ( nextBuf == outBuf ) { return false; }   // sentence is lost
  // we define the char arrays to receive the fields that exist in the nmea sentence
  char GMT[10]; char VAL[2]; char LAT[12]; char N_S[2]; 
  char LON[13]; char E_W[2]; char SOG[6]; char COG[6]; char DAT[7];
  pTOKEN = nmea_1; pTOKEN = pTOKEN + 7;  // pTOKEN points to GMT time
  char *p;  // pointer to the receiving char arrays
  p = GMT; if ( !FillToken(p) ) { return false; };
  p = VAL; if ( !FillToken(p) ) { return false; };
  if (VAL[0] != 65) { return false; }    // 65 is ASCII A which validates the sentence
  p = LAT; if ( !FillToken(p) ) { return false; }; if ( LAT[0] == 0 ) { return false; }
  p = N_S; if ( !FillToken(p) ) { return false; }; if ( N_S[0] == 0 ) { return false; }
  p = LON; if ( !FillToken(p) ) { return false; }; if ( LON[0] == 0 ) { return false; }
  p = E_W; if ( !FillToken(p) ) { return false; }; if ( E_W[0] == 0 ) { return false; }
  p = SOG; if ( !FillToken(p) ) { return false; }; 
  p = COG; if ( !FillToken(p) ) { return false; }; 
  p = DAT; if ( !FillToken(p) ) { return false; }; 
  // now start with GMT
  // ==================
  if ( GMT[0] != 0 ) {
    // the field exists - so generate datagram 54
    p = GMT;
    char H[1]; strncpy(H, p, 2); uint8_t HH = atoi(H);
    p = p + 2; strncpy(H, p, 2);  uint8_t MM = atoi(H);
    p = p + 2; strncpy(H, p, 2); uint8_t SS = atoi(H);
   // now we can generate datagram 54
    ST_buffer[inBuf][0] = 0x04;         // length
    ST_buffer[inBuf][1] = 0x54;         // command
    ST_buffer[inBuf][4] = HH;           // hours go to last byte! easy!
    uint8_t i = SS & 0x0F; i = i << 4; 
    ST_buffer[inBuf][2] = i | 0x01;
    i = SS & 0x30; i = i >> 4;
    uint8_t j = MM; j = j << 2;
    ST_buffer[inBuf][3] = ( i | j );     // it is done!
    inBuf = nextBuf;
    // now check if there is space in the buffer for the next datagram (latitude - 51)
    nextBuf = inBuf + 1; 
    if (nextBuf == 8) { nextBuf = 0; }
    if ( nextBuf == outBuf ) { return true; }   // return true for previous datagram to be sent 
  }
  // now process latitude
  // ====================
  p = LAT; 
  uint8_t XX = atoi(p) / 100;
  p = p + 2;
  uint16_t YYYY = 100 * atof(p);
  // check for N or S      
  ( N_S[0] == 0x4E ) ? YYYY = YYYY & 0x7FFF : YYYY = YYYY | 0x8000 ;  //  0x4E is ASCII N
  // now we can generate datagram 50
  ST_buffer[inBuf][0] = 0x05;          // length
  ST_buffer[inBuf][1] = 0x50;          // command
  ST_buffer[inBuf][2] = 0x02;
  ST_buffer[inBuf][3] = XX;    
  ST_buffer[inBuf][4] = lowByte(YYYY); 
  ST_buffer[inBuf][5] = highByte(YYYY);
  inBuf = nextBuf;    
  // now check if there is space in the buffer for the next datagram (longitude - 51)
  nextBuf = inBuf + 1; 
  if (nextBuf == 8) { nextBuf = 0; }
  if ( nextBuf == outBuf ) { return true; }   // return true for previous datagram to be sent
  // now process longitude
  // =====================
  p = LON; 
  XX = atoi(p) / 100;
  p = p + 3;
  YYYY = 100 * atof(p);
  // check for E or W
  ( E_W[0] == 0x57 ) ? YYYY = YYYY & 0x7FFF : YYYY = YYYY | 0x8000 ;  //  0x57 is ASCII W
  // now we can generate datagram 51
  ST_buffer[inBuf][0] = 0x05;          // length
  ST_buffer[inBuf][1] = 0x51;          // command
  ST_buffer[inBuf][2] = 0x02;
  ST_buffer[inBuf][3] = XX;    
  ST_buffer[inBuf][4] = lowByte(YYYY); 
  ST_buffer[inBuf][5] = highByte(YYYY);
  inBuf = nextBuf;  
  // now check if there is space in the buffer for the next datagram (SOG - 52)
  nextBuf = inBuf + 1; 
  if (nextBuf == 8) { nextBuf = 0; }
  if ( nextBuf == outBuf ) { return true; }   // return true for previous datagrams to be sent
  // now process SOG
  // ==============
  if ( SOG[0] != 0 ) {
    // the field exists - so generate datagram 52
    p = SOG;
    //  52  01  XX  XX  Speed over Ground: XXXX/10 Knots
    uint16_t sog = 10 * atof(p);
    ST_buffer[inBuf][0] = 0x04;          // length
    ST_buffer[inBuf][1] = 0x52;          // command
    ST_buffer[inBuf][2] = 0x01;   
    ST_buffer[inBuf][3] = lowByte(sog); 
    ST_buffer[inBuf][4] = highByte(sog);
    inBuf = nextBuf;  
    // now check if there is space in the buffer for the next datagram (COG - 53)
    nextBuf = inBuf + 1; 
    if (nextBuf == 8) { nextBuf = 0; }
    if ( nextBuf == outBuf ) { return true; }   // return true for previous datagrams to be sent
  }
  // now process COG
  // ==============
  if ( COG[0] != 0 ) {
    // the field exists - so generate datagram 53
    p = COG;
    // 53  U0  VW      Course over Ground (COG) in degrees
    uint16_t cog = atoi(p);
    ST_buffer[inBuf][0] = 0x03;          // length
    ST_buffer[inBuf][1] = 0x53;          // command
    uint16_t ii = cog / 90; 
    uint16_t kk = ii;
    uint16_t jj = cog % 2;
    if (jj) { kk = (kk | B00001000); }
    ST_buffer[inBuf][2] = kk << 4;
    jj = cog - ii * 90;
    ST_buffer[inBuf][3] = jj / 2; 
    inBuf = nextBuf;  
    // now check if there is space in the buffer for the next datagram (Date - 56)
    nextBuf = inBuf + 1; 
    if (nextBuf == 8) { nextBuf = 0; }
    if ( nextBuf == outBuf ) { return true; }   // return true for previous datagrams to be sent
  }
  // now process DATE
  // ================
  if ( DAT[0] != 0 ) {
    // the field exists - so generate datagram 56
    p = DAT;
    // 56  M1  DD  YY  Date: YY year, M month, DD day in month
    char H[1]; strncpy(H, p, 2); uint8_t DD = atoi(H);
    p = p + 2; strncpy(H, p, 2); uint8_t MM = atoi(H);
    p = p + 2; strncpy(H, p, 2); uint8_t YY = atoi(H);
    ST_buffer[inBuf][0] = 0x04;          // length
    ST_buffer[inBuf][1] = 0x56;          // command
    ST_buffer[inBuf][2] = ( ( MM << 4 ) | 0x01 );
    ST_buffer[inBuf][3] = DD;
    ST_buffer[inBuf][4] = YY;
    inBuf = nextBuf;  
  }
  return true;
}
As in the description of the RMC sentence latitude has 4 characters to the left of the decimal point, while longitude has 5 characters. In the following lines from the code above I advance pointer p of 3 positions to get the minutes part. The degrees part are the 1st 3 characters:

Code: Select all

  ....
 // now process longitude
  // =====================
  p = LON; 
  XX = atoi(p) / 100;
  p = p + 3;
  YYYY = 100 * atof(p);
  ...

This is described here:

Code: Select all

Where a numeric latitude or longitude is given, the two digits immediately to the left of the decimal point are whole minutes, to the right are decimals of minutes, and the remaining digits to the left of the whole minutes are whole degrees.
Eg. 4533.35 is 45 degrees and 33.35 minutes. ".35" of a minute is exactly 21 seconds.
Eg. 16708.033 is 167 degrees and 8.033 minutes. ".033" of a minute is about 2 seconds.
Conclusion - you just discovered a bug! I think it will be easy to correct. I will keep this subject open!

Thanks and Regards, Luis

Luis Sa
Site Admin
Posts: 846
Joined: Thu May 04, 2017 4:12 am

Re: Variances with Vessel GPS Co-Ordinates across devices and Apps

Post by Luis Sa » Sun Mar 28, 2021 3:09 am

Hello Mark,

Could you please try to update to version 42 found here. I am not putting this BIN file in the topic "Binary updates for the Nmea4Wifi multiplexer" because there could be more things to be corrected. This file produces 5 chars to the left of the decimal point in longitude field padding with zeros as needed. Please five feedback.

Regards, Luis

Mark Lee
Posts: 3
Joined: Sat Mar 20, 2021 8:43 pm

Re: Variances with Vessel GPS Co-Ordinates across devices and Apps

Post by Mark Lee » Sun Mar 28, 2021 6:44 pm

Hi Luis,

Thankyou for the help. I have manage to update the firmware to 4.2 and the bug has gone. Brilliant. :D

We will be released from COVID lock down here in England very soon so I am hoping to get on the water and try more of the features I hope the NMEA4WIFI will give me.

Yes I can see from the NMEA0183 reading tool that some of the Seatalk conversions are missing and I understand that you are working on them.

With regard to working in your group and advancing this area with you I will probably be out of my depth, but I am more than happy to test your developments as they progress.

Many thanks for the quick turn around with the upgrade.

Mark

WOOW
Posts: 13
Joined: Fri Nov 13, 2020 6:56 pm

Re: Variances with Vessel GPS Co-Ordinates across devices and Apps

Post by WOOW » Mon Apr 05, 2021 12:36 pm

Hi Mark, maybe you have NKE autopilot on board?

Mark Lee
Posts: 3
Joined: Sat Mar 20, 2021 8:43 pm

Re: Variances with Vessel GPS Co-Ordinates across devices and Apps

Post by Mark Lee » Thu Apr 08, 2021 6:04 pm

Hi,

No I don't have the NKE Autopilot.

I was just using the NKE free app which provides a display of the instrumentation.

Have you used NKE Autopilot, if so do you know if it works with the ST5000+


Thanks

Mark

WOOW
Posts: 13
Joined: Fri Nov 13, 2020 6:56 pm

Re: Variances with Vessel GPS Co-Ordinates across devices and Apps

Post by WOOW » Tue Apr 13, 2021 11:14 am

We do have nke Gyropilot 2.

nke Display app can be used as autopilot remote control, but multiplexer needs to have 2 way communication. So I was wondering if we can use Nmea4Wifi instead of crazy expensive nke Wifi Box.

Post Reply