12

I'm trying to communicate between my PC (Windows 7 using Netbeans and RXTX) with an Arduino Pro, using the serial port. The Arduino is actually connected to the PC using an FTDI cable.

The code is based on the Java SimpleRead.Java found here.

Currently the Arduino simply prints out a string when it starts up. My Java program should print the number of bytes that have been read and then print out the contents. The Java program works, sort of...

If the string is long (>10 bytes or so) the output will get broken up.

So if on the Arduino I print

Serial.println("123456789123456789"); //20 bytes including '\r' and '\n'

The output of my Java program may look something like:

Number of Bytes: 15   
1234567891234  
Number of Bytes: 5  
56789

or

Number of Bytes: 12   
1234567891  
Number of Bytes: 8  
23456789

I'm thinking it's a timing problem, because when I manually go through the code using the debugger, the result string is always what it should be: one 20 byte string.

I've been messing with various things but I haven't been able to fix the problem.

Here is the part of the code that is giving me problems:

static int baudrate = 9600,
           dataBits = SerialPort.DATABITS_8,
           stopBits = SerialPort.STOPBITS_1,
           parity   = SerialPort.PARITY_NONE;    

byte[] readBuffer = new byte[128];

...
...

public void serialEvent(SerialPortEvent event)
{
   if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) {

    try {
        if (input.available() > 0) { 
            //Read the InputStream and return the number of bytes read
            numBytes = input.read(readBuffer);

            String result  = new String(readBuffer,0,numBytes);
            System.out.println("Number of Bytes: " + numBytes);
            System.out.println(result);
        }
    } catch (IOException e) {
        System.out.println("Data Available Exception");
    }
}
dsolimano
  • 8,870
  • 3
  • 48
  • 63
SharpBarb
  • 1,590
  • 3
  • 16
  • 40

3 Answers3

7

Serial data is just a stream of data. Depending on when you read it and the buffering that is happening, only part of the data may be available when you read it.

Since you are using line oriented data, what you will want to do is buffer the data until you see the line terminator and only then process the data.

Matthew Murdoch
  • 30,874
  • 30
  • 96
  • 127
R Samuel Klatchko
  • 74,869
  • 16
  • 134
  • 187
  • For some reason I assumed that data would be sent contiguously in a single stream. On the PC end, I only need to view the Serial output, so I don't think I will bother trying to store the complete incoming line and then display it. I think it I will just display the data byte-by-byte as it comes in. So I'll use aByte = input.read(); instead of input.read(readBuffer); Thanks – SharpBarb Jan 06 '10 at 15:54
  • @SharpBarb - no need to switch to reading a byte at a time. If you really want to do that, I'd recommend reading a buffer and then within your app just process each byte separately. – R Samuel Klatchko Jan 06 '10 at 20:34
3

I haven't used Java RXTX, but I've played with Arduino and Processing and it's pretty easy to read/write values from Arduino. Here is a read sample that comes with Processing(File > Examples > Libraries > Serial > SimpleRead)

/**
 * Simple Read
 * 
 * Read data from the serial port and change the color of a rectangle
 * when a switch connected to a Wiring or Arduino board is pressed and released.
 * This example works with the Wiring / Arduino program that follows below.
 */


import processing.serial.*;

Serial myPort;  // Create object from Serial class
int val;      // Data received from the serial port

void setup() 
{
  size(200, 200);
  // I know that the first port in the serial list on my mac
  // is always my  FTDI adaptor, so I open Serial.list()[0].
  // On Windows machines, this generally opens COM1.
  // Open whatever port is the one you're using.
  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, 9600);
}

void draw()
{
  if ( myPort.available() > 0) {  // If data is available,
    val = myPort.read();         // read it and store it in val
  }
  background(255);             // Set background to white
  if (val == 0) {              // If the serial value is 0,
    fill(0);                   // set fill to black
  } 
  else {                       // If the serial value is not 0,
    fill(204);                 // set fill to light gray
  }
  rect(50, 50, 100, 100);
}



/*

// Wiring / Arduino Code
// Code for sensing a switch status and writing the value to the serial port.

int switchPin = 4;                       // Switch connected to pin 4

void setup() {
  pinMode(switchPin, INPUT);             // Set pin 0 as an input
  Serial.begin(9600);                    // Start serial communication at 9600 bps
}

void loop() {
  if (digitalRead(switchPin) == HIGH) {  // If switch is ON,
    Serial.print(1, BYTE);               // send 1 to Processing
  } else {                               // If the switch is not ON,
    Serial.print(0, BYTE);               // send 0 to Processing
  }
  delay(100);                            // Wait 100 milliseconds
}

*/

As far as I remember, the baud thingy you setup in Arduino when you instantiate Serial is pretty important. If you use 9600 to send for example, you should use the same number to listen.

Also it's pretty important to send your information as BYTE, otherwise you'll have stuff like \r or \n in the way.

Shorter version, try:

Serial.println(123456789123456789,BYTE);

The simpler the better.

George Profenza
  • 50,687
  • 19
  • 144
  • 218
  • Hi , can processing work without Papplet? Because I try to integrate with my java code ... – wizztjh Dec 10 '10 at 12:25
  • Thanks for the reply , @geory let say I wanna get a analog input from arduino and the arduino will reply the analog value whenever I send some thing to arduino. According to the code in the link , It will just print out the thing instead of save it in a variable , How can i Store the chunck to a variable? Because the public synchronized void serialEvent can't return value , i think ... – wizztjh Dec 10 '10 at 14:41
  • 1
    @wizztjh This off the top of my head, but you have this bit of code: byte chunk[] = new byte[available]; input.read(chunk, 0, available); ...After that, the date is stored in byte, you should be able to make the chunk variable visible for the class, not just that block. If new need a String, you could create a class variable and sets it's value to be new String(chunk) after the input.read part. HTH – George Profenza Dec 10 '10 at 14:57
1

I think you need to use event driven design patterns to solve this problem. I highly recommend you to visit: http://www.whatisarduino.org/bin/Tutorials/Java+Serial+API+and+Arduino

yadoo86
  • 11
  • 1