Home>
environment

raspberry pi 3 B
python 3.x
PyQt5

Contents of question

How to use QThead
Is it possible to pass sensor acquisition information from the main thread when creating a subthread in Qthead and executing a function?

Code I created

There are some strange and unpleasant parts of the code (such as the contents of def auto (self)), but don't worry.

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import subprocess
import time
import numpy as np
import cv2
import RPi.GPIO as GPIO

Shoden_PIN = 22
Motor_PIN_1 = 24
Motor_PIN_2 = 25
Reed_PIN_1 = 17
Reed_PIN_2 = 27
GPIO.setmode (GPIO.BCM)
GPIO.setup (Shoden_PIN, GPIO.IN)
GPIO.setup (Reed_PIN_1, GPIO.IN)
GPIO.setup (Reed_PIN_2, GPIO.IN)
def setMotor ():
    GPIO.setmode (GPIO.BCM)
    GPIO.setup (Motor_PIN_1, GPIO.OUT)
    GPIO.setup (Motor_PIN_2, GPIO.OUT)
def Motor_Forward ():
    GPIO.output (Motor_PIN_1, 1)
    GPIO.output (Motor_PIN_2, 0)
def Motor_Backward ():
    GPIO.output (Motor_PIN_1, 0)
    GPIO.output (Motor_PIN_2, 1)
def Motor_Stop ():
    GPIO.output (Motor_PIN_1, 0)
    GPIO.output (Motor_PIN_2, 0)
def Clean ():
    GPIO.cleanup (24)
    GPIO.cleanup (25)class Tab1Widget (QWidget):
    def __init __ (self, parent = None):
        super () .__ init __ (parent)
        self.qt_thread = None
        # self.running = False
        self.title = "GUI test"
        self.left = 10
        self.top = 10
        self.width = 640
        self.height = 480
        self.initUI ()
        self.counter = 0
    def init UI (self):

        btn1 = self.auto_button = QPushButton ("auto", self)
        btn2 = self.stop_button = QPushButton ("stop", self)
        btn1.clicked.connect (self.auto)
        btn2.clicked.connect (self.stop)
        self.textbox4 = QLineEdit (self)

        label3 = QLabel ("automatic door")
        label4 = QLabel ("door condition")
        #GUI layout (omitted)
    def closeEvent (self, event):
        self.stop ()
        if self.qt_thread:
            self.qt_thread.wait (2000)
        super (). closeEvent (event)
    def stop (self):
        if self.qt_thread:
            self.qt_thread.requestInterruption ()

    def setCount (self, alpha):
        self.textbox4.setText ("{}". format (alpha))

    def auto (self):
        class MyQtThread (QThread):
            sendString = pyqtSignal (str)
            def run (self):
                while 1:
                    if self.isInterruptionRequested ():
                        break
                    if GPIO.input (Shoden_PIN) == GPIO.HIGH: #Object detection
                        door = "OPENED"
                        self.sendString.emit (door)setMotor ()
                        Motor_Forward () #Door opens
                        while 1:
                            if self.isInterruptionRequested ():
                                return
                            if GPIO.input (Reed_PIN_2) == GPIO.HIGH: #Door opens completely
                                Motor_Stop ()
                                time.sleep (1)
                                if self.isInterruptionRequested ():
                                    return
                                Motor_Backward () #Door closes
                                while 1:
                                    if self.isInterruptionRequested ():
                                        return
                                    if GPIO.input (Reed_PIN_1) == GPIO.HIGH: #Door closes completely
                                        Motor_Stop ()
                                        door = "CLOSED"
                                        self.sendString.emit (door)
                                        time.sleep (1)
                                        break
                                    else: else:
                                        pass
                                break
                            else: else:
                                pass
                        break
                    else: else:
                        pass
        Clean ()

        thread = self.qt_thread = MyQtThread ()
        thread.sendString.connect (self.setCount)
        self.stop_button.clicked.connect (self.stop)
        thread.finished.connect (lambda: print ("Qt Thread Finished"))
        thread.start ()

if __name__ == "__main__":
    app = QApplication (sys.argv)
    ex = Tab1Widget ()
    sys.exit (app.exec_ ())

In the code above, all the actions (getting information from the sensor, driving the motor) are put in a subthread.
What I want to do is "use QTimer in the main thread to always get the sensor information, pass it to the sub thread and run the motor in the sub thread".
Is it possible to pass information between the main thread and the sub thread with QThead?
Please professor.

  • Answer # 1

    What I want to do is "use QTimer in the main thread to always get the sensor information, pass it to the sub thread and run the motor in the sub thread".

    Sensor information is I/O with external devices, isn't it? Here is a point that can be improved
    I think it should be processed in threads rather than QTimer.

    QTimer processes it inside the GUI event loop, so
    If you have any problems interacting with the sensor
    It's easy to get the GUI unresponsive.

    Is it possible to pass information between the main thread and the sub thread with QThead?

    You can send data to another thread's event loop with signals&slots

    Even in the code of the question, it's the opposite of what you want to do,
    Passing from another thread to the main thread (event loop).

    Send door information with self.sendString.emit (door)

    thread.sendString.connect (self.setCount) Calls setCount on emit.

    There are some strange and unpleasant parts of the code (such as the contents of def auto (self)), but don't worry.

    This is the most important part, not the appearance of the code.

    How to use "Signal&Slot Mechanism" with QThread
    Because we need an event loop, instead of overriding run ()
    It needs to be implemented in another way of using QThread.

    In this usage of QThread,Subthread event loop is not workingSo
    It is not a data transfer between threads, but a function call within the same thread.
    (Take a log and check which thread is running)

    * I remember explaining the details in the previous question.
    Reference: https://stackoverflow.com/questions/267587


    Note: GUI drawing update processing is always done
    Must be done in the main thread (running the GUI event loop).

    Suggestions for improvement:

    Assign separate threads to the sensor and motor processing,
    Signaling regular information income at the sensor,
    Connect to the motor or main (GUI) slot.

    The signal can also be connected to multiple slots.

    If you want to read information regularly with a sensor or motor, consider using a timer in the thread.