修改需求
This commit is contained in:
parent
a26e43eda8
commit
56684f834e
BIN
data_20241103_185036.png
Normal file
BIN
data_20241103_185036.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
BIN
data_20241103_185036.xlsx
Normal file
BIN
data_20241103_185036.xlsx
Normal file
Binary file not shown.
BIN
data_20241103_191048.png
Normal file
BIN
data_20241103_191048.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 245 KiB |
BIN
data_20241103_191048.xlsx
Normal file
BIN
data_20241103_191048.xlsx
Normal file
Binary file not shown.
BIN
data_20241103_211702.png
Normal file
BIN
data_20241103_211702.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
BIN
data_20241103_211702.xlsx
Normal file
BIN
data_20241103_211702.xlsx
Normal file
Binary file not shown.
BIN
data_20241103_212843.png
Normal file
BIN
data_20241103_212843.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 190 KiB |
BIN
data_20241103_212843.xlsx
Normal file
BIN
data_20241103_212843.xlsx
Normal file
Binary file not shown.
110
src/monitor.py
110
src/monitor.py
@ -3,8 +3,9 @@ import serial
|
||||
import serial.tools.list_ports
|
||||
import threading
|
||||
import time
|
||||
import random
|
||||
from collections import deque
|
||||
from PyQt5.QtWidgets import QApplication, QMainWindow, QHBoxLayout, QVBoxLayout, QWidget, QPushButton, QComboBox, QLabel, QFileDialog, QProgressBar, QGridLayout, QGroupBox, QCheckBox
|
||||
from PyQt5.QtWidgets import QApplication, QMainWindow, QHBoxLayout, QVBoxLayout, QWidget, QPushButton, QComboBox, QLabel, QFileDialog, QProgressBar, QGridLayout, QGroupBox, QCheckBox, QLineEdit
|
||||
from PyQt5.QtCore import QTimer, Qt
|
||||
import pyqtgraph as pg
|
||||
import pandas as pd
|
||||
@ -12,8 +13,8 @@ from datetime import datetime
|
||||
import pyqtgraph.exporters
|
||||
|
||||
class VoltageReaderApp(QMainWindow):
|
||||
NUM_CHANNELS = 20 # 通道数量
|
||||
PACKET_SIZE = 43 # 数据包大小
|
||||
NUM_CHANNELS = 2 # 通道数量
|
||||
PACKET_SIZE = 7 # 数据包大小
|
||||
PACKET_HEADER = [0xFE, 0xEE] # 数据包头
|
||||
PACKET_FOOTER = 0xAA # 数据包尾
|
||||
BAUD_RATES = ['9600', '19200', '38400', '57600', '115200'] # 波特率选项
|
||||
@ -33,6 +34,7 @@ class VoltageReaderApp(QMainWindow):
|
||||
self.timer.timeout.connect(self.update_plot)
|
||||
self.auto_follow = False
|
||||
self.show_raw = False
|
||||
self.test_mode = False # 添加测试模式标志
|
||||
|
||||
def initUI(self):
|
||||
self.setWindowTitle("Voltage Monitor")
|
||||
@ -117,6 +119,17 @@ class VoltageReaderApp(QMainWindow):
|
||||
self.load_button.clicked.connect(self.load_data)
|
||||
action_layout.addWidget(self.load_button)
|
||||
|
||||
self.test_button = QPushButton('测试模式')
|
||||
self.test_button.setCheckable(True)
|
||||
self.test_button.clicked.connect(self.toggle_test_mode)
|
||||
action_layout.addWidget(self.test_button)
|
||||
|
||||
self.remark_label = QLabel('备注(学生姓名):')
|
||||
action_layout.addWidget(self.remark_label)
|
||||
|
||||
self.remark_input = QLineEdit()
|
||||
action_layout.addWidget(self.remark_input)
|
||||
|
||||
self.message_label = QLabel()
|
||||
self.message_label.setWordWrap(True)
|
||||
layout.addWidget(self.message_label)
|
||||
@ -128,7 +141,7 @@ class VoltageReaderApp(QMainWindow):
|
||||
|
||||
def setup_channel_group(self, layout):
|
||||
channel_group = QGroupBox("通道选择")
|
||||
channel_layout = QGridLayout()
|
||||
channel_layout = QVBoxLayout()
|
||||
channel_group.setLayout(channel_layout)
|
||||
layout.addWidget(channel_group)
|
||||
|
||||
@ -137,11 +150,9 @@ class VoltageReaderApp(QMainWindow):
|
||||
color = (i*12, 255-i*12, 150)
|
||||
checkbox = QCheckBox(f'adc{i+1}')
|
||||
checkbox.setChecked(True)
|
||||
checkbox.setStyleSheet(f'color: rgb({color[0]}, {color[1]}, {color[2]})')
|
||||
checkbox.setStyleSheet(f'color: black; background-color: rgb({color[0]}, {color[1]}, {color[2]})')
|
||||
checkbox.stateChanged.connect(lambda state, idx=i: self.toggle_curve_visibility(state, idx))
|
||||
row = i // 2
|
||||
col = i % 2
|
||||
channel_layout.addWidget(checkbox, row, col)
|
||||
channel_layout.addWidget(checkbox)
|
||||
self.checkboxes.append(checkbox)
|
||||
|
||||
def setup_plot_widget(self, layout):
|
||||
@ -170,7 +181,7 @@ class VoltageReaderApp(QMainWindow):
|
||||
self.message_label.setText(f"连接失败: {e}")
|
||||
|
||||
def start_reading(self):
|
||||
if self.serial_port:
|
||||
if self.serial_port or self.test_mode:
|
||||
self.reading_event.set()
|
||||
self.start_button.setEnabled(False)
|
||||
self.stop_button.setEnabled(True)
|
||||
@ -190,31 +201,45 @@ class VoltageReaderApp(QMainWindow):
|
||||
self.message_label.setText("停止读取数据")
|
||||
|
||||
def read_data(self):
|
||||
while self.reading_event.is_set() and self.serial_port:
|
||||
try:
|
||||
while self.serial_port.in_waiting > 0:
|
||||
self.buffer.extend(self.serial_port.read(self.serial_port.in_waiting))
|
||||
while len(self.buffer) >= self.PACKET_SIZE:
|
||||
if self.buffer[:2] == bytearray(self.PACKET_HEADER) and self.buffer[self.PACKET_SIZE-1] == self.PACKET_FOOTER:
|
||||
packet = self.buffer[:self.PACKET_SIZE]
|
||||
self.buffer = self.buffer[self.PACKET_SIZE:]
|
||||
raw_values = [packet[2 + i*2] | (packet[3 + i*2] << 8) for i in range(self.NUM_CHANNELS)]
|
||||
voltages = [(raw / 4096.0) * 3.3 for raw in raw_values]
|
||||
for i in range(self.NUM_CHANNELS):
|
||||
self.raw_data[i].append(raw_values[i])
|
||||
self.data[i].append(voltages[i])
|
||||
if self.start_time is not None:
|
||||
elapsed_time = time.time() - self.start_time
|
||||
self.timestamps.append(elapsed_time)
|
||||
else:
|
||||
self.buffer.pop(0)
|
||||
time.sleep(0.01)
|
||||
except serial.SerialException as e:
|
||||
self.message_label.setText(f"读取数据失败: {e}")
|
||||
self.stop_reading()
|
||||
except Exception as e:
|
||||
self.message_label.setText(f"未知错误: {e}")
|
||||
self.stop_reading()
|
||||
if self.test_mode:
|
||||
self.generate_random_waveform()
|
||||
else:
|
||||
while self.reading_event.is_set() and self.serial_port:
|
||||
try:
|
||||
while self.serial_port.in_waiting > 0:
|
||||
self.buffer.extend(self.serial_port.read(self.serial_port.in_waiting))
|
||||
while len(self.buffer) >= self.PACKET_SIZE:
|
||||
if self.buffer[:2] == bytearray(self.PACKET_HEADER) and self.buffer[self.PACKET_SIZE-1] == self.PACKET_FOOTER:
|
||||
packet = self.buffer[:self.PACKET_SIZE]
|
||||
self.buffer = self.buffer[self.PACKET_SIZE:]
|
||||
raw_values = [packet[2 + i*2] | (packet[3 + i*2] << 8) for i in range(self.NUM_CHANNELS)]
|
||||
voltages = [(raw / 4096.0) * 3.3 for raw in raw_values]
|
||||
for i in range(self.NUM_CHANNELS):
|
||||
self.raw_data[i].append(raw_values[i])
|
||||
self.data[i].append(voltages[i])
|
||||
if self.start_time is not None:
|
||||
elapsed_time = time.time() - self.start_time
|
||||
self.timestamps.append(elapsed_time)
|
||||
else:
|
||||
self.buffer.pop(0)
|
||||
time.sleep(0.01)
|
||||
except serial.SerialException as e:
|
||||
self.message_label.setText(f"读取数据失败: {e}")
|
||||
self.stop_reading()
|
||||
except Exception as e:
|
||||
self.message_label.setText(f"未知错误: {e}")
|
||||
self.stop_reading()
|
||||
|
||||
def generate_random_waveform(self):
|
||||
while self.reading_event.is_set():
|
||||
elapsed_time = time.time() - self.start_time
|
||||
self.timestamps.append(elapsed_time)
|
||||
for i in range(self.NUM_CHANNELS):
|
||||
raw_value = random.randint(0, 4095)
|
||||
voltage = (raw_value / 4096.0) * 3.3
|
||||
self.raw_data[i].append(raw_value)
|
||||
self.data[i].append(voltage)
|
||||
time.sleep(0.1)
|
||||
|
||||
def update_plot(self):
|
||||
if self.timestamps:
|
||||
@ -247,6 +272,14 @@ class VoltageReaderApp(QMainWindow):
|
||||
self.show_raw_button.setText('显示计算值' if self.show_raw else '显示原始值')
|
||||
self.update_plot()
|
||||
|
||||
def toggle_test_mode(self):
|
||||
self.test_mode = not self.test_mode
|
||||
self.test_button.setText('退出测试模式' if self.test_mode else '测试模式')
|
||||
if self.test_mode:
|
||||
self.start_reading()
|
||||
else:
|
||||
self.stop_reading()
|
||||
|
||||
def save_data(self):
|
||||
current_time = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
default_file_name = f"data_{current_time}.xlsx"
|
||||
@ -259,6 +292,8 @@ class VoltageReaderApp(QMainWindow):
|
||||
if not file_name.endswith('.xlsx'):
|
||||
file_name += '.xlsx'
|
||||
|
||||
student_name = self.remark_input.text()
|
||||
|
||||
data_dict = {"Timestamp": list(self.timestamps)}
|
||||
for i in range(self.NUM_CHANNELS):
|
||||
data_dict[f"Voltage_{i+1}"] = list(self.data[i])
|
||||
@ -270,7 +305,12 @@ class VoltageReaderApp(QMainWindow):
|
||||
QApplication.processEvents()
|
||||
|
||||
try:
|
||||
df.to_excel(file_name, index=False, engine='openpyxl')
|
||||
with pd.ExcelWriter(file_name, engine='openpyxl') as writer:
|
||||
df.to_excel(writer, index=False, startrow=1)
|
||||
worksheet = writer.sheets['Sheet1']
|
||||
worksheet.merge_cells('A1:E1')
|
||||
worksheet['A1'] = f"备注: {student_name}"
|
||||
|
||||
self.progress_bar.setValue(50)
|
||||
QApplication.processEvents()
|
||||
|
||||
|
347
src/test.py
Normal file
347
src/test.py
Normal file
@ -0,0 +1,347 @@
|
||||
import sys
|
||||
import serial
|
||||
import serial.tools.list_ports
|
||||
import threading
|
||||
import time
|
||||
import random
|
||||
from collections import deque
|
||||
from PyQt5.QtWidgets import QApplication, QMainWindow, QHBoxLayout, QVBoxLayout, QWidget, QPushButton, QComboBox, QLabel, QFileDialog, QProgressBar, QGridLayout, QGroupBox, QCheckBox, QLineEdit
|
||||
from PyQt5.QtCore import QTimer, Qt
|
||||
import pyqtgraph as pg
|
||||
import pandas as pd
|
||||
from datetime import datetime
|
||||
import pyqtgraph.exporters
|
||||
|
||||
class VoltageReaderApp(QMainWindow):
|
||||
NUM_CHANNELS = 2 # 通道数量
|
||||
PACKET_SIZE = 7 # 数据包大小
|
||||
PACKET_HEADER = [0xFE, 0xEE] # 数据包头
|
||||
PACKET_FOOTER = 0xAA # 数据包尾
|
||||
BAUD_RATES = ['9600', '19200', '38400', '57600', '115200'] # 波特率选项
|
||||
PLOT_UPDATE_INTERVAL = 100 # 图表更新间隔(毫秒)
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.initUI()
|
||||
self.serial_port = None
|
||||
self.data = [deque() for _ in range(self.NUM_CHANNELS)]
|
||||
self.raw_data = [deque() for _ in range(self.NUM_CHANNELS)]
|
||||
self.timestamps = deque()
|
||||
self.reading_event = threading.Event()
|
||||
self.start_time = None
|
||||
self.buffer = bytearray()
|
||||
self.timer = QTimer()
|
||||
self.timer.timeout.connect(self.update_plot)
|
||||
self.auto_follow = False
|
||||
self.show_raw = False
|
||||
self.test_mode = False # 添加测试模式标志
|
||||
|
||||
def initUI(self):
|
||||
self.setWindowTitle("Voltage Monitor")
|
||||
self.setGeometry(100, 100, 1600, 700)
|
||||
|
||||
central_widget = QWidget()
|
||||
self.setCentralWidget(central_widget)
|
||||
main_layout = QHBoxLayout(central_widget)
|
||||
|
||||
control_layout = QVBoxLayout()
|
||||
control_widget = QWidget()
|
||||
control_widget.setLayout(control_layout)
|
||||
control_widget.setFixedWidth(250)
|
||||
main_layout.addWidget(control_widget)
|
||||
|
||||
self.setup_port_group(control_layout)
|
||||
self.setup_action_group(control_layout)
|
||||
self.setup_channel_group(control_layout)
|
||||
self.setup_plot_widget(main_layout)
|
||||
|
||||
self.update_ports()
|
||||
|
||||
def setup_port_group(self, layout):
|
||||
port_group = QGroupBox("串口设置")
|
||||
port_layout = QVBoxLayout()
|
||||
port_group.setLayout(port_layout)
|
||||
layout.addWidget(port_group)
|
||||
|
||||
self.port_label = QLabel('选择串口:')
|
||||
port_layout.addWidget(self.port_label)
|
||||
|
||||
self.port_combo = QComboBox()
|
||||
port_layout.addWidget(self.port_combo)
|
||||
|
||||
self.refresh_button = QPushButton('刷新串口')
|
||||
self.refresh_button.clicked.connect(self.update_ports)
|
||||
port_layout.addWidget(self.refresh_button)
|
||||
|
||||
self.baud_label = QLabel('选择波特率:')
|
||||
port_layout.addWidget(self.baud_label)
|
||||
|
||||
self.baud_combo = QComboBox()
|
||||
self.baud_combo.addItems(self.BAUD_RATES)
|
||||
self.baud_combo.setCurrentText('115200')
|
||||
port_layout.addWidget(self.baud_combo)
|
||||
|
||||
self.connect_button = QPushButton('连接')
|
||||
self.connect_button.clicked.connect(self.connect_serial)
|
||||
port_layout.addWidget(self.connect_button)
|
||||
|
||||
def setup_action_group(self, layout):
|
||||
action_group = QGroupBox("操作")
|
||||
action_layout = QVBoxLayout()
|
||||
action_group.setLayout(action_layout)
|
||||
layout.addWidget(action_group)
|
||||
|
||||
self.start_button = QPushButton('开始读取')
|
||||
self.start_button.clicked.connect(self.start_reading)
|
||||
self.start_button.setEnabled(False)
|
||||
action_layout.addWidget(self.start_button)
|
||||
|
||||
self.stop_button = QPushButton('停止读取')
|
||||
self.stop_button.clicked.connect(self.stop_reading)
|
||||
self.stop_button.setEnabled(False)
|
||||
action_layout.addWidget(self.stop_button)
|
||||
|
||||
self.auto_button = QPushButton('自动跟随')
|
||||
self.auto_button.setCheckable(True)
|
||||
self.auto_button.clicked.connect(self.toggle_auto_follow)
|
||||
action_layout.addWidget(self.auto_button)
|
||||
|
||||
self.show_raw_button = QPushButton('显示原始值')
|
||||
self.show_raw_button.setCheckable(True)
|
||||
self.show_raw_button.clicked.connect(self.toggle_show_raw)
|
||||
action_layout.addWidget(self.show_raw_button)
|
||||
|
||||
self.save_button = QPushButton('保存数据')
|
||||
self.save_button.clicked.connect(self.save_data)
|
||||
action_layout.addWidget(self.save_button)
|
||||
|
||||
self.load_button = QPushButton('加载数据')
|
||||
self.load_button.clicked.connect(self.load_data)
|
||||
action_layout.addWidget(self.load_button)
|
||||
|
||||
self.test_button = QPushButton('测试模式')
|
||||
self.test_button.setCheckable(True)
|
||||
self.test_button.clicked.connect(self.toggle_test_mode)
|
||||
action_layout.addWidget(self.test_button)
|
||||
|
||||
self.remark_label = QLabel('备注(学生姓名):')
|
||||
action_layout.addWidget(self.remark_label)
|
||||
|
||||
self.remark_input = QLineEdit()
|
||||
action_layout.addWidget(self.remark_input)
|
||||
|
||||
self.message_label = QLabel()
|
||||
self.message_label.setWordWrap(True)
|
||||
layout.addWidget(self.message_label)
|
||||
|
||||
self.progress_bar = QProgressBar()
|
||||
self.progress_bar.setAlignment(Qt.AlignCenter)
|
||||
self.progress_bar.setVisible(False)
|
||||
layout.addWidget(self.progress_bar)
|
||||
|
||||
def setup_channel_group(self, layout):
|
||||
channel_group = QGroupBox("通道选择")
|
||||
channel_layout = QVBoxLayout()
|
||||
channel_group.setLayout(channel_layout)
|
||||
layout.addWidget(channel_group)
|
||||
|
||||
self.checkboxes = []
|
||||
for i in range(self.NUM_CHANNELS):
|
||||
color = (i*12, 255-i*12, 150)
|
||||
checkbox = QCheckBox(f'adc{i+1}')
|
||||
checkbox.setChecked(True)
|
||||
checkbox.setStyleSheet(f'color: black; background-color: rgb({color[0]}, {color[1]}, {color[2]})')
|
||||
checkbox.stateChanged.connect(lambda state, idx=i: self.toggle_curve_visibility(state, idx))
|
||||
channel_layout.addWidget(checkbox)
|
||||
self.checkboxes.append(checkbox)
|
||||
|
||||
def setup_plot_widget(self, layout):
|
||||
self.plot_widget = pg.PlotWidget()
|
||||
self.plot_widget.showGrid(x=True, y=True, alpha=0.3)
|
||||
layout.addWidget(self.plot_widget)
|
||||
|
||||
self.plot_data = [self.plot_widget.plot([], [], pen=pg.mkPen(color=(i*12, 255-i*12, 150))) for i in range(self.NUM_CHANNELS)]
|
||||
|
||||
def update_ports(self):
|
||||
self.port_combo.clear()
|
||||
ports = [port.device for port in serial.tools.list_ports.comports()]
|
||||
self.port_combo.addItems(ports)
|
||||
self.message_label.setText("串口列表已更新")
|
||||
|
||||
def connect_serial(self):
|
||||
port = self.port_combo.currentText()
|
||||
baudrate = self.baud_combo.currentText()
|
||||
if port and baudrate:
|
||||
try:
|
||||
self.serial_port = serial.Serial(port, int(baudrate), timeout=1)
|
||||
self.start_button.setEnabled(True)
|
||||
self.stop_button.setEnabled(False)
|
||||
self.message_label.setText(f"已连接到 {port},波特率 {baudrate}")
|
||||
except serial.SerialException as e:
|
||||
self.message_label.setText(f"连接失败: {e}")
|
||||
|
||||
def start_reading(self):
|
||||
if self.serial_port or self.test_mode:
|
||||
self.reading_event.set()
|
||||
self.start_button.setEnabled(False)
|
||||
self.stop_button.setEnabled(True)
|
||||
if not self.start_time:
|
||||
self.start_time = time.time()
|
||||
threading.Thread(target=self.read_data, daemon=True).start()
|
||||
self.timer.start(self.PLOT_UPDATE_INTERVAL)
|
||||
self.message_label.setText("开始读取数据")
|
||||
else:
|
||||
self.message_label.setText("错误: 串口未打开,无法读取数据")
|
||||
|
||||
def stop_reading(self):
|
||||
self.reading_event.clear()
|
||||
self.start_button.setEnabled(True)
|
||||
self.stop_button.setEnabled(False)
|
||||
self.timer.stop()
|
||||
self.message_label.setText("停止读取数据")
|
||||
|
||||
def read_data(self):
|
||||
if self.test_mode:
|
||||
self.generate_random_waveform()
|
||||
else:
|
||||
while self.reading_event.is_set() and self.serial_port:
|
||||
try:
|
||||
while self.serial_port.in_waiting > 0:
|
||||
self.buffer.extend(self.serial_port.read(self.serial_port.in_waiting))
|
||||
while len(self.buffer) >= self.PACKET_SIZE:
|
||||
if self.buffer[:2] == bytearray(self.PACKET_HEADER) and self.buffer[self.PACKET_SIZE-1] == self.PACKET_FOOTER:
|
||||
packet = self.buffer[:self.PACKET_SIZE]
|
||||
self.buffer = self.buffer[self.PACKET_SIZE:]
|
||||
raw_values = [packet[2 + i*2] | (packet[3 + i*2] << 8) for i in range(self.NUM_CHANNELS)]
|
||||
voltages = [(raw / 4096.0) * 3.3 for raw in raw_values]
|
||||
for i in range(self.NUM_CHANNELS):
|
||||
self.raw_data[i].append(raw_values[i])
|
||||
self.data[i].append(voltages[i])
|
||||
if self.start_time is not None:
|
||||
elapsed_time = time.time() - self.start_time
|
||||
self.timestamps.append(elapsed_time)
|
||||
else:
|
||||
self.buffer.pop(0)
|
||||
time.sleep(0.01)
|
||||
except serial.SerialException as e:
|
||||
self.message_label.setText(f"读取数据失败: {e}")
|
||||
self.stop_reading()
|
||||
except Exception as e:
|
||||
self.message_label.setText(f"未知错误: {e}")
|
||||
self.stop_reading()
|
||||
|
||||
def generate_random_waveform(self):
|
||||
while self.reading_event.is_set():
|
||||
elapsed_time = time.time() - self.start_time
|
||||
self.timestamps.append(elapsed_time)
|
||||
for i in range(self.NUM_CHANNELS):
|
||||
raw_value = random.randint(0, 4095)
|
||||
voltage = (raw_value / 4096.0) * 3.3
|
||||
self.raw_data[i].append(raw_value)
|
||||
self.data[i].append(voltage)
|
||||
time.sleep(0.1)
|
||||
|
||||
def update_plot(self):
|
||||
if self.timestamps:
|
||||
for i in range(self.NUM_CHANNELS):
|
||||
if self.checkboxes[i].isChecked():
|
||||
if self.show_raw:
|
||||
self.plot_data[i].setData(list(self.timestamps), list(self.raw_data[i]), clear=True)
|
||||
else:
|
||||
self.plot_data[i].setData(list(self.timestamps), list(self.data[i]), clear=True)
|
||||
else:
|
||||
self.plot_data[i].clear()
|
||||
if self.auto_follow:
|
||||
self.plot_widget.setXRange(self.timestamps[-1] - 5, self.timestamps[-1], padding=0)
|
||||
|
||||
def toggle_curve_visibility(self, state, index):
|
||||
if state == 0:
|
||||
self.plot_data[index].clear()
|
||||
else:
|
||||
if self.show_raw:
|
||||
self.plot_data[index].setData(list(self.timestamps), list(self.raw_data[index]))
|
||||
else:
|
||||
self.plot_data[index].setData(list(self.timestamps), list(self.data[index]))
|
||||
|
||||
def toggle_auto_follow(self):
|
||||
self.auto_follow = not self.auto_follow
|
||||
self.auto_button.setText('取消自动跟随' if self.auto_follow else '自动跟随')
|
||||
|
||||
def toggle_show_raw(self):
|
||||
self.show_raw = not self.show_raw
|
||||
self.show_raw_button.setText('显示计算值' if self.show_raw else '显示原始值')
|
||||
self.update_plot()
|
||||
|
||||
def toggle_test_mode(self):
|
||||
self.test_mode = not self.test_mode
|
||||
self.test_button.setText('退出测试模式' if self.test_mode else '测试模式')
|
||||
if self.test_mode:
|
||||
self.start_reading()
|
||||
else:
|
||||
self.stop_reading()
|
||||
|
||||
def save_data(self):
|
||||
current_time = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
default_file_name = f"data_{current_time}.xlsx"
|
||||
|
||||
options = QFileDialog.Options()
|
||||
options |= QFileDialog.DontUseNativeDialog
|
||||
file_name, _ = QFileDialog.getSaveFileName(self, "保存数据文件", default_file_name, "Excel Files (*.xlsx);;All Files (*)", options=options)
|
||||
|
||||
if file_name:
|
||||
if not file_name.endswith('.xlsx'):
|
||||
file_name += '.xlsx'
|
||||
|
||||
student_name = self.remark_input.text()
|
||||
|
||||
data_dict = {"Timestamp": list(self.timestamps)}
|
||||
for i in range(self.NUM_CHANNELS):
|
||||
data_dict[f"Voltage_{i+1}"] = list(self.data[i])
|
||||
data_dict[f"Raw_{i+1}"] = list(self.raw_data[i])
|
||||
df = pd.DataFrame(data_dict)
|
||||
|
||||
self.progress_bar.setVisible(True)
|
||||
self.progress_bar.setValue(0)
|
||||
QApplication.processEvents()
|
||||
|
||||
try:
|
||||
with pd.ExcelWriter(file_name, engine='openpyxl') as writer:
|
||||
df.to_excel(writer, index=False, startrow=1)
|
||||
worksheet = writer.sheets['Sheet1']
|
||||
worksheet.merge_cells('A1:E1')
|
||||
worksheet['A1'] = f"备注: {student_name}"
|
||||
|
||||
self.progress_bar.setValue(50)
|
||||
QApplication.processEvents()
|
||||
|
||||
image_filename = file_name.replace('.xlsx', '.png')
|
||||
exporter = pg.exporters.ImageExporter(self.plot_widget.plotItem)
|
||||
exporter.parameters()['width'] = 1600
|
||||
exporter.export(image_filename)
|
||||
|
||||
self.progress_bar.setValue(100)
|
||||
QApplication.processEvents()
|
||||
|
||||
self.message_label.setText(f"数据已保存为 {file_name} 和 {image_filename}")
|
||||
except Exception as e:
|
||||
self.message_label.setText(f"保存数据失败: {e}")
|
||||
finally:
|
||||
self.progress_bar.setVisible(False)
|
||||
|
||||
def load_data(self):
|
||||
options = QFileDialog.Options()
|
||||
file_name, _ = QFileDialog.getOpenFileName(self, "加载数据文件", "", "Excel Files (*.xlsx);;All Files (*)", options=options)
|
||||
if file_name:
|
||||
df = pd.read_excel(file_name)
|
||||
self.timestamps = deque(df["Timestamp"].tolist())
|
||||
for i in range(self.NUM_CHANNELS):
|
||||
self.data[i] = deque(df[f"Voltage_{i+1}"].tolist())
|
||||
self.raw_data[i] = deque(df[f"Raw_{i+1}"].tolist())
|
||||
self.update_plot()
|
||||
self.message_label.setText(f"数据已加载自 {file_name}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = QApplication(sys.argv)
|
||||
window = VoltageReaderApp()
|
||||
window.show()
|
||||
sys.exit(app.exec_())
|
Loading…
Reference in New Issue
Block a user