Shop OBEX P1 Docs P2 Docs Learn Events
Serial Communication Protocol - Page 2 — Parallax Forums

Serial Communication Protocol

2»

Comments

  • Heater.Heater. Posts: 21,230
    edited 2011-01-23 11:55
    Yes but can you write for us a complete message, as you'd like to see it, including all start, stop markers, length, values, delimeters, CRCs etc?
    I assume it is in ASCII. For example:

    STX, length, value, DLIM, value, DLIM, value, DLIM,...., CRC, ETX

    Where: STX/ETX are the appropriate bytes, length is a length in decimal digits, value is a value in decimal digits, DLIM is a delimiter byte (whatever), CRC is the CRC in decimal digits.

    There is no reason to have a CRC error check for every value in a message. You only need one CRC covering the length of the message, say from the first byte of the first value to the last byte of the last value. Perhaps including the length bytes as well.
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 12:11
    LOL I am not going to look up all the ASCII characters... But I will give you some, the rest of the data fields will be enclosed in < >

    02 <String Message 1 Length> 31 <String Message 1 Value> 31 <CRC 1 Length> 31 <CRC 1 Value> 31 <String Message 2 Length> 31 <String Message 2 Value> 31 <CRC 2 Length> 31 <CRC 2 Value> 03

    By knowing the data size, you would know how many bytes to read for each field, by having seperate CRC's for each value, you could eliminate parsing the whole transmission and knowing that it was error free. You would just have a series of writes into the appropiate buffers.

    Bruce
  • Mike GreenMike Green Posts: 23,101
    edited 2011-01-23 12:21
    Make all the numeric data fixed length. Either use hexadecimal or use raw binary, both of which have already been suggested. In hex, a 16-bit CRC is always 4 characters. If the data strings are always less than 256 bytes, 2 hex characters will take care of that. There is already a hex output routine in the serial I/O objects and a hex input routine in the Extended FDS object.
  • MagIO2MagIO2 Posts: 2,243
    edited 2011-01-23 12:22
    I'd either go this way or that way, either send binary numbers or numbers converted to strings - even the CRC. No mixture like string numbers and binary CRC.

    If you like you can have a look at the ConfigReader I added to the ObEx a while ago (Tools section). It's reading lines converting these to numbers.
    As you have a start and end delimiter it's easy to read a line in your case. Then call the config reader code to convert it back to numbers.
    A line would then for example look like that:
    <STX>cmd<DLIM>$1000<DLIM>2342<DLIM>here is a string<DLIM>%010101<DLIM>$FF35<ETX>

    cmd is converted to a hash-value and you can check in a case statement which message you received.
    The numbers can be in any integer format. $ is a hexadecimal number, % is a binary number and no prefix is decimal.
    For a string the parser will store the start-address of the string.

    The results are stored in an array of longs. I think currently 10 parameters are supported, but you can easily change that.
  • MagIO2MagIO2 Posts: 2,243
    edited 2011-01-23 12:26
    Your read loop would be easy:

    1. wait until <STX> found
    2. read into buffer until <ETX> found
    3. build CRC of the buffer (from beginning up to last delimiter (excluding the CRC)
    4. parse the buffer
    5. compare calculated CRC with parsed CRC (last parameter)
    6. If CRC equal message can be processed
    7. goto 1
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 12:33
    @MagIO2 - It has been pointed out by Dave Hein and resolved by Kuroneko that the crc result can contain ETX

    @Mike -
    In hex, a 16-bit CRC is always 4 characters

    Okay so now how do I equate that to number of bytes?
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 12:34
    MagIO2

    So you are saying to send the CRC seperately?
  • Heater.Heater. Posts: 21,230
    edited 2011-01-23 12:40
    Having been around a bit I've seen dozens of different serial line protocols. I have never seen anyone use multiple CRCs within a message.

    Consider this:
    If a CRC on one of your data values is wrong you are now screwed for all of that message.
    Yes, the next value and it's CRC may be correct BUT now you don't know if there was some interruption in data flow such that the end of one message was missed along with the beginning of the next message. You no longer know if that next "valid" value is part of the message you were reading or part of a following message or what position in the message it should have had. That is, you don't actually know what that value represents as you have lost it's position in the scheme of things.

    This might be unlikely but unlikely things happen all the time. It's better to have no data than wrong data. Just use one CRC for the entire message.

    Now if you are using ASCII, use STX and ETC as you describe.
    Use a delimiter between values, for example a semi-colon.
    No need for a length on each value as we can count the digits being received between delimiters.
    You will need the first value in the message to be the length.
    I imagine a message would look like:

    <STX><LEN><;5678;910112;8758;937123;36446;><CRC><ETX>

    Where:
    <STX> and <ETX> are the non-printable start and end of text bytes.
    <LEN> is actually the length of the message, probably as a raw binary WORD.
    <CRC> is actually the CRC again probably as a raw binary WORD.
    The rest is your decimal digit values with semicolon delimeters.
    The angle brackets of course do not appear in the message.

    Here the length allows that this message can be read from the line byte by byte for length bytes without having to parse the content of the message until it is all received. That is to say messages can be read, error checked and buffered without knowing the format of the content.

    Again as Phil says, you could use hex, have all values the same length and drop the delimiters.
  • Mike GreenMike Green Posts: 23,101
    edited 2011-01-23 12:49
    In most current day systems, an 8-bit byte holds a character.
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 12:53
    Heater

    Okay, I am convinced with two modifications.

    1. As you said there is no need for length, simply read until a delimiter is found. You show a length right after STX, we eliminate it.

    2. Put a delimiter between CRC value and ETX, end of story.

    So it would look like this:
    CRC := ComputeCRC(@DataString, DataSize)  
      'Send Start Of Text message to the Receiver
      Sender.Tx(STX)
      { Format and send main data content between here and the next comment }
      Sender.Dec(DataSize)
      Sender.Tx(US)
      Sender.Str(DataString)
      Sender.Tx(US)
      Sender.Dec(CRC)
      Sender.Tx(US)
      { Main data content should have been formatted and sent by this point }
      'Send End Of Text message to the Receiver
      Sender.Tx(ETX)
    

    Of course the string will have to be parsed but oh well.

    Thanks Heater, and Everyone for your participation.

    Bruce
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 12:55
    Sorry I meant like this:
    CRC := ComputeCRC(@DataString, DataSize)  
      'Send Start Of Text message to the Receiver
      Sender.Tx(STX)
      { Format and send main data content between here and the next comment }
      Sender.Str(DataString)
      Sender.Tx(US)
      Sender.Dec(CRC)
      Sender.Tx(US)
      { Main data content should have been formatted and sent by this point }
      'Send End Of Text message to the Receiver
      Sender.Tx(ETX)
    
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 12:59
    Mike _ LOL yes most, I never messed with hex except for color values
  • Heater.Heater. Posts: 21,230
    edited 2011-01-23 13:06
    Hmmm...
    1. As you said there is no need for length, simply read until a delimiter is found....

    There is no need for a length along with each value because:
    1) The delimiters tell you how many digits there are in each value field.
    or
    2) If you use 8 hex digits for each value then you know the values have length of 8 and there is no longer any need for delimiters.
    You show a length right after STX, we eliminate it.
    Perhaps but:
    If you have an overall message length there then the receiver can blindly receive that many bytes, as fast as possible without knowing what they are or inspecting them in any way. Then the received message can be placed in a buffer for processing at leisure. This may or may not be useful to you.
    2. Put a delimiter between CRC value and ETX, end of story.
    Perhaps but if the CRC is a fixed length field, in raw binary or hex digits then there is no need for a delimiter. Makes life simpler.

    You might be in danger of discovering that communication protocols have a habit to fail or deliver incorrect data in all kinds of unexpected ways:)

    Happy hacking:)
  • Heater.Heater. Posts: 21,230
    edited 2011-01-23 13:11
    P.S.
    Can you now change the title of this thread to something more meaningful? Something about serial communication protocols say. Might help others who come by.
  • idbruceidbruce Posts: 6,197
    edited 2011-01-23 13:12
    Heater

    I will probably change it later when I become more acquainted with hex and binary data, but for now I think it will work as described. It would be faster with knowing the data lengths, but that would require a thorough understanding which I lack :)

    Bruce
Sign In or Register to comment.