Go Down

Topic: 'Binary' serial packet library (Read 218 times) previous topic - next topic

bms001

Oct 01, 2019, 12:46 am Last Edit: Oct 01, 2019, 12:47 am by bms001
I wrote a library for sending/receiving packets over serial using the binary representation of numbers rather than their character representations.
E.g. 67 is sent as a single byte 01000011, rather than two bytes 00110110 ('6') 00110111 ('7') if using Serial.print(67).
There are no delimiters between multiple variables in a packet, only a packet delimiter. COBS encoding of the packet is used to allow the packet delimiter to appear in the transmitted data. A checksum is also included for integrity.

The library handles almost all details of building and sending the package, and receiving and unpacking it.

For sending, the user just has to call some provided functions to add data to the buffer, and then call the send() function.
Code: [Select]

encodedSerial.addToBuffer<uint8_t>(a);
encodedSerial.addToBuffer<int8_t>(b);
encodedSerial.addToBuffer<uint16_t>(c);
encodedSerial.addToBuffer<int16_t>(d);
encodedSerial.addToBuffer<uint32_t>(e);
encodedSerial.addToBuffer<int32_t>(f);
encodedSerial.addToBuffer<float>(g);
encodedSerial.send();


For receiving, the user has to call receive() every loop(), and fill in the details of a callback function that gets called automatically when a complete and valid package is received - again, functions are provided for extracting variables from the received data.
Code: [Select]

void loop() {
  encodedSerial.receive();
}

bool callback() {
  uint8_t a = encodedSerial.extractFromBuffer<uint8_t>();
  int8_t b = encodedSerial.extractFromBuffer<int8_t>();
  uint16_t c = encodedSerial.extractFromBuffer<uint16_t>();
  int16_t d = encodedSerial.extractFromBuffer<int16_t>();
  uint32_t e = encodedSerial.extractFromBuffer<uint32_t>();
  int32_t f = encodedSerial.extractFromBuffer<int32_t>();
  float g = encodedSerial.extractFromBuffer<float>();
  // do something with these values
  return true;
}




Proper(ish) instructions, code, examples etc are here
https://github.com/matt769/EncodedStream

There's also a (very similar) version for Linux so this can be used to exchange information easily between a C++ program running on a PC and a connected Arduino (this was the main reason I started writing it actually).

Of course, for many purposes sending data using the character representation is completely sufficient and/or preferable, I just wrote this for fun/learning.
If anyone has any suggestions of how it could be improved I'd be interested to hear. I thought for a long time about how to make something that was flexible in terms of packet stucture and easy to use in terms of the code required in the main program, and this was the best I could come up with.

(FYI If you're interested in this generally there's also an existing library on Github called PacketSerial which does similar things though without the convenience functions for building/unpacking the packet. I haven't tested it myself though.)

Edit: minor clarifications.

Power_Broker

Cool library - I like how you handle different data-types automatically!

You might be interested looking at another serial packet library for further inspiration and whatnot
"The desire that guides me in all I do is the desire to harness the forces of nature to the service of mankind."
   - Nikola Tesla

bms001

Thanks, I actually found your library very soon after after I posted this thread (and maybe if I search properly I'll find a hundred more packety libraries!?).

It's really interesting to look at how different people have dealt with an identical problem. E.g. I had not considered iterating backwards through the buffer to apply the COBS encoding - your version is far more succint and readable.

Go Up