I'm trying to get two-way communication between a pi (3 b+) and an arduino (Uno R3) using a usb connection. On the arduino end I'm using the Serial library:
At the moment I'm just trying to ping a couple of uint16 values back and forth as binary values. This mostly works. Sometimes the two data streams get a byte off, and so the decoded ints are incorrect. That's fine, I can add some sort of syncronisation at the start.
My main problem though is that it'll start off correct and both ends are displaying a decoded value correctly. But after a little while (30s-2mins) the values will end up being incorrect, and it looks like a byte has been dropped somehow. Often more bytes will get dropped randomly and it'll phase in and out of sync over time.
So, questions:
Is there anything obviously wrong with the code above?
I've been treating serial comms like TCP in terms of a reliable, in-order stream. Is this a correct assumption?
I seem to get more reliable comms when I add arbitrary sleeps to both ends, but this feels like a hack and still doesn't get to 100% efficient. Is there manual syncronisation I should be adding?
I read that the Serial library only has a 64 byte buffer for input/output, so I wanted to use Serial.availableForWrite() but I get a compile error that this function doesn't exist. I can't see a way to update the Serial library in linux, is this possible?
(NB: I don't have the Arduino Serial Monitor open, as this seems to really mess with usb traffic).
Don't use links to external sites to post code. Use code tags and post the code to this forum!
Is there anything obviously wrong with the code above?
There is no synchronization. In a serial transfer you should be prepared to loose some bits or bytes. The Arduino is sending it's bytes as fast as possible, the internal buffer will fill up quite fast. Usually it will just block until the corresponding interrupt frees some space in the buffer. Under special circumstances this may fail and your code doesn't check for it and doesn't try to re-synchronize.
I've been treating serial comms like TCP in terms of a reliable, in-order stream. Is this a correct assumption?
No, TCP has special checksums to check for transmission errors and packet numbering to check for missing packets. Standard serial communication does neither of it and has to be used more like a UDP communication.
I seem to get more reliable comms when I add arbitrary sleeps to both ends, but this feels like a hack and still doesn't get to 100% efficient. Is there manual syncronisation I should be adding?
There are several ways to make your communication more reliable. I don't know what you mean by manual synchronization but you should establish some protocol to check for a reliable transmission, maybe you have to even retransmit some data if you need that feature.
I read that the Serial library only has a 64 byte buffer for input/output, so I wanted to use Serial.availableForWrite() but I get a compile error that this function doesn't exist. I can't see a way to update the Serial library in linux, is this possible?
What version of the IDE are you using? What version of the AVR core are you using?
Thanks both - looks like I had some incorrect assumptions about reliability. Interesting to compare it to udp - udp at least guarantees that a packet is valid if it's received, the serial port seems to have even less guarantees than that.
I've got a protocol designed now, so just need to actually code it up and see what the %age drop rate is actually like.