程序的目的:从串口读取串行数据,将它们转换为int并将它们存储到列表中。稍后将使用matplotlib实时处理和打印此数据。
问题:
在创建列表的所有时间之后,我得到了这个:
"(...)
文件" C:\ Users \ ianmc \ AppData \ Local \ Programs \ Python \ Python35-32 \ lib \ site-packages \ matplotlib \ lines.py",第645行,重新计算
引发RuntimeError(' xdata和ydata的长度必须相同')
RuntimeError:xdata和ydata的长度必须相同"
情节论证可能有不同的长度,但为什么呢?
代码:
import serial
import math
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
dt = 0.01
Fs = 44000.0 # sample rate
timestep = 1.0/Fs # sample spacing (1/sample rate)
n = 1024 # size of the array data (BUFFER SIZE)
t = np.arange(0, (n/100), dt) # t range
w = 10000 # frequency of the input
#initialize data list
data = [0] * n
#initialize magnitude list
magnitude = [0] * (n//2)
# open and prepare serial port
ser = serial.Serial('COM4', 9600, timeout=8,
parity=serial.PARITY_EVEN, rtscts=1)
# calculates the fft dB
def createMagnitudeDB(magnitude):
magnitudeDB = 20 * (math.log(magnitude,10))
return magnitudeDB
def update(data):
# update the curves with the incoming data
timeCurve.set_ydata(data[0])
freqCurve.set_ydata(data[1])
return timeCurve, freqCurve,
def generateData():
# simulate new data coming in
while True:
# THE EFFICIENCY PROBLEM IS IN THIS FOR
# Read data from arduino
for i in range(n): #while you are taking data
PreData = ser.readline()
data.append(int(PreData))
# fft computing and normalization
magnitude = np.fft.fft(data)/n
magnitude = np.abs(magnitude[range(n//2)])
# calculates the fft dB
magnitude_dB = [createMagnitudeDB(x) for x in magnitude]
yield (data, magnitude)
fig = plt.figure()
# create time graph axis
timeGraph = plt.subplot(2, 1, 1)
timeGraph.set_ylim(-200, 200)
timeGraph.set_xlim([0, n])
timeGraph.set_xlabel('Time')
timeGraph.set_ylabel('Amplitude')
# create frequency graph axis
freqGraph = plt.subplot(2, 1, 2)
freqGraph.set_ylim([0, 70])
freqGraph.set_xlim([0, (Fs/2)])
freqGraph.set_xlabel('Freq (Hz)')
freqGraph.set_ylabel('Magnitude')
#get frequency range
k = np.arange(n)
T = n/Fs
freq = k/T # two sides frequency range
freq = freq[range(n//2)] # one side frequency range
# plot the curves
timeCurve, = timeGraph.plot(np.linspace(0, 1, n),'b')
freqCurve, = freqGraph.plot(freq, magnitude,'g')
# animate the curves
ani = animation.FuncAnimation(fig, update, generateData,
interval = 10, blit=True)
# open window
plt.show()
# close serial connection
ser.close()
另一条信息:如果不是使用串口我生成自己的数据,程序运行正常,就是这样:
def generateData():
# simulate new data coming in
while True:
nse = np.random.randn(len(t))
r = np.exp(-t/0.05)
cnse = np.convolve(nse, r)*dt
cnse = cnse[:len(t)]
data = 100*np.sin(2*np.pi*t) + 500*cnse
# fft computing and normalization
magnitude = np.fft.fft(data)/n
magnitude = np.abs(magnitude[range(n//2)])
# calculates the fft dB
magnitude_dB = [createMagnitudeDB(x) for x in magnitude]
yield (data, magnitude)
唯一的区别是generateData函数而不使用open / close串行命令,这就是为什么我不理解" xdata和ydata必须是相同的长度"其他代码出错(两个代码的数据长度相同)
编辑:
该程序通过蓝牙从正在读取模拟引脚的arduino接收数据。我测量了arduino的读取时间,并且它正在测量" 0.015ms"阅读每个值。要阅读和打印每个值,它需要" 3.1ms"。每个值的计算机读取时间为" 100ms"。
这意味着创建列表需要n * 100(ms),n是列表元素的数量。最低限度的' n'我可以使用256,这将需要25.6秒来创建列表。这对于实时图表来说太长了。
答案 0 :(得分:0)
将1024个项目附加到列表不需要几秒钟。从您的设备读取1024行可能需要几秒钟或几分钟,但我认为我们无法提供帮助。
在generateData
中,您将项目附加到data
,但您永远不会将其删除,因此data
无限制地增长。我想你想在循环的每次迭代中从头开始重新创建data
:
# Read data from arduino
data = []
for i in range(n): #while you are taking data
PreData = ser.readline()
data.append(int(PreData))
答案 1 :(得分:0)
很难从外部判断您的数据采集需要多长时间,以及这是否太长'或者只是正常串行连接的速度是每秒9600位,但我们不知道您读入了多少位。您可以使用time
模块(start = time.time()
stop = time.time()
{计算数据采集的时间。 {1}})看看这是否超出了您的预期。在这种情况下,它也可以是在每次读取数据后更新图形的选项。
然而,真正的问题可能在于您尝试每10毫秒调用print (stop - start)
(在generateData()
中指定)。这可能会导致问题,因为数据采集肯定需要更长的时间。也就是说,即使您一次只读取一位,读取1024位也需要约100毫秒。
因此,它可能有助于将间隔设置为更合理的数字,或者根本不使用animation.FuncAnimation(..., interval = 10, ...)
,只需在读入数据后绘制数据。
问题是您使用长度为FuncAnimation
,timeGraph
的数组初始化n
。
此时,您的数组数据中已包含timeCurve, = timeGraph.plot(np.linspace(0, 1, n))
个零。在第一次迭代中,您追加从串行端口读取的另一个n
个数字。所以此时n
长data
。
现在的问题是你只更新了图的ydata(2*n
,所以x轴仍然有timeCurve.set_ydata(data[0])
个值(在开头隐含设置),这与{ {1}}要设置为该绘图的y轴的值。
解决方案:
第一个选项是在每次迭代中重新初始化数据,使其始终具有n
个条目。
第二个选项是通过
更新图表2*n
将x和y数据都设置为相同长度的数组。