使用pyserial和matplotlib实时打印
我可以通过pyserial从串行设备捕获数据,此时我只能将数据导出到文本文件,文本文件的格式如下,它有3列使用pyserial和matplotlib实时打印,matplotlib,pyserial,Matplotlib,Pyserial,我可以通过pyserial从串行设备捕获数据,此时我只能将数据导出到文本文件,文本文件的格式如下,它有3列 >21 21 0 > >41 41 0.5 > >73 73 1 > .... >2053 2053 5 > >2084 2084 5.5 > >2125 2125 6 现在我想使用matplotlib生成live图形有2个图形(x,y)x,y是第二列和第三列,第一列是“>”,没有数据的行可以删除 谢谢大家 ==
>21 21 0
>
>41 41 0.5
>
>73 73 1
>
....
>2053 2053 5
>
>2084 2084 5.5
>
>2125 2125 6
现在我想使用matplotlib生成live图形有2个图形(x,y)x,y是第二列和第三列,第一列是“>”,没有数据的行可以删除
谢谢大家
============================
更新:今天,在遵循以下指南之后
现在我可以使用线程进行实时绘图,但eliben说,这个GUI每次只打印单个值,这给我带来了很大的限制,因为我的目的是打印2列或3列,这里的代码是从blendedtechnologies修改而来的
以下是串行处理程序:
从线程导入线程
import time
import serial
last_received = ''
def receiving(ser):
global last_received
buffer = ''
while True:
buffer = buffer + ser.read(ser.inWaiting())
if '\n' in buffer:
lines = buffer.split('\n') # Guaranteed to have at least 2 entries
last_received = lines[-2]
#If the Arduino sends lots of empty lines, you'll lose the
#last filled line, so you could make the above statement conditional
#like so: if lines[-2]: last_received = lines[-2]
buffer = lines[-1]
class SerialData(object):
def __init__(self, init=50):
try:
self.ser = ser = serial.Serial(
port='/dev/ttyS0',
baudrate=9600,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=0.1,
xonxoff=0,
rtscts=0,
interCharTimeout=None
)
except serial.serialutil.SerialException:
#no serial connection
self.ser = None
else:
Thread(target=receiving, args=(self.ser,)).start()
def next(self):
if not self.ser:
return 100 #return anything so we can test when Arduino isn't connected
#return a float value or try a few times until we get one
for i in range(40):
raw_line = last_received[1:].split(' ').pop(0)
try:
return float(raw_line.strip())
except ValueError:
print 'bogus data',raw_line
time.sleep(.005)
return 0.
def __del__(self):
if self.ser:
self.ser.close()
if __name__=='__main__':
s = SerialData()
for i in range(500):
time.sleep(.015)
print s.next()
对我来说,我修改了这个片段,这样它就可以抓取我的第一列数据
for i in range(40):
raw_line = last_received[1:].split(' ').pop(0)
try:
return float(raw_line.strip())
except ValueError:
print 'bogus data',raw_line
time.sleep(.005)
return 0.
并在GUI文件中基于这些函数生成图形
from Arduino_Monitor import SerialData as DataGen
def __init__(self):
wx.Frame.__init__(self, None, -1, self.title)
self.datagen = DataGen()
self.data = [self.datagen.next()]
def init_plot(self):
self.dpi = 100
self.fig = Figure((3.0, 3.0), dpi=self.dpi)
self.axes = self.fig.add_subplot(111)
self.axes.set_axis_bgcolor('black')
self.axes.set_title('Arduino Serial Data', size=12)
pylab.setp(self.axes.get_xticklabels(), fontsize=8)
pylab.setp(self.axes.get_yticklabels(), fontsize=8)
# plot the data as a line series, and save the reference
# to the plotted line series
#
self.plot_data = self.axes.plot(
self.data,
linewidth=1,
color=(1, 1, 0),
)[0]
所以我的下一个问题是如何实时获取至少2列数据,并将2列数据传递给GUI,以便生成具有2个轴的图形
self.plot_data.set_xdata(np.arange(len(self.data))) #my 3rd column data
self.plot_data.set_ydata(np.array(self.data)) #my 2nd column data
Eli Bendersky的一个示例,演示了如何绘制从串行端口到达的数据。好的,这将读取字符串并将数字转换为浮点数。我想你可以根据需要调整
import numpy as np
import pylab as plt
str = '''>21 21 0
>
>41 41 0.5
>
>73 73 1
>
>2053 2053 5
>
>2084 2084 5.5
>
>2125 2125 6'''
nums = np.array([[float(n) for n in sub[1:].split(' ') if len(n)>0] for sub in str.splitlines() if len(sub)>1])
fig = plt.figure(0)
ax = plt.subplot(2,1,1)
ax.plot(nums[:,0], nums[:,1], 'k.')
ax = plt.subplot(2,1,2)
ax.plot(nums[:,0], nums[:,2], 'r+')
plt.show()
很久以前我也有同样的问题。我一次又一次地写同样的东西,浪费了很多时间。所以我为它写了一个python包 您只需编写从串行端口获取数据的逻辑
下面是一个例子:那么,到目前为止,您有什么经验?让我们把它分解成几个步骤。1:你能从文本中提取数字吗?2:你能画出数字吗?3:你能用传入的数据更新图表吗你在哪里卡住了?谢谢Daan让我明白,现在,我只从设备上捕获数字,下一步我真的很关心如何以我可以稍后绘制的格式提取数字,你能建议我怎么做吗?我目前在这个项目中使用Ubuntu、pyserial、wxpython谢谢joaquin,我正在阅读并将深入研究代码,我使用wxpython来实现这一点project@billyduc我不明白你说的“我用wxpython”是什么意思。您的问题表示matplotlib+pyserial。是这样吗?。如果您还在程序GUI中使用wxPython,您可能知道可以将matplotlib图形嵌入wxPython窗口中。如果你觉得答案有用,别忘了投赞成票。嗨@joaquin,我真的很想投赞成票,但我需要15个以上的声誉,我刚刚接触stackoverflow:D,顺便说一句,谢谢你的建议hi Daan,非常好,它工作顺利,非常感谢,你能解释一下你是如何将数据提取到nums数组的吗?你能告诉我如何实时更新绘图吗?谢谢你。我知道你是如何将数据提取到阵列中的!当pyserial捕获数据时,您能告诉我如何实时更新绘图吗?谢谢您。我想关于stackoverflow和matplotlib cookbook的其他问题和答案已经详细介绍了这一点。快速搜索可以找到几种可能的解决方案。祝你好运嗨,达安,你真是太好了,我跟着这个问题,现在我可以画了,但只有一列,我更喜欢你的例子bcs。它可以传递2个值,因此可以同时绘制2列,您能否建议我如何使用线程实时绘制2列。也许您可以用您的代码的最小示例更新您的问题?在我看来,如果所有单独的组件都在工作(获取数据、绘制一些数据、更新图表),那么您应该能够自己组合这些部分。如果没有,你能告诉我们在这个过程中到底哪里出了问题吗?