问题描述
我只是想从一个 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
。但是尝试一两次后仍然无法读取。
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 设置,那么 {{ 1}} 再次运行时按预期打印出来,不需要断开连接,但随后又回到不打印 V
。仅使用 V
会产生相同的效果,每隔一次对其进行注释输入/输出。
编辑 5:我发现(一旦它至少正常运行一次,首先拔掉电源或使用编辑 4 中的方法),如果我把
serial_port.setDataTerminalReady(1)
就在 serial_port.setDataTerminalReady(0)
serial_port.setDataTerminalReady(1)
serial_port.setDataTerminalReady(0)
之前,它可以再次运行多次并打印出“V”。我猜是将 DTR 重置为 0。如果有解释为什么需要发生这种情况,那就太好了。
解决方法
您的函数逻辑缩进是否正确?
在我看来,您似乎只阅读了一行内容,然后立即关闭了串行端口并退出了您的应用程序。
也许你打算:
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()