手机版 | 登陆 | 注册 | 留言 | 设首页 | 加收藏
当前位置: 网站首页 > 基础计算机 > 参考资料 > 文章 当前位置: 参考资料 > 文章

用Python串口实时显示数据并绘图

时间:2020-09-28    点击: 次    来源:网络    作者:佚名 - 小 + 大

用Python串口实时显示数据并绘图


使用pyserial进行串口传输

一、安装pyserial以及基本用法

在cmd下输入命令pip install pyserial
注:升级pip后会出现 "‘E:\Anaconda3\Scripts\pip-script.py’ is not present."错误
使用 easy_install pip命令就能解决,换一条重新能执行安装的命令

常用方法:
ser = serial.Serial(0) 是打开第一个串口
print ser.portstr 能看到第一个串口的标识,windows下是COM1
ser.write(“hello") 就是往串口里面写数据
ser.close() 就是关闭ser表示的串口
ser.open() 会打开这个串口
ser = serial.Serial(‘COM1’, 115200) 来设置波特率,当然还有专门的函数
data = ser.read()可以读一个字符
data = ser.read(20) 是读20个字符
data = ser.readline() 是读一行,以/n结束,要是没有/n就一直读,阻塞。
data = ser.readlines()和ser.xreadlines()都需要设置超时时间
ser.baudrate = 9600 设置波特率
ser 来查看当前串口的状态
ser.isOpen() 看看这个串口是否已经被打开

串行口的属性:
name:设备名字 portstr:已废弃,用name代替 port:读或者写端口 baudrate:波特率
bytesize:字节大小 parity:校验位 stopbits:停止位 timeout:读超时设置
writeTimeout:写超时 xonxoff:软件流控 rtscts:硬件流控 dsrdtr:硬件流控
interCharTimeout:字符间隔超时

二、最基本的串口代码

import serialportx="COM5"bps=9600timex=5#串口执行到这已经打开 再用open命令会报错ser = serial.Serial(portx, int(bps), timeout=1, parity=serial.PARITY_NONE,stopbits=1)if (ser.isOpen()):    print("open success")     # 向端口些数据 字符串必须译码    ser.write("hello".encode())     while (True):        line = ser.readline()          if(line):            print(line)            line=0else:	print("open failed")ser.close()#关闭端口) 	
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

三、pyqtgraph的使用

pip install pyqtgraph#显示波形的界面
pip install PyQt5#界面要Qt的支持

pyqtgraph是Python平台上一种功能强大的2D/3D绘图库,相对于matplotlib库,由于内部实现方式上,使用了高速计算的numpy信号处理库以及Qt的GraphicsView框架,因此,它在大数据量的数字处理和快速显示方面有着巨大的优势,它适合于需要快速绘图更新、视频或实时交互性的操作场合。另外,它不仅为各种数据提供了快速可交互式的图形显示,同时也提供了用于快速开发应用程序的各种小工具,如属性树、流程图等小部件,在数学、科学和工程领域都有着广泛的应用。

import pyqtgraph as pgimport numpy as npimport arrayapp = pg.mkQApp()#建立appwin = pg.GraphicsWindow()#建立窗口win.setWindowTitle(u'pyqtgraph逐点画波形图')win.resize(800, 500)#小窗口大小data = array.array('d') #可动态改变数组的大小,double型数组historyLength = 100#横坐标长度p = win.addPlot()#把图p加入到窗口中p.showGrid(x=True, y=True)#把X和Y的表格打开p.setRange(xRange=[0,historyLength], yRange=[-1.2, 1.2], padding=0)p.setLabel(axis='left', text='y / V')#靠左p.setLabel(axis='bottom', text='x / point')p.setTitle('y = sin(x)')#表格的名字curve = p.plot()#绘制一个图形idx = 0def plotData():    global idx#内部作用域想改变外部域变量    tmp = np.sin(np.pi / 50 * idx)    if len(data)<historyLength:        data.append(tmp)    else:        data[:-1] = data[1:]#前移        data[-1] = tmp    curve.setData(data)    idx += 1timer = pg.QtCore.QTimer()timer.timeout.connect(plotData)#定时调用plotData函数timer.start(50)#多少ms调用一次app.exec_() 	
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

曲线图

四、通过多线程实现串口数据的实时绘图import pyqtgraph as pg

主要是开了一个线程去处理串口 剩下的和上面内容一样 就不过多解释了 直接上代码

import arrayimport serialimport threadingimport numpy as npimport timei = 0def Serial():    while(True):        n = mSerial.inWaiting()        if(n):            if data!=" ":                dat = int.from_bytes(mSerial.readline(1),byteorder='little')  # 格式转换                n=0                global i;                if i < historyLength:                    data[i] = dat                    i = i+1                else:                    data[:-1] = data[1:]                    data[i-1] = datdef plotData():    curve.setData(data)if __name__ == "__main__":    app = pg.mkQApp()  # 建立app    win = pg.GraphicsWindow()  # 建立窗口    win.setWindowTitle(u'pyqtgraph逐点画波形图')    win.resize(800, 500)  # 小窗口大小    data = array.array('i')  # 可动态改变数组的大小,double型数组    historyLength = 200  # 横坐标长度    a = 0    data=np.zeros(historyLength).__array__('d')#把数组长度定下来    p = win.addPlot()  # 把图p加入到窗口中    p.showGrid(x=True, y=True)  # 把X和Y的表格打开    p.setRange(xRange=[0, historyLength], yRange=[0, 255], padding=0)    p.setLabel(axis='left', text='y / V')  # 靠左    p.setLabel(axis='bottom', text='x / point')    p.setTitle('semg')  # 表格的名字    curve = p.plot()  # 绘制一个图形    curve.setData(data)    portx = 'COM24'    bps = 19200    # 串口执行到这已经打开 再用open命令会报错    mSerial = serial.Serial(portx, int(bps))    if (mSerial.isOpen()):        print("open success")        mSerial.write("hello".encode()) # 向端口些数据 字符串必须译码        mSerial.flushInput()  # 清空缓冲区    else:        print("open failed")        serial.close()  # 关闭端口    th1 = threading.Thread(target=Serial)#目标函数一定不能带()被这个BUG搞了好久    th1.start()    timer = pg.QtCore.QTimer()    timer.timeout.connect(plotData)  # 定时刷新数据显示    timer.start(50)  # 多少ms调用一次    app.exec_() 	
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

效果如图
在这里插入图片描述

五、与下位机通讯实现波形实时监测

在这里与第四阶段基本相同,需要注意的是,如果收数据直接画图的话,波形会出现问题。所以串口传输数据时使用循环队列(先进先出),数据来之后先进队列,之后再定时器调用函数,出队列,更新图。理论上刷新数据的时间需要大于下位机发送数据的间隔时间,否则队列会越来越大,而且图的刷新不连贯。再就是有一个小问题,因为正弦波有负值,我又没找到很好的把Byte转为char的方法,所以只能手动代码处理,先转成int类型,再把第八位(符号位)清零,得到绝对值。然后再取负,得到我们需要的数据。但发现Python无法进行移位操作,python是int类型是无精度类型,不会发生溢出而进行截取的情况,所以只能先转为二进制在移位,太麻烦,直接通过减去一个数的方法来实现了。然后直接上代码吧

import pyqtgraph as pgimport arrayimport serialimport threadingimport numpy as npfrom queue import Queueimport timei = 0q = Queue(maxsize=0)def Serial():    global i;    global q;    while(True):        n = mSerial.inWaiting()        if(n):            dat = int.from_bytes(mSerial.readline(1),byteorder='little')  # 格式转换            if(dat>>7):                dat =256-dat                dat =0-dat            q.put(dat)def plotData():    global i;    if i < historyLength:        data[i] = q.get()        i = i+1    else:        data[:-1] = data[1:]        data[i-1] = q.get()    curve.setData(data)if __name__ == "__main__":    app = pg.mkQApp()  # 建立app    win = pg.GraphicsWindow()  # 建立窗口    win.setWindowTitle(u'pyqtgraph逐点画波形图')    win.resize(800, 500)  # 小窗口大小    data = array.array('i')  # 可动态改变数组的大小,double型数组    historyLength = 100  # 横坐标长度    a = 0    data=np.zeros(historyLength).__array__('d')#把数组长度定下来    p = win.addPlot()  # 把图p加入到窗口中    p.showGrid(x=True, y=True)  # 把X和Y的表格打开    p.setRange(xRange=[0, historyLength], yRange=[-50, 50], padding=0)    p.setLabel(axis='left', text='y / V')  # 靠左    p.setLabel(axis='bottom', text='x / point')    p.setTitle('semg')  # 表格的名字    curve = p.plot()  # 绘制一个图形    curve.setData(data)    portx = 'COM25'    bps = 19200    # 串口执行到这已经打开 再用open命令会报错    mSerial = serial.Serial(portx, int(bps))    if (mSerial.isOpen()):        dat = 0xff;        dat >> 2;        print("open success")        # 向端口些数据 字符串必须译码        mSerial.write("hello".encode())        mSerial.flushInput()  # 清空缓冲区    else:        print("open failed")        serial.close()  # 关闭端口    th1 = threading.Thread(target=Serial)    th1.start()    timer = pg.QtCore.QTimer()    timer.timeout.connect(plotData)  # 定时刷新数据显示    timer.start(1)  # 多少ms调用一次    app.exec_()

上一篇:基于51的MPU6050模块通信简介(入门级)

下一篇:Python 读取串口数据,动态绘图的示例

备案ICP编号  |   QQ:285250603  |  地址:湛江市  |  电话:15322199012  |  
Copyright © 2026 天人文章管理系统 版权所有,授权www.yajiupc.top使用 Powered by 55TR.COM