When I first started considering how to send UART (Universal Asynchronous Receiver-Transmitter) data between a microcontroller and PC, my experience with Hyperterminal and ASCII came to mind. If I wanted to send a floating point number, I naturally gravitated towards converting it directly into a floating point number that could be sent via ASCII. For example, if sending the 16 bit integer 8795, I first tried literally sending "8795" as an ASCII representation, using start and end characters such as "S" and "E", such that the total string would be "S8795E." If I wanted to send multiple signals, I would just put a "," between them, and decrypt the format upon receiving it. Using sprintf commands to make the string (or even a more optimized method), and then sending multiple 8-bit characters was very inefficient, but did work.
Looking into better solutions, I came across COBs (Consistent Overhead Byte Stuffing). A source I found very useful was in Embedded Related. COBS is a data framing method that is beneficial for several reasons:
- It eliminates the problem of data transmission errors caused by framing errors. Framing errors occur when the receiving end of the UART data stream cannot distinguish between the actual data and the data framing bits. COBS eliminates this problem by using hex "00" as the framing bit, in which the algorithm replaces any characters of this value with what is effectively a pointer.
- The algorithm is not code intensive. Without optimization, I've found it takes less than 1000 clock cycles to convert the data into a COBS format with 10 characters (256 bits) without optimization on a basic microcontroller (or around 60 16-bit integer). I had noted it was 10x this using sprintf.
- COBS is considered better than other methods, such as bit stuffing, because it has a consistent overhead, regardless of the data being transmitted.
- COBS provides a more robust solution to framing errors as it can detect and recover from errors in the data stream.
- Python has a COBS package allowing the data to be easily reconstructed.
How to implement COBS even in C - use the code presented in Wikipedia!
I had to make some changes to work with the Microchip dsPIC33, but it was more than I could ask for: