admin管理员组文章数量:1193808
I want to read real time data from my arduibo, plot it in time domain and then do fft of that data and plot that (frequency domain) but I have no clue how to do it.
can’t seem to transfer data array that I get from serial port to fft
Function freqdom is probably nonsense as I have no clue how to do it
def timedoamin(i, dataList, ser):
ser.write(b'g') # Transmit the char 'g' to receive the Arduino data point
arduinoData_string = ser.readline().decode('ascii') # Decode receive Arduino data as a formatted string
# print(i) # 'i' is a incrementing variable based upon frames = x argument
try:
arduinoData_float = float(arduinoData_string) # Convert to float
dataList.append(arduinoData_float) # Add to the list holding the fixed number of points to animate
except: # Pass if data point is bad
pass
dataList = dataList[-50:] # Fix the list size so that the animation plot 'window' is x number of points
ax.clear() # Clear last data frame
ax.plot(dataList) # Plot new data frame
ax.set_ylim([0, 2000]) # Set Y axis limit of plot
ax.set_title("Time Domain") # Set title of figure
ax.set_ylabel("Value") # Set title of y axis
def freqdomain(i,dataList1,ser):
ser.write(b'g')
arduinoData_string1 = ser.readline().decode('ascii') # Decode receive Arduino data as a formatted string
# print(i) # 'i' is a incrementing variable based upon frames = x argument
try:
arduinoData_float1 = float(arduinoData_string1) # Convert to float
dataList1.append(arduinoData_float1) # Add to the list holding the fixed number of points to animate
y=np.sin(2*np.pi*dataList1*t)
freqdom = fft.fft(y)
freqdom_real=np.fft.fftshift(np.real(freqdom))
except: # Pass if data point is bad
pass
dataList1 = dataList1[-50:] # Fix the list size so that the animation plot 'window' is x number of points
ax2.clear() # Clear last data frame
ax2.plot(dataList1) # Plot new data frame
ax2.set_ylim([0, 2000]) # Set Y axis limit of plot
ax2.set_title("Frequency domain") # Set title of figure
ax2.set_ylabel("Value") # Set title of y axis
dataList = [] # Create empty list variable for later use
dataList1 = []
freqdom = []
freqdom_real = []
fig1 = plt.figure(1) # Create Matplotlib plots fig is the 'higher level' plot window
fig2 = plt.figure(2)
ax = fig1.add_subplot(111) # Add subplot to main fig window
ax2 = fig2.add_subplot(111)
ser = serial.Serial("COM3", 9600) # Establish Serial object with COM port and BAUD rate to match Arduino Port/rate
time.sleep(2) # Time delay for Arduino Serial initialization
# Matplotlib Animation Fuction that takes takes care of real time plot.
# Note that 'fargs' parameter is where we pass in our dataList and Serial object.
ani1 = animation.FuncAnimation(fig1, timedoamin, frames=100, fargs=(dataList, ser), interval=100)
plt.show() # Keep Matplotlib plot persistent on screen until it is closed
ani2 = animation.FuncAnimation(fig2 ,freqdomain, frames=100, fargs=(freqdom_real, ser), interval=100)
plt.show()
sleep(10)
figure(3)
plt.plot(freqdom_real)
plt.show()
ser.close()
I want to read real time data from my arduibo, plot it in time domain and then do fft of that data and plot that (frequency domain) but I have no clue how to do it.
can’t seem to transfer data array that I get from serial port to fft
Function freqdom is probably nonsense as I have no clue how to do it
def timedoamin(i, dataList, ser):
ser.write(b'g') # Transmit the char 'g' to receive the Arduino data point
arduinoData_string = ser.readline().decode('ascii') # Decode receive Arduino data as a formatted string
# print(i) # 'i' is a incrementing variable based upon frames = x argument
try:
arduinoData_float = float(arduinoData_string) # Convert to float
dataList.append(arduinoData_float) # Add to the list holding the fixed number of points to animate
except: # Pass if data point is bad
pass
dataList = dataList[-50:] # Fix the list size so that the animation plot 'window' is x number of points
ax.clear() # Clear last data frame
ax.plot(dataList) # Plot new data frame
ax.set_ylim([0, 2000]) # Set Y axis limit of plot
ax.set_title("Time Domain") # Set title of figure
ax.set_ylabel("Value") # Set title of y axis
def freqdomain(i,dataList1,ser):
ser.write(b'g')
arduinoData_string1 = ser.readline().decode('ascii') # Decode receive Arduino data as a formatted string
# print(i) # 'i' is a incrementing variable based upon frames = x argument
try:
arduinoData_float1 = float(arduinoData_string1) # Convert to float
dataList1.append(arduinoData_float1) # Add to the list holding the fixed number of points to animate
y=np.sin(2*np.pi*dataList1*t)
freqdom = fft.fft(y)
freqdom_real=np.fft.fftshift(np.real(freqdom))
except: # Pass if data point is bad
pass
dataList1 = dataList1[-50:] # Fix the list size so that the animation plot 'window' is x number of points
ax2.clear() # Clear last data frame
ax2.plot(dataList1) # Plot new data frame
ax2.set_ylim([0, 2000]) # Set Y axis limit of plot
ax2.set_title("Frequency domain") # Set title of figure
ax2.set_ylabel("Value") # Set title of y axis
dataList = [] # Create empty list variable for later use
dataList1 = []
freqdom = []
freqdom_real = []
fig1 = plt.figure(1) # Create Matplotlib plots fig is the 'higher level' plot window
fig2 = plt.figure(2)
ax = fig1.add_subplot(111) # Add subplot to main fig window
ax2 = fig2.add_subplot(111)
ser = serial.Serial("COM3", 9600) # Establish Serial object with COM port and BAUD rate to match Arduino Port/rate
time.sleep(2) # Time delay for Arduino Serial initialization
# Matplotlib Animation Fuction that takes takes care of real time plot.
# Note that 'fargs' parameter is where we pass in our dataList and Serial object.
ani1 = animation.FuncAnimation(fig1, timedoamin, frames=100, fargs=(dataList, ser), interval=100)
plt.show() # Keep Matplotlib plot persistent on screen until it is closed
ani2 = animation.FuncAnimation(fig2 ,freqdomain, frames=100, fargs=(freqdom_real, ser), interval=100)
plt.show()
sleep(10)
figure(3)
plt.plot(freqdom_real)
plt.show()
ser.close()
Share
Improve this question
asked Jan 23 at 13:29
Nemanja NenadićNemanja Nenadić
11 silver badge
1 Answer
Reset to default 2The trick here is to put both graphs on the same figure, and then just update them from the same function.
I tried to replicate it as closely as possible to what you did, but since I lack the arduino with the data, I had to stream some fake data to myself. In this case, its two signals, one stable at 0.25 Hz and one that moves around a bit.
The following code was used to generate the gif:
import serial
import matplotlib
matplotlib.use('Agg') # comment this line to view it instead of save a gif
import matplotlib.pyplot as plt
from matplotlib import animation
import sys
import numpy as np
DT = 1.0
def serial_generate(port_name: str, baud: int):
data_len = 1000
total_t = DT * data_len
f1 = 0.25
f2 = 0.125
phi1 = 0.1
phi2 = 0.2
amp1 = lambda t: np.sin(phi1 + f1 * 2 * np.pi * t)
amp2 = lambda t: 0.5 * np.sin(phi2 + (f2 + t / total_t * f2 / 2) * 2 * np.pi * t)
data = np.zeros(shape=(data_len,))
for i in range(data.shape[0]):
data[i] = amp1(i * DT) + amp2(i * DT)
ser = serial.Serial(port_name, baud)
current_pos = 0
print('Ready ...')
while True:
inchar = ser.read(1)
if inchar == b'g':
ser.write(f'{data[current_pos % data.shape[0]]:.3f}\n'.encode('UTF-8'))
print(f'\rOutput value: {current_pos}', end='')
sys.stdout.flush()
current_pos += 1
def serial_consume(port_name: str, baud: int):
ser = serial.Serial(port_name, baud)
fig1 = plt.figure(1, figsize=(6, 4), layout='tight')
ax = fig1.add_subplot(2, 1, 1)
ax2 = fig1.add_subplot(2, 1, 2)
ani1 = animation.FuncAnimation(fig1, timedoamin, frames=250, fargs=([], ser, ax, ax2))
# Swap these two lines to view it instead of save a gif
ani1.save('animation.gif', fps=30, dpi=50)
# plt.show()
def timedoamin(i, dataList, ser, ax, ax2):
ser.write(b'g') # Transmit the char 'g' to receive the Arduino data point
arduinoData_string = ser.readline().decode('ascii') # Decode receive Arduino data as a formatted string
# print(i) # 'i' is a incrementing variable based upon frames = x argument
try:
arduinoData_float = float(arduinoData_string) # Convert to float
dataList.append(arduinoData_float) # Add to the list holding the fixed number of points to animate
except: # Pass if data point is bad
pass
dataList = dataList[-50:] # Fix the list size so that the animation plot 'window' is x number of points
freq_data = np.fft.fftshift(np.fft.fft(dataList))
freq_xdata = np.fft.fftshift(np.fft.fftfreq(len(dataList), DT))
ax.clear() # Clear last data frame
ax.plot(dataList) # Plot new data frame
ax2.clear()
ax2.plot(freq_xdata, np.abs(freq_data))
# ax.set_ylim([0, 2000]) # Set Y axis limit of plot
ax.set_title("Time Domain") # Set title of figure
ax.set_ylabel("Value") # Set title of y axis
def _main():
if sys.argv[1] == '0':
serial_generate('COM7', 19600)
elif sys.argv[1] == '1':
serial_consume('COM9', 19600)
if __name__ == '__main__':
_main()
I had to run this in two separate instances, once with argument 0 to set up the data generator, and one with argument 1 to create the graph. In my setup, COM7 connects to COM9.
Let me know if you have any questions.
本文标签: pythonPyserial and fftStack Overflow
版权声明:本文标题:python - Pyserial and fft - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738492783a2089805.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论