error detection problem reading data stream

The code which follows reads from a continuous data stream generated by two navigation instruments on the boat. The method is proprietary to Raymarine, the equipment vendor. The topology, if that's the right word, is single bus, with all devices both talkers and listeners at 4800 bps. The talkers issue datagrams at different intervals and listen for collisions. If there is a collision, the talker quits sending wherever it is in the datagram such that the datagram will be incomplete. It then waits a prescribed interval and tries again. Some equipment issues datagrams which have a form of error detection - bits inverted on next byte after data so that they can be summed to equal a constant.

But alas, not the datagram I'm using. My only possible method is to recognize a short datagram which will by definition be incomplete and ignore it.
Here is where the problem is. I cannot figure out how to do it.

I use "pointer" in this snippet to identify bytes in the data. What I need is a method to ignore whatever has been read if the pointer has only gotten to 11 and the next 0x100 shows up. it seems so simple and yet ....

 void readSeaTalk()

{
  if (Serial.available ()) 
   { inbyte = (Serial.read());
     if (inbyte == 0x100) 
     pointer = 0 ;
       
 /* Code above reads SeaTalk Stream and starts inbyte buffer when 
    9th bit and first byte of depth sentence (command byte)come in.  
    On my system with two talkers, ST40 depth and wind, the datagrams 
    follow each other in sequence so it's easy to pick out the 
    bytes needed to derive wanted data - always in same place */
    
   SeaTalkData[pointer++] = inbyte ;
  
   printwind = ((SeaTalkData[11] & 0x7f) + SeaTalkData[12]/10.0) ;
   printangle = (makeWord(SeaTalkData[7] , SeaTalkData[8]))/2 ;  
   printdepth = (makeWord(SeaTalkData[4] , SeaTalkData[3])) / 10.0 ;
   }
}

Maybe this will work. comments?

 void readSeaTalk()

{
  if (Serial.available ()) 
   { inbyte = (Serial.read());
     if (inbyte == 0x100) 
     if (pointer < 12) 
     errorflag = 1 ;
     else
     pointer = 0 ;
       
 /* Code above reads SeaTalk Stream and starts inbyte buffer when 
    9th bit and first byte of depth sentence (command byte)come in.  
    On my system with two talkers, ST40 depth and wind, the datagrams 
    follow each other in sequence so it's easy to pick out the 
    bytes needed to derive wanted data - always in same place */
    
   SeaTalkData[pointer++] = inbyte ;
  
   wind = ((SeaTalkData[11] & 0x7f) + SeaTalkData[12]/10.0) ;
   angle = (makeWord(SeaTalkData[7] , SeaTalkData[8]))/2 ;  
   depth = (makeWord(SeaTalkData[4] , SeaTalkData[3])) / 10.0 ;
   if (!(errorflag)) {
     printwind = wind ;
     printangle = angle ;
     printdepth = depth ;
   }
   
   }
}

jferg:
Maybe this will work. comments?

I don't know enough about the problem to tell whether that code will solve it.

I see that you are using 0x100 as a start-of-message marker, so you know when you have got the start of a message.

How can you tell whether you have received a complete message? Is there anything in the message that explicitly indicates the end of the message, or implicitly indicates it (for example by enabling you to work out the expected length)?

Hi Peter,

The message (three datagrams) contains no checksum, or other method for verification. The third byte must be 20, so that could be a check, but since the system is a bus with two talkers (one of which sends two datagrams) and no collision control other than halting a datagram transmission if another talker starts, all I have then is a short message. So i end up with apparently two checks, first is message right length and I'm going to change my check from "less than 12 bytes" to "not 12 bytes" in case it gets one that is too long, and also check for 3rd byte being correct.

data itself is wind speed, wind angle, and depth. If I was just reading these on a display it wouldn't matter because an error would be obvious, but recording max windspeed and minimum depth cannot handle an error in the right direction. if the thing sees a 90 knot wind because of an error than my record will show 90 knots even though it never happened. with depth, I could see 1 foot because of a fish, so the reading might be correct but not useful. I'm going to handle that with comparison to a running average.

anyone who reads this will see that i don't know what I'm doing. there may be better ways to do this, but i can settle for anything that works.

regards,,

I know zero about boats or this Raymarine equipment but want to ask is this device (A link would be nice) using SeaTalk1 or SeaTalkNG If it’s the latter then according to this chap Thomas Knauf     SeaTalk Technical Reference the lower nibble of the second byte contains the number of bytes expected in the datagram. A datagram is a minimum of 3 bytes, maximum of 18 so first thing would be to get at least 3 bytes (If you could read the second stop bit or parity then you would also know when a command starts) then see how many extra bytes should arrive by looking at the nibble and waiting for these bytes or timing out if they don’t arrive in x amount of time.

Thanks for the thought, Riva, you are right. I coded the errorflag routine based on the known bytes for the three datagrams and it works.

each of the datagrams i use is always the same length. i used Thomas Knauf's excellent information for writing the code which reads the datagram so I can write it to my LCD and keep track of maximum windspeed and least depth. As i said, having correct data doesn't cure the least depth errors because the sounder can see a fish once in a while. so i average the last three readings and discard the latest if it is less than 80 % of the average. that seems to work two. and if it is less than 80% the least depth record will eventually catch up.

best regards, john

Hello

I am trying also to read data from raymarine instuments with seatalk. Can you post me the code that you say it is working?