Arduino Due and JavaFX Serial Communication

Hi All,

I hava a project I am working on using a Due, which communicates with a JavaFX application, running on a raspberry pi 3.

I am using the jSerialComm libray, which works quite well, and I am able to parse all my data, and basically send commands back to the Due..all works as expected once communication is established, but that is where it gets interesting:

-IF I connect the Due to the Rpi over its programming port (USB), once my JavaFX application starts, it resets the Due upon connection (I think it is supposed to behave that way), and communication starts, data is send to my JavaFX application...all is OK with the Universe....

However,

IF, I connect the Due to the Rpi over one of its other Serial ports (I am using Serial1 on the Due, found on pins 18/19, but same behavior for Serial2 or 3), I need to reset it, before any data is sent to my Jfx application....

Is there a way to have it behave the same, if I am not using the programming port? (Would like to reserve that just for programming). Since the Serial out of Serial1,2,3 is only a two wire (RX/TX) pair, not sure if anything could be done?

Is this expected behavior? What are some workarounds, to have the Due just send data, once the JFx application starts, without having to RESET it?

Would appreciate any guidance, as I have been searching the web for two days, and cant seem to find an answer to this, and I have read the Due documentation 10 times....

thank you all in advance....

cyborgcnc: Is there a way to have it behave the same,

You have not posted your program.

...R

Sorry about that…here is my JavaFX main Serial segment, parsing inbound data…

 @Override
    public void initialize(URL location, ResourceBundle resources) {

      //
       SerialPort comPort = SerialPort.getCommPort(("/dev/ttyAMA0"));
        comPort.setComPortParameters(57600, 8, 1,0);
        comPort.setComPortTimeouts(SerialPort.TIMEOUT_SCANNER, 5, 0);
        //
        try {
            if(comPort.isOpen())
                comPort.closePort();
            //
            //
            comPort.openPort();
            //
            serialOut = comPort.getOutputStream(); //For Sending Data out the Serial port....
           // serialOut.write("<,1,0,0,>".getBytes());
            serialOut.flush();

        }
        catch (Exception e) {statusLCD.setText("ERROR OPENING PORT");}

            comPort.addDataListener((new SerialPortDataListener() {

            Scanner inputData = new Scanner(comPort.getInputStream());


            @Override
            public int getListeningEvents() {
                return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;
            }

            @Override
            public void serialEvent(SerialPortEvent serialPortEvent) {
                if(serialPortEvent.getEventType() != SerialPort.LISTENING_EVENT_DATA_AVAILABLE)
                    return;
                try {
                    String nextString = inputData.nextLine();
                    if(nextString.startsWith("<<<<") && nextString.endsWith(">>>>")){
                        tunerData = nextString.split(",");
                        parseString(tunerData);
                      }
                }catch (IOError ex){statusLCD.setText("COMPORT ERROR!");}
                Platform.runLater(()-> setValues(Value1, Value2, Value3, Value4));
            }
        }));

Also, on my DUE, I am using a serial non-blocking way reading the data off the serial port coming FROM the Rpi, for commands and such…

void receiveData(){
  static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;
 
    while (HWSERIAL3.available() > 0 && newData == false) {
        rc = HWSERIAL3.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
            }
        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}
//
void rxtxData(){
  if (newData == true){
  strcpy(tempChars, receivedChars);
  parseData();
  newData = false;  
  }
}
//
void parseData(){
  char * strtokIndx;

  strtokIndx = strtok(tempChars, ",");
  Value1 = atof(strtokIndx);  

  strtokIndx = strtok(NULL, ",");
  Value2 = atof(strtokIndx); 

  strtokIndx = strtok(NULL, ","); 
  Value3 = atof(strtokIndx);
  
  strtokIndx = strtok(NULL, ","); 
 Value4 = atof(strtokIndx);

}

Again, all this works well, once communication is established, but I need to reset the DUE to have communication begin with the JFx application running on the Rpi. If I use the USB programming port, once the JFx application starts, it resets the DUE, so communication starts right away…

thoughts?

cyborgcnc: Again, all this works well, once communication is established,

You have only posted part of the Arduino code so I cannot see the part that might have a role in establishing communication. Post a complete program.

Perhaps both the Java and the Arduino program are each waiting for the other one to start?

...R

Hi Robin,

I am not doing anything unusuall...pretty straight forward in terms of Initializing the Serial ports on the DUE, and the Serial Port Initialization on the Jfx app is shown as I posted...here it is:

void setup() {

Serial1.being(57600);
}
//
void loop() {

receiveData();
parseData ();
delay (10);
//
// Test to see parsing of the values..
//
Serial1.print(Value1);
Serial1.print(",");
Serial1.print(Value2);
Serial1.print(",");
Serial1.println(Value3);
//}

Not sure if I should be initializing the serial differently on the Due? I am fairly confident the Due is sending data, but not sure why it needs a restart before the JFx app parses it....it is almost as I need to kickstart it somehow....

cyborgcnc: I am not doing anything unusuall...

You are being a PITA by not posting a complete program :)

...R

That is my complete program…not sure what you mean…I have a few lines of code, so that I can solve this serial non-start issue…

Simple as simple gets…unless I reboot the DUE, communication does not start…

That is my complete program

Nonsense. The code you posted calls receiveData() and parseData () but does NOT contain those functions.

@PaulS

They were posted above…

OK, I guess I need to explicitly post the complete code, and not in different posts…Sorry about that…

int Value1, Value2, Value3;
const byte numChars = 32;;
char receivedChars[numChars];
char tempChars[numChars];

//
void setup() {

Serial1.being(57600);
}
//
void loop() {

receiveData();
parseData ();
delay (10);
//
// Test to see parsing of the values..
//
Serial1.print(Value1);
Serial1.print(",");
Serial1.print(Value2);
Serial1.print(",");
Serial1.println(Value3);
//}
//
void receiveData(){
  static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;
 
    while (HWSERIAL3.available() > 0 && newData == false) {
        rc = HWSERIAL3.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
            }
        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}
//
void rxtxData(){
  if (newData == true){
  strcpy(tempChars, receivedChars);
  parseData();
  newData = false;  
  }
}
//
void parseData(){
  char * strtokIndx;

  strtokIndx = strtok(tempChars, ",");
  Value1 = atof(strtokIndx);  

  strtokIndx = strtok(NULL, ",");
  Value2 = atof(strtokIndx); 

  strtokIndx = strtok(NULL, ","); 
  Value3 = atof(strtokIndx);


}

cyborgcnc: OK, I guess I need to explicitly post the complete code, and not in different posts....Sorry about that....

That's a step forward.

Now post a program without silly mistakes so that it compiles.

...R

Apologies again…Fat Fingered it…

int Value1, Value2, Value3;
boolean newData = false;
const byte numChars = 32;;
char receivedChars[numChars];
char tempChars[numChars];

//
void setup() {

Serial1.begin(57600);
}
//
void loop() {

receiveData();
parseData ();
delay (10);
//
// Test to see parsing of the values..
//
Serial1.print(Value1);
Serial1.print(",");
Serial1.print(Value2);
Serial1.print(",");
Serial1.println(Value3);
}
//
void receiveData(){
  static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;
 
    while (Serial1.available() > 0 && newData == false) {
        rc = Serial1.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
            }
        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}
//
void rxtxData(){
  if (newData == true){
  strcpy(tempChars, receivedChars);
  parseData();
  newData = false;  
  }
}
//
void parseData(){
  char * strtokIndx;

  strtokIndx = strtok(tempChars, ",");
  Value1 = atof(strtokIndx);  

  strtokIndx = strtok(NULL, ",");
  Value2 = atof(strtokIndx); 

  strtokIndx = strtok(NULL, ","); 
  Value3 = atof(strtokIndx);
}

That program seems to be sending the data on lines 21 to 25 every 10 millisecs. That will probably fill the output buffer and call a halt to proceedings. Change the delay to delay(1000); and see what happens.

Better still, Have a look at how millis() is used to manage timing without blocking in Several things at a time

EVEN BETTER do it the way it is in my Serial Input Basics - print only when there is new data.

...R

Robin2: That program seems to be sending the data on lines 21 to 25 every 10 millisecs. That will probably fill the output buffer and call a halt to proceedings. Change the delay to delay(1000); and see what happens.

Changing it to 1000, had no effect, and I also tried 2000 and 3000...In other words, even with the setting of delay(10), when the JFX application I posted is started, there is no data coming in....leaving the app running, and simply driving the RST pin on the DUE low, to reset the board, data starts flowing, with no errors, and everything works...

So excuse me, but won't that show that there is no problem with the buffer? If there was, why would it matter once I reboot the DUE?

thank you again for your help Robin...appreciate it.

cyborgcnc: So excuse me, but won't that show that there is no problem with the buffer? If there was, why would it matter once I reboot the DUE?

That may be true.

I'm not really familar with Java - it always seems to have a huge amount of baggage so that I can never figure what bits do what.

What happens if you connect the Arduino (using Serial1) to a terminal program on the RPI - perhaps PuTTY or Minicom?

Apart from the timing issue (which, as you say, may not be an issue) I don't see anything wrong with the Arduino code.

Maybe try a simpler Arduino program that just sends "Hello World" every second?

Also, please note that I have no experience with a Due in case the problem is caused by some feature of it.

...R

…well, I have tried just about everything…either the DUE is not behaving the way it should, or my jSerialcomm library on my JavaFX application is buggy…

minicom is behaving the same way…so I do not think is the library…

I will use a MOSFET connected to the RST pin of the DUE, and upon my Jfx application initialising, I will drive one of the pins of the Rpi high, to reset the DUE…done…

Until I find a coding solution to this, will have to go with this…

thank you once again for your help Robin…I really learned a lot by reading your Serial tutorials…thank you for putting those together…

cheers!

While I am not familiar with Java I have use JRuby which uses the JRE and I had no problem connecting to an Arduino with the JSSC library. I have a USB-TTL cable but I cannot recall if I ever used it with JRuby to connect to my Mega or Leonardo using Serial1 rather than Serial. I have not used JRuby for some time having switched to Python as it is more common among Arduino users.

I have one Arduino project in which I have two connectors for the TTL cable. One of them does not connect to the reset pin and I know that it works fine to collect data from the Arduino without causing it to reset. In that project the Arduino is continually sending data (it works 24/7) with nobody listening. But I built the capability to attach to it and view the data without interrupting it.

...R