简体   繁体   English

如何使用 Python 实时优化绘制串行数据

[英]How to optimise plotting Serial data in real-time using Python

I'm trying to plot tab separated values I receive from a serial device in real-time.我正在尝试实时绘制从串行设备接收到的制表符分隔值。 I'm pretty new to python but have managed to cobble together a script that manages it however it can't seem to handle the rate at which data is received and uses a lot of processing power before slowing and eventually freezing.我对 python 很陌生,但已经设法拼凑了一个管理它的脚本,但是它似乎无法处理接收数据的速率,并且在减速并最终冻结之前使用了大量处理能力。 Is the anything I can do prevent this.我能做些什么来防止这种情况发生。 I've attached an example of the data I'm working with and my script我附上了一个我正在使用的数据和我的脚本的例子

The data I receive looks like this and is received at a rate of about a line every half a second.我收到的数据看起来像这样,并且以每半秒大约一行的速度接收。

546     5986637 3598844 +26.0   01A0
547     5986641 3598843 +25.50  0198
548     5986634 3598844 +24.50  0188
from matplotlib import pyplot as plt
from matplotlib import animation
import serial
from pandas import DataFrame
from datetime import datetime
import csv

filename = datetime.now().strftime("%d-%m-%Y_%I-%M-%S_%p")  # Gets time and date in readable format for filenaming.
Data1 = {'Value': [0], 'Frequency 1': [0], 'Frequency2': [0], 'Temperature': [0]}
df = DataFrame(Data1, columns=['Value', 'Frequency1', 'Frequency2', 'Temperature'])
serial_port = 'COM5';  # Different port for linux/mac
baud_rate = 9600;  # In arduino, Serial.begin(baud_rate)
write_to_file_path = "output.txt";
data = []
ft = []
output_file = open(write_to_file_path, "w+");
ser = serial.Serial(serial_port, baud_rate)

plt.ion()
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, sharex=True, sharey=False, )

ax1.set_title('Temp')
ax2.set_title('Freq 1')
ax3.set_title('Freq 2')
ax1.set_ylabel('Temperature')
ax2.set_ylabel('Frequency')
ax3.set_ylabel('Frequency')
ax1.ticklabel_format(useOffset=False)
ax2.ticklabel_format(useOffset=False)
ax3.ticklabel_format(useOffset=False)
ax1.ticklabel_format(style='plain', axis='y', scilimits=(0, 0))
ax2.ticklabel_format(style='sci', axis='y', scilimits=(6, 6))
ax3.ticklabel_format(style='sci', axis='y', scilimits=(6, 6))
while True:
    line = ser.readline();
    line = line.decode("utf-8")  # ser.readline returns a binary, convert to string
    print(line)
    line1 = line.split('\t')  # Separates values by tabs
    output_file.write(line);  # Writes to text file
    data.append(line1)  # Adds line to data file
    newline = [float(line1[0]), float(line1[1]), float(line1[2]), float(line1[3])]  # Creates line of float values
    ft.append(newline)  # Adds to list of floats
    f1 = float(line1[0])  # Line number (count)
    f2 = float(line1[1])  # Frequency 1
    f3 = float(line1[2])  # Frequency 2
    f4 = float(line1[3])  # Temperature in C
    f5 = str(line1[4])  # Temperature in Hex, treated as a string
    #    Data2 = {'Value':[f1],'Frequency 1':[f2],'Frequency2':[f3], 'Temperature':[f4]}
    #    df2 = DataFrame(Data2,columns=['Value', 'Frequency1','Frequency2','Temperature'])
    #    df.append(df2)

    # DataFrame still not working, need to fix so that data is stores as integer or float
    plt.pause(0.1)

    ax1.plot(f1, f4, marker='.', linestyle='solid')  # subplot of freq 1
    ax2.plot(f1, f2, marker='.', linestyle='solid')  # subplot of freq 2
    ax3.plot(f1, f3, marker='.', linestyle='solid')  # subplot of Temp in C
    plt.subplot
    plt.xlabel("Count")
    with open(filename + ".csv", "a") as f:  # Writes data to CSV, hex values for temp don't seem to be writing
        writer = csv.writer(f, delimiter=",")
        writer.writerow([f1, f2, f3, f4, f5])

    plt.draw()
    plt.savefig(filename + '.png', bbox_inches='tight')  # Saves the plot

You may consider using threads to split up your tasks.您可以考虑使用线程来拆分您的任务。 You probably don't need to save the figure every time you recieve new data.您可能不需要每次收到新数据时都保存该图。 You can reduce your computational load by only updating the plot every 30 seconds or so for example.例如,您可以通过仅每 30 秒左右更新一次图来减少计算负载。 You can also split out writing to the csv, that way you have three threads, one looking for data, one storing buffered data, and one updating your plot.您还可以拆分写入 csv,这样您就有三个线程,一个查找数据,一个存储缓冲数据,一个更新您的绘图。

This answer may be a good reference.这个答案可能是一个很好的参考。

At the end of foo(), create a Timer which calls foo() itself after 10 seconds.在 foo() 的末尾,创建一个 Timer,它会在 10 秒后调用 foo() 本身。 Because, Timer create a new thread to call foo().因为,Timer 创建了一个新线程来调用 foo()。

import time, threading
def foo():
    print(time.ctime())
    threading.Timer(10, foo).start()

foo()

#output:
#Thu Dec 22 14:46:08 2011
#Thu Dec 22 14:46:18 2011
#Thu Dec 22 14:46:28 2011
#Thu Dec 22 14:46:38 2011

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM