当我绘制两个以上的值时,为什么计时器会损坏我的数据?

2024-04-25 13:23:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我用定时器同时绘图和存储。当我绘制2个值时,串行端口没有丢失数据(每分钟60行,我的设备=1Hz)。但当我试图绘制两个以上的值时,它会破坏数据(每分钟约40行)。你知道吗

1.我应该尝试thread还是queue而不是wx.Timer

2.为什么wx.Timer会损坏我的数据?或者有什么问题?

3.我应该使用串口功能吗。里面wx.Timer??

我哪里做错了什么?我需要你的帮助。任何帮助都将不胜感激。你知道吗

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import wx
import wxmplot
import serial
import serial.tools.list_ports
import numpy as np

is_wxPhoenix = 'phoenix' in wx.PlatformInfo
if is_wxPhoenix:
    PyDeadObjectError = RuntimeError
else:
    from wx._core import PyDeadObjectError



class myframe ( wx.Frame ):          #Panel ###(reading, saving, plotting as a real-time from serial port)

    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent )

        self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )

        bSizer1 = wx.BoxSizer( wx.VERTICAL )

        self.plotframe = None

        self.toggleBtn17 = wx.ToggleButton( self, wx.ID_ANY, u"GRAPH", wx.DefaultPosition, wx.DefaultSize, 0 )
        bSizer1.Add( self.toggleBtn17, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5 )

        self.toggleBtn171 = wx.ToggleButton( self, wx.ID_ANY, u"Store", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.toggleBtn171.Hide()
        bSizer1.Add( self.toggleBtn171, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5 )

        self.toggleBtn4 = wx.ToggleButton( self, wx.ID_ANY, u"Save", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.toggleBtn4.Hide()
        bSizer1.Add( self.toggleBtn4, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5 )

        self.timer1 = wx.Timer()
        self.timer1.SetOwner( self, 1 )

        self.timer2 = wx.Timer()
        self.timer2.SetOwner( self, 2 )
        self.timer2.Start( 1000 )                           ### running when app begins

        self.timer3 = wx.Timer()
        self.timer3.SetOwner( self, 3 )
        self.timer3.Start( 15000 )       #999               ### running when app begins

        self.Centre( wx.BOTH )
        self.SetSizer( bSizer1 )

        # Connect Events
        self.toggleBtn17.Bind( wx.EVT_TOGGLEBUTTON, self.plot_aio )
        self.Bind( wx.EVT_TIMER, self.timer1_plot, id=1 )

        self.toggleBtn171.Bind( wx.EVT_TOGGLEBUTTON, self.store_f )
        self.Bind( wx.EVT_TIMER, self.timer2_store, id=2 )

        self.toggleBtn4.Bind( wx.EVT_TOGGLEBUTTON, self.save_f )
        self.Bind( wx.EVT_TIMER, self.timer3_save, id=3 )

        self.x1 = np.array([])              # coming data from serial port should list. in wxmplot, numpy array is the best choice for appending data
        self.y1 = np.array([])       
        self.y2 = np.array([])
        self.y3 = np.array([])

        self.store = []
        self.store_tempr = []

        self.ser = serial.Serial('COM9', 9600)

    def ShowPlotFrame(self, do_raise=True, clear=True):   
        "make sure plot frame is enabled, and visible"
        if self.plotframe is None:
            self.plotframe = wxmplot.MultiPlotFrame(rows=3, cols=3, panelsize=(350, 275))
            self.has_plot = False
        try:
            self.plotframe.Show()
        except PyDeadObjectError:
            self.plotframe = wxmplot.MultiPlotFrame(rows=3, cols=3, panelsize=(350, 275))
            self.plotframe.Show()
        if do_raise:
            self.plotframe.Raise()
        if clear:
            self.plotframe.panel.clear()
            #self.plotframe.reset_config()

    def plot_aio( self, event ):                    ### plot button(timer 1)             
        if self.timer1.IsRunning():
            self.timer1.Stop()
            print("timer1  stopped")
        else:
            print("tgl_timer1  starting...")
            self.ShowPlotFrame()        
            self.timer1.Start( 500 )    

    def store_f( self, event ):                     ### store in the numpy array button but both Timer activated and Button hidden(timer 2)
        event.Skip()
        #=======================================================================
        # if self.timer2.IsRunning():
        #     self.timer2.Stop()
        #     print("saving stopped")
        # else:
        #     print("saving_timer2 is starting...")
        #     self.timer2.Start( 1000 )
        #=======================================================================

    def save_f( self, event ):                       ### del the storing data button for not using more memory (both Timer activated and Button hidden)
        event.Skip()
        #=======================================================================
        # if self.timer3.IsRunning():
        #     self.timer3.Stop()
        #     print("timer 3  stopped")
        # else:
        #     print("tgl_timer 3  starting...")
        #     self.timer3.Start( 10000 )           #501  
        #=======================================================================

    def timer1_plot( self, event ):                 ### PLOT STORED DATA (not button but entegrated with plot_aio func which is button)            
        for line in self.store_tempr:
            data=line.split(b",")
            if data[0] == b"$GNGGA":
                tim2=data[1]
                timm=float(tim2)
                tim=timm+30000                            
                hour = tim//10000
                minute = (tim//100)%100
                second = tim%100
                zaman = hour*3600 + minute*60 + second    
                self.x1 = np.append(self.x1, zaman)  

                latitude=data[2]
                lat=float(latitude)
                lat1=int(lat/100)
                lat2=(lat%100)/60
                lati=lat1+lat2
                self.y2 = np.append(self.y2, lati)

                longitude=data[4]
                lon=float(longitude)
                lon1=int(lon/100)
                lon2=(lon%100)/60
                longi=lon1+lon2
                self.y3 = np.append(self.y3, longi)

                altitude=data[9]
                self.y1 = np.append(self.y1, float(altitude))

                self.ShowPlotFrame()  
                self.plotframe.plot(self.x1, self.y1, panel=(0, 0), labelfontsize=6) 
                self.plotframe.plot(self.x1, self.y3, panel=(0, 1), color='red',  labelfontsize=6)
                self.plotframe.plot(self.y1, self.x1, panel=(1, 0), color='black', labelfontsize=5) 
                self.plotframe.plot(self.y2, self.y3, panel=(1, 1), fullbox=False) 
                self.plotframe.plot(self.x1, self.y1, panel=(0, 2), labelfontsize=6) 
                self.plotframe.plot(self.x1, self.y3, panel=(2, 1), color='red',  labelfontsize=6)
                self.plotframe.plot(self.y1, self.x1, panel=(2, 0), color='black', labelfontsize=5) 
                self.plotframe.plot(self.y2, self.y3, panel=(2, 2), fullbox=False) 


        del self.store_tempr[:]

    def timer2_store( self, event ):                ### STORE and WRITE TO .TXT FILE AND DELETE FROM THE LIST (not button)
        print( "storing and saving")
        for line in self.ser:
            self.store.append(line)
            self.store_tempr.append(line)


    def timer3_save( self, event ):                  ### DELETE STORED DATA IN THE LIST (not button)
        with open("C:\\Users\\Desktop\\4n.txt","a") as f: 
            for line in self.store:            
                f.writelines(str(line)+ "\n")
            del self.store[:]



if __name__ == "__main__":
    app = wx.App(False)
    frame = myframe(None)
    frame.Show(True)
    app.MainLoop()

Tags: storeselfdataifplotdefnpwx
1条回答
网友
1楼 · 发布于 2024-04-25 13:23:59

我认为您不需要使用线程或队列来代替wx定时器. 但是,我也认为实际上您只需要1wx.Timer就可以检查并从串行端口(或其他数据源)获取数据。我建议wx.Timer事件的处理程序(如果预期数据为1Hz,则可能以~2Hz的频率运行)应执行以下操作:

  1. 检查新数据。如果没有新数据,则立即返回,等待下一个wx.Timer事件。

  2. 如果有新数据,则立即解析并基于该数据进行计算,并将其附加到该事件处理程序中的数据数组中。只需删除所有存储和以后删除的临时数据,并在数据事件处理程序结束时使您self.x1self.y1等处于最新状态。代码中的所有这些del XXX特别是因为一个事件处理程序删除了在另一个地方创建的数据—看起来它们可能是个问题。

  3. 然后更新绘图。如果您认为绘图会很慢,可以使用第二个计时器事件来查看self.x1的长度是否已更改并重新生成绘图。但是,我相信您不需要使用第二个计时器,只需更新数据事件处理程序中的绘图即可。

有关如何执行此操作的示例,请参见https://github.com/newville/wxmplot/blob/master/examples/stripchart.py 它只使用一个wx.Timer获取新数据并更新绘图。请注意,它使用wxmplot.PlotPanel.update_line(),这在更新现有绘图时比为每个新数据集重做wxmplot.PlotPanel.plot()要快得多。你知道吗

该示例中的next_data()函数比从串行端口读取数据所需的操作更简单、更具确定性。但你已经在做那部分了,而且你做的看起来也不会太难或太慢。你知道吗

相关问题 更多 >