我用定时器同时绘图和存储。当我绘制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()
我认为您不需要使用线程或队列来代替wx定时器. 但是,我也认为实际上您只需要1
wx.Timer
就可以检查并从串行端口(或其他数据源)获取数据。我建议wx.Timer
事件的处理程序(如果预期数据为1Hz,则可能以~2Hz的频率运行)应执行以下操作:检查新数据。如果没有新数据,则立即返回,等待下一个
wx.Timer
事件。如果有新数据,则立即解析并基于该数据进行计算,并将其附加到该事件处理程序中的数据数组中。只需删除所有存储和以后删除的临时数据,并在数据事件处理程序结束时使您
self.x1
、self.y1
等处于最新状态。代码中的所有这些del XXX
特别是因为一个事件处理程序删除了在另一个地方创建的数据—看起来它们可能是个问题。然后更新绘图。如果您认为绘图会很慢,可以使用第二个计时器事件来查看
self.x1
的长度是否已更改并重新生成绘图。但是,我相信您不需要使用第二个计时器,只需更新数据事件处理程序中的绘图即可。有关如何执行此操作的示例,请参见https://github.com/newville/wxmplot/blob/master/examples/stripchart.py 它只使用一个
wx.Timer
获取新数据并更新绘图。请注意,它使用wxmplot.PlotPanel.update_line()
,这在更新现有绘图时比为每个新数据集重做wxmplot.PlotPanel.plot()
要快得多。你知道吗该示例中的
next_data()
函数比从串行端口读取数据所需的操作更简单、更具确定性。但你已经在做那部分了,而且你做的看起来也不会太难或太慢。你知道吗相关问题 更多 >
编程相关推荐