Как оптимизировать построение последовательных данных в режиме реального времени, используя Python - PullRequest
1 голос
/ 27 января 2020

Я пытаюсь отобразить значения, разделенные табуляцией, которые я получаю от последовательного устройства в режиме реального времени. Я довольно новичок в 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

1 Ответ

0 голосов
/ 27 января 2020

Вы можете рассмотреть возможность использования потоков для разделения ваших задач. Вам, вероятно, не нужно сохранять фигуру каждый раз, когда вы получаете новые данные. Вы можете уменьшить свою вычислительную нагрузку, например, обновляя график каждые 30 секунд или около того. Вы также можете разделить запись в CSV, таким образом, у вас есть три потока, один для поиска данных, один для хранения буферизованных данных и один для обновления графика.

Этот ответ может быть хорошим справочником.

В конце foo () создайте Timer, который сам вызывает foo () через 10 секунд. Потому что 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
...