我正试图显示我从串行端口得到的数据(由Arduino发送)在一个图表.我已经尝试了不同的东西吨,但它似乎并不像预期的那样工作.我试图有x轴的时间,因为程序开始和y轴的数据,我从串行端口是从Arduino发送.我已经尝试调试,但没有错误出现.代码似乎在update_graphs()函数的某个地方停止了,但我不知道是什么原因导致它停止。我很迷茫,不知道现在该怎么做
import tkinter as tk
from tkinter import ttk
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import serial
import threading
import queue
import time
# Function to read data from the serial port
def read_serial_data(serial_port, data_queue):
while True:
try:
line = serial_port.readline().decode().strip()
data_queue.put(line)
except UnicodeDecodeError:
pass
# Function to update the graphs
def update_graphs():
start_time = time.time()
global x_data
while True:
try:
data = data_queue.get_nowait()
# Calculate the time since the program started
current_time = time.time() - start_time
# Update the graphs with the new data and time
x_data.append(current_time)
# Attempt to add data to y_data as a float
try:
y_data.append(float(data))
except ValueError:
print(f"Error converting data to float: {data}")
x_data = x_data[-len(y_data):] #limits data in the list
ax1.clear()
ax1.plot(x_data, y_data, label='Sensor Data 1')
ax1.set_xlabel('Time (seconds)')
ax1.set_ylabel('Sensor Data 1')
ax1.legend()
canvas.draw()
except queue.Empty:
pass
root.after(100, update_graphs)
# GUI setup
root = tk.Tk()
root.title("Sensor Data Graphs")
# Serial port setup
ser = serial.Serial("COM5", baudrate=9600)
# Data queue for inter-thread communication
data_queue = queue.Queue()
# Create and start a thread to read data from the serial port
serial_thread = threading.Thread(target=read_serial_data, args=(ser, data_queue), daemon=True)
serial_thread.start()
# Create and start a thread to update the graphs
update_thread = threading.Thread(target=update_graphs, daemon=True)
update_thread.start()
# Create multiple graphs
fig, ax1 = plt.subplots()
x_data, y_data = [], [] # Lists to store data and corresponding time
# Create Tkinter canvas for embedding Matplotlib figure
canvas = FigureCanvasTkAgg(fig, master=root)
canvas_widget = canvas.get_tk_widget()
canvas_widget.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
# Start the Tkinter main loop
root.mainloop()
字符串
Arduino代码
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println(random(0, 50));
delay(200);
}
型
我试着放慢Arduino代码的速度,认为它发送数据的速度太快,Python脚本无法读取,但它不起作用
- 更新 *
相当肯定,这与时间有关,因为当我在vscode中使用调试并逐行运行时,一切都正常,但当我让它自己运行时,它只是冻结,不会做任何事情。
Arduino代码保持不变
更新代码:
import tkinter as tk
from tkinter import ttk
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import serial
import threading
import queue
import time
# Function to read data from the serial port
def read_serial_data(serial_port, data_queue):
while True:
try:
line = serial_port.readline().decode().strip()
data_queue.put(line)
except UnicodeDecodeError:
pass
# Function to update the graphs
def update_graphs(start_time):
while True:
try:
data = data_queue.get(timeout=1)
# Calculate the time since the program started
current_time = time.time() - start_time
# Update the graphs with the new data and time
x_data.append(current_time)
y_data.append(float(data))
ax1.clear()
ax1.plot(x_data, y_data, label='Sensor Data 1')
ax1.set_xlabel('Time (seconds)')
ax1.set_ylabel('Sensor Data 1')
ax1.legend()
canvas.draw()
except queue.Empty:
pass
except Exception as e:
print(f"Error in update_graphs: {e}")
# GUI setup
root = tk.Tk()
root.title("Sensor Data Graphs")
# Serial port setup
ser = serial.Serial("COM5", baudrate=9600)
# Data queue for inter-thread communication
data_queue = queue.Queue()
# Create and start a thread to read data from the serial port
serial_thread = threading.Thread(target=read_serial_data, args=(ser, data_queue), daemon=True)
serial_thread.start()
# Create multiple graphs
fig, ax1 = plt.subplots()
x_data, y_data = [], [] # Lists to store data and corresponding time
# Create Tkinter canvas for embedding Matplotlib figure
canvas = FigureCanvasTkAgg(fig, master=root)
canvas_widget = canvas.get_tk_widget()
canvas_widget.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
# Get the start time
start_time = time.time()
# Schedule the update_graphs function to run every 100 milliseconds
root.after(200, update_graphs, start_time)
# Start the Tkinter main loop
root.mainloop()
型
- 更新 *
图表似乎只在我使用vscode中的调试功能暂停和取消暂停程序时更新
1条答案
按热度按时间pjngdqdw1#
当数据发生变化时,可以使用
matplotlib.animation.FuncAnimation
来更新matplotlib图形。这个答案提供了一个基于这种方法的演示(基于问题的思想)。最终结果
下面的
gif
显示了演示程序的输出。“的数据
代码
字符串
解释说明
我已经将理解代码所需的大部分辅助信息放在代码的注解中。基本上,我们已经为matplotlib图形创建了一个
matplotlib.animation.FuncAnimation
对象,即fig
,它在interval
参数中指定的时间后定期调用updateGraph
函数。updateGraph
尝试从dataQueue
读取数据。如果找到数据,它将从dataQueue
读取一个数据值,并将其添加到sensor_data
,然后将当前时间添加到time_data
,最后更新数字(fig
)。如果dataQueue
为空,则会发生异常,它将跳过更新迭代的数据和图形。arduino
的函数,该函数每0.2秒生成一些随机数据,并通过arduinoThread
与绘图程序并行运行,以模拟真实的Arduino生成的传感器数据的行为。*