انجمن‌های فارسی اوبونتو

لطفاً به انجمن‌ها وارد شده و یا جهت ورود ثبت‌نام نمائید

لطفاً جهت ورود نام کاربری و رمز عبورتان را وارد نمائید

نویسنده موضوع: مشکل اجرا در pyqt5  (دفعات بازدید: 883 بار)

0 کاربر و 1 مهمان درحال مشاهده موضوع.

آفلاین قاسم طلایی

  • Full Member
  • *
  • ارسال: 122
  • جنسیت : پسر
مشکل اجرا در pyqt5
« : 22 آذر 1398، 11:27 ق‌ظ »
با سلام خدمت دوستان
من یه نرم افزار ساده با pyqt5 ساختم که کارش مانیتورینگ اطلاعات برد آردوینو هست.یعنی آردوینو به کامپیوتر وصل میشه و نرم افزار اونا رو مانیتور میکنه و فرمان به سمت میکرو صادر میکنه.
مشکل من بد اجرا شدن نرم افزار هست.با اینکه خیلی بار پردازشی زیادی نداره ولی خیلی سنگین اجرا میشه.البته این زمانی اتفاق میفته که درون while true قرار میگیره.یه خورده سرچ کردم و متوجه شدم باید عبارت QApplication.processEvents() رو در قسمت هایی که یه مقدار بار پردازشی سنگین میشه قرار داد.این کار رو کردم و نرم افزار یه خورده روان تر شد ولی باز هم یه خورده لگ داره.
اینم تصویر برنامه من هست.

https://pasteboard.co/IL1S2oO.png

و این هم کد برنامه هست.
import sys
from PyQt5.QtWidgets import QDialog ,QApplication ,QSlider ,QProgressBar
from out import *
import serial
import matplotlib.pyplot as plt
from matplotlib import style

lamp=0
y_temp=[]
y_hum=[]

class MyAPP(QDialog):
    def __init__(self):
        super().__init__()
        self.ui=Ui_Dialog()
        self.ui.setupUi(self)
        self.ui.pushButton.clicked.connect(self.message)
        self.ui.find_port_push.clicked.connect(self.find_port)
        self.ui.close.clicked.connect(self.close_port)
        self.ui.lamp_change.valueChanged.connect(self.change_lamp)
        self.show()
    def change_lamp(self):
        global lamp
        QApplication.processEvents()
        lamp=self.ui.lamp_change.value()
        if lamp == 0:
            self.ui.lamp_status.setText('خاموش')
        if lamp == 1:
            self.ui.lamp_status.setText('روشن')
        QApplication.processEvents()
    def close_port(self):
        ser=serial.Serial()
        global x
        x = 0
        ser.close()
        self.ui.check_connect.setText("قطع اتصال.صبر کنید")
        style.use('fivethirtyeight')
        #hum graph
        plt.subplot(2,1,1)
        plt.plot(y_hum)
        plt.title('Humidity chart')
        plt.ylabel('Humidity')
        #temp graph
        plt.subplot(2,1,2)
        plt.plot(y_temp)
        plt.title('Temperature chart')
        plt.ylabel('Temperature ($^\circ$C)')
        #show graph
        plt.show()
    def find_port(self):
        ser = serial.Serial()
        ser.baudrate=int(self.ui.buadrate.itemText(self.ui.buadrate.currentIndex()))
        coms=['COM1','COM2','COM3','COM4','COM5','COM6','COM7','COM8','COM9','COM10','COM11','COM12']
        for x in coms:
            ser.port=x
            try:
                ser.open()
            except:
                self.ui.find_port_label.setText("لطفا صبر کنید...")
            finally:
                if ser.is_open == True :
                    self.ui.find_port_label.setText(x)
                    ser.close()
                    break
                else:
                    self.ui.find_port_label.setText('پورت پیدا نشد !')
    def message(self):
        global x
        global lamp
        x = 1
        ser = serial.Serial()
        ser.baudrate=int(self.ui.buadrate.itemText(self.ui.buadrate.currentIndex()))
        ser.port=self.ui.port.itemText(self.ui.port.currentIndex())
        try:
            ser.open()
        except:
            self.ui.check_connect.setText("اتصال ناموفق")
        finally:
            if ser.is_open == True :
                QApplication.processEvents()
                self.ui.check_connect.setText("اتصال برقرار است")
                while True:
                    #QApplication.processEvents()
                    if ser.is_open == True:
                        #QApplication.processEvents()
                        s=ser.readline()
                        s=str(s)
                        s=s.strip('b')
                        s=s.strip("'")
                        s=s.split("&")
                        s[1]=s[1].strip("\\r\\n")
                        QApplication.processEvents()
                        if s[0] != ' NAN':
                            QApplication.processEvents()
                            self.ui.lcd_temp.setText(s[0])
                            QApplication.processEvents()
                            self.ui.bar_temp.setValue(abs(float(s[0])))
                            QApplication.processEvents()
                            self.ui.lcd_hum.setText(s[1])
                            QApplication.processEvents()
                            self.ui.bar_hum.setValue(abs(float(s[1])))
                            QApplication.processEvents()
                            y_hum.append(abs(float(s[1])))
                            y_temp.append(abs(float(s[0])))
                        ser.write(lamp)
                        if x != 1:
                            x = 1
                            break
                       
if __name__=="__main__":
    app=QApplication(sys.argv)
    w=MyAPP()
    w.show()
    sys.exit(app.exec_())


آفلاین Geek

  • High Hero Member
  • *
  • ارسال: 1116
  • جنسیت : پسر
  • The answer to life the universe and everything: 42
پاسخ : مشکل اجرا در pyqt5
« پاسخ #1 : 22 آذر 1398، 06:16 ب‌ظ »
باید از کلاس QThread استفاده کنی:
https://doc.qt.io/qt-5/qthread.html
اطلاعات بیشتر:
https://en.wikipedia.org/wiki/Multithreading_(computer_architecture)

آفلاین احمد حمزه ئی

  • Jr. Member
  • *
  • ارسال: 66
  • جنسیت : پسر
    • Github
پاسخ : مشکل اجرا در pyqt5
« پاسخ #2 : 23 آذر 1398، 02:22 ب‌ظ »
می‌تونید بجای pyserial از QSerialPort استفاده کنید (برای مثال این پاسخ رو ببینید).
وقتی یک بایت از درگاه سریال دریافت شد، سیگنال readyRead صدا زده میشه و بدون استفاده از حلقه بایت‌های دریافتی در دسترس هست.
به عنوان یک پروتکل ساده، میشه خروجی حسگرها رو در میکروکنترلر به شکل یک رشته درآورد که داده‌های مختلف با کاما جدا شده:
22.51,10.0\nمثلا عدد اول دما و دومی رطوبت هست. کاراکتر n\ هم انتهای پیام رو مشخص میکنه.
در پایتون وقتی کاراکتر n\ رسید یعنی یک پیام کامل دریافت شد، بنابراین کد زیر اجرا میشه و متن پیام در متغیر text و داده‌ها بصورت عدد اعشاری در آرایه data‌ قرار می‌گیره:
text = self.serial.readLine().data().decode().rstrip()
data = [float(x) for x in text.split(',')]

نمونه برنامه کامل، تصویرش رو پیوست کردم:
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QComboBox, QPushButton, QVBoxLayout, QWidget, QTextEdit, QLabel
from PyQt5.QtSerialPort import QSerialPort, QSerialPortInfo
from PyQt5.QtCore import QIODevice

class Window(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('Serial Port')
        self.statusBar().showMessage('Ready')

        layout = QVBoxLayout()
        widget = QWidget()
        widget.setLayout(layout)

        self.textView = QTextEdit(readOnly=True)
        layout.addWidget(self.textView)

        self.temperatureLabel = QLabel('Temperature: no data')
        layout.addWidget(self.temperatureLabel)

        self.humidityLabel = QLabel('Humidity: no data')
        layout.addWidget(self.humidityLabel)

        self.portCombo = QComboBox()
        ports = QSerialPortInfo.availablePorts()
        self.portCombo.addItems([port.portName() for port in ports])
        layout.addWidget(self.portCombo)

        self.connectButton = QPushButton('Connect')
        layout.addWidget(self.connectButton)
        self.connectButton.clicked.connect(self.connectSerial)

        self.serial = QSerialPort(self)
        self.serial.readyRead.connect(self.readData)

        self.setCentralWidget(widget)
        self.show()

    def connectSerial(self):
        if not self.serial.isOpen():
            portName = self.portCombo.currentText()
            self.serial.setPortName(portName)
            successful = self.serial.open(QIODevice.ReadWrite)

            if successful:
                self.statusBar().showMessage('Port opened.')
                self.connectButton.setText('Disconnect')
            else:
                self.statusBar().showMessage('Port was not opened.')
        else:
            self.serial.close()
            self.statusBar().showMessage('Port closed.')
            self.connectButton.setText('Connect')

    def readData(self):
        while self.serial.canReadLine():
            self.statusBar().showMessage('Data received.')
            text = self.serial.readLine().data().decode().rstrip()
            self.textView.append(text)

            data = [float(x) for x in text.split(',')]
            self.temperatureLabel.setText('Temperature: {}'.format(data[0]))
            self.humidityLabel.setText('Humidity: {}'.format(data[1]))

if __name__=="__main__":
    app = QApplication(sys.argv)
    win = Window()
    sys.exit(app.exec_())

توی این کد، خط self.serial.readyRead.connect(self.readData) سیگنال readyRead رو به تابع readData متصل میکنه و با دریافت هر بایت این تابع اجرا میشه.
در داخل تابع با چک کردن ()self.serial.canReadLine میشه فهمید که یک پیام کامل دریافت شده.

آفلاین قاسم طلایی

  • Full Member
  • *
  • ارسال: 122
  • جنسیت : پسر
پاسخ : مشکل اجرا در pyqt5
« پاسخ #3 : 24 آذر 1398، 08:49 ب‌ظ »
بسیار متشکرم از پاسخ جامع شما. با استفاده از کتابخانه qserialport مشکل حل شد. البته مشکل اصلی من در قسمت پایتون بود نه در قسمت میکرو.
بازم متشکرم