diff --git a/CSI-H238M/CSI-H238M/Services/ModbusService.cs b/CSI-H238M/CSI-H238M/Services/ModbusService.cs
index 3484130..5da1cd2 100644
--- a/CSI-H238M/CSI-H238M/Services/ModbusService.cs
+++ b/CSI-H238M/CSI-H238M/Services/ModbusService.cs
@@ -626,6 +626,41 @@ namespace COFTester.Services
}
}
+ ///
+ /// 触发测试停止按钮 M32(复归型)
+ /// M32 需要写入脉冲信号:true -> 延迟 -> false
+ ///
+ public virtual async Task TriggerTestStopAsync()
+ {
+ try
+ {
+ if (_modbusMaster != null && _isConnected)
+ {
+ const ushort STOP_BUTTON_ADDRESS = 32; // M32 停止按钮
+
+ System.Diagnostics.Debug.WriteLine($"[Modbus] 触发测试停止按钮 M{STOP_BUTTON_ADDRESS}");
+
+ await _modbusMaster.WriteSingleCoilAsync(1, STOP_BUTTON_ADDRESS, true);
+ System.Diagnostics.Debug.WriteLine($"[Modbus] M{STOP_BUTTON_ADDRESS} = true");
+
+ await Task.Delay(100);
+
+ await _modbusMaster.WriteSingleCoilAsync(1, STOP_BUTTON_ADDRESS, false);
+ System.Diagnostics.Debug.WriteLine($"[Modbus] M{STOP_BUTTON_ADDRESS} = false");
+
+ await Task.Delay(100);
+
+ System.Diagnostics.Debug.WriteLine($"[Modbus] M{STOP_BUTTON_ADDRESS} 脉冲信号发送完成");
+ }
+ }
+ catch (Exception ex)
+ {
+ OnErrorOccurred($"触发测试停止失败: {ex.Message}");
+ System.Diagnostics.Debug.WriteLine($"[Modbus] 触发 M32 异常: {ex.Message}");
+ throw;
+ }
+ }
+
///
/// 读取测试状态标记位 M31
/// M31: 1=测试中,0=停止
@@ -655,6 +690,46 @@ namespace COFTester.Services
}
}
+ ///
+ /// 读取当前实时传感器数据,用于非测试状态下的界面实时显示。
+ ///
+ public virtual async Task ReadCurrentDataAsync()
+ {
+ try
+ {
+ if (_modbusMaster == null || !_isConnected)
+ {
+ return null;
+ }
+
+ var dataPoint = await ReadSensorDataAsync();
+ if (dataPoint == null)
+ {
+ return null;
+ }
+
+ try
+ {
+ var (verticalPos, horizontalPos) = await ReadPositionDataAsync();
+ dataPoint.VerticalPosition = verticalPos;
+ dataPoint.HorizontalPosition = horizontalPos;
+ }
+ catch (Exception ex)
+ {
+ dataPoint.VerticalPosition = 0;
+ dataPoint.HorizontalPosition = 0;
+ System.Diagnostics.Debug.WriteLine($"[Modbus] 读取实时位置数据失败: {ex.Message}");
+ }
+
+ return dataPoint;
+ }
+ catch (Exception ex)
+ {
+ System.Diagnostics.Debug.WriteLine($"[Modbus] 读取实时数据异常: {ex.Message}");
+ return null;
+ }
+ }
+
///
/// 写入启动/停止寄存器 M31(已弃用,请使用 TriggerTestStartAsync)
/// M30 复归型, M31 标注为 1=开始,0=停止
diff --git a/CSI-H238M/CSI-H238M/ViewModels/ViewModel.cs b/CSI-H238M/CSI-H238M/ViewModels/ViewModel.cs
index 1235868..23af5bb 100644
--- a/CSI-H238M/CSI-H238M/ViewModels/ViewModel.cs
+++ b/CSI-H238M/CSI-H238M/ViewModels/ViewModel.cs
@@ -21,6 +21,7 @@ namespace COFTester.ViewModels
private readonly IDataAcquisitionService _daqService;
private readonly DataProcessingService _processingService;
private readonly DispatcherTimer _clockTimer;
+ private readonly DispatcherTimer _liveSensorTimer;
private readonly DispatcherTimer _m31StatusTimer; // M31状态检查定时器
private WpfPlot? _wpfPlot;
private readonly AppConfig _config;
@@ -40,6 +41,9 @@ namespace COFTester.ViewModels
private bool _showAllCurves = true;
private int _testCounter = 0;
private bool _disposed = false;
+ private bool _isRefreshingLiveSensorData = false;
+ private bool _isTestTransitioning = false;
+ private bool _stopRequestedByUser = false;
private string _selectedDirection = ""; // 选中的方向:Up/Down/Right/Left
private string _resetButtonText; // 复位按钮文本
private string _testButtonText; // 测试按钮文本
@@ -69,7 +73,7 @@ namespace COFTester.ViewModels
DisconnectCommand = new RelayCommand(Disconnect, () => IsConnected && !_isTesting);
ToggleConnectionCommand = new AsyncRelayCommand(ToggleConnectionAsync, () => !_isConnecting && !_isTesting);
StartCommand = new RelayCommand(StartTest, CanStartTest);
- StopCommand = new RelayCommand(StopTest, () => _isTesting);
+ StopCommand = new RelayCommand(StopTest, CanStopTest);
ResetCommand = new RelayCommand(Reset, () => !_isTesting && IsConnected);
SwitchLanguageCommand = new RelayCommand(SwitchLanguage);
OpenConfigCommand = new RelayCommand(OpenConfig);
@@ -111,6 +115,13 @@ namespace COFTester.ViewModels
_m31StatusTimer.Tick += async (s, e) => await CheckM31StatusAsync();
_m31StatusTimer.Start();
+ _liveSensorTimer = new DispatcherTimer
+ {
+ Interval = TimeSpan.FromMilliseconds(200)
+ };
+ _liveSensorTimer.Tick += async (s, e) => await RefreshLiveSensorDataAsync();
+ _liveSensorTimer.Start();
+
// 根據配置自動連接
AutoConnectOnStartup();
}
@@ -173,8 +184,9 @@ namespace COFTester.ViewModels
if (oldCanStartTest != _canStartTest)
{
System.Diagnostics.Debug.WriteLine($"[ViewModel] 开始按钮可用性变化: {_canStartTest}");
- CommandManager.InvalidateRequerySuggested();
}
+
+ CommandManager.InvalidateRequerySuggested();
}
///
@@ -184,6 +196,48 @@ namespace COFTester.ViewModels
{
return _canStartTest;
}
+
+ private bool CanStopTest()
+ {
+ return IsConnected && (_isTesting || _m31Status || _isTestTransitioning);
+ }
+
+ private async Task RefreshLiveSensorDataAsync()
+ {
+ if (_disposed || _isRefreshingLiveSensorData || !IsConnected || _isTesting || _isTestTransitioning)
+ {
+ return;
+ }
+
+ if (_daqService is not ModbusServiceBase modbusService)
+ {
+ return;
+ }
+
+ try
+ {
+ _isRefreshingLiveSensorData = true;
+
+ var point = await modbusService.ReadCurrentDataAsync();
+ if (point == null)
+ {
+ return;
+ }
+
+ CurrentForce = point.Force;
+ CurrentDisp = point.Displacement;
+ LiftPosition = point.VerticalPosition;
+ HorizontalPosition = point.HorizontalPosition;
+ }
+ catch (Exception ex)
+ {
+ System.Diagnostics.Debug.WriteLine($"[ViewModel] 实时数值刷新失败: {ex.Message}");
+ }
+ finally
+ {
+ _isRefreshingLiveSensorData = false;
+ }
+ }
///
/// 設置圖表控件(由TestPage調用)
@@ -575,6 +629,13 @@ namespace COFTester.ViewModels
TestButtonText = Lang.StartTest; // 测试完成后恢复按钮文本
_m31Status = false; // 测试完成,M31应该为0
UpdateCanStartTest(); // 更新按钮可用性
+ if (_stopRequestedByUser)
+ {
+ _stopRequestedByUser = false;
+ StatusMessage = Lang.TestStopped;
+ return;
+ }
+
StatusMessage = Lang.TestCompleted;
// 数据处理与计算
@@ -661,6 +722,7 @@ namespace COFTester.ViewModels
_m31Status = await modbusService.ReadTestStatusAsync();
System.Diagnostics.Debug.WriteLine($"[ViewModel] 连接后M31状态: {(_m31Status ? "1 (测试中)" : "0 (停止)")}");
UpdateCanStartTest();
+ await RefreshLiveSensorDataAsync();
}
catch (Exception ex)
{
@@ -799,6 +861,10 @@ namespace COFTester.ViewModels
// return;
//}
+ _stopRequestedByUser = false;
+ _isTestTransitioning = true;
+ CommandManager.InvalidateRequerySuggested();
+
_realTimePoints.Clear();
OnPropertyChanged(nameof(DataPointsCount));
LatestResult = null;
@@ -842,6 +908,8 @@ namespace COFTester.ViewModels
{
// 测试未启动,保持原状态
_m31Status = false; // 更新M31状态
+ _isTestTransitioning = false;
+ CommandManager.InvalidateRequerySuggested();
StatusMessage = "测试启动失败,请检查设备";
System.Diagnostics.Debug.WriteLine("[ViewModel] M31 = 0,测试未启动");
}
@@ -853,6 +921,8 @@ namespace COFTester.ViewModels
{
StatusMessage = $"启动测试失败: {ex.Message}";
_m31Status = false;
+ _isTestTransitioning = false;
+ CommandManager.InvalidateRequerySuggested();
System.Diagnostics.Debug.WriteLine($"[ViewModel] 启动测试异常: {ex.Message}");
});
}
@@ -861,21 +931,43 @@ namespace COFTester.ViewModels
// _daqService.StartDirectionTest(_selectedDirection); // 暂时注释掉
_daqService.StartAcquisition(Parameters);
+ _isTestTransitioning = false;
+ CommandManager.InvalidateRequerySuggested();
}
- private void StopTest()
+ private async void StopTest()
{
+ _stopRequestedByUser = true;
+ _isTestTransitioning = true;
+ CommandManager.InvalidateRequerySuggested();
+
// M30 复归型按钮,M31 状态标记位(1=测试中,0=停止)
// M31 是只读状态位,由 PLC 控制,我们只需停止数据采集
// PLC 会自动将 M31 设置为 0
- _daqService.StopAcquisition();
- IsTesting = false;
- TestButtonText = Lang.StartTest; // 恢复按钮文本为"开始测试"
- StatusMessage = Lang.TestStopped;
- UpdateCanStartTest(); // 更新按钮可用性
+ try
+ {
+ if (_daqService is ModbusServiceBase modbusService)
+ {
+ await modbusService.TriggerTestStopAsync();
+ }
+ }
+ catch (Exception ex)
+ {
+ StatusMessage = $"停止测试失败: {ex.Message}";
+ System.Diagnostics.Debug.WriteLine($"[ViewModel] 停止测试异常: {ex.Message}");
+ }
+ finally
+ {
+ _daqService.StopAcquisition();
+ IsTesting = false;
+ TestButtonText = Lang.StartTest;
+ StatusMessage = Lang.TestStopped;
+ _isTestTransitioning = false;
+ UpdateCanStartTest();
- System.Diagnostics.Debug.WriteLine("[ViewModel] 停止测试,等待 PLC 将 M31 设置为 0");
+ System.Diagnostics.Debug.WriteLine("[ViewModel] 已发送 M32 停止命令,并停止本地数据采集");
+ }
}
private async void Reset()
@@ -1626,6 +1718,7 @@ namespace COFTester.ViewModels
// 停止M31状态检查定时器
_m31StatusTimer?.Stop();
+ _liveSensorTimer?.Stop();
// 取消訂閱事件
if (_daqService != null)
diff --git a/CSI-H238M/CSI-H238M/Views/MainWindow.xaml b/CSI-H238M/CSI-H238M/Views/MainWindow.xaml
index 63f2eda..3f7da53 100644
--- a/CSI-H238M/CSI-H238M/Views/MainWindow.xaml
+++ b/CSI-H238M/CSI-H238M/Views/MainWindow.xaml
@@ -2,6 +2,8 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CSI-H238M 高配版摩擦系数仪、摩擦系数测定仪" Height="800" Width="1024"
+ WindowStartupLocation="CenterScreen"
+ WindowState="Maximized"
Background="#F0F3F5">
+
+
+