绘图时生成多个图形

问题描述 投票:0回答:0

问题: 我使用 Python 和 QtCreator (PyQt5 qtpy) 开发了一个 GUI,它从热电偶和压力计获取实时数据,并在 GUI 中持续显示最新的测量结果。 这些测量结果还用于计算后台的体积流量。 我的目标是最终生成两个输出。一方面,当我终止整个测量过程(使用“结束测量”按钮)时,应创建一个包含上述实时测量结果的 csv 文件 --> 效果很好。

第二个输出应该是一个(或两个)图,在 x 轴上显示运行时间(以秒为单位),在主 y 轴上显示温度(该参数在第 70 行中称为 t_input),在辅助轴上显示体积流量y 轴(该参数在第 132 行中称为 qv)。 其实这在我眼里是一个很简单的问题。因为我知道如何创建绘图,但它只是不想在这里工作。我之前的尝试总是导致每次迭代都会创建多个图形。 我还会给你代码和 GUI 的截图,希望你能理解。

如果您有任何疑问等,请告诉我。

我希望你能帮助我,我已经很感激你的帮助了。

致以诚挚的问候

enter image description here


#############################################    Imports für QtPy    ##################################################
from qtpy import QtWidgets
from frm_ProjectC3.mainwindow import Ui_MainWindow
from PyQt5.QtCore import QTimer
#############################################    Import für Messelemente (ADAM), Plotting und CSV-Erstellung   ##################################################
import serial, math, time, sys, csv
from datetime import datetime
import matplotlib.pyplot as plt
import numpy as np
#############################################    Globale Parameter   ##################################################
pi = math.pi
date = datetime.now()                                       # Getting the current date and time - Soll dazu genutzt werden, um der txt-Datei automatisert einen Namen geben zu können.
datetime_for_csv = date.strftime("%m%d%Y_%H_%M_%S")         # Soll genutzt werden um in die CSV Datei das richtige Datum zu printen

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent = None):
        super().__init__(parent)
        self.setWindowTitle("Projekt: C3")
        self.ui = Ui_MainWindow()

        self.ui.setupUi(self)
        self.timer = QTimer()
        self.ser = serial.Serial()
        self.ser.baudrate = 9600
        self.ser.port = self.ui.cbBox_serialPort.currentText()

        #Es benötigt die changed Funktion "currentTextChanged" um den Wert des Com-Ports neu zu setzen.
        self.ui.cbBox_serialPort.currentTextChanged.connect(self.on_combobox_changed)
        self.ser.stopbits = 1
        self.ser.bytesize = 8
        self.ser.parity = 'N'


        self.ui.btn_MessungStarten.clicked.connect(self.btn_messungStarten_click) #Führt den Button "Messung Starten" aus.
        #self.ui.btn_MessungStarten.clicked.connect(self.update_plot)
        self.ui.btn_MessungBeenden.clicked.connect(self.btn_messungBeenden_click) #Führt den Button "Messung Beenden" aus.

    # currentTextChanged Abfrage des aktuellen Wertes
    def on_combobox_changed(self):
        self.ser.port = self.ui.cbBox_serialPort.currentText()

    def showTime(self):
        #Hier werden die Temperaturen durch die entsprechenden ADAM-Controller ausgelesen.
        self.ser.write('#00\r'.encode('utf-8'))
        s1 = self.ser.read_until('\r'.encode('utf-8'), size=None)  # all channels
        t = []
        for i in range(1, len(s1) - 2, 7):
            t.append(float(s1[i:i + 7]))



        #Hier werden die Drücke durch die entsprechenden ADAM-Controller ausgelesen (ABER noch in VOLT).
        self.ser.write('#02\r'.encode('utf-8'))
        s2 = self.ser.read_until('\r'.encode('utf-8'), size=None)  # specific channel
        p = []
        for i in range(1, len(s2) - 2, 7):
            p.append(float(s2[i:i + 7]))

        ############################################################  Hier werden die Temp_Labels mit dem aktuellsten Wert beschrieben.   ###########################################################
        self.ui.temp_0_output.setText(str(round(t[0],2)))
        self.ui.ambientTemp_lbl.setText(str(round(t[0],2)))
        self.ui.temp_1_output.setText(str(round(t[1],2)))
        self.ui.temp_2_output.setText(str(round(t[2],2)))
        self.ui.temp_3_output.setText(str(round(t[3],2)))
        self.ui.temp_4_output.setText(str(round(t[4],2)))
        self.ui.temp_5_output.setText(str(round(t[5],2)))
        self.ui.temp_6_output.setText(str(round(t[6],2)))
        self.ui.temp_7_output.setText(str(round(t[7],2)))

        ############################################################  Arithmetisches Mittel der Temp_1-3 ergeben T_input (Temperatur über Schüttgut)  ###########################################################
        t_input = round(((t[1] + t[2] + t[3]) / 3), 2)
        self.ui.temp_aboveBulk_lbl.setText(str(t_input))

        ########################################################### Hier werden die Press_Labels mit dem aktuellsten Wert beschrieben --> Werden aufgrund der Linearität von Volt in [Pa] umgerechnet werden.   ###########################################################
        press_1 = round(1.013 * 10 ** 5 + (p[0] * 20 * 100), 2)
        self.ui.press_1_output.setText(str(press_1))
        d_press_1 = round(1.013 * 10 ** 5 + (p[1] * 5 * 100), 2)
        self.ui.press_dp1_output.setText(str(d_press_1))
        d_press_2 = round(1.013 * 10 ** 5 + (p[2] * 5 * 100), 2)
        self.ui.press_dp2_output.setText(str(d_press_2))
        d_press_3 = round(1.013 * 10 ** 5 + (p[3] * 5 * 100), 2)
        self.ui.press_dp3_output.setText(str(d_press_3))

        ########################################################### Beschriftung der Tabelle in der GUI ###########################################################
        # Anzahl der Tabellen-Zeilen:
        position = self.ui.dataOutput_tbl.rowCount()
        self.ui.dataOutput_tbl.insertRow(position)
        # self.ui.dataOutput_tbl.setItem(row, column,item) --> row = position, column = 0 - 13 [0 = Datum; 1-8 = Temps.; 9-13 = Drücke], und item sind die für die jeweilige Spalte zu übergebenden Daten
        self.ui.dataOutput_tbl.setItem(position, 0, QtWidgets.QTableWidgetItem(datetime_for_csv))
        self.ui.dataOutput_tbl.setItem(position, 1, QtWidgets.QTableWidgetItem(str(round(t[0],2))))
        self.ui.dataOutput_tbl.setItem(position, 2, QtWidgets.QTableWidgetItem(str(round(t[1],2))))
        self.ui.dataOutput_tbl.setItem(position, 3, QtWidgets.QTableWidgetItem(str(round(t[2],2))))
        self.ui.dataOutput_tbl.setItem(position, 4, QtWidgets.QTableWidgetItem(str(round(t[3],2))))
        self.ui.dataOutput_tbl.setItem(position, 5, QtWidgets.QTableWidgetItem(str(round(t[4],2))))
        self.ui.dataOutput_tbl.setItem(position, 6, QtWidgets.QTableWidgetItem(str(round(t[5],2))))
        self.ui.dataOutput_tbl.setItem(position, 7, QtWidgets.QTableWidgetItem(str(round(t[6],2))))
        self.ui.dataOutput_tbl.setItem(position, 8, QtWidgets.QTableWidgetItem(str(round(t[7],2))))
        self.ui.dataOutput_tbl.setItem(position, 9, QtWidgets.QTableWidgetItem(str(press_1)))
        self.ui.dataOutput_tbl.setItem(position, 10, QtWidgets.QTableWidgetItem(str(d_press_1)))
        self.ui.dataOutput_tbl.setItem(position, 11, QtWidgets.QTableWidgetItem(str(d_press_2)))
        self.ui.dataOutput_tbl.setItem(position, 12, QtWidgets.QTableWidgetItem(str(d_press_3)))


        ########################################################### Implementierung der Volumenstromberechnung / Implementation of flow rate  ###########################################################
        if self.ui.feuchtigkeit_umg_txtfield.text() == "":
            phi_umg = 60
        else:
            phi_umg = float(self.ui.feuchtigkeit_umg_txtfield.text())

        p_umg = 1.013 * 10 ** 5                    # Umgebungsdruck [Pa]
        dBlende = 0.040                            # Blendendurchmesser [m]
        dRohr = 0.054                              # Rohrdurchmesser [m]
        Kappa = 1.4                                # Isentropenkoeffizient
        beta = dBlende / dRohr                     # Durchmesserverhältnis
        p2 = press_1 - d_press_3  # Druck nach der Blende (Achtung Wirkdruck) TODO: Welche Drücke sind hier genau gemeint - press_1 und press_3 richtig????
        dynVis = (0.0000000119249 * t[0] ** 3 - 0.0000263646 * t[0] ** 2 + 0.0487178 * t[0] + 17.2638) * 1e-6  # dyn. Viskosität am Blendeneintritt (in diesem Druckbereich im wesentlichen nur Temperaturabhängig)
        self.ui.dynVis_output.setText(str(dynVis))
        psu = 6.11213 ** (17.5043 * t[0] / (241.2 + t[0]))  # Sättigungsdampfdruck bei Umgebungstemperatur[°C]
        self.ui.saettdampfdruck_umgebtemp_output.setText(str(round(psu,4)))
        xu = 0.622 * psu / ((p_umg / (phi_umg/100)) - psu)  # Wassergehalt
        self.ui.wassergehalt_output.setText(str(round(xu,8)))
        pse = 6.11213 ** (17.5043 * t[0] / (241.2 + t[0]))  # Sättigungsdampfdruck bei Eintrittstemperatur [°C] #TODO: hier muss glaube eine andere Temp. anstelle von t[0] hin!!!
        self.ui.saettdampfdruck_eintrittstemp_output.setText(str(round(pse,4)))
        phie = (p_umg + press_1) * xu / (pse * (0.622 + xu))  # Luftfeuchtigkeit Blendeneintritt
        self.ui.luftfeuchtigkeit_blendeintritt_output.setText(str(round(phie,5)))
        R = 287.058 / (1.0 - phie * pse * 0.377 / press_1)  # spez. Gaskonstante
        rho = press_1 / ((t[0] + 273.15) * R)  # Dichte der Luft
        epsilon = 1.0 - (0.351 + 0.256 * pow(beta, 4.0) + 0.93 * pow(beta, 8.0)) * (1.0 - pow((p2 / press_1), (1.0 / Kappa)))  # Expansionszahl (Korrekturfaktor)
        c = 0.6
        A1 = epsilon * pow(dBlende, 2.0) * pow((2.0 * d_press_3 * rho), 0.5) / (dynVis * dRohr * pow((1.0 - pow(beta, 4.0)), 0.5)) #TODO: press_3 hier richtig???
        x1 = c * A1
        qm = pi / 4.0 * dynVis * dRohr * x1  # Massenstrom [kg/s]
        qv = qm / rho  # Volumenstrom [m³/s]
        self.ui.volumenstrom_output.setText(str(qv))




        ###########################################################   Implementation of PLOT  ###########################################################
        """ - How do I create the x-axis for the runtime in seconds
            - How do I create the datasets for my both y-axis:
                - my primary y-axis (t_input in line 71 is a value which updates permanently)
                - my secon. y-axis (qv in line 133 is a value which updates permanently)"""
        plt.ion()
        fig, axis = plt.subplots(2, figsize=(14,9))
        fig.suptitle("Temperatur- und Volumenstrommessung")













    def btn_messungStarten_click(self):
        try:
            self.ser.open()
            self.timer.start(1000)
            self.timer.timeout.connect(self.showTime)
            self.ui.com_errormsg_lbl.setText("Sie nutzen " + self.ser.port)
            self.ui.com_errormsg_lbl.setStyleSheet("color: green")
            self.ui.com_finally_lbl.setText("Die Messung wird gestartet!")
            self.ui.com_finally_lbl.setStyleSheet("color: green")
            self.ui.btn_MessungStarten.setDisabled(True)





        except: 
            if self.ser.port == "--Auswählen--":
                self.ui.com_errormsg_lbl.setText("Bitte wählen Sie einen geeigneten COM-Port.")
                self.ui.com_errormsg_lbl.setStyleSheet("color: red")
                self.ui.com_finally_lbl.setText("")
            else:
                self.ui.com_errormsg_lbl.setText("Sie adressieren einen unbelegten COM-Port: " + self.ser.port)
                self.ui.com_errormsg_lbl.setStyleSheet("color: red")
                self.ui.com_finally_lbl.setText("")


    def btn_messungBeenden_click(self):
        if self.ser.port == "--Auswählen--":
            self.ui.com_errormsg_lbl.setText("Sie haben auf 'Messung stoppen' gedrückt")
            self.ui.com_errormsg_lbl.setStyleSheet("color: blue")
            self.ui.com_finally_lbl.setText("Das Programm wurde erfolgreich beendet!")
            self.ui.com_finally_lbl.setStyleSheet("color: green")
            self.timer.stop()
            self.ser.close()
        else:
            self.ui.com_errormsg_lbl.setText("Beendet: " + self.ser.port)
            self.ui.com_errormsg_lbl.setStyleSheet("color: blue")
            self.ui.com_finally_lbl.setText("Das Programm wurde erfolgreich beendet!")
            self.ui.com_finally_lbl.setStyleSheet("color: green")
            self.timer.stop()
            self.ser.close()

        path, ok = QtWidgets.QFileDialog.getSaveFileName(self, "'Data_Output' speichern",datetime_for_csv, '(*.txt)')
        if ok:
            columns = range(self.ui.dataOutput_tbl.columnCount())
            header = [self.ui.dataOutput_tbl.horizontalHeaderItem(column).text() for column in columns]
            with open(path, 'w', newline="") as csvfile:
                writer = csv.writer(csvfile, delimiter=';', escapechar=' ', quoting=csv.QUOTE_NONE)
                writer.writerow(header)
                for row in range(self.ui.dataOutput_tbl.rowCount()):
                    writer.writerow(self.ui.dataOutput_tbl.item(row, column).text() for column in columns)

        self.ui.btn_MessungStarten.setDisabled(False)




#Erstellt die GUI bzw. lädt die generierten Elemente aus der mainwindow.py
if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())





我尝试捕获 t_input 和 qv 值并将它们放入列表中,但它不起作用。 (仅错误消息:进程已完成,退出代码 -1073740791 (0xC0000409))

python-3.x matplotlib pyqt5 qt5 qt-creator
© www.soinside.com 2019 - 2024. All rights reserved.