This commit is contained in:
@@ -17,8 +17,7 @@ namespace MembranePoreTester.Communication
|
||||
public ushort WetFlowRegister { get; set; } // 湿膜流量寄存器起始地址
|
||||
public ushort DryFlowRegister { get; set; } // 干膜流量寄存器起始地址
|
||||
public double PressureFactor { get; set; } = 1.0; // 压力系数(单位换算)
|
||||
public double WetFlowFactor { get; set; } = 1.0; // 湿膜流量系数
|
||||
public double DryFlowFactor { get; set; } = 1.0; // 干膜流量系数
|
||||
|
||||
|
||||
// ========== 工位专用寄存器 ==========
|
||||
public ushort PressureRegisterStation1 { get; set; } // 工位1 压力寄存器起始地址
|
||||
@@ -35,7 +34,6 @@ namespace MembranePoreTester.Communication
|
||||
// ========== 运维参数(用户可设置) ==========
|
||||
public ushort PressureUpperLimit { get; set; } = 300; // 加压上限 D300
|
||||
public ushort PressureRate { get; set; } = 280; // 加压速率 D280
|
||||
public ushort PressureCoeff { get; set; } = 282; // 加压系数 D282
|
||||
|
||||
// 高压/低压系数(每个工位独立)
|
||||
public ushort HPCoeff1 { get; set; } = 3120; // 工位1 高压系数
|
||||
@@ -56,15 +54,29 @@ namespace MembranePoreTester.Communication
|
||||
// 流量模式选择寄存器(0=大流量,1=小流量)
|
||||
|
||||
public ushort FlowModeRegister { get; set; } = 4; // 工位1 流量模式
|
||||
public ushort FlowModeRegister1 { get; set; } = 5; // 工位1 流量模式
|
||||
public ushort FlowModeRegister2 { get; set; } = 6;
|
||||
public ushort FlowModeRegister3 { get; set; } = 7;
|
||||
|
||||
// 校准系数(零点/量程)寄存器地址
|
||||
public ushort PressureCalibZero { get; set; } = 3200; // 压力零点系数
|
||||
public ushort PressureCalibSpan { get; set; } = 3202; // 压力量程系数
|
||||
public ushort FlowCalibZero { get; set; } = 3204; // 流量零点系数
|
||||
public ushort FlowCalibSpan { get; set; } = 3206; // 流量量程系数
|
||||
|
||||
|
||||
|
||||
|
||||
public ushort High1 { get; set; } // 工位1
|
||||
public ushort High2 { get; set; } // 工位1
|
||||
public ushort High3 { get; set; } // 工位1
|
||||
public ushort Low1 { get; set; } // 工位1
|
||||
public ushort Low2 { get; set; } // 工位1
|
||||
public ushort Low3 { get; set; } // 工位1
|
||||
|
||||
|
||||
|
||||
|
||||
public ushort SmallFlow1 { get; set; } // 工位1
|
||||
public ushort SmallFlow2 { get; set; } // 工位1
|
||||
public ushort SmallFlow3 { get; set; } // 工位1
|
||||
public ushort BigFlow1 { get; set; } // 工位1
|
||||
public ushort BigFlow2 { get; set; } // 工位1
|
||||
public ushort BigFlow3 { get; set; } // 工位1
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -55,6 +55,7 @@ namespace MembranePoreTester.Communication
|
||||
public async Task WriteRegisterAsync(ushort registerAddress, ushort value)
|
||||
{
|
||||
await EnsureConnectedAsync();
|
||||
await Task.Delay(100);
|
||||
await _master.WriteSingleRegisterAsync(_config.SlaveId, registerAddress, value);
|
||||
}
|
||||
|
||||
@@ -62,6 +63,7 @@ namespace MembranePoreTester.Communication
|
||||
public async Task<bool> ReadCoilAsync(ushort coilAddress)
|
||||
{
|
||||
await EnsureConnectedAsync();
|
||||
await Task.Delay(100);
|
||||
bool[] result = await _master?.ReadCoilsAsync(_config.SlaveId, coilAddress, 1);
|
||||
return result[0];
|
||||
}
|
||||
@@ -70,6 +72,7 @@ namespace MembranePoreTester.Communication
|
||||
public async Task<ushort[]> ReadHoldingRegistersAsync(ushort startAddress, ushort count)
|
||||
{
|
||||
await EnsureConnectedAsync();
|
||||
await Task.Delay(100);
|
||||
return await _master.ReadHoldingRegistersAsync(_config.SlaveId, startAddress, count);
|
||||
}
|
||||
|
||||
@@ -77,12 +80,14 @@ namespace MembranePoreTester.Communication
|
||||
{
|
||||
await EnsureConnectedAsync();
|
||||
int val = (int)value;
|
||||
await Task.Delay(100);
|
||||
await _master.WriteMultipleRegistersAsync(1, registerAddress, intToushorts(val));
|
||||
}
|
||||
|
||||
public async Task WriteMultipleRegistersAsync(ushort registerAddress, float value)
|
||||
{
|
||||
await EnsureConnectedAsync();
|
||||
await Task.Delay(100);
|
||||
await _master.WriteMultipleRegistersAsync(_config.SlaveId, registerAddress, SplitFloatToUShortArray((float)value));
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +86,7 @@ namespace MembranePoreTester.ViewModels
|
||||
public ICommand GenerateReportCommand { get; }
|
||||
|
||||
public ICommand OpenPressureCalibCommand { get; }
|
||||
public ICommand OpenPressureCalibCommand2 { get; }
|
||||
|
||||
|
||||
|
||||
@@ -107,21 +108,28 @@ namespace MembranePoreTester.ViewModels
|
||||
SaveCommand = new RelayCommand(SaveToDatabase);
|
||||
ExportCommand = new RelayCommand(ExportToExcel);
|
||||
OpenPressureCalibCommand = new RelayCommand(OpenPressureCalibration);
|
||||
|
||||
OpenPressureCalibCommand2 = new RelayCommand(OpenPressureCalibration2);
|
||||
|
||||
|
||||
// 启动定时器,每秒读取一次
|
||||
_timer = new System.Windows.Threading.DispatcherTimer();
|
||||
_timer.Interval = TimeSpan.FromSeconds(1);
|
||||
_timer.Tick += async (s, e) => await ReadCurrentPlcAsync();
|
||||
_timer.Tick += async (s, e) =>
|
||||
{
|
||||
if (StationId > 0 && !IsDisposed)
|
||||
{
|
||||
await ReadCurrentPlcAsync();
|
||||
}
|
||||
};
|
||||
_timer.Start();
|
||||
|
||||
// 立即读取一次
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await ReadCurrentPlcAsync();
|
||||
}
|
||||
);
|
||||
//// 立即读取一次
|
||||
//Task.Run(async () =>
|
||||
//{
|
||||
// await Task.Delay(1000); // 等待2秒确保PLC连接稳定
|
||||
// await ReadCurrentPlcAsync();
|
||||
//}
|
||||
//);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
@@ -137,32 +145,29 @@ namespace MembranePoreTester.ViewModels
|
||||
|
||||
private async Task ReadCurrentPlcAsync()
|
||||
{
|
||||
try
|
||||
await SafeExecuteAsync("ReadCurrentPressure", async () =>
|
||||
{
|
||||
if (IsDisposed || _plcService == null) return;
|
||||
|
||||
await Task.Delay(100); // 小延迟避免过快读取
|
||||
float rawPressure = await _plcService.ReadPressureAsync(StationId);
|
||||
Record.BubbleCurrentPressure =Math.Round( rawPressure,2);
|
||||
Record.BubbleCurrentPressure = Math.Round(rawPressure, 2);
|
||||
OnPropertyChanged(nameof(Record.BubbleCurrentPressure));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"读取PLC失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private async Task ReadPlcAsync()
|
||||
{
|
||||
if (IsDisposed) return; // 改3:添加这行检查
|
||||
try
|
||||
{
|
||||
Record.BubblePointPressure = Record.BubbleCurrentPressure;
|
||||
if (IsDisposed) return;
|
||||
|
||||
Record.BubblePointPressure = Record.BubbleCurrentPressure;
|
||||
|
||||
OnPropertyChanged(nameof(Record.BubblePointPressure));
|
||||
|
||||
|
||||
OnPropertyChanged(nameof(Record.BubblePointPressure));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"读取PLC失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -248,18 +253,58 @@ namespace MembranePoreTester.ViewModels
|
||||
|
||||
private void OpenPressureCalibration()
|
||||
{
|
||||
// 使用简单的输入框获取新零点系数和量程系数
|
||||
string zeroStr = Microsoft.VisualBasic.Interaction.InputBox("请输入压力零点系数", "压力校准", "0");
|
||||
string spanStr = Microsoft.VisualBasic.Interaction.InputBox("请输入压力量程系数", "压力校准", "1");
|
||||
if (float.TryParse(zeroStr, out float zero) && float.TryParse(spanStr, out float span))
|
||||
ushort address = new ushort();
|
||||
switch (StationId)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await WriteFloatAsync(_plcConfig.PressureCalibZero, zero);
|
||||
await WriteFloatAsync(_plcConfig.PressureCalibSpan, span);
|
||||
MessageBox.Show("压力校准系数已写入", "完成");
|
||||
});
|
||||
case 1:
|
||||
{
|
||||
address = _plcConfig.High1;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
address = _plcConfig.High2;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
address = _plcConfig.High3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await _plcService.WriteCoilAsync(address, true);
|
||||
});
|
||||
}
|
||||
|
||||
private void OpenPressureCalibration2()
|
||||
{
|
||||
ushort address = new ushort();
|
||||
switch (StationId)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
address = _plcConfig.Low1;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
address = _plcConfig.Low2;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
address = _plcConfig.Low3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await _plcService.WriteCoilAsync(address, true);
|
||||
});
|
||||
}
|
||||
|
||||
private void ExportToExcel()
|
||||
|
||||
@@ -165,22 +165,25 @@ namespace MembranePoreTester.ViewModels
|
||||
}
|
||||
private async Task ReadPressureModeAsync()
|
||||
{
|
||||
try
|
||||
await SafeExecuteAsync($"ReadPressureModeAsync{StationId}", async () =>
|
||||
{
|
||||
ushort[] values = await _plcService.ReadHoldingRegistersAsync(_plcConfig.PressureModeRegister, 1);
|
||||
ushort val = values[0];
|
||||
string newValue = val == 0 ? "高压" : "低压";
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
try
|
||||
{
|
||||
// 更新选中项
|
||||
HighLowPressure = newValue;
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"读取压力模式失败: {ex.Message}");
|
||||
}
|
||||
ushort[] values = await _plcService.ReadHoldingRegistersAsync(_plcConfig.PressureModeRegister, 1);
|
||||
ushort val = values[0];
|
||||
string newValue = val == 0 ? "高压" : "低压";
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
// 更新选中项
|
||||
HighLowPressure = newValue;
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"读取压力模式失败: {ex.Message}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async Task TogglePressAsync()
|
||||
@@ -204,33 +207,38 @@ namespace MembranePoreTester.ViewModels
|
||||
MessageBox.Show($"读取加压状态失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
// 在 StationItem 类中添加字段
|
||||
private bool _lastEnableReadFailed = false;
|
||||
private DateTime _lastEnableErrorTime = DateTime.MinValue;
|
||||
private async Task ReadEnableStatusAsync()
|
||||
{
|
||||
try
|
||||
await SafeExecuteAsync($"ReadEnableStatus_Station{StationId}", async () =>
|
||||
{
|
||||
bool status = await _plcService.ReadCoilAsync(_plcConfig.EnableCoil); // 读取 M21
|
||||
EnableStatus = status;
|
||||
|
||||
|
||||
bool pressStatus = await _plcService.ReadCoilAsync(_plcConfig.PressCoil);//这里也要更新加压的按钮状态
|
||||
|
||||
_isPressing = pressStatus;
|
||||
|
||||
// 在UI线程更新按钮文字
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
try
|
||||
{
|
||||
PressButtonText = pressStatus ? "停止加压" : "加压";
|
||||
});
|
||||
bool status = await _plcService.ReadCoilAsync(_plcConfig.EnableCoil); // 读取 M21
|
||||
EnableStatus = status;
|
||||
|
||||
|
||||
bool pressStatus = await _plcService.ReadCoilAsync(_plcConfig.PressCoil);//这里也要更新加压的按钮状态
|
||||
|
||||
_isPressing = pressStatus;
|
||||
|
||||
// 在UI线程更新按钮文字
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
PressButtonText = pressStatus ? "停止加压" : "加压";
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 读取出错时保持原状态或显示错误
|
||||
System.Diagnostics.Debug.WriteLine($"读取使能状态失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 读取出错时保持原状态或显示错误
|
||||
System.Diagnostics.Debug.WriteLine($"读取使能状态失败: {ex.Message}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async Task WriteCoilAsync(ushort coil, bool value)
|
||||
@@ -283,7 +291,7 @@ namespace MembranePoreTester.ViewModels
|
||||
|
||||
public MainViewModel()
|
||||
{
|
||||
for (int i = 1; i <= 1; i++)
|
||||
for (int i = 1; i <= 3; i++)
|
||||
{
|
||||
var station = new StationItem
|
||||
{
|
||||
|
||||
@@ -92,53 +92,56 @@ namespace MembranePoreTester.ViewModels
|
||||
private async void AutoCollectTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
if (!IsActive) return; // 不在当前标签页,跳过采集
|
||||
try
|
||||
await SafeExecuteAsync($"AutoCollect_Station{StationId}", async () =>
|
||||
{
|
||||
// 1. 读取当前压力
|
||||
float rawPressure = await _plcService.ReadPressureAsync(StationId);
|
||||
double pressure = Math.Round(rawPressure,2);
|
||||
try
|
||||
{
|
||||
// 1. 读取当前压力
|
||||
float rawPressure = await _plcService.ReadPressureAsync(StationId);
|
||||
double pressure = Math.Round(rawPressure, 2);
|
||||
|
||||
double flow = 0;
|
||||
if (TestMode == "湿膜")
|
||||
{
|
||||
float rawFlow = await _plcService.ReadWetFlowAsync();
|
||||
flow = rawFlow;
|
||||
}
|
||||
else
|
||||
{
|
||||
float rawFlow = await _plcService.ReadDryFlowAsync();
|
||||
flow = rawFlow;
|
||||
}
|
||||
|
||||
flow = Math.Round(flow,2);
|
||||
// 3. 在 DataPoints 中查找是否存在相同压力的行(允许微小误差)
|
||||
var existing = Record.DataPoints.FirstOrDefault(p => Math.Abs(p.Pressure - pressure) < 0.001);
|
||||
if (existing != null)
|
||||
{
|
||||
// 更新对应列
|
||||
double flow = 0;
|
||||
if (TestMode == "湿膜")
|
||||
existing.WetFlow = flow;
|
||||
{
|
||||
float rawFlow = await _plcService.ReadWetFlowAsync();
|
||||
flow = rawFlow;
|
||||
}
|
||||
else
|
||||
existing.DryFlow = flow;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 新增一行
|
||||
var newPoint = new Models.DataPoint { Pressure = pressure };
|
||||
if (TestMode == "湿膜")
|
||||
newPoint.WetFlow = flow;
|
||||
else
|
||||
newPoint.DryFlow = flow;
|
||||
Record.DataPoints.Add(newPoint);
|
||||
}
|
||||
{
|
||||
float rawFlow = await _plcService.ReadDryFlowAsync();
|
||||
flow = rawFlow;
|
||||
}
|
||||
|
||||
// 4. 刷新曲线
|
||||
UpdatePlot();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"自动采集失败: {ex.Message}");
|
||||
}
|
||||
flow = Math.Round(flow, 2);
|
||||
// 3. 在 DataPoints 中查找是否存在相同压力的行(允许微小误差)
|
||||
var existing = Record.DataPoints.FirstOrDefault(p => Math.Abs(p.Pressure - pressure) < 0.001);
|
||||
if (existing != null)
|
||||
{
|
||||
// 更新对应列
|
||||
if (TestMode == "湿膜")
|
||||
existing.WetFlow = flow;
|
||||
else
|
||||
existing.DryFlow = flow;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 新增一行
|
||||
var newPoint = new Models.DataPoint { Pressure = pressure };
|
||||
if (TestMode == "湿膜")
|
||||
newPoint.WetFlow = flow;
|
||||
else
|
||||
newPoint.DryFlow = flow;
|
||||
Record.DataPoints.Add(newPoint);
|
||||
}
|
||||
|
||||
// 4. 刷新曲线
|
||||
UpdatePlot();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"自动采集失败: {ex.Message}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -278,7 +281,7 @@ namespace MembranePoreTester.ViewModels
|
||||
SaveCommand = new RelayCommand(SaveToDatabase);
|
||||
ExportCommand = new RelayCommand(ExportToExcel);
|
||||
OpenFlowCalibCommand = new RelayCommand(OpenFlowCalibration);
|
||||
|
||||
OpenFlowCalibCommand2 = new RelayCommand(OpenFlowCalibration2);
|
||||
|
||||
Record.DataPoints.CollectionChanged += (s, e) => UpdatePlot();
|
||||
|
||||
@@ -294,22 +297,25 @@ namespace MembranePoreTester.ViewModels
|
||||
|
||||
private async Task ReadPressureModeAsync()
|
||||
{
|
||||
try
|
||||
await SafeExecuteAsync($"ReadPressureModeAsync{StationId}", async () =>
|
||||
{
|
||||
ushort[] values = await _plcService.ReadHoldingRegistersAsync(_plcConfig.FlowModeRegister, 1);
|
||||
ushort val = values[0];
|
||||
string newValue = val == 0 ? "大流量" : "小流量";
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
try
|
||||
{
|
||||
// 更新选中项
|
||||
HighLowPressure = newValue;
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"读取流量模式失败: {ex.Message}");
|
||||
}
|
||||
ushort[] values = await _plcService.ReadHoldingRegistersAsync(_plcConfig.FlowModeRegister, 1);
|
||||
ushort val = values[0];
|
||||
string newValue = val == 0 ? "大流量" : "小流量";
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
// 更新选中项
|
||||
HighLowPressure = newValue;
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"读取流量模式失败: {ex.Message}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public string HighLowPressure
|
||||
@@ -327,11 +333,12 @@ namespace MembranePoreTester.ViewModels
|
||||
|
||||
private async Task ReadPlcAsync()
|
||||
{
|
||||
try
|
||||
await SafeExecuteAsync($"ManualRead_Station{StationId}", async () =>
|
||||
{
|
||||
|
||||
// 始终读取压力
|
||||
float rawPressure = await _plcService.ReadPressureAsync(StationId);
|
||||
double pressure = rawPressure * _plcConfig.PressureFactor;
|
||||
double pressure = rawPressure;
|
||||
|
||||
if (SelectedDataPoint != null)
|
||||
{
|
||||
@@ -340,12 +347,12 @@ namespace MembranePoreTester.ViewModels
|
||||
if (TestMode == "湿膜")
|
||||
{
|
||||
float rawWet = await _plcService.ReadWetFlowAsync();
|
||||
SelectedDataPoint.WetFlow = rawWet * _plcConfig.WetFlowFactor;
|
||||
SelectedDataPoint.WetFlow = rawWet;
|
||||
}
|
||||
else
|
||||
{
|
||||
float rawDry = await _plcService.ReadDryFlowAsync();
|
||||
SelectedDataPoint.DryFlow = rawDry * _plcConfig.DryFlowFactor;
|
||||
SelectedDataPoint.DryFlow = rawDry;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -355,20 +362,19 @@ namespace MembranePoreTester.ViewModels
|
||||
if (TestMode == "湿膜")
|
||||
{
|
||||
float rawWet = await _plcService.ReadWetFlowAsync();
|
||||
newPoint.WetFlow = rawWet * _plcConfig.WetFlowFactor;
|
||||
newPoint.WetFlow = rawWet;
|
||||
}
|
||||
else
|
||||
{
|
||||
float rawDry = await _plcService.ReadDryFlowAsync();
|
||||
newPoint.DryFlow = rawDry * _plcConfig.DryFlowFactor;
|
||||
newPoint.DryFlow = rawDry;
|
||||
}
|
||||
Record.DataPoints.Add(newPoint);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"读取PLC失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void AddDataPoint()
|
||||
@@ -422,17 +428,58 @@ namespace MembranePoreTester.ViewModels
|
||||
|
||||
private void OpenFlowCalibration()
|
||||
{
|
||||
string zeroStr = Microsoft.VisualBasic.Interaction.InputBox("请输入流量零点系数", "流量校准", "0");
|
||||
string spanStr = Microsoft.VisualBasic.Interaction.InputBox("请输入流量量程系数", "流量校准", "1");
|
||||
if (float.TryParse(zeroStr, out float zero) && float.TryParse(spanStr, out float span))
|
||||
ushort address = new ushort();
|
||||
switch (StationId)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await WriteFloatAsync(_plcConfig.FlowCalibZero, zero);
|
||||
await WriteFloatAsync(_plcConfig.FlowCalibSpan, span);
|
||||
MessageBox.Show("流量校准系数已写入", "完成");
|
||||
});
|
||||
case 1:
|
||||
{
|
||||
address = _plcConfig.BigFlow1;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
address = _plcConfig.BigFlow2;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
address = _plcConfig.BigFlow3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await _plcService.WriteCoilAsync(address, true);
|
||||
});
|
||||
}
|
||||
|
||||
private void OpenFlowCalibration2()
|
||||
{
|
||||
ushort address = new ushort();
|
||||
switch (StationId)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
address = _plcConfig.SmallFlow1;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
address = _plcConfig.SmallFlow2;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
address = _plcConfig.SmallFlow3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await _plcService.WriteCoilAsync(address, true);
|
||||
});
|
||||
}
|
||||
|
||||
private int _stationId;
|
||||
@@ -514,6 +561,8 @@ namespace MembranePoreTester.ViewModels
|
||||
|
||||
|
||||
public ICommand OpenFlowCalibCommand { get; }
|
||||
|
||||
public ICommand OpenFlowCalibCommand2 { get; }
|
||||
public ICommand ExportCommand { get; }
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using MembranePoreTester.Communication;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace MembranePoreTester.ViewModels
|
||||
@@ -58,6 +59,75 @@ namespace MembranePoreTester.ViewModels
|
||||
new System.Windows.DependencyObject());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ========== 错误抑制机制 ==========
|
||||
private class ErrorRecord
|
||||
{
|
||||
public bool HasError { get; set; }
|
||||
public DateTime LastErrorTime { get; set; }
|
||||
}
|
||||
|
||||
private readonly Dictionary<string, ErrorRecord> _errorRecords = new();
|
||||
|
||||
/// <summary>
|
||||
/// 安全执行异步操作,自动抑制重复错误
|
||||
/// </summary>
|
||||
protected async Task<bool> SafeExecuteAsync(string operationKey, Func<Task> action, int suppressSeconds = 3)
|
||||
{
|
||||
// 检查是否需要抑制
|
||||
if (_errorRecords.TryGetValue(operationKey, out var record) && record.HasError)
|
||||
{
|
||||
if ((DateTime.Now - record.LastErrorTime).TotalSeconds < suppressSeconds)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await action();
|
||||
|
||||
// 成功,清除错误记录
|
||||
if (_errorRecords.TryGetValue(operationKey, out var successRecord))
|
||||
{
|
||||
successRecord.HasError = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 记录错误
|
||||
if (!_errorRecords.TryGetValue(operationKey, out var errorRecord))
|
||||
{
|
||||
errorRecord = new ErrorRecord();
|
||||
_errorRecords[operationKey] = errorRecord;
|
||||
}
|
||||
|
||||
errorRecord.HasError = true;
|
||||
errorRecord.LastErrorTime = DateTime.Now;
|
||||
|
||||
// 静默记录到输出窗口
|
||||
Debug.WriteLine($"[{DateTime.Now:HH:mm:ss}] {operationKey} 失败: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 新增:检查是否已释放
|
||||
protected bool IsDisposed => _disposed;
|
||||
|
||||
|
||||
@@ -94,7 +94,8 @@
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,10,0,0">
|
||||
<Button Content="⚙ 压力校准" Command="{Binding OpenPressureCalibCommand}" Padding="15,8" Background="#607D8B"/>
|
||||
<Button Content="⚙ 高压校准" Command="{Binding OpenPressureCalibCommand}" Padding="15,8" Background="#607D8B"/>
|
||||
<Button Content="⚙ 低压校准" Command="{Binding OpenPressureCalibCommand2}" Padding="15,8" Background="#607D8B"/>
|
||||
<Button Content="💾 保存到历史" Command="{Binding SaveCommand}" Padding="15,8" Background="#4CAF50"/>
|
||||
<Button Content="📄 生成报告" Command="{Binding GenerateReportCommand}" Padding="15,8" Background="#2196F3"/>
|
||||
<Button Content="📊 导出Excel" Command="{Binding ExportCommand}" Padding="15,8" Background="#FF9800"/>
|
||||
|
||||
@@ -147,6 +147,14 @@
|
||||
<Label Grid.Row="3" Grid.Column="0" Content="压力单位:"/>
|
||||
<ComboBox Grid.Row="3" Grid.Column="1" ItemsSource="{Binding PressureUnits}"
|
||||
SelectedItem="{Binding Record.PressureUnit}"/>
|
||||
|
||||
<Label Grid.Row="3" Grid.Column="2" Content="(干/湿膜)/(大/小流量):"/>
|
||||
<ComboBox HorizontalAlignment="Left" Grid.Row="3" Grid.Column="3" SelectedItem="{Binding TestMode}" Width="80">
|
||||
<ComboBoxItem Content="湿膜" IsSelected="True"/>
|
||||
<ComboBoxItem Content="干膜"/>
|
||||
</ComboBox>
|
||||
<ComboBox Grid.Row="3" HorizontalAlignment="Right" Grid.Column="3" ItemsSource="{Binding PressureModeList}"
|
||||
SelectedItem="{Binding SelectedPressureMode}" Width="100"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
@@ -158,91 +166,54 @@
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- 左侧数据表格 --><!--
|
||||
<GroupBox Grid.Column="0" Header="📊 压力-流量数据" Margin="0,0,5,0">
|
||||
<DockPanel>
|
||||
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="0,0,0,10">
|
||||
<Button Content="➕ 添加行" Command="{Binding AddDataPointCommand}" Background="#4CAF50"/>
|
||||
<Button Content="➖ 删除行" Command="{Binding RemoveDataPointCommand}" Background="#F44336"/>
|
||||
|
||||
|
||||
|
||||
<ComboBox SelectedItem="{Binding TestMode}" Width="80">
|
||||
<ComboBoxItem Content="湿膜" IsSelected="True"/>
|
||||
<ComboBoxItem Content="干膜"/>
|
||||
</ComboBox>
|
||||
<ComboBox ItemsSource="{Binding PressureModeList}"
|
||||
SelectedItem="{Binding SelectedPressureMode}" Width="100"/>
|
||||
|
||||
|
||||
--><!--<Button Content="📡 读取PLC" Command="{Binding ReadPlcCommand}" Background="#FF9800"/>--><!--
|
||||
</StackPanel>
|
||||
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="400">
|
||||
<DataGrid ItemsSource="{Binding Record.DataPoints}"
|
||||
AutoGenerateColumns="False"
|
||||
CanUserAddRows="False"
|
||||
ColumnWidth="*">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="压力"
|
||||
Binding="{Binding Pressure, UpdateSourceTrigger=PropertyChanged}"
|
||||
MinWidth="120"/>
|
||||
<DataGridTextColumn Header="湿膜流量(L/min)"
|
||||
Binding="{Binding WetFlow, UpdateSourceTrigger=PropertyChanged}"
|
||||
MinWidth="120"/>
|
||||
<DataGridTextColumn Header="干膜流量(L/min)"
|
||||
Binding="{Binding DryFlow, UpdateSourceTrigger=PropertyChanged}"
|
||||
MinWidth="120"/>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</ScrollViewer>
|
||||
</DockPanel>
|
||||
</GroupBox>-->
|
||||
|
||||
|
||||
<!-- 左侧数据表格区域,改为两列 Grid -->
|
||||
<Grid Grid.Column="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- 湿膜表格 -->
|
||||
<GroupBox Grid.Column="0" Header="💧 湿膜数据" Margin="0,0,5,0">
|
||||
<DataGrid ItemsSource="{Binding Record.DataPoints}"
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="400">
|
||||
|
||||
<Grid Grid.Column="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- 湿膜表格 -->
|
||||
<GroupBox Grid.Column="0" Header="💧 湿膜数据" Margin="0,0,5,0">
|
||||
<DataGrid ItemsSource="{Binding Record.DataPoints}"
|
||||
AutoGenerateColumns="False"
|
||||
CanUserAddRows="False"
|
||||
ColumnWidth="*">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="压力"
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="压力"
|
||||
Binding="{Binding Pressure, UpdateSourceTrigger=PropertyChanged}"
|
||||
MinWidth="100"/>
|
||||
<DataGridTextColumn Header="湿膜流量(L/min)"
|
||||
<DataGridTextColumn Header="湿膜流量(L/min)"
|
||||
Binding="{Binding WetFlow, UpdateSourceTrigger=PropertyChanged}"
|
||||
MinWidth="100"/>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</GroupBox>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</GroupBox>
|
||||
|
||||
<!-- 干膜表格 -->
|
||||
<GroupBox Grid.Column="1" Header="🔥 干膜数据" Margin="5,0,0,0">
|
||||
<DataGrid ItemsSource="{Binding Record.DataPoints}"
|
||||
<!-- 干膜表格 -->
|
||||
<GroupBox Grid.Column="1" Header="🔥 干膜数据" Margin="5,0,0,0">
|
||||
<DataGrid ItemsSource="{Binding Record.DataPoints}"
|
||||
AutoGenerateColumns="False"
|
||||
CanUserAddRows="False"
|
||||
ColumnWidth="*">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="压力"
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="压力"
|
||||
Binding="{Binding Pressure, UpdateSourceTrigger=PropertyChanged}"
|
||||
MinWidth="100"/>
|
||||
<DataGridTextColumn Header="干膜流量(L/min)"
|
||||
<DataGridTextColumn Header="干膜流量(L/min)"
|
||||
Binding="{Binding DryFlow, UpdateSourceTrigger=PropertyChanged}"
|
||||
MinWidth="100"/>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
|
||||
</ScrollViewer>
|
||||
<GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Center" Background="#E9ECF0"/>
|
||||
|
||||
<!-- 右侧曲线图 -->
|
||||
@@ -280,7 +251,8 @@
|
||||
</GroupBox>
|
||||
<Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" Margin="10,0"/>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="🔧 流量校准" Command="{Binding OpenFlowCalibCommand}" Background="#607D8B"/>
|
||||
<Button Content="🔧 大流量校准" Command="{Binding OpenFlowCalibCommand}" Background="#607D8B"/>
|
||||
<Button Content="🔧 小流量校准" Command="{Binding OpenFlowCalibCommand2}" Background="#607D8B"/>
|
||||
<Button Content="📄 生成报告" Command="{Binding GenerateReportCommand}" Background="#2196F3"/>
|
||||
<Button Content="💾 保存到历史" Command="{Binding SaveCommand}" Background="#4CAF50"/>
|
||||
<Button Content="📊 导出Excel" Command="{Binding ExportCommand}" Background="#FF9800"/>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
// 流量寄存器地址(每个工位共用,但需配合流量模式切换)
|
||||
"WetFlowRegister": 12, // 湿膜流量寄存器起始地址(D2~D3)
|
||||
"DryFlowRegister": 4, // 干膜流量寄存器起始地址(D4~D5)
|
||||
"DryFlowRegister": 12, // 干膜流量寄存器起始地址(D4~D5)
|
||||
"WetFlowFactor": 1.0, // 湿膜流量系数
|
||||
"DryFlowFactor": 1.0, // 干膜流量系数
|
||||
|
||||
@@ -56,10 +56,20 @@
|
||||
"FlowModeRegister2": 6, // 工位2 流量模式
|
||||
"FlowModeRegister3": 7, // 工位3 流量模式
|
||||
|
||||
// 校准系数(零点/量程)寄存器地址(约定,若PLC未分配可自定义)
|
||||
"PressureCalibZero": 3200, // 压力零点系数(D3200~D3201)
|
||||
"PressureCalibSpan": 3202, // 压力量程系数(D3202~D3203)
|
||||
"FlowCalibZero": 3204, // 流量零点系数(D3204~D3205)
|
||||
"FlowCalibSpan": 3206 // 流量量程系数(D3206~D3207)
|
||||
|
||||
"High1": 60, // M60
|
||||
"High2": 62, // M62
|
||||
"High3": 64, // M64
|
||||
"Low1": 61, //
|
||||
"Low2": 63, //
|
||||
"Low3": 65, //
|
||||
|
||||
"SmallFlow1": 40, // M60
|
||||
"SmallFlow2": 44, // M62
|
||||
"SmallFlow3": 47, // M64
|
||||
"BigFlow1": 49, //
|
||||
"BigFlow2": 42, //
|
||||
"BigFlow3": 46 //
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user