pyqt+pyqtgraph+lka
使用环境:
win10,STM32F407串口输出,输出格式b’,’
1、问题1:需要注意的是使用pyinstaller进行打包成功生成exe,但是运行exe一直提示pyqtgraph找不到pyqt安装包,但是pyqtgraph和pyqt5和pyqt5-tools都已正确安装。
解决办法:程序中 import pyqtgraph as pg
放到import PyQt5
后面。
2、问题2:生成exe之后,点击运行提示importError: unable to find Qt5Core.dll on PATH
。
解决办法:将程序修改为如下代码所示
import sys, os
if hasattr(sys, 'frozen'):os.environ['PATH'] = sys._MEIPASS + ";" + os.environ['PATH']
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtWidgets import *
from untitled import Ui_MainWindow
from PyQt5.QtGui import *
main函数:
import os
import sys
import pyqtgraph as pg
import numpy as np
import threading
import serial
import serial.tools.list_ports
import array
import time
import PyQt5
from PyQt5.QtWidgets import *
from PyQt5.QtCore import pyqtSlot, QBasicTimer,Qt, QTimer,Qt
from PyQt5.QtWidgets import QDialog,QSplashScreen
from PyQt5 import QtWidgets
from PyQT_Form import Ui_Form
import math
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *jishu1 = 0 # type: int
#接收不到数据,循环10次之后退出
exit_sum = 0#使用matplotlib模块绘图,可以嵌入到tkinter,但是性能不好
dis = np.zeros(80) #左车道线距离
dis2 = dis
dis3 = np.zeros(80) #右车道线距离
dis4 = dis3
dis5 = np.zeros(80) #方向盘转角
dis6 = dis5
dis7 = np.zeros(80) #方位角
dis8 = dis7
dis9 = np.zeros(80) #发送扭矩大小
dis10 = dis9#截图命名
name_sum = 0
#pyqtgraph模块绘图,不能嵌入到tkinter,但是性能较好
gg = 0
zxd = 0
data = []
shuju = []
shuju2 = []
shuju3 = []
shuju4 = []
shuju5 = []
historyLength = 0
historyLength2 = 0def good():print('good')class WorkThread(QThread):trigger = pyqtSignal()def __int__(self):super(WorkThread, self).__init__()def run(self):ff = MyPyQT_Form()while 1:ff.lka_all()# ff.recv()# # 循环完毕后发出信号# self.trigger.emit()class MyPyQT_Form(QtWidgets.QWidget,Ui_Form):def __init__(self):super(MyPyQT_Form,self).__init__()self.setupUi(self)self.app_pyqt()self.restart()# self.recv()def plotData(self):global gg# global lka_cs_in, c0_l_in, c0_r_in, angle_main_in, azi_main_in, Tor_Value, deviation_reminderglobal lka_cs_in, lka_sign_timer_in, lka_on_in, torque_in, angle_main_in, c0_l_in, c0_r_in, azi_main_in, deviation_reminder, \touchline_sign, Tor_Value, c0_l_lctype, c0_r_rtype, c2_l, c3_l, c2_r, c3_r, degree_confidence_l, degree_confidence_r, zxdglobal data,shuju,shuju2,shuju3,shuju4,shuju5global idx # 内部作用域想改变外部域变量global historyLengthglobal historyLength2gg = gg + 0.01# print('lka_cs_in', lka_cs_in)try:# tmp = math.sin(gg) #测试使用# tmp2 = math.cos(gg)# tmp3 = 10 * math.sin(gg)# tmp4 = 0.1 * math.sin(gg)tmp = float(c0_l_in)tmp2 = float(c0_r_in)tmp3 = float(angle_main_in)tmp4 = float(azi_main_in)except:tmp = 0tmp2 = 0tmp3 = 0tmp4 = 0try:tmp5 = float(Tor_Value)except:tmp5 = 0try:tmp6 = float(deviation_reminder)except:tmp6 = 0if len(data) <= historyLength:data.append(tmp)shuju.append(tmp2)shuju2.append(tmp3)shuju3.append(tmp4)shuju4.append(tmp5)shuju5.append(tmp6)else:data[:-1] = data[1:] # 前移data[-1] = tmpshuju[:-1] = shuju[1:] # 前移shuju[-1] = tmp2shuju2[:-1] = shuju2[1:] # 前移shuju2[-1] = tmp3shuju3[:-1] = shuju3[1:] # 前移shuju3[-1] = tmp4shuju4[:-1] = shuju4[1:] # 前移shuju4[-1] = tmp5shuju5[:-1] = shuju5[1:] # 前移shuju5[-1] = tmp6self.curve1.setData(data)self.curve2.setData(shuju)self.curve3.setData(shuju2)self.curve4.setData(shuju3)self.curve5.setData(shuju4)self.curve6.setData(shuju5)idx += 1try:self.lineEdit.clear()self.lineEdit.setText(str(float(lka_cs_in)))self.lineEdit_2.clear()self.lineEdit_2.setText(str(float(torque_in)))self.lineEdit_3.clear()self.lineEdit_3.setText(str(float(angle_main_in)))self.lineEdit_4.clear()self.lineEdit_4.setText(str(float(c0_l_in)))self.lineEdit_5.clear()self.lineEdit_5.setText(str(float(c0_r_in)))self.lineEdit_6.clear()self.lineEdit_6.setText(str(float(azi_main_in)))self.lineEdit_7.clear()self.lineEdit_7.setText(str(float(deviation_reminder)))self.lineEdit_8.clear()self.lineEdit_8.setText(str(float(lka_sign_timer_in)))self.lineEdit_9.clear()self.lineEdit_9.setText(str(float(Tor_Value)))self.lineEdit_10.clear()self.lineEdit_10.setText(str(float(touchline_sign)))self.lineEdit_11.clear()self.lineEdit_11.setText(str(float(lka_on_in)))self.lineEdit_12.clear()self.lineEdit_12.setText(str(float(degree_confidence_l)))self.lineEdit_13.clear()self.lineEdit_13.setText(str(float(degree_confidence_r)))self.lineEdit_14.clear()self.lineEdit_14.setText(str(float(c0_l_lctype)))self.lineEdit_15.clear()self.lineEdit_15.setText(str(float(c0_r_rtype)))self.lineEdit_16.clear()self.lineEdit_16.setText(str(float(c2_l)))self.lineEdit_17.clear()self.lineEdit_17.setText(str(float(c3_l)))self.lineEdit_18.clear()self.lineEdit_18.setText(str(float(c2_r)))self.lineEdit_19.clear()self.lineEdit_19.setText(str(float(c3_r)))self.lineEdit_20.clear()self.lineEdit_20.setText(str(float(zxd)))if float(lka_cs_in) >= 30.0:if float(degree_confidence_r) < 2 or float(degree_confidence_l) < 2:self.textEdit.clear()self.textEdit.setText('置信度较低\n不能识别车道线')elif deviation_reminder == b'1.0' and jishu1 == 0:self.textEdit.clear()self.textEdit.setText('左偏离')if touchline_sign == b'1':self.textEdit.clear()self.textEdit.setText('左偏离+压线\n正在退出纠正...')elif deviation_reminder == b'-1.0' and jishu1 == 0:self.textEdit.clear()self.textEdit.setText('右偏离')if touchline_sign == b'1':self.textEdit.clear()self.textEdit.setText('右偏离+压线\n正在退出纠正...')elif touchline_sign == b'1':self.textEdit.clear()self.textEdit.setText('压线\n正在退出纠正...')elif jishu1 == 1:self.textEdit.clear()self.textEdit.setText('数据错误')elif float(zxd == 1):self.textEdit.clear()self.textEdit.setText('已开启转向灯\nLKA未激活')else:self.textEdit.clear()else:self.textEdit.clear()self.textEdit.setText('车速<30Km/h\nLKA未激活')except:passdef recv(self): # 从串口获取数据# start1 = time.time()global exit_sum, jishu1try:data3 = serial1.readline()data_str = str(data3)if data_str.count(',') != 19:data3 = b'0,0,0,0.0,0.00,0.000,0.000,0.00,0.0,0,0.00,0,0,0.000,0.000,0.000,0.000,0,0,1\n'jishu1 = 1exit_sum = exit_sum + 1elif data_str.count(',') == 19:jishu1 = 0exit_sum = 0# end1 = time.time()# print(end1 - start1)except:data3 = b'0,0,0,0.0,0.00,0.000,0.000,0.00,0.0,0,0.00,0,0,0.000,0.000,0.000,0.000,0,0,2\n'# print('data3:',data3)return data3def app_pyqt(self):global idx, historyLengthglobal data, shuju, shuju2, shuju3, shuju4, shuju5win = pg.GraphicsLayoutWidget(self.frame)self.verticalLayout.addWidget(win)win.setWindowTitle(u'实时监测卡车参数')data = array.array('d') # 可动态改变数组的大小,double型数组shuju = array.array('d') # 可动态改变数组的大小,double型数组shuju2 = array.array('d')shuju3 = array.array('d')shuju4 = array.array('d')shuju5 = array.array('d')historyLength = 200 # 横坐标长度p = win.addPlot() # 把图p加入到窗口中p.showGrid(x=True, y=True) # 把X和Y的表格打开p.setRange(xRange=[0, historyLength], yRange=[-4.0, 4.0], padding=0)p.setLabel(axis='left', text='左右车道线距离') # 靠左p.setLabel(axis='bottom', text='time')p.setTitle('车道线距离') # 表格的名字self.curve1 = p.plot(pen='w') # 绘制一个图形self.curve2 = p.plot(pen='g') # 绘制一个图形angle_steer = win.addPlot(left='方向盘转角', bottom='time',title='方向盘转角')angle_steer.showGrid(x=True, y=True) # 把X和Y的表格打开angle_steer.setRange(xRange=[0, historyLength], yRange=[-180, 180], padding=0)self.curve3 = angle_steer.plot(pen='w')win.nextRow()azi = win.addPlot(left='方位角', bottom='time', title='方位角')azi.showGrid(x=True, y=True) # 把X和Y的表格打开azi.setRange(xRange=[0, historyLength], yRange=[-0.2, 0.2], padding=0)self.curve4 = azi.plot(pen='w')T_send = win.addPlot(left='发送扭矩', bottom='time', title='发送扭矩')T_send.showGrid(x=True, y=True) # 把X和Y的表格打开T_send.setRange(xRange=[0, historyLength], yRange=[-2, 2], padding=0)self.curve5 = T_send.plot(pen='r')self.curve6 = T_send.plot(pen='g')idx = 0timer = QTimer(self)timer.timeout.connect(self.plotData)timer.start(20)# 重启程序def restart(self):global data1, serial1, com_0, com_koutry:serial1.close()except:passport_list22 = list(serial.tools.list_ports.comports())if len(port_list22) == 0:passelse:com_0 = str(port_list22[0])com_kou = com_0.split(' ')[0]try:serial1 = serial.Serial(com_kou, 115200, timeout=0.15) # com_koudata1 = self.recv() # 将数据进行解析self.lineEdit_21.clear()self.lineEdit_21.setText('串口已打开 g1')except:data1 = b'000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000\n'try:if serial1.isOpen():self.lineEdit_21.clear()self.lineEdit_21.setText('串口已打开 g2')else:self.lineEdit_21.clear()self.lineEdit_21.setText('串口未打开 error1')except:self.lineEdit_21.clear()self.lineEdit_21.setText('检测不到串口 error1')#主要数据处理def lka_all(self):global jishu1global lka_cs_in, lka_sign_timer_in, lka_on_in, torque_in, angle_main_in, c0_l_in, c0_r_in, azi_main_in, deviation_reminder, \touchline_sign, Tor_Value, c0_l_lctype, c0_r_rtype, c2_l, c3_l, c2_r, c3_r, degree_confidence_l, degree_confidence_r, zxdglobal exit_sumtry:data1 = self.recv() # 将数据进行解析except:data1 = b'0,0,0,0.0,0.00,0.000,0.000,0.00,0.0,0,0.00,0,0,0.000,0.000,0.000,0.000,0,0,3\n'# print('data1:',data1)if exit_sum > 9999: #接收不到数据,循环10次之后退出os._exit(0)if data1 != b'':lka_cs_in = data1.split(str.encode(','))[0] # 车速信息# self.lineEdit.clear()# self.lineEdit.setText(str(float(lka_cs_in)))lka_sign_timer_in = data1.split(str.encode(','))[1] # 程序执行到那一步的标志位.# self.lineEdit_2.clear()# self.lineEdit_2.setText(str(float(lka_sign_timer_in)))lka_on_in = data1.split(str.encode(','))[2] # LKA的总开关是否开启# self.lineEdit_3.clear()# self.lineEdit_3.setText(str(float(lka_on_in)))torque_in = data1.split(str.encode(','))[3] # 方向盘的扭矩,驾驶员驾驶的扭矩# self.lineEdit_4.clear()# self.lineEdit_4.setText(str(float(torque_in)))angle_main_in = data1.split(str.encode(','))[4] # 方向盘的转角# self.lineEdit_5.clear()# self.lineEdit_5.setText(str(float(angle_main_in)))c0_l_in = data1.split(str.encode(','))[5] # 距离左边线的距离# self.lineEdit_6.clear()# self.lineEdit_6.setText(str(float(c0_l_in)))c0_r_in = data1.split(str.encode(','))[6] # 距离右边线的距离# self.lineEdit_7.clear()# self.lineEdit_7.setText(str(float(c0_r_in)))azi_main_in = data1.split(str.encode(','))[7] # 车身的方位角# self.lineEdit_8.clear()# self.lineEdit_8.setText(str(float(azi_main_in)))deviation_reminder = data1.split(str.encode(','))[8] # 是否满足偏离条件,左偏为1,右偏为-1# self.lineEdit_9.clear()# self.lineEdit_9.setText(str(float(deviation_reminder)))touchline_sign = data1.split(str.encode(','))[9] # 是否压线# self.lineEdit_10.clear()# self.lineEdit_10.setText(str(float(touchline_sign)))# print(touchline_sign)Tor_Value = data1.split(str.encode(','))[10] # 发送的扭矩值# self.lineEdit_11.clear()# self.lineEdit_11.setText(str(float(Tor_Value)))c0_l_lctype = data1.split(str.encode(','))[11] # 左车道线类型# self.lineEdit_12.clear()# self.lineEdit_12.setText(str(float(c0_l_lctype)))c0_r_rtype = data1.split(str.encode(','))[12] # 右车道线类型# self.lineEdit_13.clear()# self.lineEdit_13.setText(str(float(c0_r_rtype)))c2_l = data1.split(str.encode(','))[13] # zuo曲率# self.lineEdit_14.clear()# self.lineEdit_14.setText(str(float(c2_l)))c3_l = data1.split(str.encode(','))[14] # 左曲率导数# self.lineEdit_15.clear()# self.lineEdit_15.setText(str(float(c3_l)))c2_r = data1.split(str.encode(','))[15] # 右曲率# self.lineEdit_16.clear()# self.lineEdit_16.setText(str(float(c2_r)))c3_r = data1.split(str.encode(','))[16] # 右曲率倒数# self.lineEdit_17.clear()# self.lineEdit_17.setText(str(float(c3_r)))degree_confidence_l = data1.split(str.encode(','))[17] # 左置信度# self.lineEdit_18.clear()# self.lineEdit_18.setText(str(float(degree_confidence_l)))degree_confidence_r = data1.split(str.encode(','))[18] # 右置信度# self.lineEdit_19.clear()# self.lineEdit_19.setText(str(float(degree_confidence_r)))zxd = data1.split(str.encode(','))[19] # 右置信度# self.lineEdit_20.clear()# self.lineEdit_20.setText(str(float(zxd)))# print('error error1111111111111111111111')def closecom(self):global serial1try:serial1.close()self.lineEdit_21.clear()self.lineEdit_21.setText(str('串口已关闭 g3'))except:self.lineEdit_21.clear()self.lineEdit_21.setText(str('检测不到串口 error2'))# 实现pushButton_click()函数,textEdit是我们放上去的文本框的iddef dynamicgraph(self):timer = QTimer(self)timer.timeout.connect(self.plotData)timer.start(20)def quitall(self):self.closecom()os._exit(0)def pausescreenshot(self):reply = QMessageBox.warning(self,"警告","暂时没有该功能!",QMessageBox.Yes)# self.echo(reply)if __name__ == '__main__':app = QtWidgets.QApplication(sys.argv)# splash = QSplashScreen(PyQt5.QtGui.QPixmap("kaiji.jpg"))# splash.show()# # 定义字体格式# font = PyQt5.QtGui.QFont()# font.setPointSize(20)# font.setBold(True)# font.setWeight(75)# splash.setFont(font)# splash.showMessage("正在加载。。。", Qt.AlignCenter, Qt.red, )# time.sleep(0.5)# splash.showMessage("启动。。。", Qt.AlignCenter, Qt.red)# time.sleep(0.5)# # 设置进程,启动加载页面时可以进行其他操作而不会卡死# app.processEvents()my_pyqt_form = MyPyQT_Form()workThread = WorkThread()workThread.start()my_pyqt_form.show()# # 结束启动页# splash.finish(my_pyqt_form)sys.exit(app.exec_())