I'm working on an Arduino -> Scala/Java bridge and am having some issues with serial communication. Right now I have an extremely simple command protocol that will fail upon disordered data.
Any suggestions on what I can use just for the communication? Looking for something like a very primitive version of TCP that works over serial and protects data integrity.
And just for kicks here's how it works (this is all working now perfectly besides the data transfer issues) in Scala code. I'll probably put it out open source. This is a Scala class that listens to a number of input pins and sends out appropriate responses and issues commands directly on the computer it runs on.
val arduino = Arduino("/dev/ttyACM4", 115200, 1000)
// Create LED Pin Objects
val statusLed = arduino.out(3)
val waitingLed = arduino.out(4)
val errorLed = arduino.out(5)
waitingLed.on
// TODO: Initialize Music Player
waitingLed.off
// Create Music Control Pin Objects
val play = arduino.in(11)
play.listenOn {
if (isDay()) {
execute("amixer set \"Master\" toggle")
}
}
val volume = arduino.in(12)
volume.attachInterrupt(InterruptType.Change)
volume.listenAnalogBelow(127) {
// Unmute
// Change Volume
errorLed.off
}
volume.listenAnalogAbove(128) {
errorLed.on
}
val mute = arduino.in(10)
mute.listenOn(execute("amixer set \"Master\" toggle"))
The way it works is that these "listeners" are sent to the arduino with identifiers, the arduino checks the appropriate pins in the loop. If and only if the input from that pin has changed from its previous value, a notification is sent back to the computer which triggers the listener function.
It works with interrupts as well, exactly the same except it uses Arduino's interrupt mechanism and does not check within the loop.
I read your whole post, twice, to make sure I didn't miss anything. I don't understand the question, I guess. Where does the "disordered data" originate? The Arduino or the PC?
What, exactly, does that code cause the Arduino object to send to the serial port? Where is the Arduino code that handles the data that the Arduino object sends?
tk26:
Any suggestions on what I can use just for the communication? Looking for something like a very primitive version of TCP that works over serial and protects data integrity.
Those are pretty sketchy requirements and nowhere near enough information to design a protocol, but it sounds to me as if your problem is essentially how to detect complete and valid message frames out of a byte stream. You could achieve that by defining start/end flags to denote your message boundary, define a message structure that incorporates a checksum, and if your start/end flags could legitimately appear within the message then also provide a mechanism to escape them.
PaulS:
I read your whole post, twice, to make sure I didn't miss anything. I don't understand the question, I guess. Where does the "disordered data" originate? The Arduino or the PC?
It could originate from either side, my point is I'm looking for a bit more reliability than just hoping that all of the data sent from PC -> Arduino or Arduino -> PC gets to the other side.
It probably wouldn't be disordered (sending is synchronized on the Scala side), but I could see a byte missing here and there.
PaulS:
What, exactly, does that code cause the Arduino object to send to the serial port? Where is the Arduino code that handles the data that the Arduino object sends?
There are about 9 commands, each with an integer identifier and a couple bytes of data along with them. The arduino gets them, looks at the first 2 bytes, and uses that to identify the command.
Commands are setMode, digitalWrite, digitalRead, etc. Basically the same as the Arduino's C++ functions.
PeterH:
Those are pretty sketchy requirements and nowhere near enough information to design a protocol, but it sounds to me as if your problem is essentially how to detect complete and valid message frames out of a byte stream. You could achieve that by defining start/end flags to denote your message boundary, define a message structure that incorporates a checksum, and if your start/end flags could legitimately appear within the message then also provide a mechanism to escape them.
I don't need anything fancy, just the most basic packet protocol.
I just went ahead and threw a very basic one together with a start/length/checksum.
I asked because if the data is binary (and can therefore be any value) there's no way I know of to reliably detect a start of frame by just looking at received bytes.
Graynomad:
I asked because if the data is binary (and can therefore be any value) there's no way I know of to reliably detect a start of frame by just looking at received bytes.
Oh yeah of course it's impossible to know 100%, but being a 1 in 255 chance plus the checksum and other marker bytes, it's pretty safe.
Graynomad:
length (2 byte int)
Expecting a lot of data
Hey if they had made IP addresses more than 32 bits back in the day I wouldn't be paying 2 bucks a month for every site that uses SSL.
Extra byte, I figured why not (the alternative is 255 bytes). Even though the largest command I'll send here is 9 bytes.
primitive version of TCP that works over serial and protects data integrity.
Primitive and protects data integrity don't really go together well.
At the very least, you'll need a start and end of packet marker that is unique, ie the rest of the data cannot duplicate these markers, which adds a layer of complication itself when dealing with binary data, and a checksum for the actual contents of the data packet.
You'll also have to decide how you want to handle the cases where the packet is compromised as well. You don't really have complete data integrity if you just ignore corrupted packets. The typical method of handling this is with some sort of Ack/Nak protocol. If data transmission isn't bandwidth constrained, a rather simple approach to implementing an Ack/Nak would be:
Sender transmits packet, and waits for an Ack or a Nak.
If no Ack/Nak is received within some timeout period, or a Nak is received, packet is retransmitted and Sender again waits for Ack/Nak.
If Ack is received, next packet is transmitted.
On the receiver side, if a valid packet is received, send an Ack, if a corrupted packet is detected, then send a Nak. Your corrupted packet detection will need to be fairly good for this to work well. For the most part, you just want to be able to detect missing start and end packet markers and verify checksum. Other potential data integrity checks would be a sequence number and/or packet length value added to the packet as well.