I'm working on an exciting project of controlling a Control panel (Toggle switches, rotary encoder, 7 segment display, led status annunciators...
I'm writing a C# software to that will communicate with the an Arduino mega 2560 R3 through the USB/Serial COM to set annunciators light (on/off) and to get switch states (on/off).
My current protocol is working like this:
Sender:
1st byte = 253 = "Ready to send data?"
2nd byte = 4= size of data to be sent
Receiver:
1st byte = 252 = "Ready to receive data!"
For my Arduino loop it's currently running 2 functions one that read the serial buffer and process the instruction and another that send messages to the pc on status change (button pressed).
The issue I'm facing is when both the PC and the Arduino send a message at the same time. Both are in their own send message function and the handshake will not work as both are sending the "Ready to send data?" byte and the reply received will also be "Ready to send data?" as both device are waiting to send their message.
I tried using a queue system for the out messages on the PC by saving the failed to received message in a queue and calling the read messages function to process the Arduino message, and it helped reduce the issue but it still occur when the arduino send the first init byte just before the PC sent his own (the function check just before sending the first byte if the buffer is empty but the delay between the check and sending the byte is an area where the issue could occur again).
I'm sure you guys already have great Ideas to make the protocol reliable but here's some ideas I was thinking of trying:
Using a Master/Slave system (PC as Master and Arduino as Slave) where only the PC can send command and the arduino only reply to the commands received. This would required polling the arduino for any status changes on the inputs (switches) at fast intervals (<100ms) as the arduino can't send notification to the PC.
Getting rid of the "handshake" part of the protocol so we can simply send the commands without asking the receiver and let the messages get in the buffer so when the message is sent the loop will do the read function and process the buffer. Since the Arduino's buffer is limited to 64bytes we would need to track sent message to avoid overflow but there's no way of knowing if the messages were received unless we give unique ID to each message and return that ID once the message was processed.
What are you thoughts? I'm sure you will have better ideas for my issue.
When there is a long cable with a RS-232 signal going from one side of a building to another side, then it needs a start byte a stop byte and a checksum and maybe even more, although a software-handshake seems far fetched.
This is a USB cable between the computer and the Arduino. You don't need all of that (maybe some of it).
I think the handshake does not work together with the 64 byte buffer of the Serial library.
Suppose the Arduino is ready, and then 100 bytes are pushed into the buffer at a high baudrate, then some bytes will get lost anyway.
Using the full-duplex of the RX and TX makes it faster. The handshake itself prevents that the Arduino can receive commands at a high speed.
Which problem are you trying to solve ?
Do you know about the XY-problem ? https://xyproblem.info/
The Arduino should always be ready to receive data. When it is not ready, then something is wrong with the sketch.
Why do you want to know if the message was received ? Is the sketch so bad that you don't know ?
Can you show your sketch ? Please put your sketch between code-tags. The </> button is for the code-tags.
I can make a guess. When you show your sketch, then I might say: "O, we don't wait for serial data, we never wait".
You need something at the end of a line, for example or CarriageReturn and/or LineFeed. I suggest both CarriageReturn and LineFeed.
I don't know if a start byte is needed. Suppose the Arduino is turned on and does not receive a full message. It should be able to recognize that.
What you can do, is keep track of problems with an error count. Suppose that something wrong was received then increase that value. If that value is still zero after a year, then you know that it is reliable.
1. Is InputBox of Serial Monitor (Fig-1) your Sender? Or, your application program of C# will drive communication port? 2. Is OutputBox of Serial Monitor (Fig-1) your Receiver? 3. The Serial Monitor:
Have a look at the examples in Serial Input Basics - simple reliable non-blocking ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.
The technique in the 3rd example will be the most reliable. It is what I use for Arduino to Arduino and Arduino to PC communication.
You can send data in a compatible format with code like this (or the equivalent in any other programming language)
Another source for inspiration of serial protocols is NMEA 0183. It is used by GPS modules and there are libraries like TinyGPS that can be used as starting point for your own implementation.
I agree with the suggestion to use ASCII, makes debugging easier.
My SafeString library also provides examples of non-blocking reading of Serial data ('\0' not allowed) and parsing comma separated data, but also handles other delimiters.
See the tutorials Text I/O for the Real World and the SafeString tutorial
The Text I/O for the Real World is a detailed tutorial on reading and parsing Stream data.
Includes a GPS processing example.