更新
This commit is contained in:
@@ -872,7 +872,6 @@
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Content="前进"
|
||||
Tag="SpeedTorqueForward"
|
||||
@@ -896,20 +895,16 @@
|
||||
LostTouchCapture="ManualMotionButton_LostTouchCapture"
|
||||
Margin="8,0,8,0" />
|
||||
<Button Grid.Column="2"
|
||||
Content="{Binding VentValveButtonText}"
|
||||
Command="{Binding VentValveCommand}"
|
||||
Margin="8,0,8,0" />
|
||||
<Button Grid.Column="3"
|
||||
Content="{Binding SpeedTorqueTestButtonText}"
|
||||
Command="{Binding StartSpeedTorqueCommand}"
|
||||
Style="{StaticResource StartButtonStyle}"
|
||||
Margin="8,0,8,0" />
|
||||
<Button Grid.Column="4"
|
||||
<Button Grid.Column="3"
|
||||
Content="停止"
|
||||
Command="{Binding StopSpeedTorqueCommand}"
|
||||
Style="{StaticResource StopButtonStyle}"
|
||||
Margin="8,0,8,0" />
|
||||
<Button Grid.Column="5"
|
||||
<Button Grid.Column="4"
|
||||
Content="{Binding SpeedTorqueResetButtonText}"
|
||||
Command="{Binding ResetSpeedTorqueCommand}"
|
||||
Margin="8,0,0,0" />
|
||||
|
||||
@@ -45,6 +45,7 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
private const ushort AxialDoneCoil = 72;
|
||||
private const ushort AxialStopCoil = 73;
|
||||
private const ushort SpeedTorqueStartCoil = 80;
|
||||
private const ushort SpeedTorqueEnabledCoil = 81;
|
||||
private const ushort SpeedTorqueDoneCoil = 82;
|
||||
private const ushort SpeedTorqueStopCoil = 83;
|
||||
private const ushort SpeedTorqueResetCoil = 90;
|
||||
@@ -56,6 +57,11 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
private const ushort AxialResetCoil = 95;
|
||||
private const ushort AxialResetEnabledCoil = 96;
|
||||
private const ushort AxialResetDoneCoil = 97;
|
||||
private const ushort AxialForceZeroCoil = 1100;
|
||||
private const ushort TorqueZeroCoil = 1101;
|
||||
private const ushort SpeedZeroCoil = 1300;
|
||||
private const ushort PressureZeroCoil = 1301;
|
||||
private const ushort SecondaryTorqueZeroCoil = 1302;
|
||||
private const ushort SpeedTorquePositionRegister = 14;
|
||||
private const ushort AxialPositionRegister = 16;
|
||||
private const ushort AxialSampleStartRegister = 72;
|
||||
@@ -208,7 +214,6 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
private bool _isApplyingParameterConfigToInputs;
|
||||
private bool _isDisplacementResetting;
|
||||
private bool _isSpeedTorqueResetting;
|
||||
private bool _isVentValveOpen;
|
||||
private bool _hasShownSpeedTorqueEndWarnings;
|
||||
private DateTime _lastParameterReadFailureLogAt = DateTime.MinValue;
|
||||
private string _dialIndicatorText = "0.000 mm";
|
||||
@@ -247,7 +252,6 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
private string _noLoadSpeedTestButtonText = "测试";
|
||||
private string _displacementResetButtonText = "复位";
|
||||
private string _speedTorqueResetButtonText = "复位";
|
||||
private string _ventValveButtonText = "开启通气阀";
|
||||
|
||||
public MainWindowViewModel(IPlcCoilService plcCoilService, IPlcRegisterService plcRegisterService, IFileDialogService fileDialogService)
|
||||
{
|
||||
@@ -271,7 +275,6 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
SelectAxialJumpForceSetpointModeCommand = new AsyncRelayCommand(SelectAxialJumpForceSetpointModeAsync);
|
||||
ForwardSpeedTorqueCommand = new AsyncRelayCommand(ForwardSpeedTorqueAsync);
|
||||
BackwardSpeedTorqueCommand = new AsyncRelayCommand(BackwardSpeedTorqueAsync);
|
||||
VentValveCommand = new AsyncRelayCommand(ToggleVentValveAsync);
|
||||
StartSpeedTorqueCommand = new AsyncRelayCommand(StartSpeedTorqueAsync);
|
||||
StopSpeedTorqueCommand = new AsyncRelayCommand(StopSpeedTorqueAsync);
|
||||
ResetSpeedTorqueCommand = new AsyncRelayCommand(ResetSpeedTorqueAsync);
|
||||
@@ -328,8 +331,6 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
|
||||
public IAsyncRelayCommand BackwardSpeedTorqueCommand { get; }
|
||||
|
||||
public IAsyncRelayCommand VentValveCommand { get; }
|
||||
|
||||
public IAsyncRelayCommand StartSpeedTorqueCommand { get; }
|
||||
|
||||
public IAsyncRelayCommand StopSpeedTorqueCommand { get; }
|
||||
@@ -690,12 +691,6 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
private set => SetProperty(ref _speedTorqueResetButtonText, value);
|
||||
}
|
||||
|
||||
public string VentValveButtonText
|
||||
{
|
||||
get => _ventValveButtonText;
|
||||
private set => SetProperty(ref _ventValveButtonText, value);
|
||||
}
|
||||
|
||||
private async void RealtimeTimer_Tick(object? sender, EventArgs e)
|
||||
{
|
||||
if (_isReadingRealtime)
|
||||
@@ -732,7 +727,13 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
_realtimeSpeed = realtimeSpeed;
|
||||
AppendTorqueSample(GetScaledTorque(), DateTime.Now);
|
||||
ApplyResetCoilValues(coilValues);
|
||||
UpdateVentValveState(ReadCoilValue(coilValues, VentValveCoil));
|
||||
bool isVentValveOpen = ReadCoilValue(coilValues, VentValveCoil);
|
||||
if (_isSpeedTorqueRunning && !isVentValveOpen)
|
||||
{
|
||||
Log.Error("转速/扭矩测试运行中检测到通气阀关闭,M{VentValveCoil}=0,立即停止测试", VentValveCoil);
|
||||
await AutoStopSpeedTorqueAsync("状态:通气阀关闭保护,已停止");
|
||||
}
|
||||
|
||||
CaptureRealtimeSample(dialIndicator, coilValues);
|
||||
FinalizeNoLoadSpeedRunIfDue();
|
||||
QueueSnapshotIfDue();
|
||||
@@ -2097,28 +2098,49 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
await MoveSpeedTorqueDisplacementAsync();
|
||||
}
|
||||
|
||||
private async Task ToggleVentValveAsync()
|
||||
private async Task<bool> WriteAndVerifyVentValveStateAsync(bool targetState, string reason)
|
||||
{
|
||||
try
|
||||
{
|
||||
PlcConnectionConfig config = _parameterConfig.ToPlcConnectionConfig();
|
||||
await _plcCoilService.WriteCoilAsync(config, VentValveCoil, targetState);
|
||||
await Task.Delay(100);
|
||||
|
||||
IReadOnlyDictionary<ushort, bool> values = await _plcCoilService.ReadCoilValuesAsync(
|
||||
_parameterConfig.ToPlcConnectionConfig(),
|
||||
[VentValveCoil]);
|
||||
bool targetState = !ReadCoilValue(values, VentValveCoil);
|
||||
config,
|
||||
[VentValveCoil, SpeedTorqueEnabledCoil]);
|
||||
bool actualState = ReadCoilValue(values, VentValveCoil);
|
||||
bool speedTorqueEnabled = ReadCoilValue(values, SpeedTorqueEnabledCoil);
|
||||
if (actualState != targetState)
|
||||
{
|
||||
StatusText = targetState
|
||||
? "通气阀未能保持开启,已阻止测试启动。"
|
||||
: "通气阀未能关闭,请检查 PLC 状态。";
|
||||
Log.Error(
|
||||
"PLC通气阀状态校验失败:原因 {Reason},要求 M{VentValveCoil}={Expected},实际 {Actual},扭矩使能 M{EnabledCoil}={Enabled}",
|
||||
reason,
|
||||
VentValveCoil,
|
||||
targetState ? 1 : 0,
|
||||
actualState ? 1 : 0,
|
||||
SpeedTorqueEnabledCoil,
|
||||
speedTorqueEnabled ? 1 : 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
await _plcCoilService.WriteCoilAsync(
|
||||
_parameterConfig.ToPlcConnectionConfig(),
|
||||
Log.Information(
|
||||
"PLC通气阀状态校验成功:原因 {Reason},M{VentValveCoil}={Value},扭矩使能 M{EnabledCoil}={Enabled}",
|
||||
reason,
|
||||
VentValveCoil,
|
||||
targetState);
|
||||
|
||||
UpdateVentValveState(targetState);
|
||||
StatusText = targetState ? "通气阀已开启。" : "通气阀已关闭。";
|
||||
Log.Information("PLC常开触点开关成功:通气阀,M{CoilAddress}={Value}", VentValveCoil, targetState ? 1 : 0);
|
||||
actualState ? 1 : 0,
|
||||
SpeedTorqueEnabledCoil,
|
||||
speedTorqueEnabled ? 1 : 0);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
StatusText = $"PLC 通气阀开关失败:{OperatorMessageFormatter.FromException(ex)}";
|
||||
Log.Error(ex, "PLC常开触点开关失败:通气阀,M{CoilAddress}", VentValveCoil);
|
||||
StatusText = $"PLC 通气阀状态确认失败:{OperatorMessageFormatter.FromException(ex)}";
|
||||
Log.Error(ex, "PLC通气阀状态确认失败:原因 {Reason},M{VentValveCoil}", reason, VentValveCoil);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2338,13 +2360,46 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
return;
|
||||
}
|
||||
|
||||
SpeedTorqueTestButtonText = "归零中";
|
||||
StatusText = "转速/扭矩测试启动前归零中。";
|
||||
if (!await ExecuteZeroingSequenceAsync(
|
||||
"转速/扭矩测试",
|
||||
(TorqueZeroCoil, "扭矩归零 M1101"),
|
||||
(SpeedZeroCoil, "转速归零 M1300"),
|
||||
(PressureZeroCoil, "压力归零 M1301"),
|
||||
(SecondaryTorqueZeroCoil, "扭矩归零 M1302")))
|
||||
{
|
||||
SpeedTorqueTestButtonText = "测试";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!await WriteAndVerifyVentValveStateAsync(true, "转速/扭矩测试启动前"))
|
||||
{
|
||||
SpeedTorqueTestButtonText = "测试";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!await PulsePlcAsync(SpeedTorqueStartCoil, "转速/扭矩测试"))
|
||||
{
|
||||
await WriteAndVerifyVentValveStateAsync(false, "转速/扭矩测试启动失败");
|
||||
SpeedTorqueTestButtonText = "测试";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!await WriteAndVerifyVentValveStateAsync(true, "转速/扭矩测试启动后"))
|
||||
{
|
||||
await PulsePlcAsync(SpeedTorqueStopCoil, "通气阀未保持开启,停止转速/扭矩测试");
|
||||
await WriteAndVerifyVentValveStateAsync(false, "转速/扭矩测试启动后校验失败");
|
||||
StatusText = "测试启动后通气阀未保持开启,已发送停止指令。";
|
||||
SpeedTorqueTestButtonText = "测试";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryGetRealtimeSpeed(out _) || !TryGetRealtimeTorque(out _))
|
||||
{
|
||||
await PulsePlcAsync(SpeedTorqueStopCoil, "实时数据无效,停止转速/扭矩测试");
|
||||
await WriteAndVerifyVentValveStateAsync(false, "转速/扭矩测试启动数据无效");
|
||||
SpeedTorqueTestButtonText = "测试";
|
||||
UpdateSpeedTorqueDisplay();
|
||||
return;
|
||||
}
|
||||
@@ -2362,7 +2417,13 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
AppendTorqueSample(GetScaledTorque(), _speedTorqueStartedAt.Value);
|
||||
_maxSpeedTorqueDisplacement = Math.Max(_maxSpeedTorqueDisplacement, Math.Abs(_speedTorqueDisplacement));
|
||||
UpdateSpeedTorqueDisplay();
|
||||
Log.Information("转速/扭矩测试已启动,起始转速 {Speed},起始扭矩 {Torque},起始位移 {Displacement}", _realtimeSpeed, GetScaledTorque(), _speedTorqueDisplacement);
|
||||
Log.Information(
|
||||
"转速/扭矩测试已启动,通气阀 M{VentValveCoil}=1,启动 M{StartCoil}已触发,起始转速 {Speed},起始扭矩 {Torque},起始位移 {Displacement}",
|
||||
VentValveCoil,
|
||||
SpeedTorqueStartCoil,
|
||||
_realtimeSpeed,
|
||||
GetScaledTorque(),
|
||||
_speedTorqueDisplacement);
|
||||
await AutoStopIfSpeedTorqueProtectionReachedAsync();
|
||||
}
|
||||
|
||||
@@ -2415,6 +2476,7 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
_hasShownSpeedTorqueEndWarnings = false;
|
||||
ClearTorqueSamples();
|
||||
UpdateSpeedTorqueDisplay();
|
||||
await WriteAndVerifyVentValveStateAsync(false, "转速/扭矩复位");
|
||||
Log.Information("转速/扭矩复位完成,零点 {ZeroPosition}", _speedTorqueZero);
|
||||
}
|
||||
finally
|
||||
@@ -2452,13 +2514,26 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
return;
|
||||
}
|
||||
|
||||
DisplacementTestButtonText = "归零中";
|
||||
StatusText = "轴向测试启动前归零中。";
|
||||
if (!await ExecuteZeroingSequenceAsync(
|
||||
"轴向测试",
|
||||
(AxialForceZeroCoil, "轴向力归零 M1100")))
|
||||
{
|
||||
DisplacementTestButtonText = "测试";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!await PulsePlcAsync(AxialStartCoil, "轴向测试"))
|
||||
{
|
||||
DisplacementTestButtonText = "测试";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryGetDialValue(out _) || !TryGetAxialForceValue(out _))
|
||||
{
|
||||
await PulsePlcAsync(AxialStopCoil, "实时数据无效,停止轴向测试");
|
||||
DisplacementTestButtonText = "测试";
|
||||
UpdateDisplacementDisplay();
|
||||
return;
|
||||
}
|
||||
@@ -2589,6 +2664,32 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> ExecuteZeroingSequenceAsync(
|
||||
string testName,
|
||||
params (ushort CoilAddress, string ActionName)[] zeroingActions)
|
||||
{
|
||||
foreach ((ushort coilAddress, string actionName) in zeroingActions)
|
||||
{
|
||||
if (!await PulsePlcAsync(coilAddress, actionName))
|
||||
{
|
||||
StatusText = $"{testName}启动已阻止:{actionName}失败。";
|
||||
Log.Error(
|
||||
"{TestName}启动前归零失败,停止启动序列,失败点位 M{CoilAddress},动作 {ActionName}",
|
||||
testName,
|
||||
coilAddress,
|
||||
actionName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
StatusText = $"{testName}归零完成,正在启动测试。";
|
||||
Log.Information(
|
||||
"{TestName}启动前归零序列完成,点位 {ZeroingCoils}",
|
||||
testName,
|
||||
string.Join(", ", zeroingActions.Select(static action => $"M{action.CoilAddress}")));
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<bool> BeginAxialManualMotionAsync(ushort coilAddress, string actionName)
|
||||
{
|
||||
if (!await WriteManualMotionCoilAsync(coilAddress, true, $"{actionName}按下"))
|
||||
@@ -2822,6 +2923,9 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
{
|
||||
if (!TryGetRealtimeSpeed(out double speed) || !TryGetRealtimeTorque(out double torque))
|
||||
{
|
||||
_isSpeedTorqueRunning = false;
|
||||
SpeedTorqueTestButtonText = "测试";
|
||||
await WriteAndVerifyVentValveStateAsync(false, "转速/扭矩测试结束数据无效");
|
||||
UpdateSpeedTorqueDisplay();
|
||||
return;
|
||||
}
|
||||
@@ -2837,6 +2941,11 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
PersistCurrentPayloadSnapshot("转速/扭矩测试停止");
|
||||
UpdateSpeedTorqueDisplay();
|
||||
Log.Information("转速/扭矩测试停止:{Status},最终位移 {FinalDisplacement},最终转速 {FinalSpeed},最终扭矩 {FinalTorque}", status, _finalSpeedTorqueDisplacement, _finalSpeed, _finalTorque);
|
||||
if (!await WriteAndVerifyVentValveStateAsync(false, "转速/扭矩测试结束"))
|
||||
{
|
||||
StatusText = "测试已停止,但通气阀关闭状态未确认,请检查设备。";
|
||||
}
|
||||
|
||||
await ShowSpeedTorqueEndWarningsAsync();
|
||||
}
|
||||
|
||||
@@ -2926,12 +3035,6 @@ public sealed class MainWindowViewModel : ObservableObject
|
||||
SpeedTorqueResetButtonText = _isSpeedTorqueResetting || enabled ? "复位中" : "复位";
|
||||
}
|
||||
|
||||
private void UpdateVentValveState(bool isOpen)
|
||||
{
|
||||
_isVentValveOpen = isOpen;
|
||||
VentValveButtonText = _isVentValveOpen ? "关闭通气阀" : "开启通气阀";
|
||||
}
|
||||
|
||||
private static bool ReadCoilValue(IReadOnlyDictionary<ushort, bool> coilValues, ushort address)
|
||||
{
|
||||
return coilValues.TryGetValue(address, out bool value) && value;
|
||||
|
||||
Reference in New Issue
Block a user