使用Python串口实时显示数据并绘图的例子


Posted in Python onDecember 26, 2019

使用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 serial
portx="COM5"
bps=9600
timex=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=0
else:
 print("open failed")
ser.close()#关闭端口
)

三、pyqtgraph的使用

pip install pyqtgraph#显示波形的界面

pip install PyQt5#界面要Qt的支持

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

import pyqtgraph as pg
import numpy as np
import array

app = pg.mkQApp()#建立app
win = 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 = 0
def 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 += 1

timer = pg.QtCore.QTimer()
timer.timeout.connect(plotData)#定时调用plotData函数
timer.start(50)#多少ms调用一次

app.exec_()

使用Python串口实时显示数据并绘图的例子

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

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

import array
import serial
import threading
import numpy as np
import time


i = 0
def 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] = dat

def 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_()

效果如图

使用Python串口实时显示数据并绘图的例子

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

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

import pyqtgraph as pg
import array
import serial
import threading
import numpy as np
from queue import Queue
import time


i = 0
q = 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_()

以上这篇使用Python串口实时显示数据并绘图的例子就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python生成指定长度的随机数密码
Jan 23 Python
Python抓取京东图书评论数据
Aug 31 Python
Python获取单个程序CPU使用情况趋势图
Mar 10 Python
Python里disconnect UDP套接字的方法
Apr 23 Python
Python处理PDF及生成多层PDF实例代码
Apr 24 Python
python实现录音小程序
Oct 26 Python
python实现AES加密和解密
Mar 27 Python
Python异常处理例题整理
Jul 07 Python
Django命名URL和反向解析URL实现解析
Aug 09 Python
Django模板之基本的 for 循环 和 List内容的显示方式
Mar 31 Python
win10下python3.8的PIL库安装过程
Jun 08 Python
python3 循环读取excel文件并写入json操作
Jul 14 Python
简单了解python字符串前面加r,u的含义
Dec 26 #Python
python关于调用函数外的变量实例
Dec 26 #Python
python3 实现调用串口功能
Dec 26 #Python
将python依赖包打包成window下可执行文件bat方式
Dec 26 #Python
python小项目之五子棋游戏
Dec 26 #Python
python自动识别文本编码格式代码
Dec 26 #Python
Python基于pygame实现单机版五子棋对战
Dec 26 #Python
You might like
dedecms中使用php语句指南
2014/11/13 PHP
Mac环境下php操作mysql数据库的方法分享
2015/05/11 PHP
PHP实现简单汉字验证码
2015/07/28 PHP
PHP生成图片验证码功能示例
2017/01/12 PHP
PHP单例模式与工厂模式详解
2017/08/29 PHP
ExtJs 表单提交登陆实现代码
2010/08/19 Javascript
jQuery EasyUI API 中文文档 - Calendar日历使用
2011/10/19 Javascript
JQuery插件开发示例代码
2013/11/06 Javascript
Javascript设计模式之观察者模式的多个实现版本实例
2015/03/03 Javascript
javascript制作游戏开发碰撞检测的封装代码
2015/03/31 Javascript
Jquery+ajax+JAVA(servlet)实现下拉菜单异步取值
2016/03/23 Javascript
JavaScript是如何实现继承的(六种方式)
2016/03/31 Javascript
js中使用使用原型(prototype)定义方法的好处详解
2016/07/04 Javascript
js数组常用操作方法小结(增加,删除,合并,分割等)
2016/08/02 Javascript
微信小程序网络请求wx.request详解及实例
2017/05/18 Javascript
javascript+HTML5 canvas绘制时钟功能示例
2019/05/15 Javascript
JavaScript实现拖拽功能
2020/02/11 Javascript
举例讲解Django中数据模型访问外键值的方法
2015/07/21 Python
Python装饰器入门学习教程(九步学习)
2016/01/28 Python
快速解决安装python没有scripts文件夹的问题
2018/04/03 Python
Python 新建文件夹与复制文件夹内所有内容的方法
2018/10/27 Python
Python Datetime模块和Calendar模块用法实例分析
2019/04/15 Python
Python利用WMI实现ping命令的例子
2019/08/14 Python
python web框架中实现原生分页
2019/09/08 Python
python flask中动态URL规则详解
2019/11/22 Python
快速一键生成Python爬虫请求头
2021/03/04 Python
用CSS3来实现社交分享按钮
2014/11/11 HTML / CSS
Antler英国官网:购买安特丽行李箱、拉杆箱
2019/08/25 全球购物
SAZAC的动物连体衣和动物睡衣:Kigurumi Shop
2020/03/14 全球购物
师范生教师实习自我鉴定
2013/09/27 职场文书
公积金转移接收函
2014/01/11 职场文书
酒店拾金不昧表扬信
2014/01/18 职场文书
大学自我评价
2014/02/12 职场文书
一篇文章学会Vue中间件管道
2021/06/20 Vue.js
MySQL约束超详解
2021/09/04 MySQL
Win10鼠标轨迹怎么开 Win10显示鼠标轨迹方法
2022/04/06 数码科技