Send Integers From Ardunio to Java Program Using Serial Port

I want to send integer values from my Arduino to a java application. To do so I am using a serial port. In the processing program for the Arduino I am printing the following to the serial port:

Serial.print(accel, DEC)

Accel is a signed int. In my java code I am implementing a SerialPortEventListener and I am reading an array of bytes from the inputstream input.

    public synchronized void serialEvent(SerialPortEvent oEvent) {
        if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
        try {
            int available = input.available();
            byte[] chunk = new byte[available];
            input.read(chunk);
            System.out.println (new String(chunk));
           } catch (Exception e) {
            System.err.println(e.toString());
        }
    }
}

I need to convert this array of bytes into integers, but I am not sure how to do this. This Arduino tutorial (Arduino Tutorial - Lesson 4 - Serial communication and playing with data) says that the Arduino stores signed ints in 2 bytes (16 bits). I have tried reading just 2 bytes of data into array chunk and then decoding those two bytes into integer with the following code.

    public synchronized void serialEvent(SerialPortEvent oEvent) {
    if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
        try {
            int available = input.available();
            int n = 2;
            byte[] chunk = new byte[n];
            input.read(chunk);
            int value = 0;
            value |= chunk[0] & 0xFF;
            value <<= 8;
            value |= chunk[1] & 0xFF;
            System.out.println (new String(chunk));
          System.out.println(value);
        } catch (Exception e) {
            System.err.println(e.toString());
        }
    }
}

This should print out a stream of integers fluctuating between -512 and -516 but it doesn’t. The code prints out the following :
-5
2949173
12
3211314

851978
-5
2949173
12
3211314

851978 -5 2949173 12 3211314

Can someone please help me decode the bytes coming from the Arduino through the serial port to integers? Thanks.

The Serial.print() function on the Arduino is converting the value to a string, and sending the string to the serial port.

int val = 199;
Serial.print(val, DEC);

results in the characters '1', '9', and '9' being sent to the serial port.

You need to collect the values on the other end, as a string, and convert the string to an int (atoi() works great for that).

The bit shifting stuff you are doing now is completely wrong.

Thanks for the information. This helps a lot. Do you know if there is an Arduino function that posts integers or doubles to the serial port? Or can the Arduino only post strings to the serial port?

Do you know if there is an Arduino function that posts integers or doubles to the serial port? Or can the Arduino only post strings to the serial port?

It takes some effort to send integers and doubles to the serial port as a collection of bytes, rather than strings. The easiest way is to define a union of a double or int and an array of bytes of the same size. Create an instance of the union, set the integer or double, and Serial.write() the matching byte array.

PaulS:
It takes some effort to send integers and doubles to the serial port as a collection of bytes, rather than strings. The easiest way is to define a union of a double or int and an array of bytes of the same size. Create an instance of the union, set the integer or double, and Serial.write() the matching byte array.

Ok, I want to try this. What do you mean by "defining a union of a double or int and an array of bytes of the same size". Is the union the bit shifting that creates an int into a byte array? So when you get an int (or double) you then perform a function and create an byte array that represents that int?

Start here. Learn about unions.

Then create a union what contains a float and a byte array:

union
{
  float f;
  byte b[4];
} u;

To write a float:

u.f = valueToSend;
Serial.write(u.b, 4);

This will require that you reassemble the bytes in the same order on the other end. Read 4 bytes, storing them in u.b[0], u.b[1], u.b[2], and u.b[4]. Then use u.f for whatever.

So I read the information you sent me on unions. One question, the website on unions says, "the data in the unused fields is just garbage. This happens because different types are treated differently by the computer. So if one type is set, the memory is not going to be in the format of the other types." If this is true then does just setting the float to the valueToSend fill in the byte array correctly?

Also in my java program at the other end I am reading a byte array of 4 bytes from the serial port. When I try to convert the byte array to a integer I don't get the correct values. (In the sketch I changed the float f to int i in the union.) I've tried using the ByteBuffer to convert the byte array to integer and the following method:

int n = 4;
byte[] chunk = new byte[n];
input.read(chunk);
int value = 0;
for (int i = 0; i < chunk.length; i++){
	value += (chunk[i] & 0xff) << (4 * i);
}

You said to read 4 bytes (which I am doing) and to store them in u.b[0], u.b[1], u.b[2], and u.b[4]. How can I store in u.b when I am reading in a java program? Am I not storing the bytes correctly? Is this what is causing the bit shift problem?

the data in the unused fields is just garbage.

This would be true if everything in the union was not the same size. If, for instance, you created one union to handle floats and integers, it would look like this:
union
{
int i;
float f;
byte b[4];
} u;
Now, if you set i, b[0] and b[1] have valid values, but f, b[2], and b[3] do not.

By creating a float union and an integer union, you can assure that there are no unused fields.

Also in my java program at the other end I am reading a byte array of 4 bytes from the serial port. When I try to convert the byte array to a integer I don't get the correct values.

That is because an int, in the Arduino world, is two bytes.

How can I store in u.b when I am reading in a java program?

Good question. Your bit shifting approach will certainly work for ints (when you perform it the correct number of times). I'm not sure if it will work for floats. Be sure to let us know.

The code is giving me the correct int output now. Thank you so much for walking me through this. My Arduino sketch is coded like this:

union{
  int i;
  byte b[2];
}u;
u.i = accel;
Serial.write(u.b, 2);

My java code for reading the byte array and converting it to an int looks like this:

int n = 2;
byte[] chunk = new byte[n];
input.read(chunk);
short value = 0;
// get 2 bytes, unsigned 0..255
int low = chunk[0] & 0xff;
int high = chunk[1] & 0xff;
value =  (short) (high << 8 | low) ;
System.out.println(value);

I am working on converting a 4 byte array to a float, but this is proving tricky. If I find a bit shifting technique that works for floats I will post it. Thanks again for your help.

I don't know if the operator precedence in Java is the same as in C, but the bit shift operator has low precedence. It might be necessary to use parentheses to ensure that the right value is used in the shift operation.
value = (short) ((high << 8) | low) ;

Thanks, I put those parentheses just to be safe. :slight_smile:

Hello! Can you give me this java code

Jason_123456:
Hello! Can you give me this java code

When a poster's name appears as black type it means they are no longer a member of the Forum. I any case this thread has been dead for 7 years.

...R