I connected iPod with Arduino using serial (UART) connection. Arduino sends 0-1023 number (so it's two bytes) as it's samples light sensor value.

I'm asking about advice about simple and reliable communication protocol.

  1. Do I need magic constants to start/stop communication.
  2. Maybe I need sent data of small chunks.

Now I have:

while (1)
   data = getData() ; 
   // two bytes of 0-1024
   Serial.write((data) & 0xFF)) ; 
   Serial.write((data) & 0x300)) ; 

Any suggestion how to implement simple and reliable protocol ?

Image of my device: http://cl.ly/image/051f370v3e0g


  • I wonder if Protocol Buffers would work. protobuf-c is a c port. The official C++, Java, and Python versions (from Google) are here. – Brian Apr 19 '14 at 10:05
  • Arduino only has 2Kb RAM :/ – kesrut Apr 19 '14 at 11:17
  • How do you feel about Serial.writeln? I mean just digits 0-9 and a newline? It would be about 1000 numbers/second. – User Apr 19 '14 at 15:13

There are several reasons to have a protocol, even a very simple one.

  • Reduce risk of errors, perhaps when the device is connected, started, stopped
  • Allow for future expansion: perhaps the device sends two kinds of data in the future
  • Make sure you're reading from the right device and not something different.
  • Helps debugging if you can see a stream you can recognise.

There are some advantages in using ASCII chars, if you want to debug. I'll do it in binary, and include a length byte.

I would suggest a simple protocol of 6 bytes. Say:

Serial.write(0xc5); // start
Serial.write(0x06); // total length of packet
Serial.write(0x01); // 1=temperature data
Serial.write(data & 0xff); // low byte of data
Serial.write((data >> 8) & 0xff)); // high byte of data
Serial.write(0x5c); // end

Simple, easy to code, expandable. That would be my recommendation.

Here are some notes on my choices for these items.

  • The start byte (0xc5) is a distinctive bit pattern, relatively unlikely to occur by chance, in which half the bits are off and half on. That makes it relatively easy to find with debugging tools including an oscilloscope.
  • The end byte is the same reversed, for similar reasons.
  • Including the length is the simplest kind of check for framing errors or dropped bytes. If the start byte, end byte and length match the packet is probably valid.
  • The command byte of 0x01 allows room for expansion with future packet types. All packets should take the form c5,length,cmd,data...,5c.
  • The data is sent in little-endian format, which may be easier for some servers to read. Please note the correct use of shift-mask.

As suggested in a comment, the additional of a simple checksum would improve the likelihood of detecting errors over a noisy line. A simple rotating XOR should be sufficient, and easy to code.

  • This is good practical advice. Expanding on the "reduce risk of errors" a protocol starts to give you the ability to recover from a stream that got broken midway through. This protocol is very similar to ones I see used in embedded programming everyday. The one extra thing I might suggest is to potentially swap out the end byte of 0x5c for something like a mod 256 sum of the payload (if you can) as a sort of simple checksum or some other lightweight checksum. But that's totally optional and it's nice to be able to see 0x5C off the bat. – J Trana Apr 22 '14 at 4:50
  • My intention was to show something simple and easy to implement with visible benefits, based on practical experience. See edit. – david.pfx Apr 22 '14 at 9:58

Without doing research on the topic, I would suggest the following. So, can you rapidly send the the two bytes? If so, I would break down your code into base 512 from binary, and use the following numbers for special commands. Such as...

514 = New Data Stream DATA CHUNK DATA CHUNK DATA CHUNK DATA CHUNK ... 513 = Stop Data Stream

Then convert back to binary and deserialize into a memory stream or something. This would leave you with a vast amount of basic commands to communicate with such as

EVENT#1 - 600 EVENT_PARAMSTART = 550 Param Chunk #1 Param Chunk #2 EVENT PARAMSTOP = 551 EVENTEND = 599

Does that help or am I totally off base? XD

  • Could you explain the perceived benefit of using Base 512? The data comes in byte-by-byte so you could have start/stop/command fields allocated in specific bytes, so I'm not seeing the value in using base 512. What am I missing? – Dunk Apr 22 '14 at 15:47
  • @Dunk - On a hardware level, of course, it is byte by byte. But when you write a data to it, you are writing in single number base 1024 ( so to speak ), by breaking down your data into base 512, that means that any value passed to it greater than 511 would be considered a command, not data. Since 2^9 == 512, then you you can quickly and easily decode base 512 into binary and back just as easily you would for Hex. You could use base 1024, but that would require a more complex communication protocol that I don't have to explain since I am at work. Cheers. Ask your questions away. – Ruina Apr 22 '14 at 16:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.