增加pyserial readline速度

时间:2017-06-20 13:22:17

标签: python tkinter arduino cython pyserial

我正在使用pyserial来读取arduino发送的数据。 arduino每50毫秒发送一次数据。我尝试过接收两种不同的格式,这两种格式都是字符串。我想知道是否有更快的方式在我的python gui中接收这些数据,无论是使用不同的库,接收不同的数据类型,还是优化代码。 第一格式:

String potcolumn = String(pot0holder) + "." + String(pot1holder) + "." +  String(i) + "|" + String(int(pot0holder)+30) + "." + String(int(pot1holder)+30) + "." +  String(i) + "|" + String(int(pot0holder)+60) + "." + String(int(pot1holder)+60) + "." +  String(i) + "|" + String(int(pot0holder)+90) + "." + String(int(pot1holder)+90) + "." +  String(i); 

这取平均值:0.0523106797228秒读取

第二格式:

  pressure1 = String(pot0array[0]) + "," + String(pot0array[1]);
  displacement1 = String(pot1array[0]) + "," + String(pot1array[1]);
  iteration1 = String(i-1) + "," + String(i);
  full1 = pressure1 + ">" + displacement1 + ">" + iteration1;
  pressure2 = String(pot0array[0]+30) + "," + String(pot0array[1]+30);
  displacement2 = String(pot1array[0]+30) + "," + String(pot1array[1]+30);
  iteration2 = String(i-1) + "," + String(i);
  full2 = pressure2 + ">" + displacement2 + ">" + iteration2;
  pressure3 = String(pot0array[0]+60) + "," + String(pot0array[1]+60);
  displacement3 = String(pot1array[0]+60) + "," + String(pot1array[1]+60);
  iteration3 = String(i-1) + "," + String(i);
  full3 = pressure3 + ">" + displacement3 + ">" + iteration3;
  pressure4 = String(pot0array[0]+90) + "," + String(pot0array[1]+90);
  displacement4 = String(pot1array[0]+90) + "," + String(pot1array[1]+90);
  iteration4 = String(i-1) + "," + String(i);
  full4 = pressure4 + ">" + displacement4 + ">" + iteration4;
  fulltotal = full1 + "|" + full2 + "|" + full3 + "|" + full4;
  Serial.println(fulltotal);

这取平均值:0.0937848151484秒读取有意义,因为它是数据的两倍

这是一个非常简单的GUI,用于接收数据并使用pyserial,tkinter和python测试读取时间:

import Tkinter
import serial
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from matplotlib import pyplot as plt
import matplotlib.animation as animation
from collections import deque
import random
import time
import cProfile

class App:
    def __init__(self, master):
        self.arduinoData = serial.Serial('com5', 250000, timeout=None)

        frame = Tkinter.Frame(master)

        self.go = 0

        self.run = Tkinter.LabelFrame(frame, text="Testing", borderwidth=10, relief=Tkinter.GROOVE, padx=10, pady=10)
        self.run.grid(row=0, column=0, padx=20, pady=20)

        self.run_respiration = Tkinter.Button(self.run, text="RUN",bd=10, height=5, width=10, command=self.getData)
        self.run_respiration.grid(row=0, column=0, padx=5, pady=5)

        self.test_options = Tkinter.LabelFrame(frame, text="Test Options", borderwidth=10, relief=Tkinter.GROOVE, padx=10, pady=10 )
        self.test_options.grid(row=0, column=1, padx=20, pady=20)

        self.stop = Tkinter.Button(self.test_options, text="STOP", bd=10, height=5, width=10, command=self.stopTest)
        self.stop.grid(row=0, column=0, padx=5, pady=5)


        frame.grid(row=0, column=0, padx=20, pady=20)


    def getData(self):
        return self.start()


    def stopTest(self):
        self.arduinoData.write("<H>")
        self.go = 0

    def start(self):
        self.arduinoData.write("<L>")
        self.go = 1
        self.timer()

    def readData(self):
        if (self.arduinoData.inWaiting()>0):
            t = time.time()
            x = self.arduinoData.readline()
            print str(time.time()-t)# + "\t" + str(x)



    def timer(self):
        if self.go == 1:
            self.readData()
            root.after(0, self.timer)

root = Tkinter.Tk()
app = App(root)
root.mainloop()

arduino很容易以正确的速度发送数据,只是python gui读取的速度不够快,不能使用。

使用cython或使用C ++的扩展是否有可能读得更快如果有的话,我可以使用任何资源作为指南我还没有找到任何东西。

即使只运行此代码也会产生平均时间.11438秒:

import time
import serial

def readData():
    if arduinoData.inWaiting()>0:
        t = time.time()
        x = arduinoData.readline()
        y = str(time.time()-t)
        print y


def run():
    x = 5000
    z = 0
    while z < x:
        readData()
        z += 1

if __name__ == "__main__":
    arduinoData = serial.Serial('com5', 250000, timeout=None)
    arduinoData.write("<L>")
    run()
    print('done')

感谢您提供任何帮助和建议

1 个答案:

答案 0 :(得分:0)

在对上述代码进行概要分析后,我收到了这个作为输出

Ordered by: standard name

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    0.000    0.000    0.001    0.001 profile_stack.py:61(readData)
     1    0.001    0.001    0.001    0.001 serialwin32.py:234(inWaiting)
     2    0.000    0.000    0.000    0.000 {_ctypes.byref}
     1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}


      270 function calls in 0.025 seconds

Ordered by: standard name

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    24    0.000    0.000    0.000    0.000 __init__.py:49(create_string_buffer)
     1    0.000    0.000    0.025    0.025 profile_stack.py:61(readData)
    24    0.000    0.000    0.000    0.000 serialutil.py:404(getTimeout)
     1    0.001    0.001    0.001    0.001 serialwin32.py:234(inWaiting)
    24    0.023    0.001    0.024    0.001 serialwin32.py:242(read)
   146    0.000    0.000    0.000    0.000 {_ctypes.byref}
    48    0.000    0.000    0.000    0.000 {isinstance}
     1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
     1    0.000    0.000    0.024    0.024 {method 'readline' of '_io._IOBase' objects}


      5 function calls in 0.001 seconds

以下是我用来获取此信息的代码:

import Tkinter
import serial
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from matplotlib import pyplot as plt
import matplotlib.animation as animation
from collections import deque
import random
import time
import cProfile

class App:
    def __init__(self, master):
        self.arduinoData = serial.Serial('com5', 250000, timeout=None)

        frame = Tkinter.Frame(master)

        self.go = 0

        self.run = Tkinter.LabelFrame(frame, text="Testing", borderwidth=10, relief=Tkinter.GROOVE, padx=10, pady=10)
        self.run.grid(row=0, column=0, padx=20, pady=20)

        self.run_respiration = Tkinter.Button(self.run, text="RUN",bd=10, height=5, width=10, command=self.getData)
        self.run_respiration.grid(row=0, column=0, padx=5, pady=5)

        self.test_options = Tkinter.LabelFrame(frame, text="Test Options", borderwidth=10, relief=Tkinter.GROOVE, padx=10, pady=10 )
        self.test_options.grid(row=0, column=1, padx=20, pady=20)

        self.stop = Tkinter.Button(self.test_options, text="STOP", bd=10, height=5, width=10, command=self.stopTest)
        self.stop.grid(row=0, column=0, padx=5, pady=5)


        frame.grid(row=0, column=0, padx=20, pady=20)

    def do_cprofile(func):
        def profiled_func(*args, **kwargs):
            profile = cProfile.Profile()
            try:
                profile.enable()
                result = func(*args, **kwargs)
                profile.disable()
                return result
            finally:
                profile.print_stats()
        return profiled_func

    def getData(self):
        return self.start()


    def stopTest(self):
        self.arduinoData.write("<H>")
        self.go = 0

    def start(self):
        self.arduinoData.write("<L>")
        self.go = 1
        self.timer()


    @do_cprofile
    def readData(self):
        if (self.arduinoData.inWaiting()>0):
            t = time.time()
            x = self.arduinoData.readline()
            print str(time.time()-t)# + "\t" + str(x)



    def timer(self):
        if self.go == 1:
            self.readData()
            root.after(0, self.timer)

root = Tkinter.Tk()
app = App(root)
root.mainloop()