Linking Live data from an Arduino to a LCDNumber f

2020-03-31 06:58发布

问题:

I am fairly new to making a GUI. I designed one for a project that I would like to have LCDs update as the data comes in from the Arduino. I am using pyqt5 to convert my Qtdesigner GUI. The trouble is I do not know how to link the incoming data to the GUI.

Currently I have a program that gathers all of the data I would like and it opens up the display that was created by Qtdesigner. In the picture I have attached the LCD that is selected is called: lcdNumber_4 in the object name.

"""
SCSU DYNO GUI PROGRAM

created 10/20/2017

"""


import sys
import time
import serial
import serial.tools.list_ports
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QThread,QTimer
from PyQt5.QtWidgets import QMessageBox,QWidget
from DynoTest1 import Ui_DynoTest1
import csv
import numpy as np
import warnings
import serial
import serial.tools.list_ports

__author__ = 'Matt Munn'

class GetData(QThread):
    def __init__(self):        

        QThread.__init__(self)

        arduino_ports = [ # automatically searches for an Arduino and selects the port it's on
            p.device
            for p in serial.tools.list_ports.comports()
            if 'Arduino' in p.description
        ]
        if not arduino_ports:
            raise IOError("No Arduino found - is it plugged in? If so, restart computer.")
        if len(arduino_ports) > 1:
            warnings.warn('Multiple Arduinos found - using the first')
        self.ArduinoData = serial.Serial(arduino_ports[0], 9600, timeout = 1)
        self.ArduinoData.close()
        self.ArduinoData.open()


        self.Arduino.flush()
        self.Arduino.reset_input_buffer()

        start_time=time.time()
        Distance = 0.5 # This is how long the lever arm is in feet

    def __del__(self): # part of the standard format of a QThread

        self.wait()
    def run(self): # also a required QThread function, the working part    

        while True:
            while (Arduino.inWaiting()==0):
                pass
            try:
                data = Arduino.readline()
                dataarray = data.decode().rstrip().split(',')
                Arduino.reset_input_buffer()
                Force = round(float(dataarray[0]),3)
                RPM = round(float (dataarray[1]),3)
                Torque = round(Force * Distance,3)
                HorsePower = round(Torque * RPM / 5252,3)
                Run_Time = round(time.time()-start_time,3)
                print (Force , 'Grams',"," , RPM ,'RPMs',"," ,Torque,"ft-lbs",",", HorsePower, "hp", Run_Time, "Time Elasped")
            except (KeyboardInterrupt, SystemExit,IndexError,ValueError):
                pass


class GUI(Ui_DynoTest1): # create GUI and functionality



    def __init__(self):
        self.MainWindow = QtWidgets.QWidget() # pull code from DynoTest1.py and initialize
        self.setupUi(self.MainWindow)




def main(): # follow PYQT5 proper format for a GUI

    app=QtWidgets.QApplication(sys.argv)    
    Dyno = GUI()
    Dyno.MainWindow.show()
    sys.exit(app.exec_())
# In[8]:
if __name__ == '__main__':

    main()

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'dynotest1.ui'
#
# Created by: PyQt5 UI code generator 5.9
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_DynoTest1(object):
    def setupUi(self, DynoTest1):
        DynoTest1.setObjectName("DynoTest1")
        DynoTest1.resize(1001, 695)
        self.verticalLayout_4 = QtWidgets.QVBoxLayout(DynoTest1)
        self.verticalLayout_4.setObjectName("verticalLayout_4")
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.verticalLayout_3 = QtWidgets.QVBoxLayout()
        self.verticalLayout_3.setObjectName("verticalLayout_3")
        self.gridLayout = QtWidgets.QGridLayout()
        self.gridLayout.setObjectName("gridLayout")
        self.pushButton_2 = QtWidgets.QPushButton(DynoTest1)
        self.pushButton_2.setObjectName("pushButton_2")
        self.gridLayout.addWidget(self.pushButton_2, 1, 0, 1, 1)
        self.pushButton_4 = QtWidgets.QPushButton(DynoTest1)
        self.pushButton_4.setObjectName("pushButton_4")
        self.gridLayout.addWidget(self.pushButton_4, 1, 1, 1, 1)
        self.pushButton_3 = QtWidgets.QPushButton(DynoTest1)
        self.pushButton_3.setObjectName("pushButton_3")
        self.gridLayout.addWidget(self.pushButton_3, 0, 1, 1, 1)
        self.pushButton = QtWidgets.QPushButton(DynoTest1)
        self.pushButton.setObjectName("pushButton")
        self.gridLayout.addWidget(self.pushButton, 0, 0, 1, 1)
        self.verticalLayout_3.addLayout(self.gridLayout)
        self.label_3 = QtWidgets.QLabel(DynoTest1)
        self.label_3.setObjectName("label_3")
        self.verticalLayout_3.addWidget(self.label_3)
        self.label_2 = QtWidgets.QLabel(DynoTest1)
        self.label_2.setObjectName("label_2")
        self.verticalLayout_3.addWidget(self.label_2)
        self.label = QtWidgets.QLabel(DynoTest1)
        self.label.setObjectName("label")
        self.verticalLayout_3.addWidget(self.label)
        self.horizontalLayout.addLayout(self.verticalLayout_3)
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.label_5 = QtWidgets.QLabel(DynoTest1)
        self.label_5.setObjectName("label_5")
        self.verticalLayout.addWidget(self.label_5)
        self.lcdNumber_4 = QtWidgets.QLCDNumber(DynoTest1)
        self.lcdNumber_4.setObjectName("lcdNumber_4")
        self.verticalLayout.addWidget(self.lcdNumber_4)
        self.lcdNumber_5 = QtWidgets.QLCDNumber(DynoTest1)
        self.lcdNumber_5.setObjectName("lcdNumber_5")
        self.verticalLayout.addWidget(self.lcdNumber_5)
        self.lcdNumber_6 = QtWidgets.QLCDNumber(DynoTest1)
        self.lcdNumber_6.setObjectName("lcdNumber_6")
        self.verticalLayout.addWidget(self.lcdNumber_6)
        self.horizontalLayout.addLayout(self.verticalLayout)
        self.verticalLayout_2 = QtWidgets.QVBoxLayout()
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.label_6 = QtWidgets.QLabel(DynoTest1)
        self.label_6.setObjectName("label_6")
        self.verticalLayout_2.addWidget(self.label_6)
        self.lcdNumber = QtWidgets.QLCDNumber(DynoTest1)
        self.lcdNumber.setObjectName("lcdNumber")
        self.verticalLayout_2.addWidget(self.lcdNumber)
        self.lcdNumber_2 = QtWidgets.QLCDNumber(DynoTest1)
        self.lcdNumber_2.setObjectName("lcdNumber_2")
        self.verticalLayout_2.addWidget(self.lcdNumber_2)
        self.lcdNumber_3 = QtWidgets.QLCDNumber(DynoTest1)
        self.lcdNumber_3.setObjectName("lcdNumber_3")
        self.verticalLayout_2.addWidget(self.lcdNumber_3)
        self.horizontalLayout.addLayout(self.verticalLayout_2)
        self.horizontalLayout_2.addLayout(self.horizontalLayout)
        self.verticalLayout_5 = QtWidgets.QVBoxLayout()
        self.verticalLayout_5.setObjectName("verticalLayout_5")
        self.label_7 = QtWidgets.QLabel(DynoTest1)
        self.label_7.setObjectName("label_7")
        self.verticalLayout_5.addWidget(self.label_7)
        self.lcdNumber_7 = QtWidgets.QLCDNumber(DynoTest1)
        self.lcdNumber_7.setObjectName("lcdNumber_7")
        self.verticalLayout_5.addWidget(self.lcdNumber_7)
        self.horizontalLayout_2.addLayout(self.verticalLayout_5)
        self.verticalLayout_4.addLayout(self.horizontalLayout_2)
        self.graphicsView = QtWidgets.QGraphicsView(DynoTest1)
        self.graphicsView.setStyleSheet("border-image: url(:/newPrefix/husky_head5.png);")
        self.graphicsView.setObjectName("graphicsView")
        self.verticalLayout_4.addWidget(self.graphicsView)

        self.retranslateUi(DynoTest1)
        QtCore.QMetaObject.connectSlotsByName(DynoTest1)

    def retranslateUi(self, DynoTest1):
        _translate = QtCore.QCoreApplication.translate
        DynoTest1.setWindowTitle(_translate("DynoTest1", "DynoTest1"))
        self.pushButton_2.setText(_translate("DynoTest1", "Pause"))
        self.pushButton_4.setText(_translate("DynoTest1", "Print"))
        self.pushButton_3.setText(_translate("DynoTest1", "Stop"))
        self.pushButton.setText(_translate("DynoTest1", "Start"))
        self.label_3.setText(_translate("DynoTest1", "<html><head/><body><p align=\"center\"><span style=\" font-size:18pt; font-weight:600;\">RPMs</span></p></body></html>"))
        self.label_2.setText(_translate("DynoTest1", "<html><head/><body><p align=\"center\"><span style=\" font-size:18pt; font-weight:600;\">Torque (ft-lbs)</span></p></body></html>"))
        self.label.setText(_translate("DynoTest1", "<html><head/><body><p align=\"center\"><span style=\" font-size:18pt; font-weight:600;\">Horse Power</span></p></body></html>"))
        self.label_5.setText(_translate("DynoTest1", "<html><head/><body><p align=\"center\"><span style=\" font-size:18pt; font-weight:600;\">Now</span></p></body></html>"))
        self.label_6.setText(_translate("DynoTest1", "<html><head/><body><p align=\"center\"><span style=\" font-size:18pt; font-weight:600;\">Max</span></p></body></html>"))
        self.label_7.setText(_translate("DynoTest1", "<html><head/><body><p align=\"center\"><span style=\" font-size:18pt; font-weight:600;\">Run Time</span></p></body></html>"))

import Resource_rc

回答1:

For the correct operation I have modified the name of some variables because they do not match their use. In order to send information between elements of PyQt it is advisable to use signals and slots, for this you must create a signal in QThread that sends the information that is required to be displayed in the GUI for this we use pyqtSignal() where we indicate the types of parameters that go to send.

class GetData(QThread):
    dataChanged = pyqtSignal(float, float, float, float)
    Distance = 0.5

    def __init__(self, parent=None):
        QThread.__init__(self, parent)

        arduino_ports = [  # automatically searches for an Arduino and selects the port it's on
            p.device
            for p in serial.tools.list_ports.comports()
            if 'Arduino' in p.description
        ]

        if not arduino_ports:
            raise IOError("No Arduino found - is it plugged in? If so, restart computer.")
        if len(arduino_ports) > 1:
            warnings.warn('Multiple Arduinos found - using the first')
        self.Arduino = serial.Serial(arduino_ports[0], 9600, timeout=1)

    def __del__(self):  # part of the standard format of a QThread
        self.wait()

    def run(self):  # also a required QThread function, the working part
        self.Arduino.close()
        self.Arduino.open()

        self.Arduino.flush()
        self.Arduino.reset_input_buffer()
        start_time = time.time()

        while True:
            while self.Arduino.inWaiting() == 0:
                pass
            try:
                data = self.Arduino.readline()
                dataarray = data.decode().rstrip().split(',')
                self.Arduino.reset_input_buffer()
                Force = round(float(dataarray[0]), 3)
                RPM = round(float(dataarray[1]), 3)
                Torque = round(Force * GetData.Distance, 3)
                HorsePower = round(Torque * RPM / 5252, 3)
                Run_Time = round(time.time() - start_time, 3)
                print(Force, 'Grams', ",", RPM, 'RPMs', ",", Torque, "ft-lbs", ",", HorsePower, "hp", Run_Time,
                      "Time Elasped")
                self.dataChanged.emit(RPM, Torque, HorsePower, Run_Time)
            except (KeyboardInterrupt, SystemExit, IndexError, ValueError):
                pass

Qt Designer provides a design, does not provide a widget, for that it is best to create a class inherit from a widget and use the design, create an instance of QThread and connect the dataChanged signal to some slot, and in that slot is where we place the values in the QLCDNumber.

class GUI(QWidget, Ui_DynoTest1):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.setupUi(self)
        self.thread = GetData(self)
        self.thread.dataChanged.connect(self.onDataChanged)
        self.thread.start()

    def onDataChanged(self, RPM, Torque, HorsePower, Run_Time):
        self.lcdNumber_4.display(RPM)
        self.lcdNumber_5.display(Torque)
        self.lcdNumber_6.display(HorsePower)
        self.lcdNumber_7.display(Run_Time)


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    Dyno = GUI()
    Dyno.show()
    sys.exit(app.exec_())