gpt4 book ai didi

serial-port - 为什么 serial.available 在此代码段中不起作用?

转载 作者:行者123 更新时间:2023-12-04 15:23:46 30 4
gpt4 key购买 nike

我有一个处理草图,需要与 USB 设备建立 2 个连接。我无法提前判断哪个设备是 USB0 哪个是 USB1。 (不是我至少知道)

其中一台设备发出问候语,另一台设备根本不回答。因此,我编写了带有简单超时的代码。在设置中,我不断检查是否有字节要读取。但是 while 和 if 语句都会产生不正确的结果

while( dccCentral.available() < 5 ) {
if( dccCentral.available() >= 5) break;
if(millis() > 5000 ) {
println("timeout occured");
println(dccCentral.available());
break;
}
}

这些线路正在设置中。始终打印文本“发生超时”。在其下方,打印了 dccCentral.available() 的结果。这个数字是 12,这是正确的。

无论如何,如果 dccCentral.available() 当时打印 12。第一个 if 语句:

if( dccCentral.available() >= 5) break;

应该在该超时发生之前已经跳出 while 循环。当接收到 5 个或更多字节时,while 循环本身也应该退出。

为什么这两行都是

while( dccCentral.available() < 5 ) {
if( dccCentral.available() >= 5) break;

失败了?

最佳答案

我个人尽量避免 while 循环,除非没有其他方法(例如在线程内),这既可以避免逻辑陷阱,也可以避免干扰可能需要一些时间来初始化的其他对象的生命周期。

如果您从 Arduino 发送字符串并且还使用 println() 您可以初始化端口以使用 Serial 的 bufferUntil() 轻松捕获它结合serialEvent()最后readString() .

一旦开始获取数据,您就可以:

  1. 使用对您之后的串行端口的引用以及一些额外的端口,直到您知道哪个端口是哪个
  2. 使用 bool “切换”只处理一次“你好”
  3. 如果收到问候,您可以使用 serialEvent() Serial 参数来分配 dccCentral 并通过消除过程分配另一个端口

这里有一个注释草图来说明这个想法:

import processing.serial.*;

// be sure to set this to the baud rate your device use with Arduino as well
final int BAUD_RATE = 115200;
// reference to Serial port sending "Hello" (when that get's detected)
Serial dccCentral;
// reference to the other Serial port
Serial otherDevice;
// temporary references
Serial usb0;
Serial usb1;
// 'toggle' to keep track where the hello was received and handled or not (by default initialised as false)
boolean wasHelloReceived;

void setup(){
usb0 = initSerial("/dev/ttyUSB0", BAUD_RATE);
usb1 = initSerial("/dev/ttyUSB1", BAUD_RATE);
}

Serial initSerial(String portName, int baudRate){
Serial port = null;

try{
port = new Serial(this, portName, baudRate);
// if sending strings and using println() from Arduino
// you can buffer all chars until the new line ('\n') character is found
port.bufferUntil('\n');
}catch(Exception e){
println("error initialising port: " + portName);
println("double check name, cable connections and close other software using the same port");
e.printStackTrace();
}

return port;
}

void draw(){
background(0);
text("wasHelloReceived: " + wasHelloReceived + "\n"
+"dccCentral: " + dccCentral + "\n"
+"otherDevice: " + otherDevice , 10 ,15);
// do something with the devices once they're ready (e.g. send a message every 3 seconds)
if(millis() % 3000 == 0){
if(dccCentral != null){
dccCentral.write("ping\n");
}
if(otherDevice != null){
otherDevice.write("pong\n");
}
}
}

void serialEvent(Serial port){
try{
String serialString = port.readString();
// if the received string is not null, nor empty
if(serialString != null && !serialString.isEmpty()){
// for debugging purposes display the data received
println("received from serial: " + serialString);
// trim any white space
serialString = serialString.trim();
// check if "hello" was received
if(serialString.equals("hello")){
println("hello detected!");
// if the dccCEntral (hello sending) serial port wasn't assigned yet, assign it
// think of this as debouncing a button: setting the port once "hello" was received should happen only once
if(!wasHelloReceived){

// now what dccCentral is found, assign it to the named reference
dccCentral = port;

// by process elimiation, assign the other port
// (e.g. if dccCentral == usb0, then other is usb1 and vice versa)
otherDevice = (dccCentral == usb0 ? usb1 : usb0);
/*
the above is the same as
if(dccCentral == usb0){
otherDevice = usb1;
}else{
otherDevice = usb0;
}
*/

wasHelloReceived = true;
}
}
}
}catch(Exception e){
println("error processing serial data");
e.printStackTrace();
}
}

请注意以上代码尚未经过测试,因此可能包含语法错误,但希望能理解这一点。

我不禁注意到 USB0/USB1 是串行设备有时在 Linux 上的显示方式。如果您使用的是 Raspberry Pi,并且熟悉 Python,我可以推荐一种稍微简单一些的方法。 PySerial它有一些技巧:

  1. 您可以简单地调用:python -m serial.tools.list_ports -v 它将列出带有额外信息的端口,例如串行转换器芯片组的序列号。无论制造商和使用的 USB 端口如何,这都有助于区分哪个设备是哪个
  2. 除了串行端口名称/位置之外,它还支持多种访问端口的方式(URL),非常巧妙:hwgrep://将允许您按设备的唯一序列号过滤设备

这是两个具有相同芯片组的设备的基本 list_ports -v 输出:

column 1

/dev/ttyUSB9
desc: TTL232R-3V3
hwid: USB VID:PID=0403:6001 SER=FT94O21P LOCATION=1-2.2

column 2

/dev/ttyUSB8
desc: TTL232R-3V3
hwid: USB VID:PID=0403:6001 SER=FT94MKCI LOCATION=1-2.1.4

要使用串行分配设备,您可以使用类似的东西:

"hwgrep://FT94O21P"
"hwgrep://FT94MKCI"

更新

逐步调试系统并一次尝试一个端口可能会有所帮助。这个想法是让代码读取预期的串行字符串。这是一个基本示例,它应该一次简单地将一个字符累积到一个字符串中并显示它:

import processing.serial.*;

Serial port;

String fromSerial = "";

void setup(){
size(300,300);
port = initSerial("/dev/ttyUSB0", 115200);
}

Serial initSerial(String portName, int baudRate){
Serial port = null;

try{
port = new Serial(this, portName, baudRate);
// if sending strings and using println() from Arduino
// you can buffer all chars until the new line ('\n') character is found
port.bufferUntil('\n');
}catch(Exception e){
println("error initialising port: " + portName);
println("double check name, cable connections and close other software using the same port");
e.printStackTrace();
}

return port;
}

void draw(){

if(port != null){
if(port.available() > 0){
char inChar = port.readChar();
fromSerial += inChar;
if(inChar == '\n'){
println("newline encountered");
println(fromSerial.split("\n"));
}
}
}

background(0);
text("from serial:" + fromSerial, 10,15);
}

如果来自 dccCentral 的数据符合预期:太好了,可以简化代码并在将来应用正确的条件来过滤设备,否则,如果使用 Serial.println() 来自 Arduino)

关于Python,一点问题都没有。如果这个想法将来有帮助,您可以查看 this answer . (AFAIK Processing Serial 在幕后使用 JSSC)

关于serial-port - 为什么 serial.available 在此代码段中不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62746214/

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