温度采集数据可视化

实现功能:

  • 实时显示近3分钟温度随时间的变化曲线
  • 实时显示当前温度、温度均值、温度波动
  • 根据温度数据实时调整纵坐标轴范围

使用的工具:

  • 硬件使用树莓派4B,烧录的是Raspberry Pi OS系统
  • 使用Qt Creator软件中UI Designer工具设计界面
  • 使用python语言编写逻辑,主要使用python中的pyqt5包以及其中的pyqtchart模块

程序原理:

  • 下位机每0.1秒采集1次温度并实时上传
  • 上位机创建0.1秒周期的定时器,定时检查收到的数据并处理,添加到显示序列后更新曲线
  • 同时进行3分钟温度均值与波动的计算并显示。

下载QT creator,使用里面的UI designer工具创建界面,如下图:
界面
在这里插入图片描述
下位机数据格式,ADC值加回车换行
在这里插入图片描述
使用pyqt自带工具将.ui文件转换为.py文件,转化后的py文件如下:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'widget.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_TemperatureDispaly(object):
    def setupUi(self, TemperatureDispaly):
        TemperatureDispaly.setObjectName("TemperatureDispaly")
        TemperatureDispaly.resize(1024, 600)
        self.gridLayout = QtWidgets.QGridLayout(TemperatureDispaly)
        self.gridLayout.setObjectName("gridLayout")
        self.verticalLayout_2 = QtWidgets.QVBoxLayout()
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
        self.pushButton = QtWidgets.QPushButton(TemperatureDispaly)
        font = QtGui.QFont()
        font.setPointSize(41)
        self.pushButton.setFont(font)
        self.pushButton.setObjectName("pushButton")
        self.horizontalLayout_3.addWidget(self.pushButton)
        self.TEMP = QtWidgets.QLineEdit(TemperatureDispaly)
        font = QtGui.QFont()
        font.setPointSize(44)
        font.setBold(False)
        self.TEMP.setFont(font)
        self.TEMP.setObjectName("TEMP")
        self.horizontalLayout_3.addWidget(self.TEMP)
        spacerItem = QtWidgets.QSpacerItem(200, 100, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_3.addItem(spacerItem)
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.Average_label = QtWidgets.QLabel(TemperatureDispaly)
        font = QtGui.QFont()
        font.setPointSize(16)
        font.setBold(False)
        font.setKerning(True)
        self.Average_label.setFont(font)
        self.Average_label.setAutoFillBackground(False)
        self.Average_label.setObjectName("Average_label")
        self.horizontalLayout.addWidget(self.Average_label)
        self.Average_lineEdit = QtWidgets.QLineEdit(TemperatureDispaly)
        font = QtGui.QFont()
        font.setPointSize(17)
        self.Average_lineEdit.setFont(font)
        self.Average_lineEdit.setObjectName("Average_lineEdit")
        self.horizontalLayout.addWidget(self.Average_lineEdit)
        spacerItem1 = QtWidgets.QSpacerItem(150, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem1)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.Fluctuate_label = QtWidgets.QLabel(TemperatureDispaly)
        font = QtGui.QFont()
        font.setPointSize(16)
        self.Fluctuate_label.setFont(font)
        self.Fluctuate_label.setObjectName("Fluctuate_label")
        self.horizontalLayout_2.addWidget(self.Fluctuate_label)
        self.Fluctuate_lineEdit = QtWidgets.QLineEdit(TemperatureDispaly)
        font = QtGui.QFont()
        font.setPointSize(17)
        self.Fluctuate_lineEdit.setFont(font)
        self.Fluctuate_lineEdit.setObjectName("Fluctuate_lineEdit")
        self.horizontalLayout_2.addWidget(self.Fluctuate_lineEdit)
        spacerItem2 = QtWidgets.QSpacerItem(150, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_2.addItem(spacerItem2)
        self.verticalLayout.addLayout(self.horizontalLayout_2)
        self.horizontalLayout_3.addLayout(self.verticalLayout)
        self.verticalLayout_2.addLayout(self.horizontalLayout_3)
        self.frame = QtWidgets.QFrame(TemperatureDispaly)
        self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame.setObjectName("frame")
        self.gridLayout_2 = QtWidgets.QGridLayout(self.frame)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.QgraphicsView = QChartView(self.frame)
        self.QgraphicsView.setObjectName("QgraphicsView")
        self.gridLayout_2.addWidget(self.QgraphicsView, 0, 0, 1, 1)
        self.verticalLayout_2.addWidget(self.frame)
        self.gridLayout.addLayout(self.verticalLayout_2, 0, 0, 1, 1)

        self.retranslateUi(TemperatureDispaly)
        self.pushButton.clicked.connect(TemperatureDispaly.close) # type: ignore
        QtCore.QMetaObject.connectSlotsByName(TemperatureDispaly)

    def retranslateUi(self, TemperatureDispaly):
        _translate = QtCore.QCoreApplication.translate
        TemperatureDispaly.setWindowTitle(_translate("TemperatureDispaly", "IKKEM-温度曲线"))
        self.pushButton.setText(_translate("TemperatureDispaly", "退出"))
        self.Average_label.setText(_translate("TemperatureDispaly", "3分钟温度均值"))
        self.Fluctuate_label.setText(_translate("TemperatureDispaly", "3分钟温度波动"))
from PyQt5.QtChart import QChartView

编写逻辑代码如下:

#温度可视化展示


import sys, math, random
import numpy as np
import serial
from PyQt5.QtWidgets import  QWidget, QApplication
from PyQt5.QtChart import QChart, QLineSeries, QValueAxis,QChartView
from PyQt5 import QtGui, QtWidgets
from ui_widget import Ui_TemperatureDispaly
from PyQt5.QtGui import QPainter,QPen
from PyQt5.QtCore import Qt
from PyQt5.QtCore import QTimer


class QmyWidget(QWidget):
    def __init__(self, parent=None):
      super().__init__(parent)   #调用父类构造函数,创建QWidget窗口

      self.ui = Ui_TemperatureDispaly()  # 创建UI对象
      self.ui.setupUi(self)  # 构造UI界面

      self.timer = QTimer()  # 初始化定时器
      self.timer.timeout.connect(self.my_timer_cb)#将定时器连接到回调函数

      self.chart = None  # 图表
      self.axisY = QValueAxis()
      self.counter=0
      self.createChart()#调用创建图标方法
      self.timer.start(100)#定时器开始,400ms回调一次
      self.ser = serial.Serial("/dev/ttyAMA0", 9600)  # 打开串口,波特率9600

    def createChart(self):
       self.chart = QChart()
       self.chart.legend().hide()
       self.ui.QgraphicsView.setChart(self.chart)
       self.ui.QgraphicsView.setRenderHint(QPainter.Antialiasing)
       self.ui.QgraphicsView.setRubberBand(QChartView.RectangleRubberBand)

       font1 = QtGui.QFont()  # 创建字体对象font,用QFont类
       font1.setPointSize(50)  # 设置字体大小
       font1.setBold(True)  # 设置为粗体
       self.ui.TEMP.setFont(font1)
       self.ui.TEMP.setStyleSheet("color:blue")

       self.ui.TEMP.setAlignment(Qt.AlignCenter)
       self.ui.Average_lineEdit.setAlignment(Qt.AlignCenter)
       self.ui.Fluctuate_lineEdit.setAlignment(Qt.AlignCenter)#居中对其

       op = QtWidgets.QGraphicsOpacityEffect()
       # 设置透明度的值,0.0到1.0,最小值0是透明,1是不透明
       op.setOpacity(0)
       self.ui.pushButton.setGraphicsEffect(op)#设置退出按钮透明

       series = QLineSeries()
       series.setUseOpenGL(True)
       self.chart.addSeries(series)
       pen = QPen(Qt.red)
       pen.setStyle(Qt.SolidLine)  # SolidLine, DashLine, DotLine, DashDotLine
       pen.setWidth(2)
       series.setPen(pen)  # 序列的线条设置

       font2 = QtGui.QFont()  # 创建字体对象font,用QFont类
       font2.setPointSize(11)  # 设置字体大小
       font2.setBold(True)  # 设置为粗体

       axisX = QValueAxis()
       axisX.setRange(0, 3)
       axisX.setLabelFormat("%.1f")  # 标签格式
       axisX.setLabelsFont(font2)
       axisX.setTickCount(7)  # 主分隔个数
       axisX.setMinorTickCount(1)
       axisX.setGridLineVisible(True)
       axisX.setMinorGridLineVisible(True)


       self.axisY.setLabelFormat("%.3f")  # 标签格式
       self.axisY.setLabelsFont(font2)
       self.axisY.setTickCount(8)
       self.axisY.setGridLineVisible(True)
       self.axisY.setMinorGridLineVisible(False)

       self.chart.addAxis(axisX, Qt.AlignBottom)  # 坐标轴添加到图表,并指定方向
       self.chart.addAxis(self.axisY, Qt.AlignLeft)

       series.attachAxis(axisX)  # 序列 series坐标轴
       series.attachAxis(self.axisY)

    def my_timer_cb(self, temp_average=None):
      chart = self.ui.QgraphicsView.chart()  # 获取chartView中的QChart对象
      series = chart.series()[0]  # 获取第1个序列,QLineSeries
      received_data = self.ser.read()  # 读取串口端口
      data_left = self.ser.inWaiting()  # 检查串口数据
      received_data += self.ser.read(data_left)#将串口数据添加到变量里
      if len(received_data)>9:#这里处理两个数据连接在一起的情况
          re_data = int(received_data[-9:-1:1])
      else:
          re_data = int(received_data)
      #标定后修改下一句代码
      re_data = round((re_data * 4000 / 8388607-1000)/3.85, 4)#将AD值处理成温度
      self.ui.TEMP.setText('%.4f' % re_data+"℃") #改变当前温度窗口数据

      if self.counter < 3:
          series.append(self.counter, re_data)
          self.counter+=3/1800
      else:
          points = series.pointsVector()
          for i in range(1800):
              points[i].setY(points[i + 1].y())
          points[-1].setY(re_data)
          series.replace(points)

      num=[]
      p = series.pointsVector()
      y_min = min(p, key=lambda point: point.y()).y()
      y_max = max(p, key=lambda point: point.y()).y()
      for i in range(len(p)):
          num.append(p[i].y())
      temp_average = np.average(num)

      self.ui.Average_lineEdit.setText('%.4f' % temp_average)
      self.ui.Fluctuate_lineEdit.setText('%.4f' % (y_max-y_min))
      self.axisY.setRange(y_min, y_max)

if  __name__ == "__main__":        #用于当前窗体测试

    app = QApplication(sys.argv)    #创建GUI应用程序
    form=QmyWidget()            #创建窗体
    form.showFullScreen()       #全屏展示
    form.show()
    sys.exit(app.exec_())

实现功能:
在这里插入图片描述

在这里插入图片描述

  • 7
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值