readyRead signal not activating while using QSerialProt
-
Hello. I have this program here:
import sys from time import sleep from PySide6 import QtSerialPort as qts from PySide6 import QtCore as qtc class Serial_Port(): def __init__(self): self.port = qts.QSerialPort() self.port.setBaudRate(qts.QSerialPort.Baud38400) self.port.readyRead.connect(self.on_receive) self.port.errorOccurred.connect(self.on_error) qtc.QTimer.singleShot(0, self.program) def program(self): print(self.con_discon()) order = [0x86, 0x01] for o in order: self.send(o.to_bytes()) sleep(0.001) print("fin") def con_discon(self): if self.port.isOpen(): self.port.close() return False else: for port in qts.QSerialPortInfo.availablePorts(): if port.manufacturer() == 'STMicroelectronics' and port.serialNumber() == '0668FF505271754867083433': self.port.setPort(port) break return self.port.open(qtc.QIODeviceBase.ReadWrite) def send(self, data): print("send: ", data) self.port.write(data) def on_receive(self): print('!') print("message: ", self.port.read(2)) def on_error(self, error): print("Serial port error:") print(error.name) exit() def main(): if not qtc.QCoreApplication.instance(): app = qtc.QCoreApplication(sys.argv) else: app = qtc.QCoreApplication.instance() Serial_Port() app.exec() if __name__ == '__main__': main()
It's supposed to send 0x86 and then 0x01 through serial port and get an answer from a device. I know the device is working correctly, because the answer is showing up with Termite and, interestingly, when I run this program without an event loop, which looks like this:
import sys from time import sleep from PySide6 import QtSerialPort as qts from PySide6 import QtCore as qtc class Serial_Port(): def __init__(self): self.port = qts.QSerialPort() self.port.setBaudRate(qts.QSerialPort.Baud38400) self.port.readyRead.connect(self.on_receive) self.port.errorOccurred.connect(self.on_error) def program(self): print(self.con_discon()) order = [0x86, 0x01] for o in order: self.send(o.to_bytes()) sleep(0.001) self.port.waitForReadyRead() print("fin") def con_discon(self): if self.port.isOpen(): self.port.close() return False else: for port in qts.QSerialPortInfo.availablePorts(): if port.manufacturer() == 'STMicroelectronics' and port.serialNumber() == '0668FF505271754867083433': self.port.setPort(port) break return self.port.open(qtc.QIODeviceBase.ReadWrite) def send(self, data): print("send: ", data) self.port.write(data) def on_receive(self): print('!') print("message: ", self.port.read(2)) def on_error(self, error): print("Serial port error:") print(error.name) exit() def main(): sp = Serial_Port() sp.program() if __name__ == '__main__': main()
I don't know why it doesn't work nor why only without the event loop. With the event loop, after sending the data, it just does nothing. Please help.
-
@Adar70
Maybe you are doing the above (mostly) in your first code, I looked initially at your second.Meanwhile, I am worried about your Python lifetime of the instance you create in first code via plain
Serial_Port()
call. You do not assign return result to any variable. If I am not mistaken, won't the createdSerial_Port
instance be destroyed immediately after return fromSerial_Port.__init__()
? Not certain whether theqtc.QTimer.singleShot(0, self.program)
will keep it alive. Even if it does, it may die before the reply bytes are received, at least with nowaitFor...()
. Verify if that is the case, do something to keep theSerial_Port
instance around? -
@Adar70
Maybe you are doing the above (mostly) in your first code, I looked initially at your second.Meanwhile, I am worried about your Python lifetime of the instance you create in first code via plain
Serial_Port()
call. You do not assign return result to any variable. If I am not mistaken, won't the createdSerial_Port
instance be destroyed immediately after return fromSerial_Port.__init__()
? Not certain whether theqtc.QTimer.singleShot(0, self.program)
will keep it alive. Even if it does, it may die before the reply bytes are received, at least with nowaitFor...()
. Verify if that is the case, do something to keep theSerial_Port
instance around? -
@JonB Thanks for the reply. After putting the call to
Serial_Port()
in a variable likesp = Serial_Port()
in the code with event loop it worked. Sadly the amount of times the readyRead signal is emitted is unreliable. Sometimes it's two, sometimes it's three. I don't know how to make it more robust. Could you help with that? -
@Adar70 said in readyRead signal not activating while using QSerialProt:
I don't know how to make it more robust
Don't rely on the number of times readyRead is emitted. Instead accumulate the received data until you received all you expect to receive.
-