从串行数据绘制的图表在几秒钟后关闭。

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

下面我提供了一个从STM32单片机串行读取数据的python代码.我需要用收到的串行数据绘制一个图形。我还使用了一个GUI,在需要的时候,我可以从这个GUI中选择选项来绘制图形。

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar
import sys
import serial
import datetime
import time
import threading


headingFont = QFont("Times", 20)
headingFont.setBold(True)
textfont = QFont("Candara Light", 11)
textfont.setBold(True)
on_off_font = QFont("Times", 12)
on_off_font.setBold(True)


class MainWindow(QWidget):

    def __init__(self, t):
        super().__init__()
        self.setWindowTitle("Main Window")
        self.setWindowIcon(QIcon('icon.png'))
        self.setFixedSize(500, 500)
        self.mwUI()
        self.th = t

    def mwUI(self):
        self.mwtext1 = QLabel("Measurement Select", self)
        self.mwtext1.setFont(headingFont)

        self.mwbutton1 = QPushButton("Voltage", self)
        self.mwbutton1.clicked.connect(self.mwb1f)
        self.mwbutton1.setFont(textfont)



        #########################Layout########################################
        mwmainlayout = QVBoxLayout()
        mwtoplayout = QHBoxLayout()
        mwbottomlayout = QVBoxLayout()

        mwmainlayout.addLayout(mwtoplayout)
        mwmainlayout.addLayout(mwbottomlayout)

        mwtoplayout.setContentsMargins(100, 80, 0, 0)
        mwtoplayout.addWidget(self.mwtext1)

        mwbottomlayout.setContentsMargins(80, 30, 80, 150)
        mwbottomlayout.addWidget(self.mwbutton1)

        self.setLayout(mwmainlayout)

        self.show()

    ############################Functions#######################
    def mwb1f(self):
        self.voltage_window = Graphwindow(self.th)


class Graphwindow(QMainWindow):
    def __init__(self, t):
        QMainWindow.__init__(self)
        self.widget = QWidget()
        self.setCentralWidget(self.widget)
        self.widget.setLayout(QVBoxLayout())
        self.widget.layout().setContentsMargins(0,0,0,0)
        self.widget.layout().setSpacing(0)
        self.flag1 = 0
        self.th = t

        self.fig = Figure(figsize=(50, 20), dpi=100)
        self.axes = self.fig.add_subplot(111)
        self.axes.grid()

        self.line, = self.axes.plot(self.th.time1, self.th.data1, 'r')
        self.line2, = self.axes.plot(self.th.time1, self.th.data2, 'b')
        self.line3, = self.axes.plot(self.th.time1, self.th.data3, 'g')
        self.line4, = self.axes.plot(self.th.time1, self.th.data4, 'k')

        self.canvas = FigureCanvas(self.fig)

        self.nav = NavigationToolbar(self.canvas, self.widget)
        self.widget.layout().addWidget(self.nav)
        self.widget.layout().addWidget(self.canvas)

        self.show()

        self.timer = QTimer()
        self.timer.setInterval(510)
        self.timer.timeout.connect(self.update_plot)
        self.timer.start()

    def update_plot(self):
        if self.flag1 == 0:
            pass
            self.flag1 = 1
        else:
            self.axes.cla()
            self.axes.grid()
            self.line, = self.axes.plot(self.th.time1, self.th.data1, 'r')
            self.line2, = self.axes.plot(self.th.time1, self.th.data2, 'b')
            self.line3, = self.axes.plot(self.th.time1, self.th.data3, 'g')
            self.line4, = self.axes.plot(self.th.time1, self.th.data4, 'k')
            self.axes.xaxis.set_major_locator(plt.MaxNLocator(3))
            self.canvas.draw()


class thread_class():
    def __init__(self):
        self.vc1_thread = threading.Thread(target=self.thread_module3)
        self.vc1_thread.daemon = True
        self.vc1_thread.start()
        self.data1 = [0] * 100
        self.data2 = [0] * 100
        self.data3 = [0] * 100
        self.data4 = [0] * 100
        self.time1 = [""] * 100

    def thread_module3(self):
        self.ser5 = serial.Serial(port="COM6", baudrate=115200, timeout=None)
        self.bu = ""
        self.w = 0
        self.flag2 = 0
        self.current_time = 0
        while self.ser5.readable():
            current_char = self.ser5.read()
            if current_char != b'&':
                pass
            else:
                self.read_module()
                break

    def read_module(self):
        while self.ser5.readable():
            try:
                current_char = self.ser5.read()
                if current_char == b'&':
                    self.bu = ""
                elif current_char == b'a':
                    self.time_calc()
                    self.w = 1
                    self.update_list()
                elif current_char == b'b':
                    self.time_calc()
                    self.w = 2
                    self.update_list()
                elif current_char == b'c':
                    self.time_calc()
                    self.w = 3
                    self.update_list()
                elif current_char == b'd':
                    self.time_calc()
                    self.w = 4
                    self.update_list()
                elif current_char == b'1' or b'2' or b'3' or b'4' or b'5' or b'6' or '7' or b'8' or b'9' or b'0' or b'.':
                    self.bu = self.bu + current_char.decode("utf-8")
            except AttributeError:
                pass

    def time_calc(self):
        if self.flag2 == 0:
            self.current_time = int(round(time.time() * 1000))
            self.flag2 = 1
        else:
            self.current_time = self.current_time + 1
        self.s = self.current_time / 1000.0
        self.d = datetime.datetime.fromtimestamp(self.s).strftime('%d/%m/%Y %H:%M:%S.%f')
        current_time_str = str(self.d[-15:-3])
        self.time1.append(current_time_str)

    def update_list(self):
        self.bu = self.bu.split('\x00', 1)[0]
        if self.w == 1:
            self.data1.append(float(self.bu))
            if len(self.data1) > 99:
                self.data1 = self.data1[1:]
                self.time1 = self.time1[1:]
        elif self.w == 2:
            self.data2.append(float(self.bu))
            if len(self.data2) > 99:
                self.data2 = self.data2[1:]
                self.time1 = self.time1[1:]
        elif self.w == 3:
            self.data3.append(float(self.bu))
            if len(self.data3) > 99:
                self.data3 = self.data3[1:]
                self.time1 = self.time1[1:]
        elif self.w == 4:
            self.data4.append(float(self.bu))
            if len(self.data4) > 99:
                self.data4 = self.data4[1:]
                self.time1 = self.time1[1:]


def main():
    App = QApplication(sys.argv)
    t = thread_class()
    w1 = MainWindow(t)
    quit(App.exec_())

if __name__ == "__main__":
    main()

我在读取串行数据时没有问题,但当我点击GUI上的按钮显示图形时,图形是正确的,但只有几秒钟的时间,之后整个程序就关闭了。无论是GUI窗口还是图形.谁能帮助理解为什么会发生这种情况,也能纠正这个问题。

我先谢谢你。

P.S.在thread_module类中,我如何读取数据以及对数据的操作并不是很重要。

python multithreading matplotlib pyqt5 pyserial
© www.soinside.com 2019 - 2024. All rights reserved.