Java/Arduino Serial Communication PROBLEMS!!!!!!!!

Hey guys,
I am working on building a quadcopter right now, with an Arduino Mega as the brain. I need to get the communication between it and the computer up and working before I can test it though, and I've been having some problems. I have two XBee radio antennas (one in the computer usb (COM15) and the other on the Arduino (Serial2)) which are successfully connected and communicating.

However, when I try to communicate using my Java program, the arduino sends back garbage data. Please help, as I have no idea what's going wrong.

Also, I realize the buffer size doesn't match the size of the char[] sent, but after changing each size many times, I haven't gotten any different results.

Java Program

package txrx;

// derived from SUN's examples in the javax.comm package
import java.io.*;
import java.util.*;
//import javax.comm.*; // for SUN's serial/parallel port libraries
import gnu.io.*; // for rxtxSerial library

public class Txrx implements Runnable, SerialPortEventListener {
   static CommPortIdentifier portId;
   static CommPortIdentifier saveportId;
   static Enumeration        portList;
   InputStream           inputStream;
   SerialPort           serialPort;
   Thread           readThread;

   static String        messageString = "Hello, world!";
   static OutputStream      outputStream;
   static boolean        outputBufferEmptyFlag = false;

   public static void main(String[] args) {
      boolean           portFound = false;
      String           defaultPort;
      
      // determine the name of the serial port on several operating systems
      String osname = System.getProperty("os.name","").toLowerCase();
      if ( osname.startsWith("windows") ) {
         // windows
         defaultPort = "COM15";
      } else if (osname.startsWith("linux")) {
         // linux
        defaultPort = "/dev/ttyS0";
      } else if ( osname.startsWith("mac") ) {
         // mac
         defaultPort = "????";
      } else {
         System.out.println("Sorry, your operating system is not supported");
         return;
      }
          
      if (args.length > 0) {
         defaultPort = args[0];
      } 

      System.out.println("Set default port to "+defaultPort);
      
            // parse ports and if the default port is found, initialized the reader
      portList = CommPortIdentifier.getPortIdentifiers();
      while (portList.hasMoreElements()) {
         portId = (CommPortIdentifier) portList.nextElement();
         if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
            if (portId.getName().equals(defaultPort)) {
               System.out.println("Found port: "+defaultPort);
               portFound = true;
               // init reader thread
               Txrx reader = new Txrx();
            } 
         } 
         
      } 
      if (!portFound) {
         System.out.println("port " + defaultPort + " not found.");
      } 
      
   } 

   public void initwritetoport() {
      // initwritetoport() assumes that the port has already been opened and
      //    initialized by "public Txrx()"

      try {
         // get the outputstream
         outputStream = serialPort.getOutputStream();
      } catch (IOException e) {}

      try {
         // activate the OUTPUT_BUFFER_EMPTY notifier
         serialPort.notifyOnOutputEmpty(true);
      } catch (Exception e) {
         System.out.println("Error setting event notification");
         System.out.println(e.toString());
         System.exit(-1);
      }
      
   }

   public void writetoport() {
      System.out.println("Writing \""+messageString+"\" to "+serialPort.getName());
      try {
         // write string to serial port
         outputStream.write(messageString.getBytes());
      } catch (IOException e) {}
   }

   public Txrx() {
      // initalize serial port
      try {
         serialPort = (SerialPort) portId.open("SimpleReadApp", 2000);
      } catch (PortInUseException e) {}
   
      try {
         inputStream = serialPort.getInputStream();
      } catch (IOException e) {}
   
      try {
         serialPort.addEventListener(this);
      } catch (TooManyListenersException e) {}
      
      // activate the DATA_AVAILABLE notifier
      serialPort.notifyOnDataAvailable(true);
   
      try {
         // set port parameters
         serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, 
                     SerialPort.STOPBITS_1, 
                     SerialPort.PARITY_NONE);
      } catch (UnsupportedCommOperationException e) {}
      
      // start the read thread
      readThread = new Thread(this);
      readThread.start();
      
   }

   public void run() {
      // first thing in the thread, we initialize the write operation
      initwritetoport();
      try {
         while (true) {
            // write string to port, the serialEvent will read it
            writetoport();
            Thread.sleep(1000);
         }
      } catch (InterruptedException e) {}
   } 

   public void serialEvent(SerialPortEvent event) {
      switch (event.getEventType()) {
      case SerialPortEvent.BI:
      case SerialPortEvent.OE:
      case SerialPortEvent.FE:
      case SerialPortEvent.PE:
      case SerialPortEvent.CD:
      case SerialPortEvent.CTS:
      case SerialPortEvent.DSR:
      case SerialPortEvent.RI:
      case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
         break;
      case SerialPortEvent.DATA_AVAILABLE:
         // we get here if data has been received
         byte[] readBuffer = new byte[20];
         try {
            // read data
            while (inputStream.available() > 0) {
               int numBytes = inputStream.read(readBuffer);
            } 
            // print data
            String result  = new String(readBuffer);
            System.out.println("Read: "+result);
         } catch (IOException e) {}
   
         break;
      }
   } 

}

Arduino Program

char serial[13];

void setup(){

  Serial2.begin(9600);
  
}

void loop(){
  
  if(Serial2.available()){
    
    for(int i = 0; i < 13; i ++){
      
      serial[i] = Serial2.read();
      
    }
    
    Serial2.println(serial);
    
  }
  
}

"Communication" (Output from Java Program)

run:
Set default port to COM15
Stable Library
=========================================
Native lib Version = RXTX-2.1-7
Java lib Version   = RXTX-2.1-7
Found port: COM15
Writing "Hello, world!" to //./COM15
Read: H[ch65533][ch65533][ch65533][ch65533][ch65533][ch65533][ch65533][ch65533][ch65533][ch65533][ch65533][ch65533]
e
Read: llo, world![ch65533]
Writing "Hello, world!" to //./COM15
Read: H[ch65533]
Read: [ch65533][ch65533][ch65533][ch65533][ch65533][ch65533][ch65533][ch65533][ch65533][ch65533][ch65533]
el
Read: lo, world![ch65533]
Writing "Hello, world!" to //./COM15
Read: H[ch65533][ch65533][ch65533]
Read: [ch65533][ch65533][ch65533][ch65533][ch65533][ch65533][ch65533][ch65533][ch65533]
ello
Read: , world![ch65533]

Writing "Hello, world!" to //./COM15
Read: H[ch65533][ch65533][ch65533][ch65533][ch65533][ch65533]
Read: [ch65533][ch65533][ch65533][ch65533][ch65533][ch65533]
ello, w
Read: orld![ch65533]

The output continues indefinitely in that fashion.

If you setup works ok using the serial monitor, then it must be a java issue. There is a free application on the net called Portmon that you can use to see what the differences are between what the serial monitor sends/receives compared to your java application.

Also, I've had slightly more success having the Arduino send it's own data, rather than reading and sending data, although it's still unpredictable garbage. It seems that precision is lost in sending as well as receiving.

            while (inputStream.available() > 0) {
               int numBytes = inputStream.read(readBuffer);
            }

The array readBuffer is filled with data read in from the serial port. It is not NULL terminated after each byte is added. The number of characters written into the buffer is stored in a variable that goes out of scope when the while loop ends.

            String result  = new String(readBuffer);
            System.out.println("Read: "+result);

All of the data in readBuffer, garbage after the characters that read put there as well as the characters that read put there, is now converted to a string.

This string should be NULL terminated at the appropriate point, but you don't know the appropriate point, because that variable is out of scope.

I'd suggest two things. First, the first bit of code should be an if statement, not a while statement. Second, the numBytes variable's scope should be changed, so that it is still in scope after the read operation, so that you can terminate the string at the appropriate place.

Or you could look at other read methods of the serial class. Perhaps there is a readUntil type function that will stop reading only when a specific character, like carriage return, is encountered.