簡體   English   中英

如何使用 Python 實時優化繪制串行數據

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

我正在嘗試實時繪制從串行設備接收到的制表符分隔值。 我對 python 很陌生,但已經設法拼湊了一個管理它的腳本,但是它似乎無法處理接收數據的速率,並且在減速並最終凍結之前使用了大量處理能力。 我能做些什么來防止這種情況發生。 我附上了一個我正在使用的數據和我的腳本的例子

我收到的數據看起來像這樣,並且以每半秒大約一行的速度接收。

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

您可以考慮使用線程來拆分您的任務。 您可能不需要每次收到新數據時都保存該圖。 例如,您可以通過僅每 30 秒左右更新一次圖來減少計算負載。 您還可以拆分寫入 csv,這樣您就有三個線程,一個查找數據,一個存儲緩沖數據,一個更新您的繪圖。

這個答案可能是一個很好的參考。

在 foo() 的末尾,創建一個 Timer,它會在 10 秒后調用 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