ich bin neu in diesem Forum und hoffe, dass ich hier richtig bin

Folgendes Anliegen:
Ich habe mittels Python und QtCreator eine eine GUI entwickelt, die Echtzeit-Daten von Thermoelementen und Druckmessonden aufnimmt und die aktuellsten Messungen kontinuierlich in der GUI darstellt. Diese Messergebnisse werden zudem dazu genutzt um im Hintergrund den Volumenstrom auszurechnen. Mein Ziel ist es, dass am Ende zwei Outputs generiert werden. Zum einen soll eine csv.-Datei erstellt werden, die besagte Echtzeitmessungen beinhaltet, wenn ich den gesamten Messvorgang (mit Messungen beenden button) terminiere --> Das funktioniert auch super.
Der zweite Output soll ein Plot sein, der auf der x-Achse die Runtime in Sekunden zeigt, auf der primären Y-Achse die Temperaturen (der Parameter heißt t_input in Zeile 70) und auf der sekundären Y-Achse den Volumenstrom (der Parameter heißt qv in Zeile 132).
Eigentlich ist das ein sehr einfaches Problem in meinen Augen. Denn ich weiß wie man plots erstellt, aber hier will es einfach nicht funktionieren. Meine bisherigen Versuche hatten immer zur Folge, das mit jeder Iteration quasi eine neue Figure erstellt wird.
Ich werde euch auch den Code geben und hoffe, dass ihr den versteht.
Falls ihr irgendwelche Fragen etc. habt, lasst es mich bitte wissen.
Ich hoffe Ihr könnt mir helfen und bin jetzt schon für jede Hilfe dankbar.
Beste Grüße
Code: Alles auswählen
############################################# 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))
########################################################### Hier beginnt die Beschriftung der Tabelle ###########################################################
# 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)))
########################################################### Hier kommt die Implementierung der Volumenstromberechnung. ###########################################################
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 ###########################################################
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())