当前位置: 首页 > 面试题库 >

使用Python最大化来自Teensy 3.2的实时绘图数据的串行通信速度

孔嘉茂
2023-03-14
问题内容

我试图使用从Teensy
3.2接收到的Python(PyQtGraph)尽快绘制数据,该Python通过串行通信发送模拟数据。该代码可以充分绘制较高频率的测试波形(约5kHz的正弦波),但是绘制该图表要显示频率变化大约需要30秒。例如,如果测试波形被关闭,它将继续绘制正弦波另外半分钟。

我尝试执行“串行刷新”以清除Python端和Teensy端的缓冲区,但是,这会严重减慢绘图速度,并且绘图的频率响应会下降到单赫兹。

Python(绘图)面:

# Import libraries
from numpy import *
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
import serial
import re

# Create object serial port
portName = "COM8"                      
baudrate = 115200 
ser = serial.Serial(portName,baudrate)

### START QtApp #####
app = QtGui.QApplication([])           
####################

win = pg.GraphicsWindow(title="Signal from serial port") # creates a window
p = win.addPlot(title="Realtime plot")  # creates empty space for the plot in the window
curve = p.plot()                        # create an empty "plot" (a curve to plot)
windowWidth = 100                       # width of the window displaying the curve - this is the time scale of the plot
Xm = linspace(0,0,windowWidth)          # create array of zeros that is the size of the window width   
ptr = -windowWidth                      # set first x position

# Realtime data plot. Each time this function is called, the data display is updated
def update():

    global curve, ptr, Xm    
    Xm[:-1] = Xm[1:]                    # shift data in the temporal mean 1 sample left 
    if ser.isOpen():                    # make sure there is data coming in
        b1 = ser.read(1)                # read the first byte of data
        b2 = ser.read(1)                # read the second byte of data
        data = b1 + b2                  # concatenate the two bytes
        data_int = int.from_bytes(data, byteorder='big')

        Xm[-1] = data_int                     # stack the data in the array
        ptr += 1                              # update x position for displaying the curve
        curve.setData(Xm)                     # set the curve with this data
        curve.setPos(ptr,0)                   # set x-y position in the graph to 0 and most recent data point - this creates the scrolling of the plot 
        QtGui.QApplication.processEvents()    # process the plot

### MAIN PROGRAM #####    
# this is a brutal infinite loop calling realtime data plot
while True: update()

### END QtApp ####
pg.QtGui.QApplication.exec_() 
##################

Teensy 3.2侧面:

const int sensorPin = A9;
uint16_t sensorValue = 0;
byte b1;
byte b2;
int flag = 0;
IntervalTimer heartBeatTimer;

void setup() 
{
  analogReadRes(12);
  Serial.begin(115200);
  heartBeatTimer.begin(heartBeat, 140); // (1 / 115200 Baud) * 16 bits / integer = 139us per 16 bits sent. Interrupt at 140 us to synchronize with baud rate.
  pinMode(13, OUTPUT);
}

void heartBeat() 
{
  flag = 1;                           // Interrupt routine every 140us
}


void loop() 
{
  if (flag == 1) {
    sensorValue = analogRead(sensorPin);  // read the analog pin as a 16 bit integer
    b1 = (sensorValue >> 8) & 0xFF;       // break up the reading to two bytes
    b2 = sensorValue & 0xFF;              // get the second byte
    Serial.write(b1);                     // write the first byte (trying to speed things up by sending only strictly necessary data)
    Serial.write(b2);                     // write the second byte
    digitalWrite(13, HIGH);               // just to make sure we're interrupting correctly
    flag = 0;                             // wait for next interrupt
  }
  digitalWrite(13, LOW);                  // just to make sure we're interrupting correctly 
}

有人对如何加快速度有任何建议吗?


问题答案:

正如上面MR所建议的,如果在发送之前打包更多数据而不是一次发送两个字节的数据包,则可能会更好。

但是,您看到的可怕性能与在计算机上读取数据的方式有关。如果您仅从串行端口读取两个字节并将它们附加到绘图上,那么最终的开销将是巨大的。

如果改用RX缓冲区中可用的字节数来处理,则几乎可以获得实时性能。

只需更改您的更新功能

def update():

    global curve, ptr, Xm

    if ser.inWaiting() > 0                         # Check for data not for an open port
        b1 = ser.read(ser.inWaiting())             # Read all data available at once
        if len(b1) % 2 != 0:                       # Odd length, drop 1 byte
            b1 = b1[:-1]
        data_type = dtype(uint16)
        data_int = fromstring(b1, dtype=data_type) # Convert bytes to numpy array
        data_int = data_int.byteswap()             # Swap bytes for big endian
        Xm = append(Xm, data_int)              
        ptr += len(data_int)                              
        Xm[:-len(data_int)] = Xm[len(data_int):]   # Scroll plot
        curve.setData(Xm[(len(Xm)-windowWidth):])                     
        curve.setPos(ptr,0)                   
        QtGui.QApplication.processEvents()

在略过一次迭代两个字节的想法之后,我认为可以用numpy进行处理,巧合的是,我发现了这个问题,该问题与您的非常相似。因此,值得信赖的是numpy解决方案。

不幸的是,便携式示波器的电池没电了,所以我无法正确测试上面的代码。但是我认为从那里开始一个好的解决方案应该是可行的。

我没有详细检查Teensy代码,但快速浏览一下,我认为您用于提供ADC速度的中断定时器可能太紧了。您忘了考虑随每个数据字节移动的起始位和停止位,并且您没有考虑完成AD转换所花费的时间(我想这应该很小,可能是10微秒)。考虑到所有因素,我认为您可能需要增加心跳,以确保您不会引入不规则的采样时间。Teensy应该有可能获得更快的采样率,但是要做到这一点,您需要使用完全不同的方法。我猜是另一个问题的好话题…



 类似资料:
  • 我正在尝试构建一个代码,以便在我的代码和我的Arduino Uno之间进行通信。我有一个温度传感器(tmp36)连接到COM3中的Arduino板,我想实时绘制温度值。我还有一个开始按钮,用来开始获取数据并将其绘制在图形中,还有一个停止按钮用来停止这样做。当我运行代码时,我收到一条消息:“无法将字符串转换为float:b'Anal'”,参考第19行:“data=np.append(data,flo

  • 本文向大家介绍使用Python串口实时显示数据并绘图的例子,包括了使用Python串口实时显示数据并绘图的例子的使用技巧和注意事项,需要的朋友参考一下 使用pyserial进行串口传输 一、安装pyserial以及基本用法 在cmd下输入命令pip install pyserial 注:升级pip后会出现 "‘E:\Anaconda3\Scripts\pip-script.py' is not p

  • 为了绘制一个地区的障碍物,我计划使用与Arduino Mega连接的夏普红外测距仪,然后尝试使用python和matplotlib在极地直方图类型地图上实时绘制。我对如何继续通过串行连接的Arduino和python接口有点困惑。 任何帮助都会很好。 谢谢

  • 我正在尝试从串行端口读取数据,并使用matplot在图形中绘制数据。下面是我的代码:我看到由于绘图,有巨大的延迟(队列中的数据高达10000字节),因此我看不到实时绘图。如果我做错了什么,你能帮我一下吗。

  • Arduino代码 虽然很简单,但有一个问题,可能是因为我无法理解串行方法。它首先向串口发送一个测试字节,告诉计算机上的C#程序它可以开始发送信息。接下来,它会检查序列中是否有任何字节,如果有,它会检查第一个字节是否与r、g或b中的任何一个匹配,并从序列中获取接下来的三个字节,并将其转换为整数。 在VisualStudio方面 在visual studio上,如果它检测到arduino已使用“x”

  • 问题内容: 我以两个数组获取一些数据:一个用于时间,另一个用于值。当我达到1000点时,我会触发信号并绘制这些点(x =时间,y =值)。 我需要保持与之前相同的图形,但只有一个合理的数字才能避免减慢处理速度。例如,我想在图表上保留10,000点。matplotlib交互式绘图工作正常,但是我不知道如何删除第一个点,这会很快减慢计算机速度。我查看了matplotlib.animation,但它似乎