Search code examples
pythonqtreal-timepyqtgraphpyqt6

How to use pyqtgraph and QSerialPort to create a real-time graph?


I am still a little new to Qt and python in general so I was wondering if I could get a little help with a project I am working on. I want to create a real-time graph with pyqtgraph that plots the data it receives through an RS232 connection using QSerialPort. Theoretically, the user should click start, signaling a flow of data from the RS232 connection unit it is stopped when the user clicks stop. The code down below opens and closes the port; however, the data isn't being plotted on the graph. Thanks ahead of time!


class Graph(QtGui.QWidget):
    def __init__ (self):                    
        super(Graph, self).__init__()      
        self.initializeSpace()
        
    def initializeSpace(self):
        # Create basic buttons next to graph
        self.start = QtGui.QPushButton(
            text = "Start",
            clicked = self.send)
        self.stop = QtGui.QPushButton(
            text = "Stop",
            clicked = self.stop)
         
        # Create plot
        self.graph = pg.PlotWidget()

        # Add grid
        self.graph.showGrid(x = True, y = True)

        # Set X-axis and Y-axis range
        self.graph.setXRange(0, 10)
        self.graph.setYRange(0, 200)

        # Create Layout
        self.layout = QtGui.QGridLayout()
       
        # Add widgets to layout
        self.layout.addWidget(self.start, 0, 0)
        self.layout.addWidget(self.stop, 1, 0)
        self.layout.addWidget(self.graph, 0, 1, 3, 1)

        # Set layout
        self.setLayout(self.layout)

        # Define himmelstein serial
        self.serial = QtSerialPort.QSerialPort(
            'COM4',
            baudRate = QtSerialPort.QSerialPort.Baud9600,     
            dataBits = QtSerialPort.QSerialPort.Data8,
            parity = QtSerialPort.QSerialPort.NoParity,
            stopBits = QtSerialPort.QSerialPort.OneStop, 
            flowControl = QtSerialPort.QSerialPort.NoFlowControl,
            readyRead = self.receive
            )

    @QtCore.pyqtSlot()
    def receive(self):
        while self.serial.canReadLine():
            data = self.serial.readLine().data().decode()
            data = data.strip('\r\n')
            torque = data[0]
            speed = data[1]
            self.graph.plot(x = torque, y = speed)
    
    # Send command and receive data
    @QtCore.pyqtSlot()
    def send(self):
        self.serial.open(QIODevice.ReadWrite)
        print("Port is open!")
        self.serial.write(b'ACD0\r\n')
        self.receive()

    def stop(self):
        if self.serial.isOpen():
            self.serial.close()
        print("Port closed!")

Solution

  • No it can not be done. At this moment even Qt has not included the QSerialPort module to Qt6 as this post points out:

    For Qt 6.2 we are planning to provide the following additional libraries:

    • Qt Bluetooth
    • Qt Data Visualization
    • Qt Lottie Animation
    • Qt Multimedia
    • Qt NFC
    • Qt Positioning
    • Qt Quick Dialogs: Folder, Message Box
    • Qt Remote Objects
    • Qt Sensors
    • Qt SerialBus
    • Qt SerialPort
    • Qt WebChannel
    • Qt WebEngine
    • Qt WebSockets
    • Qt WebView

    (emphasis mine)

    Currently only Qt 6.1.2 is available, and PyQt6 6.1.1 uses Qt 6.1.1.