Pyserial 卡在读了一会儿

问题描述 投票:0回答:0

我正在用 python 创建一个信号绘图应用程序。我想用蓝牙 hc05 从 arduino 接收数据。要使用过滤器,我需要分别以 5000 的采样率接收 4 个通道的数据。使用下面的代码,我可以接收一段时间的数据,但之后程序就卡住了。当我用ctrl+C中断程序时,发现卡在了BT.py中的

rv = self.ser.read(1)
行。我猜这是因为 python 的缓冲区已满或正在挨饿?在 arduino 代码中添加
Serial.print(val)
后,程序不会停止,但对于实时绘图来说它变得太慢了。有谁知道如何解决这个问题? 这是界面.py

import BT

# hint: You may design additional functions to execute the input command, which will be helpful when debugging :)

class interface:
    def __init__(self):
        print("")
        print("Arduino Bluetooth Connect Program.")
        print("")
        self.ser = BT.bluetooth()
        while(not self.ser.do_connect("COM40")):
            self.ser.do_connect("COM40")
        # self.write('s')

    def read(self):
        return self.ser.SerialReadInt()

    def end_process(self):
        self.ser.disconnect()

    def write(self, input):
        # print("write")
        return self.ser.SerialWrite(input)

这里是 BT.py

from time import sleep
import serial
# these codes are for bluetooth
# hint: please check the function "sleep". how does it work?

class bluetooth:
    def __init__(self):
        self.ser = serial.Serial()

    def do_connect(self,port):
        self.ser.close()
        print("Connecting...")
        try:
            self.ser = serial.Serial(port,115200,timeout=2)
            self.ser.set_buffer_size(rx_size = 115200, tx_size = 115200)
            print("connect success")
            print("")
            # self.ser.timeout=None
        except serial.serialutil.SerialException as ex:
            print("fail to connect")
            print(ex)
            print("")
            return False
        return True


    def disconnect(self):
        self.ser.close()

    def SerialWrite(self,output):
        # send = 's'.encode("utf-8")
        if output.isdigit():
            send = int(output).to_bytes(1, 'little')
        else:
            send = output.encode("utf-8")
        self.ser.write(send)

    def SerialReadInt(self):
        waiting = self.ser.in_waiting
        if waiting >= 0:
            rv = self.ser.read(1)
            rv=int.from_bytes(rv, byteorder='big', signed=False)
            return rv
        return

    def SerialReadByte(self):
        sleep(0.005)
        waiting = self.ser.inWaiting()
        rv = self.ser.read(waiting)
        return rv


这里是 filter.py(这是主文件)

import scipy.io
import matplotlib.pyplot as plt
import numpy as np
from scipy.signal import butter,iirnotch,lfilter
from scipy.fft import fft,fftfreq
from numpy import *
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
import interface
import time
from PyQt5.QtWidgets import QApplication
def filter(data, notchcut,q,lowcut, highcut, fs, order=3):    
    avg=sum(data)/len(data)
    b,a=iirnotch(notchcut,q,fs)
    y = lfilter(b, a, data)+avg
    nyq = 0.5 * fs
    low = lowcut / nyq
    high = highcut / nyq
    b, a = butter(order, [low, high], btype='band')
    y = lfilter(b, a, y)+avg
    # print(y)
    return y
interf = interface.interface()
### START QtApp #####
app = QApplication([])            # you MUST do this once (initialize things)
####################

win = pg.GraphicsLayoutWidget(title="Signal from arduino") # creates a window
p1 = win.addPlot(title="channel1",row=0, col=0)  # creates empty space for the plot in the window
p2 = win.addPlot(title="channel2",row=1, col=0)  # creates empty space for the plot in the window
p3 = win.addPlot(title="channel3",row=2, col=0)  # creates empty space for the plot in the window
p4 = win.addPlot(title="channel4",row=3, col=0)  # creates empty space for the plot in the window
p1.setYRange(0, 5, padding=0)
p2.setYRange(0, 5, padding=0)
p3.setYRange(0, 5, padding=0)
p4.setYRange(0, 5, padding=0)
curve=[p1.plot(),p2.plot(),p3.plot(),p4.plot()]
# curve1 = p1.plot()                  # create an empty "plot" (a curve to plot)
# curve2 = p2.plot()                  # create an empty "plot" (a curve to plot)
# curve3 = p3.plot()                  # create an empty "plot" (a curve to plot)
# curve4 = p4.plot()                  # create an empty "plot" (a curve to plot)

windowWidth = 5000                      # width of the window displaying the curve
X =[linspace(0,0,windowWidth),linspace(0,0,windowWidth),linspace(0,0,windowWidth),linspace(0,0,windowWidth)]
# X1 = linspace(0,0,windowWidth)          # create array that will contain the relevant time series
# X2 = linspace(0,0,windowWidth)
# X3 = linspace(0,0,windowWidth)
# X4 = linspace(0,0,windowWidth)   
ptr = -windowWidth                      # set first x position
# filtRes=[linspace(0,0,windowWidth),linspace(0,0,windowWidth),linspace(0,0,windowWidth),linspace(0,0,windowWidth)]
# Realtime data plot. Each time this function is called, the data display is updated
def update():
    global curve, ptr, X
    ptr += 1                              # update x position for displaying the curve    
    for i in range(4):
        X[i][:-1]=X[i][1:]   # shift data in the temporal mean 1 sample left    
        value = float(float(interf.read())*5/255)               # read line (single value) from the serial port
        X[i][-1] = value                 # vector containing the instantaneous values  
        # print(value)
        filtRes=filter(X[i],60,0.5,10.2,410,5000)
        
        curve[i].setData(filtRes)   # set the curve with this data    
    # time.sleep(0.0002)        
    QApplication.processEvents()    # you MUST process the plot now
    win.show()

### MAIN PROGRAM #####
# this is a brutal infinite loop calling your realtime data plot
interf.write('s')
while True: 
    # print("update")
    update()

### END QtApp ####
QApplication.exec_() # you MUST put this at the end
##################

最后是arduino文件

#include <SoftwareSerial.h>
SoftwareSerial BTSerial(8, 9);
int adc[4]={A0,A1,A2,A3};
byte val=0;
unsigned long cTime = 0;
bool start;
void setup()
{
  BTSerial.begin(115200);
  Serial.begin(9600);
  pinMode(adc[0], INPUT);
  pinMode(adc[1], INPUT);
  pinMode(adc[2], INPUT);
  pinMode(adc[3], INPUT);
  start=false;
}

void loop()
{
  if(BTSerial.available())
  {
    if(BTSerial.read()=='s')
    {
      start=true;
      cTime=micros();
    }
  }
  if (start&&cTime - micros() >= 200)
  {
    cTime=micros();
    for(int i=0;i<4;i++)
    {
      val = map(analogRead(adc[i]), 0, 1023, 0, 255);
      // Serial.println(val);
      BTSerial.write(val);
    }
  }
}

我已经用AT命令设置了hc05的波特率到115200.

python arduino bluetooth pyserial
© www.soinside.com 2019 - 2024. All rights reserved.