Send data to arduino from PC in java over Serial (RXTXlib)

Hi everyone,
I am intending to parse an excel file in my pc and send the data to my arduino.
As a beginning I'm trying to send one character "1" and when Arduino receives "1" it turns on the led 13.
My problem for now is that my java program sends the data to arduino and I can see the RX TX leds blinking but the led 13 doesn't turn on as I told my arduino. So I suppose that Arduino receives the char "1" but it doesn't understand it. There is probably a format/type problem.
Here is the java part that sends the char s which is actually a string converted to bytes then sent to arduino :

public static void main(String[] args) throws IOException, PortInUseException, NoSuchPortException{
        SerialPortHandler serial = new SerialPortHandler();
        serial.connect("COM2");
        OutputStream serialOut = serial.getSerialOutputStream();
        String s = "1";
        serialOut.write(s.getBytes());
	serialOut.flush();
	serial.disconnect();
 }

And here is the Arduino code which works fine on the serial monitor.

char byteRead;
int led = 13 ;
void setup() {
      Serial.begin(9600);
      pinMode(led, OUTPUT);           
}
void loop() {
     if (Serial.available()) {
            delay(100);
            while (Serial.available()){
                byteRead = Serial.read();
                if (byteRead == '1'){
                   digitalWrite(led, HIGH);
                } 
             }
          }
         delay(1000);
}

I also tried to get the data in an int and used serial.parseInt and nothing worked.
Help please :~

It's always a good idea to find out what if happening before using IF tests that depend on the data.

Can you add to your Java program (or write a short new program) so that it can act as a serial monitor to show the data received from the Arduino? The just get the Arduino program to echo back every character it receives. That way you can see what the communication is actually doing.

I don't like Java but I use JRuby on my Linux PC. I wrote a program to communicate between a PC and an Arduino in this Thread. The main example is in Python but in one of the Posts I included the JRuby code - which was actually written before the Python code.

As far as I can see RxTx seems to have disappeared from the web and JSSC is the current equivalent.

...R

Open the port, resetting the Arduino. While it is rebooting, send it some data. Then, close the port, resetting the Arduino again. Then, expect the Arduino to do something with the serial data. Is it any wonder why it doesn't?

@PaulS is correct - I hadn't spotted that.

When the PC program opens the Serial port the Arduino resets - which takes a few seconds. Your Java program must leave the Serial port open all the time it is in communication with the Arduino and it must allow time for the Arduino to reset after opening the Serial port.

...R

Maybe you have to wait for a while after open connection. Insert in the Java application a sleep and then send your data. If you aren't interested in programming connection but you want just to control arduino from java you can try my library.

www.ardulink.org

I suggest you to see this tutorial.

After Link class is retrieved you can send to Arduino all the data you need.

I belive that you solved this by now, but still:

The type returned by Serial.read() is an int which is an decimal equivalent of a character - character '1' is 49. You must thus convert that int to a char to check the condition like that:

int led = 13 ;
char charRead;
void setup() {
      Serial.begin(9600);
      pinMode(led, OUTPUT);           
}
void loop() {
     if(Serial.available()>0) {
            delay(100);
            while(Serial.available()>0){
              charRead = char(Serial.read());
              if(charRead=='1'){
                digitalWrite(led,1);
              }
             }
          }
         delay(1000);
}

You could also just check the int if you do not want to convert to a char

int intRead = Serial.read();
if(intRead==49){...}

Yes, I agree.

In my sketches I use the cast statement in this way:

/*
  SerialEvent occurs whenever a new data comes in the
 hardware serial RX.  This routine is run between each
 time loop() runs, so using delay inside loop can delay
 response.  Multiple bytes of data may be available.
 This is general code you can reuse.
 */
void serialEvent() {
    
  while (Serial.available() && !stringComplete) {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the inputString:
    inputString += inChar;
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == '\n') {
      stringComplete = true;
    }
  }
}

This is the row you are interested in: char inChar = (char)Serial.read();

Note: serialEvent works with Arduino UNO but not with Leonardo or Micro. If you use Leo or Micro you should move this code into loop() func.

www.ardulink.org

I don't like serialEvent(). The documentation is almost non-existent. What triggers it? What stops it being triggered if you don't want it?

Just use "if (Serial.available > 0) { }"

...R

Thank you guys for all your answers :slight_smile: I haven't solved my problem yet as I had another part to develop in my project.
Now, I'm back and I tried to send back the data received by arduino to java to show what it really receives.
I also added a sleep after serial.connect .

public static void main(String[] args) throws IOException, PortInUseException, NoSuchPortException{
        SerialPortHandler serial = new SerialPortHandler();
        serial.connect("COM2");
        OutputStream serialOut = serial.getSerialOutputStream();
        InputStream serialIn=serial.getSerialInputStream();
        try {
			Thread.sleep(200);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        String s = "1";
        byte[] b=new byte[5];
        for (int i = 0 ; i<10; i++){
                System.out.println("write " +i%2);
        	if(i%2==0)
        		serialOut.write(1);
        	else
        		serialOut.write(0);
        	serialOut.flush();

       		try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
        	serialIn.read(b);
        	System.out.print("Reçu ");
        	for (int j = 0; j < b.length; j++) {
				System.out.print(b[j]+ " ");
			}
        	System.out.println();
        	try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

        }  
        serial.disconnect();
    }

In my arduino code, I changed the control sequence and I used ascii code instead of the char itself :

int byteRead;
int led = 13 ;
void setup() {
      Serial.begin(9600);
      pinMode(led, OUTPUT);     
}
void loop() {
     if (Serial.available()) {
            delay(100);
            while (Serial.available()){
                byteRead = Serial.read();
                switch(byteRead){
                case 49:
                   digitalWrite(led, HIGH);
                   break;
                case 0:
                  digitalWrite(led, LOW);
                   break;
                default:
                  break;
            }  
        Serial.write(byteRead);     
      }
     }
delay(500);
}

That's what I receive in the java console :
write 0
Reçu 0 0 0 0 0
write 1
Reçu 0 0 0 0 0
write 0
Reçu 0 0 0 0 0
write 1
Reçu 0 0 0 0 0
and the led doesn't blink of course.
when I insert the serial.write into the case process :

case 49:
                   digitalWrite(led, HIGH);
                   serial.write(byteRead)
                   break;

the java program shows :
Reçu -32 1 1 1 1
I don't really know what does -32 stand for.

Does your Arduino program work correctly when interfaced with the Serial Monitor rather than your Java code? If not I suggest you write a sketch that does work with the Serial monitor and then get your Java program to interface with that Arduino sketch. That way you have only one area of uncertainty.

The -32 reminds me that I think Java bytes are usually (always?) signed - and they are never signed on the Arduino. So -32 would have the same binary representation as +178. I came across this while using JRuby so I don't know how to deal with the issue in Java. Or there may be a totally different explanation.

Why do you have try/catch surrounding the sleep commands? Is that essential? An error seems unlikely.

What exactly does "serialIn.read(b);" do? (to save me researching the Java documentation - perhaos you have a link).

...R

                switch(byteRead){
                case 49:
                   digitalWrite(led, HIGH);
                   break;
                case 0:
                  digitalWrite(led, LOW);
                   break;
                default:
                  break;
              Serial.write(byteRead);
             }

The Serial.write() call after the break statement is pretty useless, don't you think?

Perhaps NOW you can see why we ask you to put every { on a new line, and use Tools + Auto Format.

The Serial.write() statement goes AFTER the }.

use Tools + Auto Format.
The Serial.write() statement goes AFTER the }.

Definitely serial.write should be after the " } " it's a typo when editing the post. and thank you for the auto format tip I like it :wink:
I think there are a problem with the unsigned and signed bytes.
Now I tried with a very simple arduino program :

char byteRead;
int led = 13 ;
void setup() {
  Serial.begin(9600);
  pinMode(led, OUTPUT);     

}

void loop() {
  if (Serial.available()) {

    byteRead = Serial.read();
    Serial.write(byteRead);
  }

}

and a simpler java code

public static void main(String[] args) throws IOException, PortInUseException, NoSuchPortException, InterruptedException{
        SerialPortHandler serial = new SerialPortHandler();
        serial.connect("COM2");
        Thread.sleep(3000);
		OutputStream serialOut = serial.getSerialOutputStream();
        InputStream serialIn=serial.getSerialInputStream();
        String s = "1";
        byte[] b=new byte[] {0,0,0,0} ;
        serialOut.write(s.getBytes());
        serialOut.flush();
        Thread.sleep(1000);
        serialIn.read(b);
        System.out.print("Reçu ");
    	for (int j = 0; j < b.length; j++) {
			System.out.print(b[j]+ " ");
		}
    	System.out.println();
    	b[0]=0 ;
    	b[1]=0;
    	b[2]=0;
    	b[3]=0;
    	
        serial.disconnect();
    }
}

I keep receiving the same result -32 0 0 0 0 with any caracter that I send.
All my arduino codes work fine on the serial monitor.

serialIn.read(b);

serialIn.read(b) reads data from the SerialInputStream and put them in b which is a byte array.
I tried so many codes until now and I also having the same output : -32 which is 224 in decimal.
Can anyone help me check if my data types are correct ?

I repeat ...

Does your Arduino program work properly with the Arduino Serial Monitor ??

A simple question.

If the answer is NO then you are wasting your own time as well as ours.

...R

I already said:

All my arduino codes work fine on the serial monitor.

It means I always test on the serial monitor before testing with the java program :slight_smile:
Since I couldn't solve the problem I turned to JSSC library which is quite similar to RXTX.
Now it works fine and I can command arduino from java. That's the code for java :

import jssc.SerialPort;
import jssc.SerialPortException;

/**
 *
 * @author scream3r
 */
public class Write {

    /**
     * @param args the command line arguments
     * @throws InterruptedException 
     */
    public static void main(String[] args) throws InterruptedException {
        SerialPort serialPort = new SerialPort("COM2");
        try {
            System.out.println("Port opened: " + serialPort.openPort());
            System.out.println("Params setted: " + serialPort.setParams(9600, 8, 1, 0));
            Thread.sleep(3000);
            for (int i = 0; i<10; i++){
            	if (i%2 == 0){
            		System.out.println("\"Hello World!!!\" successfully writen to port: " + serialPort.writeBytes("1".getBytes()));
            	}
            	else {
            		System.out.println("\"Hello World!!!\" successfully writen to port: " + serialPort.writeBytes("0".getBytes()));
            	}
            	Thread.sleep(1000);
            }
            System.out.println("Port closed: " + serialPort.closePort());
        }
        catch (SerialPortException ex){
            System.out.println(ex);
        }
    }
}

And that's the Arduino code :

int r ;
int led = 13 ;
void setup(){
  Serial.begin(9600);
  pinMode(led, OUTPUT);
}
void loop(){
  if (Serial.available()){
    r = Serial.read() ;
    if (r == 49){
      digitalWrite(led, HIGH);
    }
    else {
      digitalWrite(led, LOW);
    }
  }
}

Thank you all for your help :slight_smile:

    if (r == 49){

How do you know what to send to get a 49?

    if (r == '1'){

How do You know what to send to get a '1'?

Which is easier to know?

I started using JSSC recently with JRuby and it seems easier to use then RXTX - which seems to have disappeared from the web.

But I don't think I have anything that doesn't work with RXTX.

...R

The RXTXComm library works just fine. I used is just recently and I got bidirecional communication between my Java program and my arduino board. There are a few thing to watch out for, but i will not post because the author of the thread seems to have got what he wants and the post would be rather long to write. Besides, i just joined this forum, but i am sure there must be a working example here on using RXTXComm jar.

If someone is interested, i will post the info thou ...