Python开发串口通讯上位机程序三部曲 第三部 用图形方式显示数据

用Visual Basic或者C#, LabVIEW等软件开发的上位机界面,和文本式交互界面比较而言,就是可以用图形方式来显示数据。那么python可不可以用图形来显示数据呢?Of course! 和串口通讯,保存文件一样,绘制曲线对于python而言也是易如反掌。接下来,就让大伙儿看看我的神操作。

绘制曲线,我们可以使用python自带的Turtle(海龟画图)模块。绘图的基本步骤如下:

  1. 导入Turtle模块
  2. 设定画笔的宽度,速度,颜色等
  3. 抬起画笔,移动画笔到起点,放下画笔,移动画笔到终点。
  4. 重复2、3步骤,直到图形画完。

Turtle的常用的绘图函数有:
turtle.home() - 将位置和方向恢复到初始状态,位置初始坐标为(0,0),方向初始为("standard"模式为right向右即东,"logo"模式是up向上即北)
turtle.dot(size, *color) - 按给定直径size画圆点, color圆点颜色
turtle.speed(speed) – 设置画笔的速度,speed为0-10的整数(1-10越来越快,但是0表示最快)
turtle.pencolor(*args) - 设置或返回画笔颜色(设置后海龟箭头的外轮廓也是这个颜色)
turtle.pensize(width) – 设置画笔宽度
turtle.pendown() - 画笔落下,海龟移动时将画线
turtle.penup() - 画笔抬起,海龟移动时不画线
turtle.goto(x,y) - 前往一个绝对坐标
turtle.left(angle) - 画笔方向向左转,angle为左转的角度
turtle.right(angle) - 画笔方向向右转,angle为右转的角度
turtle.write(arg, move=False, align=“left”, font=(“Arial”, 8, “normal”)) - 绘制文字,arg为要绘制的纹波,align为对齐方式,font为字体
turtle.showturtle() - 显示画笔(即海龟箭头)
turtle.hideturtle() - 隐藏画笔(即海龟箭头)
turtle.clear() - 清屏并且画笔形状也恢复默认,保持画笔位置和方向不变

这些函数的命名真是简单直观而易懂。和我们用笔画图的动作也非常相似。相信大家几分钟之内就能掌握,并且画出自己的第一个图形。
当python从串口中读取到数据存储到列表data中以后,我们就可以把data中的数据按照时间顺序,把这些数据用图形显示出来:

  1. 先绘制x轴和y轴,x轴表示的是时间,y轴表示收到的数据的值的大小。
turtle.speed(0)      #画笔速度,10为最慢
turtle.goto(200,0)   #画时间轴
turtle.write("时间")  #标注为时间轴
turtle.penup()       #抬起画笔
turtle.goto(0,200)   #到y轴的终点
turtle.write("数据")  #标注为数据轴
turtle.pendown()     #画笔落下
turtle.home()        #绘制y轴,同时画笔回到原点,
  1. 选择画笔颜色
turtle.pencolor("blue")  #重新选择画笔颜色为蓝色
  1. 计算每个数据点的x坐标和y坐标
for i in range(len(data)):  #把所有的数据循环一遍
    x = i*20           #设置时间值,比如20ms一个点
    y = int(data[i])   #获取y的值 
  1. 绘制每一个点
turtle.goto(x,y)   #画笔移动到x,y坐标
turtle.dot(5,"red")#在该点绘制一个红色圆点
  1. 抬起画笔,回到原点,绘图结束
turtle.penup()  #画笔抬起
turtle.home()   #画笔回到原点,画线结束

下图是整个程序的源代码:

import serial  #导入串口模块
import time    #导入时间模块,时间模块是Python自带模块,无需安装
import csv     #导入csv模块,csv模块是Python自带模块,无需安装
import turtle  #导入Turtle画图模块,此模块为Python自带,无需安装
try:
    SCI1 = serial.Serial("com15",9600,timeout=50)  #打开串口,并且获得串口对象
    #判断是否打开成功
    if (SCI1.isOpen()==True):
        print("串口已经打开!")
except Exception as exc:
    print("串口打开异常:",exc)
while True:
    commandFromECU = input("请输入控制命令,c-向ECU发送命令;r-从ECU中读取数据。")  #从键盘上输入一个命令
    SCI1.write(str(commandFromECU).encode("utf-8"))  #将键盘输入的控制命令发送给ECU上的单片机
    if commandFromECU == 'r':          #如果是读取数据,则从串口中接收数据。
        data = []                      #将data列表清空,准备存放新的数据
        time.sleep(1)                  #等待1秒,等待接收ECU上单片机返回的数据. ECU会依次发送0x30-0x39等10个数据
        bufferSize = SCI1.in_waiting   #接收ECU上单片机发过来的数据,并且返回数据的大小
        print("接收到",str(bufferSize),'个数据') #打印缓冲区中接收到数据的个数 
        for i in range(bufferSize):
            data.append(SCI1.read(1).hex())     #将接收缓冲区中数据读取到data中
        print(data)
        #将数据保存到csv文件中
        with open ('C:\\Users\\tti\\Desktop\\python\\test.csv', 'a+',newline='') as file1: #打开文件,在文件末尾,追加数据
            writer = csv.writer(file1) #创建一个实例
            writer.writerow(data)      #给csv文件写入一行数据
        #把接收到的数据打印成曲线输出
        turtle.speed(0)      #画笔速度,10为最慢
        turtle.goto(200,0)   #画时间轴
        turtle.write("时间")  #标注为时间轴
        turtle.penup()       #抬起画笔
        turtle.goto(0,200)   #到y轴的终点
        turtle.write("数据")  #标注为数据轴
        turtle.pendown()     #画笔落下
        turtle.home()        #绘制y轴,同时画笔回到原点,
        turtle.pencolor("blue")  #重新选择画笔颜色为蓝色
        for i in range(len(data)):  #把所有的数据循环一遍
            x = i*20           #设置时间值,比如20ms一个点
            y = int(data[i])   #获取y的值 
            turtle.goto(x,y)   #画笔移动到x,y坐标
            turtle.dot(5,"red")#在该点绘制一个红色圆点
        turtle.penup()  #画笔抬起
        turtle.home()   #画笔回到原点,画线结束
    time.sleep(1)                      #等待1秒
    if(input("如果退出,请输入n,如果继续发送命令,请按其他键 ") == 'n'):
        break
SCI1.close()    #关闭端口
分享自己的串口接收GUI可实时观察数据图像-MyScomTest可实时显示数据.rar 做这个软件的想法是这样的 先是阅读了飞哥的串口收发助手程序 其中 在第二版书中的P512页末端提出了一个串口接收数据的要求 即 假设计算机与某硬件设备用串口相连 设备每隔固定时间(我这里是5mS 速度非常快)通过串口给计算机发送数据 这帧数据中包含有 帧头 两字节 0x55 0xAA 数据字节数20 一共每帧22个数据 飞哥提出的是仅用串口的定时器定时读取的方法 并且他说 “经实践证明是可以的” 费劲九牛二虎之力我把它实现了 还是挺艰辛的 程序刚刚完成基本调试 代码也不是特别整齐 我用单片机做上位机发送串口数据 按一帧20个数据并 2个帧起始位  帧发送间歇时间是定时的5mS 为什么要做这个东西呢?因为 这个做法是很有意义的  实时地观察采样数据 我参加的智能车比赛中就意识到 上位机调试 看数据曲线十分重要  否则 不知道参数的变化情况 怎么调试? 大概描述一下这个程序 STM32底层A/D转换采样 通过DMA连接片上USART  定时地发送数据上位机 其中我对一个通道进行采样 采样十次 即同一个传感器  一共20个数据(STM32是12位的片上AD 参考电压3.3V) 数据传入Matlab的串口中 用矩阵相乘的方法求出平均值 后plot到axes图上   由于是定时器触发的读取数据函数 那么每次读取到的数据有以下几种情况: ||Data, Data,StartByte1,StartByte2,Data,...,StartByte1,StartByte2|| ||Data, Data,StartByte1,StartByte2,Data,...,StartByte1|| ||Data, Data,StartByte1,StartByte2,Data,...,Data||  %这一次定时器定时接收的到的数据末尾的最后一帧的Data不满20个 不够一帧 ||StartByte1,StartByte2,Data,...,Data,Data,StartByte1,StartByte2|| %这次读到的数据末尾只有帧头的2位标志数据 连原始数据全部都得在下一次定时读取中才能读得到 情况比较多 即一帧的数据可能会被中间间断成2次读取!每一次定时读取的时候 就意味着至多会有2帧数据是不完整的! 大家一般的想法大概就是丢失被中断的帧 这样做程序简洁 方便读 但不可避免地会丢失掉一些数据 我在这里耽误了很久 写了很多段程序代码来完整地恢复了这些被打断的数据 (吹毛求疵吧 但我觉得如果在非常严格的数据观察里是有意义的) 程序有时还是有些不知道为什么的BUG 工科人 表达能力不行 分享一个小作品 可能程序写得比较乱 大家看不明白 或运行不了 有需要就问吧    使用方法 我把STM32 工程里的USER文件放进来了 整个工程太大放不下   连接STM32 ADC1 通道15到外设 把USART1接到电脑上 Matlab 打开GUI 'serial_communication2'  ‘打开串口’ OK 看看数据吧 (有时可能会Matlab报错 关闭再重新执行一次GUI 这BUG一直不知道错在哪)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值