0

I am trying to achieve what seems looks like a simple task, but like anything looks can be deceiving. Hoping someone here can point me in the right direction of what STUPID thing I am doing wrong...cant seem to get this going after days of searching....

Have a JavaFX application, that receives data from an Arduino nano, with data the provides voltage levels from two sensors. I also want to be able to send data back to the arduino, to have it alter some parameters. I have the data streaming in, comma delimited, and I am able through a bufferedreader to parse the data and stuff an Array. So far this has been working quite well.

On my JavaFX GUI (Build with Scenebuilder) I have several Radio buttons, that when pressed, I want to be able to send back some very simple data (like 1, 2, 3,4 etc) depending on what radio button was pushed. This in turn I will parse on the arduino, to have it change what it is sending, or perform some logic. This is where I AM STUCK! For the LIFE OF ME, I cant get my JavaFX application to SEND DATA BACK through the serial port. I am sure I am doing something dumb and stupid, maybe mixing up my threads etc. Have created buffered input and output streams, but I need some help on calling these methods under the serialport thread/event handler...Here is my Java Code:

    package JSWRV3;

import com.fazecast.jSerialComm.SerialPort;
import com.fazecast.jSerialComm.SerialPortDataListener;
import com.fazecast.jSerialComm.SerialPortEvent;
import com.sun.org.apache.xpath.internal.operations.String;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Cursor;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;

import java.io.*;
import java.lang.*;
import java.util.Scanner;
import static java.lang.System.out;


public class Main extends Application {
private java.lang.String Values[];
public double fwdVolts, revVolts, fwdPower, revPower;


  SerialPort commPort = SerialPort.getCommPort("COM20");

@Override
public void start(Stage primaryStage) throws Exception{
    FXMLLoader loader = new FXMLLoader(getClass().getResource("ZTfxml.fxml"));
    Parent root = loader.load(); //Need to create an instance of my controller here
    ZTController myController = loader.getController(); //Injects controller here for us to use
    primaryStage.setTitle("POWER METER");
    primaryStage.setScene(new Scene(root, 800, 480));
    primaryStage.show();
    root.setCursor(Cursor.NONE);

    //
           //
    primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
        @Override
        public void handle(WindowEvent event) {
            commPort.closePort();
            Platform.exit();
            System.exit(0);
        }
    });
    //
    if (commPort.isOpen()) commPort.closePort();
        try {
            commPort.setComPortParameters(115200, 8, 1, 0);
            commPort.setComPortTimeouts(SerialPort.TIMEOUT_SCANNER, 1, 1);
            commPort.openPort();
        } catch (IOError ex) {out.println("Serial Port Error" + ex.toString()); }
    //
    //
        commPort.addDataListener(new SerialPortDataListener() {
        //
            BufferedInputStream inputStream = new BufferedInputStream(commPort.getInputStream());
            BufferedReader inputReader = new BufferedReader(new InputStreamReader(inputStream));
            BufferedOutputStream outputStream = new BufferedOutputStream(commPort.getOutputStream());
            BufferedWriter outputWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
            //
            //
        @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 {
                java.lang.String nextString = inputReader.readLine();
                Values = nextString.split(",");
                }catch(IOException ex){ex.printStackTrace();}
            if(Values.length == 4){
              parseString(Values);} //All this works GREAT!
            Platform.runLater(()-> myController.setGauge(fwdVolts, revVolts,     fwdPower, revPower));//Send to GUI Thread
          }
    });
}
//
public void parseString(java.lang.String[] inputString){
    fwdVolts = Double.parseDouble(inputString[0]);
    revVolts = Double.parseDouble(inputString[1]);
    fwdPower = Double.parseDouble(inputString[2]);
    revPower = Double.parseDouble(inputString[3]);
}
  public void sendData(byte[] dataOut) {   
  try {//STUCK How do I access the port to write to it???
        commPort.writeBytes(dataOut, dataOut.length);
       } catch (IOError ex) {
        ex.printStackTrace();
      }
   }
//
public static void main(java.lang.String args) {
    launch(args);
  }
 }

and my Controller Class

    package JSWRV3;

import com.fazecast.jSerialComm.SerialPort;
import eu.hansolo.enzo.gauge.RectangularGauge;
import eu.hansolo.enzo.lcd.Lcd;
import eu.hansolo.enzo.ledbargraph.LedBargraph;

import java.io.IOError;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.util.ResourceBundle;

import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;

public class ZTController {

@FXML
private ResourceBundle resources;
@FXML
private URL location;
@FXML
private RectangularGauge fwdpower;
@FXML
private RectangularGauge revpower;

@FXML
private RadioButton B160;
@FXML
private RadioButton B80;
@FXML
private RadioButton B60;
@FXML
private RadioButton B40;
@FXML
private RadioButton B30;
@FXML
private RadioButton B20;
@FXML
private RadioButton B17;
@FXML
private RadioButton B15;
@FXML
private RadioButton B12;
@FXML
private RadioButton B10;


public void initialize( ) {
    assert fwdpower != null : "fx:id=\"fwdpower\" was not injected: check your FXML file 'ZTfxml.fxml'.";
    assert revpower != null : "fx:id=\"revpower\" was not injected: check your FXML file 'ZTfxml.fxml'.";
    assert B160 != null : "fx:id=\"B160\" was not injected: check your FXML file 'ZTfxml.fxml'.";
    assert B80 != null : "fx:id=\"B80\" was not injected: check your FXML file 'ZTfxml.fxml'.";
    assert B60 != null : "fx:id=\"B60\" was not injected: check your FXML file 'ZTfxml.fxml'.";
    assert B40 != null : "fx:id=\"B40\" was not injected: check your FXML file 'ZTfxml.fxml'.";
    assert B30 != null : "fx:id=\"B30\" was not injected: check your FXML file 'ZTfxml.fxml'.";
    assert B20 != null : "fx:id=\"B20\" was not injected: check your FXML file 'ZTfxml.fxml'.";
    assert B17 != null : "fx:id=\"B17\" was not injected: check your FXML file 'ZTfxml.fxml'.";
    assert B15 != null : "fx:id=\"B15\" was not injected: check your FXML file 'ZTfxml.fxml'.";
    assert B12 != null : "fx:id=\"B12\" was not injected: check your FXML file 'ZTfxml.fxml'.";
    assert B10 != null : "fx:id=\"B10\" was not injected: check your FXML file 'ZTfxml.fxml'.";
    //
    ToggleGroup toggleRbuttons = new ToggleGroup(); //This allows ONLY ONE button to be selected!
    B160.setToggleGroup(toggleRbuttons); //==> Has sendString action event defined (below);
    B80.setToggleGroup(toggleRbuttons);
    B60.setToggleGroup(toggleRbuttons);
    B40.setToggleGroup(toggleRbuttons);
    B30.setToggleGroup(toggleRbuttons);
    B20.setToggleGroup(toggleRbuttons);
    B17.setToggleGroup(toggleRbuttons);
    B15.setToggleGroup(toggleRbuttons);
    B12.setToggleGroup(toggleRbuttons);
    B10.setToggleGroup(toggleRbuttons);
    //
}

    Main objects = new Main(); //Allows us to access non-static methods in       Main!


   //
  @FXML
   public void setGauge(Double fwdVolts, Double revVolts, Double fwdPower,       Double revPower) {

    fwdpower.setValue(fwdPower);
    revpower.setValue(revPower);
    }
   }
  // All the Radio button Events, and we need to send data BACK to the      Arduino
 //
@FXML
public  void sendString(ActionEvent event){
  byte[] testByte = "this is data FROM javaFX..testing..\r\n".getBytes();

 //STUCK!!  How to I send this to my bufferedWriter to be send to Serial     port??????
 //Trying to access objects.sendData(testByte); ==>Does not work...HELP!
 //This is what I try:
   objects.sendData(testByte);
   }

   }
CYBORGCNC
  • 45
  • 2
  • 7
  • Do you need all the communication to be set up in the `Application` subclass for some reason? It would seem much more natural to define it in the controller class (or delegate it to another class entirely). – James_D Apr 28 '16 at 18:13
  • No, there is no need to have it all in the Application subclass....but I should be able to call the class from the controller, and have it send a simple byte to the serial port right? I guess I am looking for the best way and guidance to do that....everything I have tried produces a nullpointer exception, so I am missing something obvious...and all examples I have seen on the Jserialcomm class show receiving data...not sending.... – CYBORGCNC Apr 28 '16 at 19:14
  • The controller needs a reference to the object that has the communication set up. That's why I suggested it would be easier to do it in the controller itself; but if not you just have to pass a reference to the correct object to the controller instance. E.g. you just do `myController.setMain(this);` and just define the corresponding method in `ZTController`. I have never used JSerialComm but for sending data don't you just do [`commPort.writeBytes(...)`](http://fazecast.github.io/jSerialComm/javadoc/com/fazecast/jSerialComm/SerialPort.html#writeBytes-byte:A-long-)? – James_D Apr 28 '16 at 19:19
  • Thank you James. I am not clear, and need to see an example if I am not asking too much...apologies for asking, but I am really stuck... I define an event handler in Controller, which fires when I push a radial button. I can then call a method in my application class that does do a commPort.write(string.getbytes();, but always returns a null pointer when called, because I guess it is not under the serialport event handler? I am not sure how to marry the two together...the inputstream works great, the outputstream does not...... – CYBORGCNC Apr 28 '16 at 19:45
  • Again, you need to pass the reference to the application to the controller. See http://stackoverflow.com/questions/14187963 if you don't know how to pass parameters to controllers. – James_D Apr 28 '16 at 19:51
  • Thank you James....I modified the code above to show the method I am calling from my controller...when I do this now, I do not get a stackoverflow, but NOTHING gets written to the serial port...I will study the link you provided.... – CYBORGCNC Apr 28 '16 at 20:01

0 Answers0