Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. readyRead signal not activating while using QSerialProt

readyRead signal not activating while using QSerialProt

Scheduled Pinned Locked Moved Solved Qt for Python
5 Posts 3 Posters 215 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    Adar70
    wrote on 26 Feb 2025, 09:35 last edited by
    #1

    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.

    J 2 Replies Last reply 26 Feb 2025, 10:04
    0
    • A Adar70
      26 Feb 2025, 09:35

      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.

      J Offline
      J Offline
      JonB
      wrote on 26 Feb 2025, 10:13 last edited by
      #3

      @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 created Serial_Port instance be destroyed immediately after return from Serial_Port.__init__()? Not certain whether the qtc.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 no waitFor...(). Verify if that is the case, do something to keep the Serial_Port instance around?

      A 1 Reply Last reply 26 Feb 2025, 11:01
      2
      • A Adar70
        26 Feb 2025, 09:35

        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.

        J Offline
        J Offline
        JonB
        wrote on 26 Feb 2025, 10:04 last edited by
        #2

        @Adar70
        Don't do sleep()s. Allow the event loop to run. Don't use both readyRead() signal and waitForReadyRead(). Get rid of the latter. Don't read 2 bytes in case there is only 1. There's a start.

        1 Reply Last reply
        0
        • A Adar70
          26 Feb 2025, 09:35

          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.

          J Offline
          J Offline
          JonB
          wrote on 26 Feb 2025, 10:13 last edited by
          #3

          @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 created Serial_Port instance be destroyed immediately after return from Serial_Port.__init__()? Not certain whether the qtc.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 no waitFor...(). Verify if that is the case, do something to keep the Serial_Port instance around?

          A 1 Reply Last reply 26 Feb 2025, 11:01
          2
          • J JonB
            26 Feb 2025, 10:13

            @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 created Serial_Port instance be destroyed immediately after return from Serial_Port.__init__()? Not certain whether the qtc.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 no waitFor...(). Verify if that is the case, do something to keep the Serial_Port instance around?

            A Offline
            A Offline
            Adar70
            wrote on 26 Feb 2025, 11:01 last edited by
            #4

            @JonB Thanks for the reply. After putting the call to Serial_Port() in a variable like sp = 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?

            jsulmJ 1 Reply Last reply 26 Feb 2025, 12:30
            0
            • A Adar70
              26 Feb 2025, 11:01

              @JonB Thanks for the reply. After putting the call to Serial_Port() in a variable like sp = 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?

              jsulmJ Offline
              jsulmJ Offline
              jsulm
              Lifetime Qt Champion
              wrote on 26 Feb 2025, 12:30 last edited by
              #5

              @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.

              https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              5
              • A Adar70 has marked this topic as solved on 27 Feb 2025, 16:04

              1/5

              26 Feb 2025, 09:35

              • Login

              • Login or register to search.
              1 out of 5
              • First post
                1/5
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved