Closed Brunosalata closed 1 year ago
Hi Brunosalata, this doesn't seem to relate to a JavaFX problem. Your code uses the wrong string in the method: SerialPort.getCommPort(cbPorts.getSelectionModel().getSelectedItem().toString())
Of cause, the systemName of the port (getSystemPortName) is more practical in the combo box, but only the value of this method should work: getDescriptivePortName() The API documentation states: "Gets a descriptive string representing this serial port or the device connected to it."
Your "connect" method might check, if your retrieve a port object, before calling port.openPort()
kind regards Torge
Hi, Soulsurfering! Thanks so much for answer me.
I understood what you said, I tried changing the code in different ways to fit the method, but it didn't work. Most likely due to my own fault.
could you show me how i can make this change?
Something I did here was to start the "Initialize" method with 'port = SerialPort.getCommPort("0");' still Thread didn't work. But, again, certainly due to my lack of knowledge.
Do you think it makes sense?
What I see:
Hi Brunosalata,
I need to applogize: actually "getSystemPortName()" seems to be the right string to get a port instance, at least on my linux system.
Did you add the "null" check on the port variable?
I still don't understand, why you send "1" and "2" to the output stream and try to read 20ms later the input stream.
Are you expecting to retrieve "1" and "2"? Because there must be a device "on the other end" to send any echo back to your input stream?
What device is listening to your output stream?
Does that device receive your output data?
the serial device you're calling may need more to set than just the baudrate, e.g.: port.setComPortParameters(115200, 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY); port.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING | SerialPort.TIMEOUT_WRITE_BLOCKING, 50, 50); port.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);
regards, soulsurfering
Hi, Soulsurfering!
Yes, I added the null check like you sad. But I dont think it's the problema. Because the communication is working fine, but only on the main Thread.. I don't know how to create a structure to writing and reading data as the same time the application is running. Most time I try to create a Thread or Task, the application breaks with the error "this.port = null", because my Thread code is another class (RunnableThread) and I dont't know how to import the MainSceneController there, to recognise the port name or the end of my outputs
I think It was confusing, right? hahaha just let me know and I'll try again.
Just clarifying 1- I'm building an application that communicates with an arduino, which controls a traction device. When I send the string "1", the arduino returns me the value of the force of the equipment, when I send "2", it returns the displacement of the axis where the force is made. I need this data to be read constantly without crashing the application or making the buttons unfeasible (after openPort, sure.
2- Others outputs, like "3", "4", "5" are done from the press of a button, and it is going well (but I need buttons to do it). When I output "1" or "2" in a button, the arduino returns the right value, but I need to press all the time. It's not automatic.
I think I'm almost there! I started portDescription as "0", just to don't crash, it won't be a problem propably.
After it, I inserted a simple Thread in the "connect()" method and I get the values!! But only printing in my console. If I try to setText() the respective label, it doesn't works..
PS: I had to change the output to "1x" and "2x" for some tests in arduino code (nothing else has changed) PS 2: I made a method to Input and Output the values, so, I just call inputValue() and outputInjection(String stg)
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
port = SerialPort.getCommPort("0");
portConnectionList();
lbCurrentData.setText(String.valueOf(systemDate));
}
/**
* Método que define o algorítmo da Thread que faz a leitura dinâmica da Força e da Posição
*/
private void FPReadingThread() {
try{
Thread.sleep(1000);
outputInjection("1x");
Thread.sleep(20);
//String impF = inputValue();
System.out.println(inputValue());
//lbForceView.setText(impF);
outputInjection("2x");
Thread.sleep(20);
//String impP = inputValue();
System.out.println(inputValue());
//lbPositionView.setText(impP);
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
/**
* Método de abertura e fechamento de conexão
*/
@FXML
private void connect() {
if (port != null) {
//Método de abertura e fechamento de conexão serial
if (btnConnect.getText().equals("Conectar")) {
port = SerialPort.getCommPort(cbPorts.getSelectionModel().getSelectedItem().toString());
if (port.openPort()) {
btnConnect.setText("Desconectar");
cbPorts.setDisable(true);
port.setComPortParameters(115200, 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY);
port.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING | SerialPort.TIMEOUT_WRITE_BLOCKING, 50, 50);
port.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);
Thread t = new Thread(() -> {
while (true) {
FPReadingThread();
}
});
t.start();
}
} else {
port.closePort();
cbPorts.setDisable(false);
btnConnect.setText("Conectar");
}
} else{
System.out.println("Nenhuma porta encontrada!");;
}
}
Just to make this topic DONE, a final post.
I solved it inserting the Platform.runLater() in the FPReadingThread() method at the same I call this method in the connection() one.
So, if you are doing your JavaFX project to get data from serial port, it's a good alternative to you.
Just an observation: I implemented autoconnect getting the portName from database and send my serial data to database too, but not for this UI problem. I'll use it later.
My SceneController code becomes this
private void FPReadingThread() {
try{
Thread.sleep(2000);
outputInjection("1x");
Thread.sleep(20);
String impF = inputValue();
// System.out.println(impF);
outputInjection("2x");
Thread.sleep(20);
String impP = inputValue();
// System.out.println(impP);
//Atualização da UI pela Thread
Platform.runLater(() -> {
lbForceView.setText(impF);
lbPositionView.setText(impP);
});
SystemVariable sysVar = new SystemVariable(1,Double.valueOf(impF),Double.valueOf(impP));
systemVariableDAO.update(sysVar);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
/**
* Método de conexão automática
*/
@FXML
private void autoConnect(){
SystemParameter sysPar = systemParameterDAO.find();
System.out.println("Conectado");
if(sysPar==null){
sysPar.setPortName(cbPorts.getSelectionModel().getSelectedItem().toString());
sysPar.setSystemLanguage("pt");
sysPar.setSoundOn("false");
systemParameterDAO.create(sysPar);
}
port = SerialPort.getCommPort(sysPar.getPortName());
System.out.println(port);
if (port.openPort()) {
btnConnect.setText("Conectado");
cbPorts.setDisable(true);
port.setComPortParameters(115200, 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY);
port.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING | SerialPort.TIMEOUT_WRITE_BLOCKING, 50, 50);
port.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);
// Thread para solicitar Posição e Força e atualizar lbForceView e lbPositionView
Thread t = new Thread(() -> {
while (true) {
FPReadingThread();
}
});
t.start();
} else {
port.closePort();
btnConnect.setText("Conectar");
}
}
Thanks so much for any help!
Hi, everyone! This is my first issue in my life. hahaha Thanks for any help.
I'm building a javafx project to communicate with arduino. JSerialComm did the communication well, but I don't know how to include a Thread to expose a realtime value in a label in the interface.
I'm doing it in Java. the arduino programming was made to return this value, if it receives the char "1". So, I need to send "1" via serial and read the return in parallel with the main routine of the software.
For the connection, I created a comboBox with the list of available ports and a "Connect" button. I select the port on the CB and connect to the port with that name (SerialPort.getCommPort).
The application starts exclusively by loading the comboBox, the rest happens by clicking the buttons. I don't know where to implement the Thread because it always results in <Cannot invoke "com.fazecast.jSerialComm.SerialPort.getOutputStream()" because "this.port" is null>
What option do I have to make it work?
class FXMLController