你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

功能强大却简单好用的串口数据图形化程序

[复制链接]
fanjiezz 发布时间:2019-6-17 23:02
    在嵌入式行业中,串口的多个数据可视化在工作中是经常要用的。除去在组态软件中应用较方便外,作为单独应用的也有几个。但要称得上有交互功能和实时功能的以前几乎没看到过。目前在pyqtgraph的应用中这些功能的实施已不再是高不可攀了。最近看到的一个实例相信肯定会让我们眼前一亮,不敢独享。博客地址如下:/ v# Z% ^+ s! R* Y% R6 K
<http://blog.csdn.net/u013555402/article/details/85124452>; J( N: Q) K5 [. Z& ^5 `
    该作者的功力了得,且施惠与众人。非常值得敬佩!
- F- m! Z" o8 D    本文参考上述博客,针对一般场合的应用在如下几个方面精简、改进。" `' c$ D& u" _( u9 S" @: A1 S
1.适应整数数据输入(需输入浮点数据的请不用再看下去了)/ _0 B% |6 K4 R; h
  python的诟病是速度不快。我们平时用的数据有许多是可归一化为整数的,连numpy都可以不用了,以加快程序的运行速度,更好的适应实时化需求。, j2 |" N9 V5 N/ p/ e( S3 q+ r6 ?
2.输入数据的出错处理
/ z: F  Z/ V  C; f! u/ o0 d5 h  数据的第一行输入极有可能不完整,扔掉。7 t! D$ p- H- s0 K  Y) j
3.简化程序" x, i0 U2 b% e$ [6 ^1 U
  如果串口号、输入数据及格式都正常时,该程序运行非常稳定。因此去掉了一些出错处理语句。% o! j8 o" J( L( p+ K& |" j5 k4 n
4.改善x轴抖动
+ K; C; _! J9 ^3 z( G8 S3 f: g7 W4 z  当采样数据的个数与最大显示限制个数相同时,x轴会抖动。增加2个采样数据时,即可避免该抖动。
7 N! R9 ?$ }" i代码如下:(Python 3.4)
: ~$ B/ {3 }7 q# |- `3 `  `* [import array,serial,re,threading
& Y3 I6 ~1 p- Iimport pyqtgraph as pg' k5 t+ \# o% B1 [0 Y1 `! Q# M. \

4 R2 F& Z+ P& {app = pg.mkQApp()
3 y( D7 H2 {# r' A" H1 T/ C3 vwin = pg.GraphicsWindow()5 K. P/ g% P" ^( D4 y, O
win.setWindowTitle(u'AD波形显示')& w& K. @& W& d, ]
p = win.addPlot() #win.addPlot()添加一个波形窗口,多次调用会将窗口分成多个界面 , S8 |; c+ [; k& X
data_dict = {}    #存放所有收到的数据
) ]( d9 @) t) F" Cp.addLegend()     #在plot前调用显示图例
' u6 F% x8 e  h9 i& X6 zMax_count_1 = 500  #页面数据个数$ m7 Z! a6 m5 l/ @- z) k
Max_count_2 = Max_count_1 + 2  #避免X轴抖动
  Y6 X% e9 A5 k5 `color = ['b','g','r', 'c','m','y', 'k','w'] #线的颜色表
* j: f$ i( D: f1 m' K) Hser = serial.Serial('com18',115200)  #请自己修改成相应的串口号和波特率
+ h) d! T( N! T! x# Y& L6 [ser.readline()      #第一行的数据极有可能不完整,扔掉
, m. E' H, z1 x) F7 J& Y$ A7 B. Y0 _
def ComRecvDeal():
' H9 M2 h: R3 E  \+ I  while(True):
% l' c; J& ?' ?/ i) m    line = ser.readline().decode()   #line是bytes格式,转成字符串 ***. }0 T! f- h; o1 `
    line = line.split("\\n")      #去除最后的\n换行 str
" X0 h. b2 o7 D+ i7 Z) _# l: ?    str_arr = line[0].split(';')  #list ***
+ d8 p) ^+ T! k# O    str_arr.pop()
3 u  L7 U" T" ~- f! B- n8 ^2 |  _    for a in str_arr:2 j2 `: u0 p7 F2 D" D: L5 d* |0 Z4 F8 {
      s = a.split(',')
" M( {1 ], d9 z) J      name ,val = s[0], int(s[1]) #提取名称和数据部分, Q! C+ O3 N3 s+ `
      if(data_dict.get(name) == None):
0 |) k. C2 C: Q. Y/ F9 t( y1 A5 V! q        #判断是否存在添加当前键值,None则需要添加键值  ***                  
% ]3 w% L7 @' Q7 x, L6 ]        #curve = p.plot(pen = color[len(data_dict)],name = name,symbolBrush = color[len(data_dict)])) ?" Z7 e9 z. e" _
        #为新的变量添加新的曲线,显示数据点
# c2 l8 h$ K" V  [) Y& d        curve = p.plot(pen = color[len(data_dict)],name = name)
1 @) t. j5 Y3 U, d8 W        #为新的变量添加新的曲线* i5 X8 y6 n& i5 U9 p- E9 e5 Z3 R8 C
        data_dict[name] = [curve]
+ x' W9 x" v  m        #在字典中添加当前键值,并赋值曲线,字典数据格式{key:[curve,[dadta1,data2,...]]}
+ D- i1 I# Y' I7 J* w. s        data_dict[name].append([val])
: _/ v* G) I& J  d7 K6 N. w        #将当前数据已列表的形式添加到字典对象中
& U7 X* t' m# B* {7 J2 `" q      else:
  E; y. i3 u' f0 j3 Y% G0 {        #键值存在直接添加到对应的数据部分
$ ^% G: n- d2 u' @9 l3 H5 P* ~        if(len(data_dict[s[0]][1]) == Max_count_2):. ~2 ^; d% X9 F+ h7 ~
          data_dict[s[0]][1] = data_dict[s[0]][1][1:-1]
, ?: x3 C! ?' T2 ~+ r0 g9 N- e          data_dict[s[0]][1][-1] = int(s[1])  #float(s[1])
0 N, i& ]1 H, ^  x8 M        else:
  |0 e# M4 I! U; D          data_dict[s[0]][1].append(val); z% b. t  {3 r2 A5 D* @
          . X. I. {* N9 o/ Z  _
def addToDisplay():
% p1 d2 \# {0 \2 H% q  for i in data_dict.items():2 Z+ O4 Z% }5 @8 x+ G5 i6 M4 g
    data ,curve = i[1][1], i[1][0]$ |9 r) F7 m# V* h) G$ t$ \# ^5 `
    data = data[( -Max_count_1):] if(len(data) > Max_count_1) else data[:]! _" _" m& T' j1 e% Y' ~! W
    curve.setData(data) #添加数据显示
1 e" A) f  S3 Z0 P; Q  I    1 Z% ?) ^" u' N/ n4 y
if __name__ == "__main__":
( Q5 y" T" s% \% K7 \! y  threading.Thread(target = ComRecvDeal).start()  #创建串口接收线程  ; A1 t* ~. x6 A! W6 |" b: A. P
  td = pg.QtCore.QTimer()% r' e, w0 a: v" O! G- M
  td.timeout.connect(addToDisplay)             #定时刷新数据显示% G& E+ _  a. w3 {- V! j" U
  td.start()
6 f6 D4 w  @6 h* g2 Q  app.exec_()2 V% p/ E; @$ }( F; W- P# k  D3 V9 q
    0 o# I) N2 i7 w( ?# c7 _
    数据输入格式为:6 ~, z0 V# n0 w3 d( n# p& j# W2 z" o% W
    “字符串1,” 1234;“字符串2,” 2345;....“字符串n,” 3456;\n7 Y- L; g9 k, P9 F, i0 v
    数据输入不仅仅限制于串口,大家可灵活应用。5 b' j. r6 t( O7 k, d
    简单可靠但功能强大是我们梦寐以求。pyqtgraph功能极其强大,可用鼠标拖拉、放大,在应用界面上击右键可看到不少的设置功能,甚至包含FFT。
3 u6 _" Y* }+ w' U    pyqtgraph简单的应用说明和pyqtgraph包的安装请看:
6 O. h) t$ \' p; G$ t9 ?
<http://blog.csdn.net/qq_41590417/article/details/80277241>
. R$ \  f6 n+ U; d, j$ a    如需提供串口数据源样板的,请招呼。为贪图方便我是用ARDUINO的。
2 s! v% u( X/ N9 \# O* U( X
0 E/ I( e4 P2 c" n4 [0 h, z- g1 E
    相信大家用过之后会有很好的体验,但仍欢迎抛砖!/ X# B, Q2 K7 ^% H
赞 收藏 1 评论1 发布时间:2019-6-17 23:02

举报

1个回答
瞻_ 回答时间:2019-6-21 08:51:18
很好的资料,非常感谢!
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版