20260311 更新

This commit is contained in:
GukSang.Jin
2026-03-11 18:30:40 +08:00
parent f90be4b12a
commit 061de713d5
4 changed files with 189 additions and 9 deletions

View File

@@ -626,6 +626,41 @@ namespace COFTester.Services
}
}
/// <summary>
/// 触发测试停止按钮 M32复归型
/// M32 需要写入脉冲信号true -> 延迟 -> false
/// </summary>
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;
}
}
/// <summary>
/// 读取测试状态标记位 M31
/// M31: 1=测试中0=停止
@@ -655,6 +690,46 @@ namespace COFTester.Services
}
}
/// <summary>
/// 读取当前实时传感器数据,用于非测试状态下的界面实时显示。
/// </summary>
public virtual async Task<TestDataPoint?> 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;
}
}
/// <summary>
/// 写入启动/停止寄存器 M31已弃用请使用 TriggerTestStartAsync
/// M30 复归型, M31 标注为 1=开始0=停止

View File

@@ -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();
}
/// <summary>
@@ -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;
}
}
/// <summary>
/// 設置圖表控件由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)

View File

@@ -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">
<Window.Resources>
<Style x:Key="NavButtonStyle" TargetType="RadioButton">

View File

@@ -201,6 +201,7 @@
</Button.Style>
</Button>
<!-- 向右按钮 -->
<Button x:Name="BtnRight" Content="{Binding Lang.DirectionRight}"
Height="70" Width="100"
@@ -273,6 +274,15 @@
</Button>
<!-- 复位按钮 - 动态显示状态:复位 → 复位中 → 复位 -->
<Button Content="{Binding Lang.Stop}" Command="{Binding StopCommand}"
Height="70" Width="110" Margin="5">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource IndustrialButtonStyle}">
<Setter Property="Background" Value="#C0392B"/>
</Style>
</Button.Style>
</Button>
<Button Content="{Binding ResetButtonText}" Command="{Binding ResetCommand}"
Height="70" Width="110" Background="#3498DB"
Style="{StaticResource IndustrialButtonStyle}" Margin="5"/>