gpt4 book ai didi

javafx - 串行连接(Arduino --> Java)

转载 作者:行者123 更新时间:2023-12-01 03:42:49 26 4
gpt4 key购买 nike

这将是我的第一篇文章,我会尽力做到简洁明了。我已经查看了该论坛上的其他一些帖子,但无法找到满意的答案。

我的问题与 JavaFX 和 jSSC(java 简单串行连接)库的使用有关。我设计了一个非常简单的 GUI 应用程序,它将托管四个不同的图表。其中两个图表将显示过去一小时的温度和太阳能传感器读数,而另外两个图表则显示较长时间段(14 小时)的数据。最终,我想让它更灵活,并在读数大致为零(夜间)时将应用程序设置为“ sleep ”。

如何流式传输数据以实时显示此数据?

在引用了几个在线来源和“JavaFX 8 Intro. by Example”之后,我已经能够构建大部分串行连接类。我在处理数据读数时遇到问题,无法将其显示在图表上。

public class SerialComm  implements SerialPortEventListener {
Date time = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("mm");

boolean connected;
StringBuilder sb;
private SerialPort serialPort;

final StringProperty line = new SimpleStringProperty("");

//Not sure this is necessary
private static final String [] PORT_NAMES = {
"/dev/tty.usbmodem1411", // Mac OS X
"COM11", // Windows
};
//Baud rate of communication transfer with serial device
public static final int DATA_RATE = 9600;

//Create a connection with the serial device
public boolean connect() {
String [] ports = SerialPortList.getPortNames();
//First, Find an instance of serial port as set in PORT_NAMES.
for (String port : ports) {
System.out.print("Ports: " + port);
serialPort = new SerialPort(port);
}
if (serialPort == null) {
System.out.println("Could not find device.");
return false;
}

//Operation to perform is port is found
try {
// open serial port
if(serialPort.openPort()) {
System.out.println("Connected");
// set port parameters
serialPort.setParams(DATA_RATE,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
serialPort.setEventsMask(SerialPort.MASK_RXCHAR);

serialPort.addEventListener(event -> {
if(event.isRXCHAR()) {
try {
sb.append(serialPort.readString(event.getEventValue()));
String str = sb.toString();
if(str.endsWith("\r\n")) {
line.set(Long.toString(time.getTime()).concat(":").concat(
str.substring(0, str.indexOf("\r\n"))));
System.out.println("line" + line);

sb = new StringBuilder();
}
} catch (SerialPortException ex) {
Logger.getLogger(SerialComm.class.getName()).log(Level.SEVERE, null, ex); }
}
});
}
} catch (Exception e) {
System.out.println("ErrOr");
e.printStackTrace();
System.err.println(e.toString());
}
return serialPort != null;
}

@Override
public void serialEvent(SerialPortEvent spe) {
throw new UnsupportedOperationException("Not supported yet.");
}

public StringProperty getLine() {
return line;
}

}

在 try 块中,我了解端口参数,但 eventListener 是我遇到困难的地方。 stringbuilder 的意义在于将数据附加到从设备读取的新数据中。
我将如何解释这两个传感器读数?我会通过创建单独的数据速率来区分来自每个传感器的传入数据吗?

我希望这很清楚,并且我提供了足够的信息,但没有提供太多信息。感谢您提供任何帮助。

- - - - - - - - - - - - - - - -更新 - - - - - - - - - --------

自从您回复 Jose 以来,我已开始对我的代码进行添加。在 JavaFX 类中添加监听器,我遇到了一些问题。我不断收到 NullPointerException,我认为这是 String[]data 没有被 SerialCommunication 类中的任何数据初始化。
serialPort.addEventListener(event -> {
if(event.isRXCHAR()) {
try {
sb.append(serialPort.readString(event.getEventValue()));
String str = sb.toString();

if(str.endsWith("\r\n")) {
line.set(Long.toString(time.getTime()).concat(":").concat(
str.substring(0, str.indexOf("\r\n"))));
System.out.println("line" + line);
sb = new StringBuilder();
}
} catch (SerialPortException ex) {
Logger.getLogger(SerialComm.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
} catch (Exception e) {
System.err.println(e.toString());
}

我正在为正在读取的数据添加时间。正如 Jose 在下面提到的,我在 arduino 代码中为数据变量添加了标签,我正在使用:Serial.print("Solar:"); Serial.println(solarData);

JavaFx 监听器的粗略代码:
serialPort.getLine().addListener((ov, t, t1) -> {
Platform.runLater(()-> {
String [] data = t1.split(":");

try {
//data[0] is the timestamp
//data[1] will contain the label printed by arduino "Solar: data"

switch (data[1]) {
case "Solar":
data[0].replace("Solar:" , "");
solarSeries.getData().add(new XYChart.Data(data[0], data[1]));
break;
case "Temperature":
temperatureSeries.getData().add(new XYChart.Data(data[0], data[1]));
break;
}

这段代码有 NullPointerException 的原因是 String [] 数据数组未初始化的结果吗?

异常错误

端口:/dev/tty.usbmodem1411Connected
线程“EventThread/dev/tty.usbmodem1411”中的异常 java.lang.NullPointerException
在 SerialComm.lambda$connect$0(SerialComm.java:61)
在 SerialComm$$Lambda$1/1661773475.serialEvent(来源不明)
在 jssc.SerialPort$LinuxEventThread.run(SerialPort.java:1299)

最佳答案

SerialPortEventListenerjssc 中定义库允许监听串行端口事件。这些事件之一是 RXCHAR事件,当 Arduino 板正在发送一些数据并且一些字节在输入缓冲区中时发生。
event.getEventValue()返回 int与字节数,和 serialPort.readString(event.getEventValue())获取 String从这些字节格式化。

请注意,此方法不会返回整行,因此您需要收听回车和换行符。一旦找到"\r\n" ,你可以得到线路,并重置StringBuilder对于下一个:

sb.append(serialPort.readString(event.getEventValue()));
String str=sb.toString();
if(str.endsWith("\r\n")){
line.set(str.substring(0,str.indexOf("\r\n")));
sb=new StringBuilder();
}

哪里 line是一个可观察的 String :
final StringProperty line=new SimpleStringProperty("");

在 Arduino 方面,如果您想以不同的速率从不同的传感器发送值,我建议您在 Arduino 草图上为每个传感器定义一些识别字符串,并为每个值打印其传感器的 id。

例如,这些将是您将通过串行事件监听器获得的读数:
ID1,val1
ID1,val2
ID2,val3
ID1,val4
ID3,val5
...

最后,在 JavaFX 线程上,为 line 中的更改定义一个监听器。并处理 String获取传感器和值。像这样的东西:
serial.getLine().addListener(
(ObservableValue<? extends String> observable, String oldValue, String newValue) -> {
Platform.runLater(()->{
String[] data=newValue.split("\\,");
if(data[0].equals("ID1"){
// add to chart from sensor 1, value data[1];
} else if(data[0].equals("ID2"){
// add to chart from sensor 2, value data[1];
} else if(data[0].equals("ID3"){
// add to chart from sensor 3, value data[1];
}
});
});

注意你需要添加 Platform.runLater() , 因为从串口获取数据并更新的线程 line不在 JavaFX 线程上。

关于javafx - 串行连接(Arduino --> Java),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29719405/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com