Serial Communication in Java

Hello!

I'm trying to get a simple echo-program working on a arduino NG with java. I'm sending a string from my java program, and the arduino simply sends in back. My problem is that i seem to be getting loads of garbage data when receiving in my java program. I can see that almost all characters are returned, but the text is almost unreadable because of garbage characters showing up as "boxes".

When i use processing instead the reply is read perfectly and without error. I tried lowering the baud rate all the way down to 300, but that actually seems to be making my problem worse. The only thing i can think of is that some serial setting is different in my java program. It is set to use 8N1 standard, and both the arduino and the java program are set to 9600 baud at the moment.

Any suggestions?

My arduino code:

void setup() 
{ 
  Serial.begin(9600);
  
  
  // prints title with ending line break 
  Serial.println("Pinky's echo-program"); 

  // wait for the long string to be sent 
  delay(100); 
}

void loop() {
  byte incomingByte;

      // send data only when you receive data:
      if (Serial.available() > 0) {
            // read the incoming byte:
            incomingByte = Serial.read();

            // say what you got:
            Serial.print("I received: ");
            Serial.println(incomingByte, BYTE);
      }
}

I will post my java code in a new post because it won't fit in this one.

My java code:

// 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 nulltest 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 = "COM1";
      } else if (osname.startsWith("linux")) {
         // linux
        defaultPort = "/dev/ttyUSB0";
      } 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
               nulltest reader = new nulltest();
            } 
         } 
         
      } 
      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 nulltest()"

      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 nulltest() {
      // 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(result);
         } catch (IOException e) {}
   
         break;
      }
   } 

}

I have a fairly complete Java program. Take a look at http://www.opencircuits.com/BitWacker_Java_Communications

Try specifying a charset on the constructor of the String e.g. new String(readBuffer, "ASCII");

Maybe it helps?

Lee

I don't really know java, but from a brief look at your code - you might want to add a small delay between your DATA_AVAILABLE event being thrown and the actual reading of the data from the serial port. You need to allow time for all of the data to be read into the port's buffer before you read it, otherwise you'll be reading incomplete stuff, which will translate into those undisplayable ascii characters. I would guess this is why the problem seems to get worse when you try a lower baud rate - at this slower speed, even less of the data gets a chance to come in before you read the buffer. You won't need much of a delay, just experiment to find the lowest value that doesn't result in corruption for any given baud rate.

Hope this helps, Dan

Delay is one way to deal with the issue, another is to keep reading until the sender is done. Usually this is indicated with a special character, usually a carriage return You can learn more at: http://www.opencircuits.com/MC_RS232_Comm

Hello.I m trying to get data from Com4 which is connected to Atmel 8051 kit (via USB/rs232 converter). With this program that sent by @pinky , I can get value when the kit's mode is upload. But the problem is , when i try to get data on "execute mode", i cant get any value. The kit is connected to another circuit which is desinged with LM35 sensor and Adc0804 with P0 in order to get temparature value. The kit can get value if only works on execute mode.Does anyone has idea? why the program works like that?