PyQt GUI on Raspberry Pi 2 running slow

1.8k views Asked by At

Recently I was given a project to develop a GUI on RaspberryPi 2 to control a machine. I don't particularly have much experience with Qt GUIs and Qthreads so please bear with me.

I used Qt4 and Python to develop the GUI and the underlying program.

And the program was running fairly smoothly without any issues on my PCs. I used threads and had everything running fine until I tried it with the RaspberryPi2 which controls the machine.

It's got a Qthread which grabs a frame from a camera and displays it using a label. This works fine but does not update in real time (very slow update rate). I've got several buttons which controls the machine axis Movements, running in a Qthread and would also like to incorporate another Qthread with a program that has a specific set of instructions for the machine.

It all seem to work but the response from the machine is very slow (sometimes it takes up to 5 seconds to execute a single command when button is pressed). I have debugged it and traced it back to the GUI.

Also Note: The RaspberryPi 2 CPU usage while the program is running is about 30-35%.... So it's not maxing out the CPU.

Can someone please let me know what I'm doing wrong. I suspects its got something to do with the thread execution and Queuing.

I have attached a sample of the CODE below:

class IO_Worker(QtCore.QThread):

    def MoveLeft(self):
        print "MovingLeft" 
        RPIO.output(4,0) # this is pin 7 the direction switch (lowwest)
        RPIO.output(15,0) # this is pin 10 the middle toggle switch
        RPIO.output(18,0) # this is pin 12 the top toggle switchdirno=4
        time.sleep(.05)

        RPIO.output(23,1) # next three lines press blue Go button for x stage
        time.sleep(0.2)
        RPIO.output(23,0)

    def MoveRight(self):
        print "MovingRight"
        RPIO.output(4,1) # this is pin 7 the direction switch (lowwest)
        RPIO.output(15,0) # this is pin 10 the middle toggle switch
        RPIO.output(18,0) # this is pin 12 the top toggle switchdirno=4
        time.sleep(.05)

        RPIO.output(23,1) # next three lines press blue Go button for x stage
        time.sleep(0.2)
        RPIO.output(23,0)


class frameGrabber(QtCore.QThread):

    def __init__(self, cameraID=0):
        QtCore.QThread.__init__(self)
        self.cameraID = cameraID

    def run(self):
        cap = cv2.VideoCapture(self.cameraID)
        cap.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH,320)
        cap.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT,180)

        while(True): 
            time.sleep(0.25)
            ret, frame = cap.read()
            height, width, depth = frame.shape
            #print "H:",height,"W:",width
            frame = QtGui.QImage(frame.tostring(),width,height, QtGui.QImage.Format_RGB888).rgbSwapped()
            self.emit(QtCore.SIGNAL('webcam_frame(QImage)'), frame)


class Main(QtGui.QMainWindow):

    def __init__(self, parent = None):
        QtGui.QMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        ## Initialise IO (Raspberry Pi GPIO)
        self.InitIO(self.ui)

        ## SetupSignals
        self.SetupSignals()

    class InitIO(QtCore.QThread):
        def __init__(self,ui):
            print "IO Initialised"
            RPIO.setmode(RPIO.BCM)  
            RPIO.cleanup()

            RPIO.setup(21,RPIO.OUT,initial=1)    
            RPIO.setup(20,RPIO.OUT,initial=0)    # LSB
            RPIO.setup(16,RPIO.OUT,initial=0)   
            RPIO.setup(12,RPIO.OUT,initial=0)    #
            RPIO.setup(7,RPIO.OUT,initial=0)    # MSB
            RPIO.setup(26,RPIO.IN,pull_up_down=RPIO.PUD_UP)                 


    def RightAxisMovement(self):
        print "Moving Up"
        IO_WorkerThread = IO_Worker()
        IO_WorkerThread.MoveRight()

    def LeftAxisMovement(self):
        IO_WorkerThread = IO_Worker()
        IO_WorkerThread.MoveLeft()

    def ProcessCamFrame(self,frame):
        #print "Frame update", frame
        pix = QtGui.QPixmap(frame)
        pix = pix.scaled(self.ui.Video_Out.size())       
        self.ui.Video_Out.setPixmap(pix)



    def SetupSignals(self):

        ##############################################################
        ## Start Camera Thread
        ##############################################################
        camWorker = frameGrabber()
        camWorker.start()
         QtCore.QObject.connect(camWorker,QtCore.SIGNAL("webcam_frame(QImage)"),self.ProcessCamFrame)


        IO_WorkerThread = IO_Worker()
        IO_WorkerThread.start()

        ##############################################################
        ## Listen to Movement Button Class
        ##############################################################
        self.ui.pButton_Left.clicked.connect(self.LeftAxisMovement)
        self.ui.pButton_Right.clicked.connect(self.RightAxisMovement)


##---------------------------------------------------------------------
if __name__== "__main__":

    app = QtGui.QApplication(sys.argv)
    window = Main()    
    window.show()

    sys.exit(app.exec_())
0

There are 0 answers