
总概:
(1)使用 Raspberry 4B作为主控芯片,通过不同模块采集信息。
(2)搭建BP神经网络模型并训练,根据采集信息算出蓄电池的补水量。
(3)使用PyQT编写人机交互界面。
硬件准备:
Raspberry Pi 4B

PT1000温度传感器

MAX31865放大器

超声波测距传感器

模数转换器

比重检测模块

总体连接图

环境配置:
树莓派新板子配置可以看我之前的博客,有详细介绍树莓派开机
蓝牙配置
以下是DM35密度仪蓝牙配置及数据传输

Blueman插件

在树莓派上将所需依赖安装上
sudo apt update && sudo apt upgrade
sudo apt install bluetooth pi-bluetooth bluez blueman


之后右上角就出线了蓝牙的图标,可以通过GUI点击蓝牙配对比重仪并且信任该设备,或者通过以下命令行:
sudo bluetoothctl
scan on
pair XX:XX:XX:XX:XX:XX
connect XX:XX:XX:XX:XX:XX
exit
当比重仪点击发送数据后,树莓派就能接受到数据

发送的是一个Iso8859编码格式的txt文件

这里使用正则表达式将比重、温度、密度等需要信息提取出来


屏幕驱动

可以上LCDWIKI找到具体的LCD信号及其驱动文件。

按照步骤一步一步配置即可,注意的是有些触摸板上是power和touch接口,并不是下图这种双power接口,所以接线时除了HDMI还需要接touch线而不接power线。

软件编写
写得很烂,完全没有去耦合,能跑就行
- #用到的python解释库导入
- import re
- from PyQt5.QtWidgets import QLabel,QLineEdit
- from PyQt5.QtCore import QTimer,QDateTime, QSize, Qt
- from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QComboBox
- from PyQt5.QtGui import *
-
- import sys
- import os
-
- import numpy as np
- import pandas as pd
- from matplotlib import pyplot as plt
- from openpyxl.styles.builtins import output
- import time
- import board
- import digitalio
- import adafruit_max31865
- import ADS1263.ADS1263 as AD
- import RPi.GPIO as GPIO
-
- os.environ["QT_IM_MODULE"] = "qtvirtualkeyboard"
-
- #接下来这部分是BP神经网络的内容
-
- #定义每一层之间用到的传递函数
- def sigmoid(x):
- # 第一层到第二层的激活函数
- return 1 / (1 + np.exp(-x))
-
- def deriv_sigmoid(x):
- # 第一层到第二层的激活函数的求导函数
- fx = sigmoid(x)
- return fx * (1 - fx)
-
- def mse_loss(y_true, y_pred):
- # 使用方差作为损失函数
- return ((y_true - y_pred) ** 2).mean()
-
- #开始神经网络的建立过程
- class OurNeuralNetwork:
-
- def __init__(self):
- # 第一层到第二层的权重初始值设置
- self.w11 = np.random.normal()
- self.w12 = np.random.normal()
- self.w13 = np.random.normal()
- self.w14 = np.random.normal()
- self.w21 = np.random.normal()
- self.w22 = np.random.normal()
- self.w23 = np.random.normal()
- self.w24 = np.random.normal()
- # 第二层到第三层的权重初始值设置
- self.w1 = np.random.normal()
- self.w2 = np.random.normal()
- # 每一层截距项的初始值设置,Biases
- self.b1 = np.random.normal()
- self.b2 = np.random.normal()
- self.b3 = np.random.normal()
-
- # 前向传播学习函数
- def feedforward(self, x):
- h1 = sigmoid(self.w11 * x[0] + self.w12 * x[1] + self.w13 * x[2] + self.w14 * x[3] + self.b1)
- h2 = sigmoid(self.w21 * x[0] + self.w22 * x[1] + self.w23 * x[2] + self.w24 * x[3] + self.b1)
- o1 = self.w1 * h1 + self.w2 * h2 + self.b3
- return o1
- #训练函数
- def train(self, data, all_y_trues):
- learn_rate = 0.001 # 学习率
- epochs = 1000 # 训练的次数
- # 画图数据
- self.loss = np.zeros(100)
- self.sum = 0
- # 开始训练
- for epoch in range(epochs):
- for x, y_true in zip(data, all_y_trues):
- # 计算h1
- h1 = sigmoid(self.w11 * x[0] + self.w12 * x[1] + self.w13 * x[2] + self.w14 * x[3] + self.b1)
- # 计算h2
- h2 = sigmoid(self.w21 * x[0] + self.w22 * x[1] + self.w23 * x[2] + self.w24 * x[3] + self.b2)
- #计算输出节点
- y_pred = self.w1 * h1 + self.w2 * h2 + self.b3
- # 反向传播计算导数
- d_L_d_ypred = -2 * (y_true - y_pred)
- d_ypred_d_w1 = h1
- d_ypred_d_w2 = h2
- d_ypred_d_b3 = 0
- d_ypred_d_h1 = self.w1
- d_ypred_d_h2 = self.w2
- sum_1=self.w11 * x[0] + self.w12 * x[1] + self.w13 * x[2] + self.w14 * x[3] + self.b1
- d_h1_d_w11 = x[0] * deriv_sigmoid(sum_1)
- d_h1_d_w12 = x[1] * deriv_sigmoid(sum_1)
- d_h1_d_w13 = x[2] * deriv_sigmoid(sum_1)
- d_h1_d_w14 = x[3] * deriv_sigmoid(sum_1)
- d_h1_d_b1 = deriv_sigmoid(sum_1)
- sum_2 = self.w21 * x[0] + self.w22 * x[1] + self.w23 * x[2] + self.w24 * x[3] + self.b2
- d_h1_d_w21 = x[0] * deriv_sigmoid(sum_2)
- d_h1_d_w22 = x[1] * deriv_sigmoid(sum_2)
- d_h1_d_w23 = x[2] * deriv_sigmoid(sum_2)
- d_h1_d_w24 = x[3] * deriv_sigmoid(sum_2)
- d_h1_d_b2 = deriv_sigmoid(sum_2)
-
- # 梯度下降法
- self.w11 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w11
- self.w12 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w12
- self.w13 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w13
- self.w14 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w14
- self.b1 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_b1
- self.w21 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h1_d_w21
- self.w22 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h1_d_w22
- self.w23 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h1_d_w23
- self.w24 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h1_d_w24
- self.b2 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h1_d_b2
- self.w1 -= learn_rate * d_L_d_ypred * d_ypred_d_w1
- self.w1 -= learn_rate * d_L_d_ypred * d_ypred_d_w2
- self.b3 -= learn_rate * d_L_d_ypred * d_ypred_d_b3
-
- if epoch % 10 == 0:
- y_preds = np.apply_along_axis(self.feedforward, 1, data)
- loss = mse_loss(all_y_trues, y_preds)
- print("Epoch %d loss: %.3f" % (epoch, loss))
- self.loss[self.sum] = loss
- self.sum = self.sum + 1
-
- # 训练数据文件导入
- FILENAME = "/home/pi/Downloads/data.xlsx"
- # 禁用科学计数法
- pd.set_option('float_format', lambda x: '%.3f' % x)
- np.set_printoptions(suppress=True,threshold=sys.maxsize)
- # 得到的DataFrame分别为补水量、密度、电压、高度、温度
- data = pd.read_excel(FILENAME, header=0, usecols="A,B,C,D,E")
- DataArray = data.values
- Y = DataArray[:, 0]
- X = DataArray[:, 1:5]
- X = np.array(X)#转化为array,自变量
- Y = np.array(Y)#转化为array,因变量
-
- # 处理数据
- data = np.array(X)
- data_mean = np.sum(data, axis=0) / np.size(data, 0)
- data = (data - data_mean) / np.max(data)
- all_y_trues = np.array(Y)
- all_y_trues_mean = np.sum(all_y_trues) / np.size(all_y_trues)
- all_y_trues = (all_y_trues - all_y_trues_mean) / np.max(all_y_trues)
-
- # 训练数据
- network = OurNeuralNetwork()
- network.train(data, all_y_trues)
-
- # 输出神经网络参数
- print("w11-->%.3f" % network.w11)
- print("w12-->%.3f" % network.w12)
- print("w13-->%.3f" % network.w13)
- print("w14-->%.3f" % network.w14)
- print("w21-->%.3f" % network.w21)
- print("w22-->%.3f" % network.w22)
- print("w23-->%.3f" % network.w23)
- print("w24-->%.3f" % network.w24)
- print("w1-->%.3f" % network.w1)
- print("w2-->%.3f" % network.w2)
- print("b1-->%.3f" % network.b1)
- print("b2-->%.3f" % network.b2)
- print("b3-->%.3f" % network.b3)
-
-
- #这部分是人机界面的建立过程
- class Stats():
- def __init__(self):
- #主窗口设计参数
- self.window = QMainWindow()
- self.window.showFullScreen()
- self.window.move(0, 0)
- self.window.setWindowTitle('测控界面')
- self.window.setWindowFlags(Qt.FramelessWindowHint)
- self.window.setObjectName("MainWindow")
- self.window.setStyleSheet("#MainWindow{border-image:url(bg.jpg)}")
- self.state = True
-
- self.wendu = QLabel('温度(°)', self.window) # 温度按钮
- self.wendu.setGeometry(80, 200, 150, 60) # (x坐标,y坐标,宽,高)
-
- self.tem = 0
- self.Label1 = QLineEdit(f'{self.tem}', self.window) # 单文本框1:温度显示值
- self.Label1.setGeometry(250, 200, 150, 60) # (x坐标,y坐标,宽,高)
- self.Label1.setAlignment(Qt.AlignCenter) # 设置文本框中内容居中
-
- self.bizhong = QLabel('密度(g/cm3)', self.window) # 比重按钮
- self.bizhong.setGeometry(80, 350, 150, 60) # (x坐标,y坐标,宽,高)
-
- self.midu = 0
- self.Label4 = QLineEdit(f'{self.midu}', self.window) # 单文本框4:比重显示值
- self.Label4.setGeometry(250, 350, 150, 60) # (x坐标,y坐标,宽,高)
- self.Label4.setAlignment(Qt.AlignCenter) # 设置文本框中内容居中
-
- self.gaodu = QLabel('高度(cm)', self.window) # 高度按钮
- self.gaodu.setGeometry(640, 200, 150, 60) # (x坐标,y坐标,宽,高)
-
- self.hei = 0
- self.Label2 = QLineEdit(f'{self.hei}', self.window) # 单文本框2:高度显示值
- self.Label2.setGeometry(810, 200, 150, 60) # (x坐标,y坐标,宽,高)
- self.Label2.setAlignment(Qt.AlignCenter) # 设置文本框中内容居中
-
- self.bushui = QLabel('水量(ml)', self.window) # 补水量按钮
- self.bushui.setGeometry(640, 350, 150, 60) # (x坐标,y坐标,宽,高)
-
- self.shui = 0
- self.Label3 = QLineEdit(f'{self.shui}', self.window) # 单文本框3:补水量显示值
- self.Label3.setGeometry(810, 350, 150, 60) # (x坐标,y坐标,宽,高)
- self.Label3.setAlignment(Qt.AlignCenter) # 设置文本框中内容居中
-
- self.ceshi = QPushButton('刷新', self.window) # 开始按钮,点击来对此时测量量进行显示以及赋值
- self.ceshi.setGeometry(100, 100, 60, 30) # (x坐标,y坐标,宽,高)
- self.ceshi.clicked.connect(self.handleCalc)
-
-
- self.caculate_out_label = QLabel('补水量',self.window)
- self.caculate_out_label.setGeometry(100, 50, 60, 30) # (x坐标,y坐标,宽,高)
- self.caculate_out_label.setAlignment(Qt.AlignCenter)
-
- self.Ncalculate_data=0
- self.caculate_outData_label = QLabel(f'{self.Ncalculate_data}',self.window) # 在self.window窗口添加一个标签time_label
- self.caculate_outData_label.setGeometry(180, 50, 60, 30) # (x坐标,y坐标,宽,高)
- self.caculate_outData_label.setAlignment(Qt.AlignCenter)
-
- self.state_label = QLabel(f'OK',self.window) # 在self.window窗口添加一个标签time_label
- self.state_label.setGeometry(250, 50, 60, 30) # (x坐标,y坐标,宽,高)
- self.state_label.setAlignment(Qt.AlignCenter)
-
- self.time_label = QLabel(self.window) # 在self.window窗口添加一个标签time_label
- self.time_label.setGeometry(700, 0, 300, 200) # (x坐标,y坐标,宽,高)
- self.time_label.setAlignment(Qt.AlignCenter) # 函数setAlignment()主要将是消除布局中的空隙,让两个控件紧紧挨在一起
- self.Timer = QTimer() # 创建定时器
- self.Timer.start(500) # 定时器每500ms工作一次
- self.Timer.timeout.connect(self.TimeUpdate) # 500指的是500ms,即每500ms调用一下这个TimeUpdate函数
- # 建立定时器连接通道 注意这里调用TimeUpdate方法,不是方法返回的的结果,所以不能带括号, # 写成self.TimeUpdate()是不对的,带括号代表返回值
-
- self.setup = QPushButton('设置', self.window) # 设置按钮:点击进入下一界面
- self.setup.setGeometry(300, 100, 60, 30) # (x坐标,y坐标,宽,高)
- self.setup.clicked.connect(self.call_dialog)
-
- self.Ncalculate = QPushButton('计算', self.window) # 开始按钮,点击来对此时测量量进行显示以及赋值
- self.Ncalculate.setGeometry(200, 100, 60, 30) # (x坐标,y坐标,宽,高)
- self.Ncalculate.clicked.connect(self.Ncalculate_handle)
-
- # 电池类型选择:模式一,模式二,模式三分别代表不同的电池组类型
- self.moshi = QComboBox(self.window)
- self.moshi.setGeometry(400, 100, 110, 30) # (x坐标,y坐标,宽,高)
- self.moshi.addItem("模式1")
- self.moshi.addItem("模式2")
- self.moshi.addItem("模式3")
-
-
-
- # 下面是前面用到的函数功能定义总结
- # 函数一:用于变量显示
- def handleCalc(self): # 开始按钮对应的函数 def handleCalc(self):
-
-
- # 通过SPI通讯读取MAX31865上面的数据(读取热电偶输出值)
- spi = board.SPI()
- cs = digitalio.DigitalInOut(board.D5) # Chip select of the MAX31865 board.
- sensor = adafruit_max31865.MAX31865(spi, cs, rtd_nominal=1000.0, ref_resistor=4300.0, wires=4)
- print("Temperature: {0:0.3f}C".format(sensor.temperature))
- print("resistance: {0:0.3f} Ohms".format(sensor.resistance))
- self.tem = round(sensor.temperature,2)
- self.temperature=sensor.temperature
- # 通过SPI通讯分时复用读取ADS1263上面的数据(读取超声波传感器上输出值)
- REF = 5.08 # Modify according to actual voltage
- try:
- ADC = AD.ADS1263()
- if (ADC.ADS1263_init_ADC1('ADS1263_7200SPS') == -1):
- exit()
- ADC.ADS1263_SetMode(0)
- self.ADC_Value = ADC.ADS1263_GetAll() # get ADC1 value
- self.height = self.ADC_Value[1] * REF / 0x7fffffff
- print("ADC1 IN1 = %lf" % self.height) # 32bit
- self.hei=round(self.height, 2)
- except IOError as e:
- print(e)
-
-
- self.buttonLabel1 = f'{self.tem}'
- self.Label1.setText(self.buttonLabel1) # 改变标签1的函数,给标签1赋当前温度值
-
- self.buttonLabel2 = f'{self.hei}'
- self.Label2.setText(self.buttonLabel2) # 改变标签1的函数,给标签2赋当前温度值
-
- try:
- f = open('./measureLog_export.txt',encoding='iso8859')
- except:
- self.Density=0
- print(f'bluetooth error:not file')
- self.state = False
- else:
- read_data_line=f.readlines()
- f.close()
- read_data_line_count=len(read_data_line)
- os.remove("./measureLog_export.txt")
-
- regex = re.compile("[0-9]+.*[0-9]")
- search_data=regex.search(read_data_line[read_data_line_count-6])
- SampleID=str(search_data.group())
- print(f'SampleID is {SampleID}')
-
-
- regex = re.compile("[0-9]+.*[0-9]")
- search_data=regex.search(read_data_line[read_data_line_count-5])
- self.Density=float(search_data.group())
- print(f'Density is {self.Density}')
-
- regex = re.compile("[0-9]+.*[0-9]")
- search_data=regex.search(read_data_line[read_data_line_count-3])
- SG=float(search_data.group())
- print(f'SG is {SG}')
- self.state = True
-
-
- self.midu=round(self.Density, 2)
-
- self.buttonLabel4 = f'{self.midu}'
- self.Label4.setText(self.buttonLabel4)
-
- info = self.moshi.currentText() # 提取模式多组合选择里面的文本出来,此时文本包括字符串以及数字
- salary = re.sub("\D", "", info) # 提取info里面的数字出来
-
- if int(salary) == 1: # 根据模式不同,赋给按钮6补水量的值也有所不同
- self.shui = 10
- self.buttonLabel3 = f'{self.shui}'
- self.Label3.setText(self.buttonLabel3) # 改变按钮6标签的函数
- if int(salary) == 2:
- self.shui = 20
- self.buttonLabel3 = f'{self.shui}'
- self.Label3.setText(self.buttonLabel3) # 改变按钮6标签的函数
- if int(salary) == 3:
- self.shui = 30
- self.buttonLabel3 = f'{self.shui}'
- self.Label3.setText(self.buttonLabel3) # 改变按钮6标签的函数
-
-
- # 函数二:用于时间刷新,实时时间显示:目前是调用当前电脑上时间
- def TimeUpdate(self):
- self.time_label.setText(QDateTime.currentDateTime().toString('yyyy-MM-dd hh:mm:ss dddd'))
- if self.state == False :
- self.state_label.setText('Error')
- else :
- self.state_label.setText('OK')
-
- def is_number(self,s):
- pattern = re.compile(r'^[-+]?[-0-9]\d*\.\d*|[-+]?\.?[0-9]\d*$')
- result = pattern.match(s)
- if result:
- return True
- else:
- return False
-
- def Ncalculate_handle(self):
-
- calculate_data_Density=self.Label4.text()
- if not self.is_number(calculate_data_Density):
- calculate_data_Density = 0
- print('Density input is not number')
- self.Label4.setText('0')
- self.state = False
- else :
- calculate_data_Density = float(calculate_data_Density)
- if calculate_data_Density==self.midu :
- calculate_data_Density=self.Density
- else :
- self.state = True
-
-
- calculate_data_temperature=self.Label1.text()
- if not self.is_number(calculate_data_temperature):
- calculate_data_temperature = 0
- print('Temperature input is not number')
- self.state = False
- self.Label1.setText('0')
- else :
- calculate_data_temperature = float(calculate_data_temperature)
- if calculate_data_temperature==self.tem :
- calculate_data_temperature=self.temperature
-
- calculate_data_shui=self.Label3.text()
- if not self.is_number(calculate_data_shui):
- calculate_data_shui = 0
- print('Water input is not number')
- self.state = False
- self.Label3.setText('0')
- else :
- calculate_data_shui = float(calculate_data_shui)
- if calculate_data_shui==self.shui :
- calculate_data_shui=self.shui
-
- calculate_data_height=self.Label2.text()
- if not self.is_number(calculate_data_height):
- calculate_data_height = 0
- print('Height input is not number')
- self.state = False
- self.Label2.setText('0')
- else :
- calculate_data_height = float(calculate_data_height)
- if calculate_data_height==self.hei :
- calculate_data_height=self.height
-
- self.k1 = calculate_data_Density
- self.k2 = calculate_data_height
- self.k3 = calculate_data_shui
- self.k4 = calculate_data_temperature
- z = [self.k1, self.k2, self.k3, self.k4]
- z = (z - data_mean) / np.max(data)
- z1 = z[0]
- z2 = z[1]
- z3 = z[2]
- z4 = z[3]
-
- self.h1 = sigmoid(network.w11 * z1 + network.w12 * z2 + network.w13 * z3 + network.w14 * z4 + network.b1)
- self.h2 = sigmoid(network.w21 * z1 + network.w22 * z2 + network.w23 * z3 + network.w24 * z4 + network.b2)
- self.output = network.w1 * self.h1 + network.w2 * self.h2 + network.b3
- self.output = self.output * np.max(all_y_trues) + all_y_trues_mean
- self.d1 = round(self.output, 2) # 0.0005 is changed as 0.05
-
- self.Ncalculate_data=self.d1
- self.caculate_outData_label.setText(f'{self.Ncalculate_data}')
-
- print(f'Neural Networks OutPut is {self.d1}')
-
- # 函数三:点击设置按钮后用于主界面的关闭与子界面1的打开
- def call_dialog(self):
- self.childwindow = QMainWindow() # 子界面childwindow的设置
- self.childwindow.resize(400, 300)
- self.childwindow.move(300, 100)
- self.childwindow.setWindowTitle('设置界面')
-
-
- self.save = QPushButton('返回', self.childwindow) # 存储按钮
- self.save.move(80, 200)
- self.save.clicked.connect(self.back)
-
- self.language = QPushButton('语言', self.childwindow) # 语言按钮
- self.language.move(80, 40)
- self.language.clicked.connect(self.call_dialog2)
-
- self.test = QPushButton('校零', self.childwindow) # 校零按钮
- self.test.move(80, 120)
- self.test.clicked.connect(self.backzero)
-
-
- self.childwindow.show()
-
- # 函数四 语言按钮的子窗口2
- def call_dialog2(self):
- self.childwindow2 = QMainWindow() # 子界面childwindow的设置
- self.childwindow2.resize(400, 300)
- self.childwindow2.move(300, 100)
- self.childwindow2.setWindowTitle('语言界面')
-
- self.foreign = QPushButton('英语', self.childwindow2) # 存储按钮
- self.foreign.move(80, 40)
- self.foreign.clicked.connect(self.English)
-
- self.china = QPushButton('中文', self.childwindow2) # 语言按钮
- self.china.move(80, 120)
- self.china.clicked.connect(self.Chinese)
-
- self.childwindow.close()
- self.childwindow2.show()
-
- def English(self):
- self.wendu.setText('Temeratiure')
- self.gaodu.setText('Height')
- self.ceshi.setText('Begin')
- self.bizhong.setText('Density')
- self.setup.setText('Setting')
- self.save.setText('Save')
- self.language.setText('Language')
- self.test.setText('Test')
- self.foreign.setText('English')
- self.china.setText('Chinese')
- self.save.setText('Save')
-
- self.childwindow2.close()
- self.childwindow.show()
-
- def Chinese(self):
- self.wendu.setText('温度')
- self.gaodu.setText('高度')
- self.ceshi.setText('刷新')
- self.bizhong.setText('密度')
- self.setup.setText('设置')
- self.save.setText('存储')
- self.language.setText('语言')
- self.test.setText('校零')
- self.foreign.setText('英语')
- self.china.setText('中文')
- self.save.setText('返回')
-
- self.childwindow2.close()
- self.childwindow.show()
-
- # 函数五:点击返回按钮后用于子界面1的关闭与主界面的打开
- def back(self):
- self.childwindow.close()
- self.window.show()
-
- # 函数六:点击返回按钮后用于子界面1的关闭与主界面的打开
- def backzero(self):
-
- self.shui = 0
- self.buttonLabel1 = f'{self.shui}c'
- self.Label1.setText(self.buttonLabel1) # 改变单文本框1标签的函数,给赋当前温度值
- self.buttonLabel2 = f'{self.shui}cm'
- self.Label2.setText(self.buttonLabel2) # 改变单文本框2标签的函数,赋当前高度值
- self.buttonLabel3 = f'{self.shui}ml'
- self.Label3.setText(self.buttonLabel3) # 改变单文本框3标签的函数
- self.buttonLabel4 = f'{self.shui}ml'
- self.Label4.setText(self.buttonLabel4) # 改变单文本框4标签的函数
- self.childwindow.close()
- self.window.show()
-
- app = QApplication([])
- stats = Stats()
- stats.window.show()
- app.exec_()
-


为方便调试、测量数据,编写两套启动脚本
auto_start_test.sh:不含神经网络计算,只为测量、调试,启动、运行更快
auto_start.sh:含神经网络计算部分,先将测量后的数据进行训练学习,利用模型得出计算量