Search code examples
javamacosserial-portarduinorxtx

Arduino crashes when sending bytes from Java


I used the sample program from the arduino website in order to send and receive data via serial to my Arduino one. However, for some reason, even when I try to send only one byte, the Arduino crashes after a while. It doesn't happen if I send the chars manually via the IDE's own serial monitor.

I wrote the following method to output the character to Arduino:

public synchronized void serialWrite(char sendIt){
    try {
            output.write((byte)'0');
            output.flush();
            for (int j=0;j<1000000000;j++){
            }
        }catch (Exception e){System.out.println("Not connected...");}
    notify();
}

What I try above is to send just one character when the method is called. I send just a '0' char for testing. After manually calling the method two or three times, Arduino crashes. Is there anything I should be looking into?

The Arduino code:

#include <SoftwareSerial.h>
int buttonState=0;
int lastButtonState=0;
int buttonPushCounter=0;
long previousMillis=0;
long interval=250;
int ledState=LOW;
int ledState2=LOW;
int ledState3=LOW;
long timeElapsed=0;
SoftwareSerial portOne(10,11);

void setup(){
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(2,INPUT); 
  Serial.begin(9600);
  portOne.begin(9600);

}

boolean turnoff; 

void loop(){

  if(portOne.overflow()){
    Serial.println("There's an overflow here!");
  }
  buttonState= digitalRead(2);

  if(buttonState!=lastButtonState){
    if (buttonState==HIGH){
      buttonPushCounter++;
    }
  }
  lastButtonState=buttonState;

  if (turnoff){
    unsigned long currentMillis=millis();

    if (currentMillis-previousMillis>0 && currentMillis-previousMillis<interval){
     ledState=HIGH;
     ledState2=LOW;
     ledState3=LOW;
  }else
     if (currentMillis-previousMillis>interval && currentMillis-previousMillis<interval*2){

     ledState=LOW;
     ledState2=LOW;
     ledState3=HIGH;
  }else
     if (currentMillis-previousMillis>interval*2 && currentMillis-previousMillis<interval*3){

     ledState=LOW;
     ledState2=HIGH;
     ledState3=LOW;
  }else if (currentMillis-previousMillis>interval*3){
    previousMillis=currentMillis;  
  }

    digitalWrite(3,ledState);
   digitalWrite(4,ledState2);
   digitalWrite(5,ledState3);
  }else{
   digitalWrite(3,LOW);
   digitalWrite(4,LOW);
   digitalWrite(5,LOW);

  }


   if (buttonPushCounter==1){
     Serial.print("Button pressed!\n");
    turnoff=!turnoff;
    buttonPushCounter=0;

   }

   noInterrupts();
   char ch=Serial.read();

   delay(1);
   if(ch=='0'){

     Serial.println("Changed by serial"+turnoff);
     Serial.println(ch);
     turnoff=!turnoff;
   } 
   interrupts();


}

The part of the java program that was reading the serial interface was this:

public synchronized void serialEvent(SerialPortEvent oEvent) {
    if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
        try {
            String inputLine=input.readLine();
            System.out.println(inputLine);
        } catch (Exception e) {
            System.err.println(e.toString());
        }
    }
    // Ignore all the other eventTypes, but you should consider the other ones.
}

Solution

  • Your Arduino code is sending data back over the serial connection, but you're not reading it from your Java program. It doesn't take long for the various buffers to fill up, and then the Arduino is waiting for you to unblock them.

    You need to be reading the output from the serial port and doing something with it. I suggest running a background thread that blocks on reading the serial port and just writes the character to System.out and flushes whenever it receives one.