AS3 Timer.reset

前几天在PC版本写的一个在线时长,犯了一个低级错误,在没有移除的情况下,重新调用了一次,导致时间不按正确的显示。

原因是:在定时器启动后,使用currentCount属性查询当前累计触发次数,使用“stop()”方法可以停止一个定时器。需要指出的是:“stop()”方法不过是暂停了定时器,并没有清除定时器。当一个定时器被“stop()”方法停止后,Timer对象的currentCount并没有被清除。当再次使用“start()”方法启动Timer对象时,定时器将继续执行,直到触发次数达到repeatCount属性规定的数值。用户不能在代码中为CurrentCount赋值,要改变 currentCount属性,只能使用“reset()”方法。“reset()”方法可以清零定时器的currentCount属性。

解决方法:不要重新调用初始时间函数了,重新写个函数, 函数里一定要reset()一下。

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="80" height="65" 
		   xmlns:com="game.view.component.*" xmlns:help="game.help.*" 
		   verticalScrollPolicy="off" horizontalScrollPolicy="off"
		   useHandCursor="true"  buttonMode="true" creationComplete="init()" >
	
	<mx:Script>
		<![CDATA[
			import game.events.RPCType;
			import game.events.WarEvent;
			import game.events.WarEventDispatcher;
			import game.help.CoolDownTime;
			import game.help.TimeUtil;
			import game.manager.SocketManager;
			import game.manager.UIManager;
			import game.model.MainModelLocator;
			import game.view.component.alert.AlertWindow;

			[Bindable]
			private var _model:MainModelLocator = MainModelLocator.getInstance();
			[Bindable]
			private var dispatch:WarEventDispatcher = WarEventDispatcher.getInstance();
			
			private var timer:Timer = null;
			private var t:int;
			
			private function init():void
			{
				dispatch.addEventListener(WarEvent.EVENT_SYNC_OT_OVER,syncOc);
				t = 0;
				t = _model.OL_T;
				onTimeHandler();
			}
			
			private function onTimeHandler():void
			{
				timer = new Timer(1000);
				timer.addEventListener(TimerEvent.TIMER,timerHandler);	
				timer.start();
			}
			
			private function syncOc(event:WarEvent):void
			{
				timer.reset();
				t = 0;
				t = _model.OL_T;
				timer.start();
			}
			
			private function timerHandler(event:TimerEvent):void
			{
				txt.text = '';
				if(t < _model.OL_M )
				{
					t++;
					txt.text = transadvanceTime(t);	
					cav.styleName = 'online2';
				}else
				{					
					//与服务器时间同步
					if(_model.sync)
					{
						SocketManager.getInstance().sendFeed(RPCType.SYNC_OT,{});
					}else
					{
						timer.stop();
						txt.text = transadvanceTime(t);	
						cav.styleName = 'online1';
					}
				}
			}
			
			private function transadvanceTime(timeNum:Number):String
			{
				var total_seconds:uint = Math.floor(timeNum);
				var total_minutes:uint = Math.floor(total_seconds/60);
				var total_hours:uint = Math.floor(total_minutes/60);
				var total_days:uint = Math.floor(total_hours/24);
				var days:uint = total_days;
				var hours:uint = total_hours%24;
				var minutes:uint = total_minutes%60;
				var seconds:uint = total_seconds%60;
				return  (days==0?"":days.toString()+"天")+(hours<10?"0"+hours:hours.toString())+":"+(minutes<10?"0"+minutes:minutes.toString())+":"+(seconds<10?"0"+seconds:seconds.toString());
			}	
			
			
		]]>
	</mx:Script>
	
	<mx:Canvas id="cav" styleName="{_model.OL_D?'online1':'online2'}" x="10" width="35" height="35"/>
	<help:TextL id="txt"  x="5" y="34" width="80" height="20"/>
</mx:Canvas>

import pyfirmata import time import sys import numpy as np import matplotlib.pyplot as plt from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.figure import Figure from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QGroupBox, QComboBox, QStatusBar, QGridLayout, QTabWidget, QTableWidget, QTableWidgetItem, QHeaderView, QDoubleSpinBox, QProgressBar, QMessageBox, QCheckBox, QSizePolicy) from PyQt5.QtCore import QTimer, Qt, QThread, pyqtSignal from PyQt5.QtGui import QFont, QColor, QIcon from PyQt5.QtCore import QSize # 设置中文字体支持 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;, &#39;Microsoft YaHei&#39;, &#39;WenQuanYi Zen Hei&#39;] # 中文字体 plt.rcParams[&#39;axes.unicode_minus&#39;] = False # 解决负号显示问题 class ConnectionThread(QThread): progress = pyqtSignal(int) success = pyqtSignal(object) error = pyqtSignal(str) def __init__(self, port): super().__init__() self.port = port def run(self): try: # 模拟连接进度 for i in range(1, 101): time.sleep(0.03) # 更快的进度更新 self.progress.emit(i) if i == 50: # 在实际连接位置暂停 try: self.board = pyfirmata.Arduino(self.port) time.sleep(1.5) # 等待连接稳定 except Exception as e: self.error.emit(str(e)) return # 初始化引脚模式 digital_pins = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] for pin in digital_pins: self.board.digital[pin].mode = pyfirmata.OUTPUT self.board.digital[pin].write(0) # 初始化为低电平 # 设置模拟输入 self.it = pyfirmata.util.Iterator(self.board) self.it.start() # 初始化所有模拟引脚 for i in range(6): self.board.analog[i].enable_reporting() self.success.emit(self.board) except Exception as e: self.error.emit(f"连接失败: {str(e)}") class ArduinoControlApp(QMainWindow): def __init__(self): super().__init__() self.board = None self.it = None self.is_connected = False self.led_state = False self.voltage_data = [] self.time_data = [] self.start_time = time.time() self.max_data_points = 500 self.analog_pin = 0 # 默认使用 A0 引脚读取电压 self.digital_pin_states = {} self.analog_pin_values = {} # 数字引脚监控相关变量 self.digital_monitor_pin = 2 # 默认监控D2引脚 self.digital_state_data = [] # 存储数字引脚状态数据 self.digital_time_data = [] # 存储数字引脚状态变化时间 self.digital_monitor_start_time = time.time() self.last_digital_state = None self.rise_count = 0 self.fall_count = 0 self.init_ui() self.init_plot() # 确保窗口大小适合屏幕 self.adjustSize() self.center_window() def center_window(self): """将窗口置于屏幕中央""" screen = QApplication.primaryScreen().geometry() window_size = self.geometry() self.move( (screen.width() - window_size.width()) // 2, (screen.height() - window_size.height()) // 2 ) def init_ui(self): self.setWindowTitle("Arduino 控制器 v2.2") self.setMinimumSize(1200, 800) # 设置最小尺寸 self.setWindowIcon(QIcon("cpu.png")) # 如果有图标文件 # 设置全局字体 app_font = QFont("Microsoft YaHei", 9) QApplication.setFont(app_font) # 主布局 main_widget = QWidget() self.setCentralWidget(main_widget) main_layout = QVBoxLayout(main_widget) main_layout.setSpacing(10) main_layout.setContentsMargins(10, 10, 10, 10) # 状态栏 self.status_bar = QStatusBar() self.setStatusBar(self.status_bar) self.status_bar.showMessage("准备就绪") # 状态指示灯 self.status_indicator = QLabel() self.status_indicator.setFixedSize(16, 16) self.status_indicator.setStyleSheet("background-color: gray; border-radius: 8px;") self.status_bar.addPermanentWidget(self.status_indicator) # 当前时间显示 self.time_label = QLabel() self.time_label.setStyleSheet("color: #616161; font-weight: bold; padding: 0 10px;") self.status_bar.addPermanentWidget(self.time_label) self.update_time() # 初始更新时间显示 # 时间更新定时器 self.time_timer = QTimer() self.time_timer.timeout.connect(self.update_time) self.time_timer.start(1000) # 每秒更新一次 # 进度条(初始时隐藏) self.progress_bar = QProgressBar() self.progress_bar.setFixedWidth(200) self.progress_bar.setRange(0, 100) self.progress_bar.setValue(0) self.progress_bar.setVisible(False) self.status_bar.addPermanentWidget(self.progress_bar) # 连接状态标签 self.status_label = QLabel("未连接") self.status_label.setStyleSheet("color: #9E9E9E; font-weight: bold; padding: 0 10px;") self.status_bar.addPermanentWidget(self.status_label) # 创建选项卡 self.tab_widget = QTabWidget() main_layout.addWidget(self.tab_widget, 1) # 控制选项卡 control_tab = QWidget() self.tab_widget.addTab(control_tab, "控制面板") control_layout = QVBoxLayout(control_tab) control_layout.setSpacing(10) control_layout.setContentsMargins(10, 10, 10, 10) # 连接控制组 - 使用卡片式设计 conn_group = QGroupBox("Arduino 连接设置") conn_group.setStyleSheet("QGroupBox { font-weight: bold; }") conn_layout = QGridLayout(conn_group) conn_layout.setSpacing(8) conn_layout.setContentsMargins(10, 15, 10, 15) conn_layout.addWidget(QLabel("<b>端口:</b>"), 0, 0) self.port_combo = QComboBox() self.port_combo.addItems(["COM3", "COM4", "COM5", "COM6", "COM7", "/dev/ttyACM0", "/dev/ttyUSB0"]) self.port_combo.setCurrentText("COM5") self.port_combo.setMinimumWidth(120) conn_layout.addWidget(self.port_combo, 0, 1) self.refresh_btn = QPushButton("刷新端口") self.refresh_btn.setToolTip("重新扫描可用的串口") self.refresh_btn.setFixedHeight(30) self.refresh_btn.setStyleSheet("background-color: #2196F3; color: white; border-radius: 4px;") self.refresh_btn.clicked.connect(self.refresh_ports) conn_layout.addWidget(self.refresh_btn, 0, 2) self.connect_btn = QPushButton("连接 Arduino") self.connect_btn.setToolTip("连接到选定的Arduino设备") self.connect_btn.setFixedHeight(30) self.connect_btn.setStyleSheet(""" QPushButton { background-color: #4CAF50; color: white; font-weight: bold; padding: 6px; border-radius: 4px; } QPushButton:disabled { background-color: #A5D6A7; } """) self.connect_btn.clicked.connect(self.connect_arduino) conn_layout.addWidget(self.connect_btn, 0, 3) self.disconnect_btn = QPushButton("断开连接") self.disconnect_btn.setToolTip("断开当前Arduino连接") self.disconnect_btn.setFixedHeight(30) self.disconnect_btn.setStyleSheet(""" QPushButton { background-color: #f44336; color: white; padding: 6px; border-radius: 4px; } QPushButton:disabled { background-color: #EF9A9A; } """) self.disconnect_btn.clicked.connect(self.disconnect_arduino) self.disconnect_btn.setEnabled(False) conn_layout.addWidget(self.disconnect_btn, 0, 4) # 扩展信息区域 self.conn_info_label = QLabel("<b>连接信息:</b> 请连接Arduino设备") self.conn_info_label.setStyleSheet("color: #616161; padding: 5px 0;") conn_layout.addWidget(self.conn_info_label, 1, 0, 1, 5) # 引脚控制组 pin_group = QGroupBox("引脚控制") pin_group.setStyleSheet("QGroupBox { font-weight: bold; }") pin_layout = QGridLayout(pin_group) pin_layout.setSpacing(6) pin_layout.setContentsMargins(8, 12, 8, 12) # 数字引脚控制表 pin_layout.addWidget(QLabel("<b style=&#39;font-size: 10.5pt; color: #1565C0;&#39;>数字引脚控制</b>"), 0, 0, 1, 6) # 表头 headers = ["引脚", "名称", "模式", "当前状态", "操作"] for col, header in enumerate(headers): label = QLabel(f"<b>{header}</b>") label.setStyleSheet("color: #263238;") pin_layout.addWidget(label, 1, col) # 数字引脚列表 (简化到常用引脚) self.digital_pins = [ {&#39;pin&#39;: 2, &#39;name&#39;: &#39;数字端口2&#39;, &#39;mode&#39;: &#39;输出&#39;, &#39;color&#39;: &#39;#E3F2FD&#39;}, {&#39;pin&#39;: 3, &#39;name&#39;: &#39;数字端口3&#39;, &#39;mode&#39;: &#39;输出&#39;, &#39;color&#39;: &#39;#E3F2FD&#39;}, {&#39;pin&#39;: 4, &#39;name&#39;: &#39;数字端口4&#39;, &#39;mode&#39;: &#39;输出&#39;, &#39;color&#39;: &#39;#E3F2FD&#39;}, {&#39;pin&#39;: 5, &#39;name&#39;: &#39;数字端口5&#39;, &#39;mode&#39;: &#39;输出&#39;, &#39;color&#39;: &#39;#E3F2FD&#39;}, {&#39;pin&#39;: 6, &#39;name&#39;: &#39;PWM端口6&#39;, &#39;mode&#39;: &#39;输出&#39;, &#39;color&#39;: &#39;#FFF3E0&#39;}, {&#39;pin&#39;: 7, &#39;name&#39;: &#39;数字端口7&#39;, &#39;mode&#39;: &#39;输出&#39;, &#39;color&#39;: &#39;#E3F2FD&#39;}, {&#39;pin&#39;: 8, &#39;name&#39;: &#39;数字端口8&#39;, &#39;mode&#39;: &#39;输出&#39;, &#39;color&#39;: &#39;#E3F2FD&#39;}, {&#39;pin&#39;: 9, &#39;name&#39;: &#39;PWM端口9&#39;, &#39;mode&#39;: &#39;输出&#39;, &#39;color&#39;: &#39;#FFF3E0&#39;}, {&#39;pin&#39;: 10, &#39;name&#39;: &#39;PWM端口10&#39;, &#39;mode&#39;: &#39;输出&#39;, &#39;color&#39;: &#39;#FFF3E0&#39;}, {&#39;pin&#39;: 11, &#39;name&#39;: &#39;PWM端口11&#39;, &#39;mode&#39;: &#39;输出&#39;, &#39;color&#39;: &#39;#FFF3E0&#39;}, {&#39;pin&#39;: 12, &#39;name&#39;: &#39;数字端口12&#39;, &#39;mode&#39;: &#39;输出&#39;, &#39;color&#39;: &#39;#E3F2FD&#39;}, {&#39;pin&#39;: 13, &#39;name&#39;: &#39;板载LED&#39;, &#39;mode&#39;: &#39;输出&#39;, &#39;color&#39;: &#39;#FFEBEE&#39;} ] # 创建引脚控制行 self.pin_controls = [] for i, pin_info in enumerate(self.digital_pins): row = i + 2 pin_num = pin_info[&#39;pin&#39;] # 设置行样式 widget = QWidget() widget.setStyleSheet(f"background-color: {pin_info[&#39;color&#39;]};") # 引脚标签 pin_label = QLabel(f"<b>D{pin_num}</b>") pin_label.setAlignment(Qt.AlignCenter) pin_layout.addWidget(pin_label, row, 0) # 名称标签 name_label = QLabel(pin_info[&#39;name&#39;]) name_label.setAlignment(Qt.AlignCenter) pin_layout.addWidget(name_label, row, 1) # 模式标签 mode_label = QLabel(pin_info[&#39;mode&#39;]) mode_label.setAlignment(Qt.AlignCenter) pin_layout.addWidget(mode_label, row, 2) # 状态标签 state_label = QLabel("低电平") state_label.setAlignment(Qt.AlignCenter) state_label.setStyleSheet("color: #d32f2f; font-weight: bold;") pin_layout.addWidget(state_label, row, 3) self.digital_pin_states[pin_num] = state_label # 操作按钮 btn_layout = QHBoxLayout() btn_layout.setAlignment(Qt.AlignCenter) btn_layout.setSpacing(4) high_btn = QPushButton("高电平") high_btn.setFixedSize(70, 26) high_btn.setStyleSheet("background-color: #388E3C; color: white; border-radius: 3px;") high_btn.clicked.connect(lambda checked, p=pin_num: self.set_pin_high(p)) low_btn = QPushButton("低电平") low_btn.setFixedSize(70, 26) low_btn.setStyleSheet("background-color: #D32F2F; color: white; border-radius: 3px;") low_btn.clicked.connect(lambda checked, p=pin_num: self.set_pin_low(p)) toggle_btn = QPushButton("切换") toggle_btn.setFixedSize(60, 26) toggle_btn.setStyleSheet("background-color: #1976D2; color: white; border-radius: 3px;") toggle_btn.clicked.connect(lambda checked, p=pin_num: self.toggle_pin(p)) btn_layout.addWidget(high_btn) btn_layout.addWidget(low_btn) btn_layout.addWidget(toggle_btn) # 将按钮布局添加到单元格 container = QWidget() container.setLayout(btn_layout) pin_layout.addWidget(container, row, 4) # 状态指示器 status_indicator = QLabel() status_indicator.setFixedSize(16, 16) status_indicator.setStyleSheet("background-color: #d32f2f; border-radius: 8px;") pin_layout.addWidget(status_indicator, row, 5) self.digital_pin_states[f"{pin_num}_indicator"] = status_indicator # 模拟引脚监控 pin_layout.addWidget(QLabel("<b style=&#39;font-size: 10.5pt; color: #1565C0;&#39;>模拟引脚监控</b>"), len(self.digital_pins) + 2, 0, 1, 6) # 模拟引脚表头 analog_headers = ["引脚", "名称", "电压值"] for col, header in enumerate(analog_headers): label = QLabel(f"<b>{header}</b>") label.setStyleSheet("color: #263238;") pin_layout.addWidget(label, len(self.digital_pins) + 3, col) # 模拟引脚列表 self.analog_pins = [ {&#39;pin&#39;: 0, &#39;name&#39;: &#39;模拟输入A0&#39;, &#39;color&#39;: &#39;#F1F8E9&#39;}, {&#39;pin&#39;: 1, &#39;name&#39;: &#39;模拟输入A1&#39;, &#39;color&#39;: &#39;#F1F8E9&#39;}, {&#39;pin&#39;: 2, &#39;name&#39;: &#39;模拟输入A2&#39;, &#39;color&#39;: &#39;#F1F8E9&#39;}, {&#39;pin&#39;: 3, &#39;name&#39;: &#39;模拟输入A3&#39;, &#39;color&#39;: &#39;#F1F8E9&#39;}, {&#39;pin&#39;: 4, &#39;name&#39;: &#39;I2C SDA&#39;, &#39;color&#39;: &#39;#E0F7FA&#39;}, {&#39;pin&#39;: 5, &#39;name&#39;: &#39;I2C SCL&#39;, &#39;color&#39;: &#39;#E0F7FA&#39;} ] # 创建模拟引脚监控行 self.analog_value_labels = {} for i, pin_info in enumerate(self.analog_pins): row = len(self.digital_pins) + 4 + i pin_num = pin_info[&#39;pin&#39;] # 设置行样式 widget = QWidget() widget.setStyleSheet(f"background-color: {pin_info[&#39;color&#39;]};") # 引脚标签 pin_label = QLabel(f"<b>A{pin_num}</b>") pin_label.setAlignment(Qt.AlignCenter) pin_layout.addWidget(pin_label, row, 0) # 名称标签 name_label = QLabel(pin_info[&#39;name&#39;]) name_label.setAlignment(Qt.AlignCenter) pin_layout.addWidget(name_label, row, 1) # 电压值标签 value_label = QLabel("0.00 V") value_label.setAlignment(Qt.AlignCenter) value_label.setStyleSheet("color: #1976D2; font-weight: bold;") pin_layout.addWidget(value_label, row, 2) self.analog_pin_values[pin_num] = value_label # 控制按钮组 button_group = QGroupBox("快速控制") button_layout = QHBoxLayout(button_group) self.led_btn = QPushButton("启动 LED 闪烁") self.led_btn.setToolTip("启动或停止板载LED闪烁") self.led_btn.setFixedHeight(36) self.led_btn.setStyleSheet(""" QPushButton { background-color: #FF9800; color: white; padding: 8px; border-radius: 4px; font-weight: bold; } QPushButton:disabled { background-color: #FFCC80; } """) self.led_btn.clicked.connect(self.toggle_led_blink) self.led_btn.setEnabled(False) self.reset_btn = QPushButton("重置所有引脚") self.reset_btn.setToolTip("将所有引脚重置为低电平") self.reset_btn.setFixedHeight(36) self.reset_btn.setStyleSheet(""" QPushButton { background-color: #607D8B; color: white; padding: 8px; border-radius: 4px; font-weight: bold; } QPushButton:disabled { background-color: #B0BEC5; } """) self.reset_btn.clicked.connect(self.reset_all_pins) self.reset_btn.setEnabled(False) button_layout.addWidget(self.led_btn, 1) button_layout.addWidget(self.reset_btn, 1) button_layout.addStretch(2) # 添加到控制选项卡 control_layout.addWidget(conn_group) control_layout.addWidget(pin_group, 1) # 添加伸缩因子 control_layout.addWidget(button_group) # 监控选项卡 monitor_tab = QWidget() self.tab_widget.addTab(monitor_tab, "数据监控") monitor_layout = QVBoxLayout(monitor_tab) monitor_layout.setSpacing(10) monitor_layout.setContentsMargins(10, 10, 10, 10) # 模拟电压监控部分 sim_group = QGroupBox("模拟电压监控") sim_layout = QVBoxLayout(sim_group) # 绘图区域 plot_group = QGroupBox("电压波形监控") plot_layout = QVBoxLayout(plot_group) plot_layout.setSpacing(8) self.figure = Figure(figsize=(10, 4), dpi=100) self.canvas = FigureCanvas(self.figure) self.canvas.setMinimumHeight(300) plot_layout.addWidget(self.canvas, 1) # 绘图控制 plot_controls = QHBoxLayout() plot_controls.setSpacing(8) self.clear_plot_btn = QPushButton("清除图表") self.clear_plot_btn.setToolTip("清除当前图表数据") self.clear_plot_btn.setFixedHeight(30) self.clear_plot_btn.setStyleSheet("background-color: #9C27B0; color: white; padding: 6px; border-radius: 4px;") self.clear_plot_btn.clicked.connect(self.clear_plot) self.pause_plot_btn = QPushButton("暂停监控") self.pause_plot_btn.setToolTip("暂停或恢复监控") self.pause_plot_btn.setFixedHeight(30) self.pause_plot_btn.setStyleSheet("background-color: #E91E63; color: white; padding: 6px; border-radius: 4px;") self.pause_plot_btn.clicked.connect(self.toggle_plot_monitoring) self.save_data_btn = QPushButton("保存数据") self.save_data_btn.setToolTip("将数据保存为CSV文件") self.save_data_btn.setFixedHeight(30) self.save_data_btn.setStyleSheet("background-color: #009688; color: white; padding: 6px; border-radius: 4px;") self.save_data_btn.clicked.connect(self.save_voltage_data) self.autoscale_check = QCheckBox("自动缩放") self.autoscale_check.setToolTip("自动调整图表缩放") self.autoscale_check.setFixedHeight(30) self.autoscale_check.setChecked(True) self.autoscale_check.stateChanged.connect(self.toggle_autoscale) plot_controls.addWidget(self.clear_plot_btn) plot_controls.addWidget(self.pause_plot_btn) plot_controls.addWidget(self.save_data_btn) plot_controls.addStretch(1) plot_controls.addWidget(self.autoscale_check) # 监控设置 monitor_settings = QHBoxLayout() monitor_settings.setSpacing(8) monitor_settings.addWidget(QLabel("监控引脚:")) self.monitor_pin_combo = QComboBox() self.monitor_pin_combo.setFixedHeight(28) self.monitor_pin_combo.addItems(["A0", "A1", "A2", "A3", "A4", "A5"]) self.monitor_pin_combo.currentIndexChanged.connect(self.change_analog_pin) monitor_settings.addWidget(self.monitor_pin_combo) monitor_settings.addWidget(QLabel("采样间隔(ms):")) self.sampling_interval = QDoubleSpinBox() self.sampling_interval.setFixedHeight(28) self.sampling_interval.setRange(10, 5000) self.sampling_interval.setValue(100) self.sampling_interval.setSuffix(" ms") self.sampling_interval.valueChanged.connect(self.update_sampling_interval) self.sampling_interval.setSingleStep(10) monitor_settings.addWidget(self.sampling_interval) monitor_settings.addStretch(1) plot_layout.addLayout(plot_controls) plot_layout.addLayout(monitor_settings) # 电压统计 self.voltage_stats = QLabel("电压统计: 等待数据...") self.voltage_stats.setStyleSheet("color: #1976D2; font-weight: bold; font-size: 12px; padding: 5px;") plot_layout.addWidget(self.voltage_stats) sim_layout.addWidget(plot_group, 1) # 添加伸缩因子 monitor_layout.addWidget(sim_group, 60) # 60%高度 # 数字引脚状态监控部分 digi_group = QGroupBox("数字引脚状态监控") digi_layout = QVBoxLayout(digi_group) # 数字引脚监控图表 digi_plot_group = QGroupBox("数字引脚状态变化") digi_plot_layout = QVBoxLayout(digi_plot_group) self.digital_figure = Figure(figsize=(10, 3), dpi=100) self.digital_canvas = FigureCanvas(self.digital_figure) self.digital_canvas.setMinimumHeight(250) digi_plot_layout.addWidget(self.digital_canvas, 1) # 数字引脚监控控制 digi_controls = QHBoxLayout() digi_controls.setSpacing(8) self.clear_digital_btn = QPushButton("清除图表") self.clear_digital_btn.setFixedHeight(30) self.clear_digital_btn.setStyleSheet( "background-color: #9C27B0; color: white; padding: 6px; border-radius: 4px;") self.clear_digital_btn.clicked.connect(self.clear_digital_plot) self.save_digital_btn = QPushButton("保存数据") self.save_digital_btn.setFixedHeight(30) self.save_digital_btn.setStyleSheet( "background-color: #009688; color: white; padding: 6px; border-radius: 4px;") self.save_digital_btn.clicked.connect(self.save_digital_data) self.highlight_check = QCheckBox("高亮变化点") self.highlight_check.setToolTip("在状态变化点显示标记") self.highlight_check.setFixedHeight(30) self.highlight_check.setChecked(True) self.highlight_check.stateChanged.connect(self.update_digital_plot) digi_controls.addWidget(self.clear_digital_btn) digi_controls.addWidget(self.save_digital_btn) digi_controls.addStretch(1) digi_controls.addWidget(self.highlight_check) # 数字引脚监控设置 digi_settings = QHBoxLayout() digi_settings.setSpacing(8) digi_settings.addWidget(QLabel("监控引脚:")) self.digital_monitor_combo = QComboBox() self.digital_monitor_combo.setFixedHeight(28) for pin_info in self.digital_pins: pin_num = pin_info[&#39;pin&#39;] self.digital_monitor_combo.addItem(f"D{pin_num} - {pin_info[&#39;name&#39;]}", pin_num) self.digital_monitor_combo.currentIndexChanged.connect(self.change_digital_monitor_pin) digi_settings.addWidget(self.digital_monitor_combo) self.digital_stats = QLabel("状态统计: 等待数据...") self.digital_stats.setStyleSheet("color: #1976D2; font-weight: bold; font-size: 12px; padding: 5px;") digi_settings.addWidget(self.digital_stats, 1) digi_settings.addStretch(1) digi_plot_layout.addLayout(digi_controls) digi_plot_layout.addLayout(digi_settings) digi_layout.addWidget(digi_plot_group, 1) # 添加伸缩因子 monitor_layout.addWidget(digi_group, 40) # 40%高度 # LED 闪烁定时器 self.led_timer = QTimer() self.led_timer.timeout.connect(self.blink_led) # 电压读取定时器 self.voltage_timer = QTimer() self.voltage_timer.timeout.connect(self.read_voltage) self.voltage_timer.setInterval(100) # 监控是否正在运行 self.plot_monitoring = True def update_time(self): """更新状态栏中的当前时间""" current_time = time.strftime("%Y-%m-%d %H:%M:%S") self.time_label.setText(f"当前时间: {current_time}") def init_plot(self): # 初始化模拟电压图表 self.ax = self.figure.add_subplot(111) self.ax.set_title("实时电压波形", fontsize=12) self.ax.set_xlabel("时间 (秒)", fontsize=10) self.ax.set_ylabel("电压 (V)", fontsize=10) self.ax.set_ylim(0, 5.1) self.ax.grid(True, linestyle=&#39;--&#39;, alpha=0.7) # 添加图例 self.line, = self.ax.plot([], [], &#39;b-&#39;, linewidth=1.5, label="电压值") self.avg_line, = self.ax.plot([], [], &#39;r--&#39;, linewidth=1.2, label="平均电压") self.ax.legend(loc=&#39;upper right&#39;) # 初始化数字引脚状态图表 self.digital_ax = self.digital_figure.add_subplot(111) self.digital_ax.set_title("数字引脚状态变化", fontsize=12) self.digital_ax.set_xlabel("时间 (秒)", fontsize=10) self.digital_ax.set_ylabel("状态", fontsize=10) self.digital_ax.set_ylim(-0.1, 1.1) self.digital_ax.set_yticks([0, 1]) self.digital_ax.set_yticklabels([&#39;低电平&#39;, &#39;高电平&#39;]) self.digital_ax.grid(True, linestyle=&#39;--&#39;, alpha=0.7) # 创建阶梯图和散点图 self.digital_line, = self.digital_ax.step([], [], &#39;g-&#39;, where=&#39;post&#39;, linewidth=1.5) self.digital_scatter = self.digital_ax.scatter([], [], s=30, c=&#39;red&#39;, marker=&#39;o&#39;, zorder=10, label=&#39;状态变化点&#39;) self.digital_ax.legend(loc=&#39;upper right&#39;) self.canvas.draw() self.digital_canvas.draw() def update_plot(self): if not self.voltage_data: return # 计算统计值 avg_voltage = np.mean(self.voltage_data) if self.voltage_data else 0 min_voltage = min(self.voltage_data) if self.voltage_data else 0 max_voltage = max(self.voltage_data) if self.voltage_data else 0 # 更新曲线数据 self.line.set_data(self.time_data, self.voltage_data) # 更新平均线 if self.time_data: avg_data = [avg_voltage] * len(self.time_data) self.avg_line.set_data(self.time_data, avg_data) # 自动调整坐标轴 if self.autoscale_check.isChecked(): if self.time_data: max_time = max(self.time_data) self.ax.set_xlim(0, max(10, max_time * 1.05)) if self.voltage_data: min_v = min(self.voltage_data) max_v = max(self.voltage_data) y_margin = max(0.5, (max_v - min_v) * 0.2) self.ax.set_ylim(max(0, min_v - y_margin), min(5.1, max_v + y_margin)) # 更新图表 self.canvas.draw() # 更新电压统计 self.voltage_stats.setText( f"电压统计: 当前 {self.voltage_data[-1]:.3f}V | 最小 {min_voltage:.3f}V | 最大 {max_voltage:.3f}V | 平均 {avg_voltage:.3f}V" ) def update_digital_plot(self): if not self.digital_time_data: return # 更新数字引脚状态图表 self.digital_line.set_data(self.digital_time_data, self.digital_state_data) # 自动调整X轴范围 if self.digital_time_data: max_time = max(self.digital_time_data) self.digital_ax.set_xlim(0, max(10, max_time * 1.05)) # 仅当数据点超过100个时才限制显示范围 if len(self.digital_time_data) > 100: max_time = self.digital_time_data[-1] min_time = max(0, max_time - 30) # 显示最后30秒的数据 self.digital_ax.set_xlim(min_time, max_time) else: self.digital_ax.set_xlim(0, max(10, max_time)) # 高亮状态变化点 if self.highlight_check.isChecked(): # 查找所有状态变化点 change_points = [] change_times = [] for i in range(1, len(self.digital_state_data)): if self.digital_state_data[i] != self.digital_state_data[i - 1]: change_points.append(self.digital_state_data[i]) change_times.append(self.digital_time_data[i]) if change_times: self.digital_scatter.set_offsets(np.column_stack([change_times, change_points])) self.digital_scatter.set_visible(True) else: self.digital_scatter.set_visible(False) else: self.digital_scatter.set_visible(False) # 更新图表 self.digital_canvas.draw() # 更新状态统计 if self.digital_state_data: last_state = self.digital_state_data[-1] state_text = "高电平" if last_state == 1 else "低电平" changes = len(self.digital_state_data) self.digital_stats.setText( f"当前状态: {state_text} | 状态变化: {changes}次 | 上升沿: {self.rise_count} | 下降沿: {self.fall_count}" ) def refresh_ports(self): # 模拟刷新端口列表 self.status_bar.showMessage("刷新可用端口...") current_port = self.port_combo.currentText() self.port_combo.clear() self.port_combo.addItems(["COM3", "COM4", "COM5", "COM6", "COM7", "/dev/ttyACM0", "/dev/ttyUSB0"]) if current_port in [self.port_combo.itemText(i) for i in range(self.port_combo.count())]: self.port_combo.setCurrentText(current_port) else: self.port_combo.setCurrentIndex(0) self.status_bar.showMessage("端口列表已刷新") def connect_arduino(self): port = self.port_combo.currentText() if not port: QMessageBox.warning(self, "端口错误", "请选择有效的串口") return self.status_bar.showMessage(f"正在连接 Arduino ({port})...") self.connect_btn.setEnabled(False) self.disconnect_btn.setEnabled(False) self.refresh_btn.setEnabled(False) # 显示进度条 self.progress_bar.setVisible(True) self.progress_bar.setValue(0) self.status_indicator.setStyleSheet("background-color: #FFC107; border-radius: 8px;") self.status_label.setText("连接中...") # 创建并启动连接线程 self.conn_thread = ConnectionThread(port) self.conn_thread.progress.connect(self.progress_bar.setValue) self.conn_thread.success.connect(self.handle_connection_success) self.conn_thread.error.connect(self.handle_connection_error) self.conn_thread.start() def handle_connection_success(self, board): self.board = board self.it = self.conn_thread.it self.is_connected = True # 更新UI状态 self.progress_bar.setVisible(False) self.status_indicator.setStyleSheet("background-color: #4CAF50; border-radius: 8px;") self.status_label.setText("已连接") self.conn_info_label.setText(f"<b>连接信息:</b> Arduino 已成功连接到 {self.port_combo.currentText()}") self.status_bar.showMessage(f"成功连接到 Arduino ({self.port_combo.currentText()})") # 更新按钮状态 self.connect_btn.setEnabled(False) self.disconnect_btn.setEnabled(True) self.refresh_btn.setEnabled(True) self.led_btn.setEnabled(True) self.reset_btn.setEnabled(True) self.clear_plot_btn.setEnabled(True) self.pause_plot_btn.setEnabled(True) self.save_data_btn.setEnabled(True) self.clear_digital_btn.setEnabled(True) self.save_digital_btn.setEnabled(True) # 启动电压读取 self.update_sampling_interval() # 设置初始引脚状态 for pin_info in self.digital_pins: pin = pin_info[&#39;pin&#39;] self.digital_pin_states[pin].setText("低电平") self.digital_pin_states[pin].setStyleSheet("color: #d32f2f; font-weight: bold;") indicator = self.digital_pin_states.get(f"{pin}_indicator") if indicator: indicator.setStyleSheet("background-color: #d32f2f; border-radius: 8px;") def handle_connection_error(self, message): self.board = None self.is_connected = False # 更新UI状态 self.progress_bar.setVisible(False) self.status_indicator.setStyleSheet("background-color: #f44336; border-radius: 8px;") self.status_label.setText("连接失败") self.conn_info_label.setText(f"<b>连接信息:</b> 连接失败: {message}") QMessageBox.critical(self, "连接错误", f"连接失败:\n{message}") self.status_bar.showMessage(f"连接失败: {message}") # 更新按钮状态 self.connect_btn.setEnabled(True) self.disconnect_btn.setEnabled(False) self.refresh_btn.setEnabled(True) self.led_btn.setEnabled(False) self.reset_btn.setEnabled(False) def disconnect_arduino(self): if self.board: # 停止所有定时器 self.led_timer.stop() self.voltage_timer.stop() # 重置所有引脚 self.reset_all_pins() if hasattr(self, &#39;it&#39;): self.it.stop() self.board.exit() self.board = None self.is_connected = False self.progress_bar.setVisible(False) self.status_indicator.setStyleSheet("background-color: #9E9E9E; border-radius: 8px;") self.status_label.setText("未连接") self.conn_info_label.setText("<b>连接信息:</b> Arduino 已断开连接") self.status_bar.showMessage("已断开连接") # 更新按钮状态 self.connect_btn.setEnabled(True) self.disconnect_btn.setEnabled(False) self.led_btn.setEnabled(False) self.led_btn.setText("启动 LED 闪烁") self.refresh_btn.setEnabled(True) def set_pin_high(self, pin): if not self.is_connected: QMessageBox.warning(self, "未连接", "请先连接到Arduino") return try: self.board.digital[pin].write(1) self.digital_pin_states[pin].setText("高电平") self.digital_pin_states[pin].setStyleSheet("color: #388E3C; font-weight: bold;") # 更新指示灯 indicator = self.digital_pin_states.get(f"{pin}_indicator") if indicator: indicator.setStyleSheet("background-color: #388E3C; border-radius: 8px;") self.status_bar.showMessage(f"引脚 D{pin} 设置为高电平") # 记录状态变化 if pin == self.digital_monitor_pin: current_time = time.time() - self.digital_monitor_start_time self.digital_state_data.append(1) self.digital_time_data.append(current_time) # 统计边缘变化 if self.last_digital_state == 0: self.rise_count += 1 self.last_digital_state = 1 # 限制数据点数 if len(self.digital_time_data) > self.max_data_points: self.digital_time_data.pop(0) self.digital_state_data.pop(0) self.update_digital_plot() except Exception as e: self.status_bar.showMessage(f"设置引脚失败: {str(e)}") def set_pin_low(self, pin): if not self.is_connected: QMessageBox.warning(self, "未连接", "请先连接到Arduino") return try: self.board.digital[pin].write(0) self.digital_pin_states[pin].setText("低电平") self.digital_pin_states[pin].setStyleSheet("color: #d32f2f; font-weight: bold;") # 更新指示灯 indicator = self.digital_pin_states.get(f"{pin}_indicator") if indicator: indicator.setStyleSheet("background-color: #d32f2f; border-radius: 8px;") self.status_bar.showMessage(f"引脚 D{pin} 设置为低电平") # 记录状态变化 if pin == self.digital_monitor_pin: current_time = time.time() - self.digital_monitor_start_time self.digital_state_data.append(0) self.digital_time_data.append(current_time) # 统计边缘变化 if self.last_digital_state == 1: self.fall_count += 1 self.last_digital_state = 0 # 限制数据点数 if len(self.digital_time_data) > self.max_data_points: self.digital_time_data.pop(0) self.digital_state_data.pop(0) self.update_digital_plot() except Exception as e: self.status_bar.showMessage(f"设置引脚失败: {str(e)}") def toggle_pin(self, pin): if not self.is_connected: QMessageBox.warning(self, "未连接", "请先连接到Arduino") return try: current_state = self.board.digital[pin].read() new_state = 0 if current_state else 1 self.board.digital[pin].write(new_state) if new_state: self.digital_pin_states[pin].setText("高电平") self.digital_pin_states[pin].setStyleSheet("color: #388E3C; font-weight: bold;") # 更新指示灯 indicator = self.digital_pin_states.get(f"{pin}_indicator") if indicator: indicator.setStyleSheet("background-color: #388E3C; border-radius: 8px;") self.status_bar.showMessage(f"引脚 D{pin} 切换为高电平") else: self.digital_pin_states[pin].setText("低电平") self.digital_pin_states[pin].setStyleSheet("color: #d32f2f; font-weight: bold;") # 更新指示灯 indicator = self.digital_pin_states.get(f"{pin}_indicator") if indicator: indicator.setStyleSheet("background-color: #d32f2f; border-radius: 8px;") self.status_bar.showMessage(f"引脚 D{pin} 切换为低电平") # 记录状态变化 if pin == self.digital_monitor_pin: current_time = time.time() - self.digital_monitor_start_time self.digital_state_data.append(new_state) self.digital_time_data.append(current_time) # 统计边缘变化 if self.last_digital_state is not None: if self.last_digital_state == 0 and new_state == 1: self.rise_count += 1 elif self.last_digital_state == 1 and new_state == 0: self.fall_count += 1 self.last_digital_state = new_state # 限制数据点数 if len(self.digital_time_data) > self.max_data_points: self.digital_time_data.pop(0) self.digital_state_data.pop(0) self.update_digital_plot() except Exception as e: self.status_bar.showMessage(f"切换引脚失败: {str(e)}") def reset_all_pins(self): if not self.is_connected: QMessageBox.warning(self, "未连接", "请先连接到Arduino") return try: # 重置所有数字引脚 for pin_info in self.digital_pins: pin = pin_info[&#39;pin&#39;] self.board.digital[pin].write(0) self.digital_pin_states[pin].setText("低电平") self.digital_pin_states[pin].setStyleSheet("color: #d32f2f; font-weight: bold;") # 更新指示灯 indicator = self.digital_pin_states.get(f"{pin}_indicator") if indicator: indicator.setStyleSheet("background-color: #d32f2f; border-radius: 8px;") # 记录状态变化 if self.digital_monitor_pin in [p[&#39;pin&#39;] for p in self.digital_pins]: current_time = time.time() - self.digital_monitor_start_time self.digital_state_data.append(0) self.digital_time_data.append(current_time) # 重置最后状态 self.last_digital_state = 0 # 限制数据点数 if len(self.digital_time_data) > self.max_data_points: self.digital_time_data.pop(0) self.digital_state_data.pop(0) self.update_digital_plot() # 停止LED闪烁 if self.led_timer.isActive(): self.led_timer.stop() self.led_btn.setText("启动 LED 闪烁") self.status_bar.showMessage("所有引脚已重置") except Exception as e: self.status_bar.showMessage(f"重置引脚失败: {str(e)}") def toggle_led_blink(self): if not self.is_connected: QMessageBox.warning(self, "未连接", "请先连接到Arduino") return if self.led_timer.isActive(): self.led_timer.stop() self.board.digital[13].write(0) # 关闭LED self.digital_pin_states[13].setText("低电平") self.digital_pin_states[13].setStyleSheet("color: #d32f2f; font-weight: bold;") # 更新指示灯 indicator = self.digital_pin_states.get(f"13_indicator") if indicator: indicator.setStyleSheet("background-color: #d32f2f; border-radius: 8px;") self.led_btn.setText("启动 LED 闪烁") self.status_bar.showMessage("LED 闪烁已停止") else: self.led_timer.start(500) # 500ms间隔 self.led_btn.setText("停止 LED 闪烁") self.status_bar.showMessage("LED 闪烁已启动") def blink_led(self): if not self.is_connected: return self.led_state = not self.led_state self.board.digital[13].write(1 if self.led_state else 0) if self.led_state: self.digital_pin_states[13].setText("高电平") self.digital_pin_states[13].setStyleSheet("color: #388E3C; font-weight: bold;") # 更新指示灯 indicator = self.digital_pin_states.get(f"13_indicator") if indicator: indicator.setStyleSheet("background-color: #388E3C; border-radius: 8px;") else: self.digital_pin_states[13].setText("低电平") self.digital_pin_states[13].setStyleSheet("color: #d32f2f; font-weight: bold;") # 更新指示灯 indicator = self.digital_pin_states.get(f"13_indicator") if indicator: indicator.setStyleSheet("background-color: #d32f2f; border-radius: 8px;") # 记录状态变化 if 13 == self.digital_monitor_pin: current_time = time.time() - self.digital_monitor_start_time self.digital_state_data.append(1 if self.led_state else 0) self.digital_time_data.append(current_time) # 统计边缘变化 if self.last_digital_state is not None: if self.last_digital_state == 0 and self.led_state == 1: self.rise_count += 1 elif self.last_digital_state == 1 and self.led_state == 0: self.fall_count += 1 self.last_digital_state = 1 if self.led_state else 0 # 限制数据点数 if len(self.digital_time_data) > self.max_data_points: self.digital_time_data.pop(0) self.digital_state_data.pop(0) self.update_digital_plot() def read_voltage(self): if not self.is_connected or not self.plot_monitoring: return try: # 读取所有模拟引脚值 for i in range(6): analog_value = self.board.analog[i].read() if analog_value is not None: # 转换为电压值 (0-5V) voltage = analog_value * 5.0 # 更新模拟引脚显示 self.analog_pin_values[i].setText(f"{voltage:.3f} V") # 如果是当前监控的引脚,则添加到图表 if i == self.analog_pin: current_time = time.time() - self.start_time # 添加到数据列表 self.voltage_data.append(voltage) self.time_data.append(current_time) # 限制数据点数 if len(self.voltage_data) > self.max_data_points: self.voltage_data.pop(0) self.time_data.pop(0) # 更新图表 self.update_plot() except Exception as e: print(f"读取电压失败: {str(e)}") def change_analog_pin(self, index): if not self.is_connected: return try: # 更新当前监控引脚 self.analog_pin = index # 清空数据 self.clear_plot() self.status_bar.showMessage(f"已切换到监控模拟输入 A{index}") except Exception as e: self.status_bar.showMessage(f"切换引脚失败: {str(e)}") def change_digital_monitor_pin(self, index): pin = self.digital_monitor_combo.currentData() if pin is not None: self.digital_monitor_pin = pin self.clear_digital_plot() self.last_digital_state = None self.rise_count = 0 self.fall_count = 0 # 更新图表标题 for pin_info in self.digital_pins: if pin_info[&#39;pin&#39;] == pin: pin_name = pin_info[&#39;name&#39;] break else: pin_name = f"D{pin}" self.digital_ax.set_title(f"数字引脚状态变化 - {pin_name}", fontsize=12) self.digital_canvas.draw() self.status_bar.showMessage(f"已切换到监控数字引脚 D{pin}") def clear_plot(self): self.voltage_data = [] self.time_data = [] self.start_time = time.time() self.update_plot() self.voltage_stats.setText("电压统计: 等待数据...") self.status_bar.showMessage("模拟电压图表已清除") def clear_digital_plot(self): self.digital_state_data = [] self.digital_time_data = [] self.digital_monitor_start_time = time.time() self.last_digital_state = None self.rise_count = 0 self.fall_count = 0 self.update_digital_plot() self.digital_stats.setText("状态统计: 等待数据...") self.status_bar.showMessage("数字引脚状态图表已清除") def toggle_plot_monitoring(self): self.plot_monitoring = not self.plot_monitoring if self.plot_monitoring: self.pause_plot_btn.setText("暂停监控") self.pause_plot_btn.setStyleSheet("background-color: #E91E63; color: white;") self.status_bar.showMessage("电压监控已恢复") else: self.pause_plot_btn.setText("恢复监控") self.pause_plot_btn.setStyleSheet("background-color: #4CAF50; color: white;") self.status_bar.showMessage("电压监控已暂停") def toggle_autoscale(self): if self.autoscale_check.isChecked(): self.status_bar.showMessage("自动缩放已启用") else: self.status_bar.showMessage("自动缩放已禁用") self.update_plot() def update_sampling_interval(self): interval = int(self.sampling_interval.value()) self.voltage_timer.setInterval(interval) if self.is_connected: self.voltage_timer.start() self.status_bar.showMessage(f"采样间隔设置为 {interval}ms") else: self.status_bar.showMessage("连接后采样间隔将生效") def save_voltage_data(self): if not self.voltage_data: self.status_bar.showMessage("无数据可保存") return try: timestamp = time.strftime("%Y%m%d_%H%M%S") filename = f"电压数据_A{self.analog_pin}_{timestamp}.csv" with open(filename, &#39;w&#39;) as f: f.write("时间(秒),电压(V)\n") for t, v in zip(self.time_data, self.voltage_data): f.write(f"{t:.3f},{v:.4f}\n") self.status_bar.showMessage(f"模拟电压数据已保存到 {filename}") QMessageBox.information(self, "保存成功", f"数据已保存到文件:\n{filename}") except Exception as e: self.status_bar.showMessage(f"保存失败: {str(e)}") QMessageBox.critical(self, "保存失败", f"保存数据时出错:\n{str(e)}") def save_digital_data(self): if not self.digital_time_data: self.status_bar.showMessage("无数据可保存") return try: timestamp = time.strftime("%Y%m%d_%H%M%S") filename = f"数字引脚_D{self.digital_monitor_pin}_数据_{timestamp}.csv" with open(filename, &#39;w&#39;) as f: f.write("时间(秒),状态,电压(V),变化类型\n") last_state = None for t, s in zip(self.digital_time_data, self.digital_state_data): voltage = 5.0 if s == 1 else 0.0 # 检测变化类型 change_type = "" if last_state is not None: if last_state == 0 and s == 1: change_type = "上升沿" elif last_state == 1 and s == 0: change_type = "下降沿" last_state = s f.write(f"{t:.3f},{s},{voltage:.1f},{change_type}\n") self.status_bar.showMessage(f"数字引脚数据已保存到 {filename}") QMessageBox.information(self, "保存成功", f"数据已保存到文件:\n{filename}") except Exception as e: self.status_bar.showMessage(f"保存失败: {str(e)}") QMessageBox.critical(self, "保存失败", f"保存数据时出错:\n{str(e)}") def closeEvent(self, event): if self.is_connected: self.disconnect_arduino() event.accept() if __name__ == "__main__": app = QApplication(sys.argv) # 设置应用全局字体 font = QFont("Microsoft YaHei", 9) app.setFont(font) window = ArduinoControlApp() window.show() sys.exit(app.exec_())删除数字引脚部分引脚控制,保留2,3,4,8,9,10,13的端口控制,其余端口控制删除,在此基础上优化界面显示
最新发布
08-02
import utime import gc from maix import GPIO from fpioa_manager import fm from machine import Timer, PWM, UART import time import math import lcd, image import sensor def main(): # 初始化摄像头 sensor.reset() sensor.set_pixformat(sensor.GRAYSCALE) sensor.set_framesize(sensor.QQVGA) # 160x120 sensor.set_brightness(-2) sensor.set_saturation(-2) sensor.skip_frames(time=2000) # 初始化LCD lcd.init() lcd.clear(lcd.WHITE) lcd.draw_string(10, 10, "System Starting...", lcd.RED, lcd.WHITE) time.sleep(1) # 配置PYAIK210引脚映射 # 紫外线LED - 排针15 (IO14) fm.register(14, fm.fpioa.GPIO0, force=True) LED_B = GPIO(GPIO.GPIO0, GPIO.OUT) LED_B.value(1) # 初始熄灭紫外线 # 初始化舵机PWM - 使用3.3V区域引脚 # 舵机1 (X轴) -> 排针9 (IO8) # 舵机2 (Y轴) -> 排针10 (IO9) tim = Timer(Timer.TIMER0, Timer.CHANNEL0, mode=Timer.MODE_PWM) S1 = PWM(tim, freq=50, duty=0, pin=8) # IO8 tim2 = Timer(Timer.TIMER0, Timer.CHANNEL1, mode=Timer.MODE_PWM) S2 = PWM(tim2, freq=50, duty=0, pin=9) # IO9 # 舵机控制函数 def set_servo_angle(servo, angle): """设置舵机角度(0-180度)""" duty = angle / 180 * 10 + 2.5 # 转换为占空比(2.5%-12.5%) servo.duty(duty) # 舵机位置转换函数 def func_servo(id0, posit0): """将4096位置值转换为角度并设置""" angle = (posit0 / 4096) * 180 if id0 == 1: # X轴舵机 set_servo_angle(S1, angle) elif id0 == 2: # Y轴舵机 set_servo_angle(S2, angle) # 初始位置设置 posit = 2085 # Y轴初始位置 (调整激光上下) positx = 2048 # X轴初始位置 (中心) # 设置串口 (UART1) fm.register(34, fm.fpioa.UART1_RX, force=True) # PYAIK210排针34 fm.register(7, fm.fpioa.UART1_TX, force=True) # 使用IO7 uart = UART(UART.UART1, 115200, read_buf_len=4096) # 初始化舵机位置 func_servo(1, positx) func_servo(2, posit) time.sleep(1) # 系统参数 ZX, xin = 70, 70 # 激光X中心位置 ZY, yin = 70, 70 # 激光Y中心位置 I, I2 = 0, 0 last_cor = [(0,0), (0,0), (0,0), (0,0)] state = 0 text2 = &#39;&#39; text2_last = &#39;&#39; # 显示系统状态 lcd.clear() lcd.draw_string(10, 10, "Tracking System Ready", lcd.GREEN, lcd.BLACK) lcd.draw_string(10, 30, f"Free Mem: {gc.mem_free()//1024}KB", lcd.BLUE, lcd.WHITE) time.sleep(1) while True: # 捕获图像 img = sensor.snapshot() # 读取串口指令 if uart.any(): try: text2 = uart.read(1).decode(&#39;utf-8&#39;) except: text2 = &#39;&#39; # 使用拉普拉斯算子增强边缘 img.laplacian(1, sharpen=True) # 寻找矩形 rects = img.find_rects(threshold=26000) if rects: r = rects[0] # 只处理第一个检测到的矩形 img.draw_rectangle(r.rect(), color=(255, 0, 0)) for p in r.corners(): img.draw_circle(p[0], p[1], 5, color=(0, 255, 0)) cor = r.corners() # 稳定性检查 if last_cor != [(0,0), (0,0), (0,0), (0,0)]: try: ratio = (cor[2][0]-cor[3][0])/(cor[1][1]-cor[3][1] or 0.001) if ratio > 1.7 or ratio < 1.35: cor = last_cor except: pass last_cor = cor # 计算矩形中心 ZX = (cor[0][0] + cor[1][0] + cor[2][0] + cor[3][0]) / 4 ZY = (cor[0][1] + cor[1][1] + cor[2][1] + cor[3][1]) / 4 # PID计算 I = (ZX - xin) * 0.8 + I * 0.9 I2 = (ZY - yin) * 0.8 + I2 * 0.9 # 目标锁定指示LED LED_B.value(0 if abs(ZX - xin) < 5 else 1) # 指令处理 if text2 != text2_last: state = 1 text2_last = text2 if state == 1: state = 0 if text2 == &#39;1&#39;: positx = 2048 # 中心位置 elif text2 == &#39;2&#39;: positx = 1500 # 右转 elif text2 == &#39;3&#39;: positx = 1000 # 右转 elif text2 == &#39;4&#39;: positx = 500 # 右转 elif text2 == &#39;5&#39;: positx = 4000 # 左转 elif text2 == &#39;6&#39;: positx = 3500 # 左转 elif text2 == &#39;7&#39;: positx = 3000 # 左转 elif text2 == &#39;8&#39;: positx = 2500 # 左转 # 重置积分项 I, I2 = 0, 0 # 更新舵机位置 func_servo(1, int(positx - I)) func_servo(2, int(posit)) # 显示状态信息 img.draw_string(5, 5, f"Target: ({int(ZX)},{int(ZY)})", color=(255,255,255), scale=1) img.draw_string(5, 20, f"Adjust: ({int(I)},{int(I2)})", color=(255,255,255), scale=1) img.draw_string(5, 35, f"ServoX: {int(positx - I)}", color=(255,255,255), scale=1) # 显示图像 lcd.display(img) # 定期垃圾回收 if time.ticks_ms() % 5000 == 0: gc.collect() print("GC collected, free mem:", gc.mem_free()) # 程序入口 if __name__ == "__main__": try: main() except Exception as e: # 错误处理:打印错误并重启 import sys sys.print_exception(e) lcd.clear() lcd.draw_string(10, 10, "System Error!", lcd.RED, lcd.WHITE) lcd.draw_string(10, 30, str(e)[:30], lcd.RED, lcd.WHITE) time.sleep(3) import machine machine.reset()对这个代码做修改,要求可以实现原来的功能,完全符合MaixPy IDE的语法
08-02
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值