1
votes

How do I get the following int to a byte array. I have been reading other SO questions and everything is confusing, could someone explian what is happening in the code.

int val = 1023; // the int will vary from 0 to 1023 (it's the analogRead value from an Arduino board)

the purpose of me wanting this as a byte array is so that i can use it for Arduino's server.write().

This is what I've come up with so far:

  int val = analogRead(A0);
  Serial.println(val);
  byte value[2];
  value[1] = val & 0x000000ff;
  value[0] = (val & 0x0000ff00) >> 8;
  server.write(value[0]);
  server.write(value[1]);

I am trying to communicate TCP with an Android application I have written, here is the recieving end:

mmInStream = mmSocket.getInputStream();
final byte[] buffer = new byte[16384]; // two bytes
int bytes;
bytes = mmInStream.read(buffer);
Log.d(null,buffer[0]+buffer[1]);

is this correct?

The Arduino console is spitting out the values, example:

870
870
870
872

However my Android application is spitting out the following, example:

3102
3105
1033
1035

I must be doing something wrong here!

ANSWER: Arduino sends unsigned bytes, java recieves only signed bytes. I fixed it with a little code on the java end.

2
Yes that's fine and a good way of doing things. You can drop the leading zeroes from your hex constants. - M.M
@MattMcNabb However, since he's dealing with a 4-byte int, it certainly makes it clear which bytes he's working with. Personally, I like it with the leading zeros - it shows the full width. - Jonathon Reinhart
does the line Log.d(null,buffer[0]+buffer[1]); convert buffer[0] to string first? If not, you're adding the bytes together, messing the result - phuclv

2 Answers

1
votes

Whenever you're going to be dealing with some binary communications protocol, be it a TCP connection, Serial Port, USB, etc. you need to save yourself some future headaches and define your protocol.

Specifically, this means field widths, and byte order. When sending binary data over a network protocol, we almost always send it in "network order", which is "big-endian", meaning the most-significant byte first.

Example: I want to send a four-byte int a = 0x12345678 over the network. If you do it correctly, the bytes go out in the order 12 34 56 78.

However, I believe your ATMEGA chip is little-endian, which means that bytes are stored (in memory) with the least-significant byte first. So if you were to just cast that int to a unsigned char* and send 4 bytes, they would go out in the order 78 56 34 12.

So in order to send that value out, you should first decide how many bytes it's going to be. Since you've limited it to the range 0 - 1023, you've observed that it will fit into just two bytes. Good. So your protocol is:

Offset 0:  value   Size: 2

Now, you need to send it in network order. Your example code:

byte value [2];
value[1] = val & 0x000000ff;
value[0] = (val & 0x0000ff00) >> 8;

is putting the most significant byte at position 0, and the least significant byte at position 1. So a value of 0x1234 will go out in the order 12 34. Perfect.

Your code is correct (on the Arduino side).


Now, on the receiving side, you need to make sure that you're receiving data in network order also. I haven't done any Java network programming, so you'll need to check with the documentation to see how it handles network binary streams. In particular, when you go to read that "16-bit unsigned integer" from the network, the byte order needs to be respected.

Perhaps this will help you on the Java side:

0
votes

This will encode an int as a byte array.

// Encoding
byte value[2] = { highByte(val), lowByte(val) };

This will convert a byte array back to an integer

// Decoding
int val = value[0] << 8 + value[1];