为啥 QtSerialPort 在运行超过一次或两次后不会读取?
Posted
技术标签:
【中文标题】为啥 QtSerialPort 在运行超过一次或两次后不会读取?【英文标题】:Why would QtSerialPort not read after running more than once or twice?为什么 QtSerialPort 在运行超过一次或两次后不会读取? 【发布时间】:2021-03-24 21:07:43 【问题描述】:我只是想在一个值表示开始后从 QtSerialPort 连接读取值到 arduino。我可以在 python 代码中有一个最大计数,但这并不会改变它在多次运行 python 脚本后没有从 arduino 读取 println 的结果。起初它会打印出“开始”、“阅读”和“V”,如果我很快再次运行它,可能会再次打印出来。但在那之后,它在打印出“开始”后停止阅读。这是python代码。
from PyQt5 import QtCore, QtSerialPort
import sys
app = QtCore.QCoreApplication([])
serial_port = QtSerialPort.QSerialPort('COM3')
serial_port.open(QtCore.QIODevice.ReadWrite)
def handle_ready_read():
print('to read')
while serial_port.canReadLine():
serialrd = serial_port.readLine().data().decode().strip()
print(serialrd)
serial_port.close()
app.quit()
serial_port.readyRead.connect(handle_ready_read)
serial_port.write(bytes([100]))
print('start')
sys.exit(app.exec_())
这是arduino代码。
int measured;
int counter = 0;
int maxnum = 10;
void setup()
Serial.begin(9600);
void loop()
if(Serial.available() > 0)
while(counter < maxnum)
Serial.println("V");
counter++;
delay(100);
任何可以解释为什么它不会再次阅读的想法都会很有用。我每次都必须拔下并重新插入 arduino 才能读取它,但最好避免这样做。我还注意到我无法在 pyserial 连接之后运行 PyQt5 串行端口连接,首先断开 arduino,但我可以在 PyQt5 串行端口连接之后运行 pyserial,尽管我不知道该问题是否与某种相关。
编辑:我在handle_ready_read中添加了'to read'打印语句,第一次运行时有时会打印两次,所以虽然有要读取的内容,但readline并不总是可以读取,所以我添加了到最后去handle_ready_read吧,
while serial_port.bytesAvailable():
dataByte = serial_port.readLineData(1)
print(dataByte)
serial_port.close()
app.quit()
因此有时会在读取时打印出b'V'
,而不仅仅是V
。但一两次尝试后仍然无法读取。
编辑 2:我添加了一个计时器和函数来检查字节是否被写入,
attempts = []
def check_bytes_written():
print('bytes to write' , serial_port.bytesToWrite())
attempts.append(1)
if len(attempts) > 10:
serial_port.close()
timer.stop()
app.quit()
timer = QtCore.QTimer()
timer.setInterval(50)
timer.timeout.connect(check_bytes_written)
timer.start()
这不会在第一次或第二次尝试时打印出任何内容,然后在以后的尝试中说“要写入 0 的字节”,即使端口和应用程序已结束,仍然没有打印出任何形式的“V”,除非我仍然断开 arduino 并将其重新插入(至少现在不需要每次都重新启动内核)。我还在 arduino 中添加了代码,以检查写入的值是否可用于更改输出引脚的电压,它可以工作并且每次运行 python 脚本时都会更改输出电压,是否读取了“V” .所以我稍微改变了问题标题和之前的文字,因为它并没有真正崩溃或冻结,它只是没有阅读 arduino 正在打印的内容。
编辑 3:我将if(Serial.available() > 0) int counter = 0;
放在 arduino 代码中,而不是在开始时初始化计数器,python 代码将在重新运行脚本时从 arduino 读取(尽管 V 周围有一堆空格,或者只是从 readlineData 部分打印 b'\x00',但这可能是另一个问题,可以通过在 readyRead 之前放置 serial_port.clear()
来清除它,但是仍然会打印 V 或 b'V')。所以看起来python脚本没有重新启动arduino代码,也许这是qserialport如何关闭或打开的问题(如DTR或RTS),不像pyserial那样?更多讨论here。
编辑 4:如果我添加(在 arduino 代码的开头初始化计数器时,如最初所示,撤消最后一次编辑)
serial_port.setDataTerminalReady(1)
serial_port.setDataTerminalReady(0)
serial_port.setDataTerminalReady(1)
在serial_port.open
语句并运行它之后,它仍然不会从串行读取中打印(没有断开arduino 并首先重新连接它),但是如果我评论DTR 设置,那么V
是再次运行时按预期打印,无需断开连接,但随后又回到不打印V
。仅使用 serial_port.setDataTerminalReady(1)
也会产生相同的效果,每隔一段时间将其评论输入/输出。
编辑 5:我发现(一旦它至少正常运行一次,首先拔掉插头或使用编辑 4 中的方法),如果我放了
serial_port.setDataTerminalReady(0)
serial_port.setDataTerminalReady(1)
serial_port.setDataTerminalReady(0)
就在serial_port.close()
之前,它可以再次运行多次并打印出“V”。我猜它正在将 DTR 重置为 0。如果有解释为什么需要发生这种情况,那就太好了。
【问题讨论】:
【参考方案1】:你的函数逻辑是否正确缩进?
在我看来,你读了一行就立即关闭串行端口并退出你的应用程序。
也许你打算:
def handle_ready_read():
while serial_port.canReadLine():
serialrd = serial_port.readLine().data().decode().strip()
print(serialrd)
# Close serial port and quit app when no more data is available
serial_port.close()
app.quit()
【讨论】:
这给出了相同的结果,它仍然卡住了。在任何一种情况下,它都只读取一行。我知道 arduino 的 println 比读取的要多,但它适用于 pyserial。 如果我读到了arduino发送的最大行数,然后退出,它仍然卡住,这主要是为了举一个更简单的例子。 您可以尝试打印serial_port.baudRate()
吗?我想知道 Qt 是否无法正确设置它
默认是 9600,所以设置它不会改变任何东西。它按原样工作一两次。
pyserial
可能就是这种情况,但 Qt 文档建议 QSerialPort
尝试查找端口配置本身。所以也许它可能弄错了。以上是关于为啥 QtSerialPort 在运行超过一次或两次后不会读取?的主要内容,如果未能解决你的问题,请参考以下文章
Java - 如何一次或从一个文件夹中依次运行几个 shell/bat 文件