Thursday, November 3, 2022

MiniProto, a mini protocol for data exchange between devices


MiniProto is a mini protocol for data exchange between devices.

It is build and tested over the serial communication protocol, but it can be ported to others.
It is designed to send strings and byte arrays.
MiniProto in the current implementation you can send up to 999 commands, and 999 byte long byte array.


The command structure is the following:
STX|ACK|NAK CMD LENGTH DATA CRC ETX

Command parts are:
  • STX (hex 0x02): command begin 
  • ACK (hex 0x06): acknowledgment command begin
  • NAK (hex: 0x15): negative acknowledgment command begin
  • CMD: 3 byte, ascii number, command number
  • LENGTH: 3 byte, ascii number, length of data
  • DATA: byte array
  • CRC: 1 byte CRC code
  • ETX (hex 0x03): command end
Send command can request an acknowledgment to be sent back. The acknowledgment command must contain the command number, and must start with ACK or NAK byte.

The ESC special char (hex: 0x1B) is used as escape character. Indeed if a ETX byte is sent in DATA, it is preceded by the ESC character. The escape character reduce the max length of DATA. An alternative strategy to prevent the use of the ESC character is to use the LENGTH field to read data, instead of using a read to ETX character. This may be implemented in a future version of this protocol.
Each command must have a CRC hex byte, this prevents communications errors.
CRC function is CRC polynomial x^8 + x^7 + x^2 +1  implemented using a lookup table to speed up the computation process.


DATA max length, and protocol timing can be personalized in the header file of the protocol.

Errors in communications may happens, due to timing or interference. However I'm using this protocol with decent results.

On the embedded side, there are two ways this protocol process input data.
A "blocking" one, and a "timed" one.
In the blocking way, the called functions try to read input from the selected channel, that is UART in this example. If a char is read, then the next one is processed, till the the end of protocol command, or till the threshold time passed.
In the timed way, two function are involved, one that read characters, and another that can be called to get the last command found. Most of the works is done inside the read/input function. This function read one, or up to a threshold bytes until the end of protocol command.
On both function a few other error preventing mechanism are implemented.
The timed functions most of the time it's the way to go, cause it does not stop the working loop that much. One can even put this function in a TIMER, and use the read last command function in the program loop.

I've tested this protocol on AVR ATmega8 running @8Mhz.
A NET C# client library is implemented for test.


Code

Notes
  • read risk disclaimer
  • excuse my bad english