This commit is contained in:
@@ -33,12 +33,45 @@ namespace MembranePoreTester.Communication
|
||||
public ushort EnableCoil { get; set; } // 使能线圈(M21,只读状态)
|
||||
public ushort StopCoil { get; set; } // 停止线圈(M7)
|
||||
|
||||
|
||||
public ushort UpAndDown1 { get; set; } // 高压/低压模式寄存器
|
||||
|
||||
public ushort UpAndDown2 { get; set; } // 高压/低压模式寄存器
|
||||
|
||||
public ushort UpAndDown3 { get; set; } // 高压/低压模式寄存器
|
||||
|
||||
|
||||
public ushort StartCoil2 { get; set; } // 启动线圈(M20)
|
||||
public ushort EnableCoil2 { get; set; } // 使能线圈(M21,只读状态)
|
||||
public ushort StopCoil2 { get; set; } // 停止线圈(M7)
|
||||
|
||||
public ushort StartCoil3 { get; set; } // 启动线圈(M20)
|
||||
public ushort EnableCoil3 { get; set; } // 使能线圈(M21,只读状态)
|
||||
public ushort StopCoil3 { get; set; } // 停止线圈(M7)
|
||||
|
||||
|
||||
|
||||
|
||||
// ========== 运维参数(用户可设置) ==========
|
||||
public ushort PressureUpperLimit { get; set; } = 300; // 加压上限 D300
|
||||
|
||||
public ushort PressureUpperLimit2 { get; set; } = 302; // 加压上限 D300
|
||||
|
||||
|
||||
public ushort PressureUpperLimit3 { get; set; } = 304; // 加压上限 D300
|
||||
|
||||
|
||||
|
||||
public ushort PressureRate { get; set; } = 280; // 加压速率 D280
|
||||
|
||||
public ushort PressureRate2 { get; set; } = 284; // 加压速率 D280
|
||||
|
||||
public ushort PressureRate3 { get; set; } = 286; // 加压速率 D280
|
||||
|
||||
|
||||
public ushort HPCoeff11 { get; set; } = 74; // 1工位加压速率
|
||||
public ushort HPCoeff12 { get; set; } = 92; // 1工位加压速率
|
||||
public ushort HPCoeff13 { get; set; } = 96; // 1工位加压速率
|
||||
|
||||
// 高压/低压系数(每个工位独立)
|
||||
public ushort HPCoeff1 { get; set; } = 3120; // 工位1 高压系数
|
||||
@@ -92,6 +125,12 @@ namespace MembranePoreTester.Communication
|
||||
public ushort LowPressAlarm { get; set; } // 低压超限 M195
|
||||
|
||||
|
||||
|
||||
public ushort Midnight1 { get; set; } // 高压超限 M180
|
||||
public ushort Midnight2 { get; set; } // 低压超限 M195
|
||||
public ushort Midnight3 { get; set; } // 高压超限 M180
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -51,6 +51,10 @@ namespace MembranePoreTester.Models
|
||||
|
||||
public string SpeedRate1 { get; set; }
|
||||
|
||||
public string SpeedRate2 { get; set; }
|
||||
|
||||
public string SpeedRate3 { get; set; }
|
||||
|
||||
|
||||
public double MaxPoreSize => CalculateMaxPore();
|
||||
|
||||
|
||||
@@ -28,6 +28,20 @@ namespace MembranePoreTester.ViewModels
|
||||
set => SetProperty(ref _record, value);
|
||||
}
|
||||
|
||||
// 初始化,确保 StationId 在读取PLC前已设置
|
||||
public void Initialize(int stationId)
|
||||
{
|
||||
StationId = stationId;
|
||||
|
||||
// 延迟读取当前PLC值以确保连接稳定
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(200);
|
||||
await ReadCurrentPlcAsync();
|
||||
await ReadSpeedRateAsync();
|
||||
});
|
||||
}
|
||||
|
||||
public List<TestLiquid> Liquids => TestLiquid.Predefined;
|
||||
public List<string> PressureUnits => new() { "Pa", "cmHg", "psi" };
|
||||
public List<string> MembraneTypes => new() { "平板膜", "中空纤维膜" };
|
||||
@@ -140,20 +154,25 @@ namespace MembranePoreTester.ViewModels
|
||||
try
|
||||
{
|
||||
float speedRate = 0;
|
||||
ushort address = 0;
|
||||
switch (StationId)
|
||||
{
|
||||
|
||||
case 1:
|
||||
speedRate = await _plcService. ReadFloatAsync(_plcConfig.HPCoeff11);
|
||||
address = _plcConfig.HPCoeff11;
|
||||
speedRate = await _plcService.ReadFloatAsync(address);
|
||||
Record.SpeedRate1 = speedRate.ToString("F3");
|
||||
break;
|
||||
case 2:
|
||||
address = _plcConfig.HPCoeff12;
|
||||
speedRate = await _plcService.ReadFloatAsync(address);
|
||||
Record.SpeedRate1 = speedRate.ToString("F3");
|
||||
break;
|
||||
case 3:
|
||||
address = _plcConfig.HPCoeff13;
|
||||
speedRate = await _plcService.ReadFloatAsync(address);
|
||||
Record.SpeedRate1 = speedRate.ToString("F3");
|
||||
break;
|
||||
//case 2:
|
||||
// speedRate = await _plcService.ReadFloatAsync(_plcConfig.PressureRate2);
|
||||
// Record.SpeedRate2 = speedRate.ToString("F3");
|
||||
// break;
|
||||
//case 3:
|
||||
// speedRate = await _plcService.ReadFloatAsync(_plcConfig.PressureRate3);
|
||||
// Record.SpeedRate3 = speedRate.ToString("F3");
|
||||
// break;
|
||||
}
|
||||
OnPropertyChanged(nameof(Record));
|
||||
}
|
||||
|
||||
@@ -83,6 +83,33 @@ namespace MembranePoreTester.ViewModels
|
||||
}
|
||||
|
||||
|
||||
|
||||
private PressureModeItem _selectedInTakeMode;
|
||||
private List<PressureModeItem> _inTakeModeList;
|
||||
|
||||
public List<PressureModeItem> InTakeModeList => _inTakeModeList ??= new List<PressureModeItem>
|
||||
{
|
||||
new PressureModeItem { Text = "底部进气", Value = 0 },
|
||||
new PressureModeItem { Text = "顶部进气", Value = 1 }
|
||||
};
|
||||
|
||||
public PressureModeItem SelecteInTakeMode
|
||||
{
|
||||
get => _selectedInTakeMode;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedInTakeMode, value))
|
||||
{
|
||||
Task.Run(async () => await WriteInTakeModeAsync(value?.Text ?? "底部进气"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private readonly IPlcService _plcService;
|
||||
private readonly PlcConfiguration _plcConfig;
|
||||
private bool _isPressing;
|
||||
@@ -108,6 +135,19 @@ namespace MembranePoreTester.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public string UpAndDown
|
||||
{
|
||||
get => _selectedInTakeMode?.Text ?? "底部";
|
||||
set
|
||||
{
|
||||
var mode = InTakeModeList.FirstOrDefault(m => m.Text == value);
|
||||
if (mode != null)
|
||||
{
|
||||
SelecteInTakeMode = mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string PressButtonText
|
||||
{
|
||||
get => _pressButtonText;
|
||||
@@ -174,7 +214,10 @@ namespace MembranePoreTester.ViewModels
|
||||
// 仅在非抑制模式下将改变写回PLC,避免把PLC读回的值再次写入造成循环
|
||||
if (changed && !_suppressPressureValidation)
|
||||
{
|
||||
_ = _plcService.WriteMultipleRegistersAsync(_plcConfig.PressureUpperLimit, (float)value);
|
||||
ushort address = StationId == 1 ? _plcConfig.PressureUpperLimit
|
||||
: StationId == 2 ? _plcConfig.PressureUpperLimit2
|
||||
: _plcConfig.PressureUpperLimit3;
|
||||
_ = _plcService.WriteMultipleRegistersAsync(address, (float)value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,7 +230,7 @@ namespace MembranePoreTester.ViewModels
|
||||
if (SetProperty(ref _pressureRate, value))
|
||||
{
|
||||
// 值改变时写入PLC
|
||||
_ = _plcService.WriteMultipleRegistersAsync(_plcConfig.PressureRate, (float)value);
|
||||
_ = _plcService.WriteMultipleRegistersAsync(StationId == 1 ? _plcConfig.PressureRate : StationId == 2 ? _plcConfig.PressureRate2 : _plcConfig.PressureRate3, (float)value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,8 +240,13 @@ namespace MembranePoreTester.ViewModels
|
||||
{
|
||||
try
|
||||
{
|
||||
float upperLimit = await _plcService.ReadFloatAsync(_plcConfig.PressureUpperLimit);
|
||||
float rate = await _plcService.ReadFloatAsync(_plcConfig.PressureRate);
|
||||
// 根据工位选择加压上限的PLC地址
|
||||
ushort upperLimitAddress = StationId == 1 ? _plcConfig.PressureUpperLimit
|
||||
: StationId == 2 ? _plcConfig.PressureUpperLimit2
|
||||
: _plcConfig.PressureUpperLimit3;
|
||||
|
||||
float upperLimit = await _plcService.ReadFloatAsync(upperLimitAddress);
|
||||
float rate = await _plcService.ReadFloatAsync(StationId == 1 ? _plcConfig.PressureRate : StationId == 2 ? _plcConfig.PressureRate2 : _plcConfig.PressureRate3);
|
||||
|
||||
|
||||
|
||||
@@ -241,7 +289,7 @@ namespace MembranePoreTester.ViewModels
|
||||
StartCommand = new RelayCommand(async () =>
|
||||
{
|
||||
// 启动PLC
|
||||
await WriteCoilAsync(_plcConfig.StartCoil, true);
|
||||
await WriteCoilAsync(StationId == 1 ? _plcConfig.StartCoil : StationId == 2 ? _plcConfig.StartCoil2 : _plcConfig.StartCoil3, true);
|
||||
|
||||
// 启动孔分布自动采集
|
||||
PoreDistributionVM.StartCollecting();
|
||||
@@ -253,7 +301,7 @@ namespace MembranePoreTester.ViewModels
|
||||
// 停止自动采集
|
||||
PoreDistributionVM.StopCollecting();
|
||||
// 停止PLC
|
||||
await WriteCoilAsync(_plcConfig.StopCoil, true);
|
||||
await WriteCoilAsync(StationId == 1 ? _plcConfig.StopCoil : StationId == 2 ? _plcConfig.StopCoil2 : _plcConfig.StopCoil3, true);
|
||||
});
|
||||
|
||||
|
||||
@@ -274,6 +322,7 @@ namespace MembranePoreTester.ViewModels
|
||||
{
|
||||
await ReadPressureModeAsync();
|
||||
await ReadPressureParametersAsync(); // 新增:读取压力参数
|
||||
await ReadInTakeModeAsync();
|
||||
|
||||
}, TaskScheduler.Default);
|
||||
|
||||
@@ -301,6 +350,44 @@ namespace MembranePoreTester.ViewModels
|
||||
});
|
||||
}
|
||||
|
||||
private async Task ReadInTakeModeAsync()
|
||||
{
|
||||
await SafeExecuteAsync($"ReadInTakeModeAsync{StationId}", async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
ushort address = 0;
|
||||
|
||||
if (StationId == 1)
|
||||
{
|
||||
address = _plcConfig.UpAndDown1;
|
||||
}
|
||||
else if (StationId == 2)
|
||||
{
|
||||
address = _plcConfig.UpAndDown2;
|
||||
}
|
||||
else if (StationId == 3)
|
||||
{
|
||||
address = _plcConfig.UpAndDown3;
|
||||
}
|
||||
|
||||
ushort[] values = await _plcService.ReadHoldingRegistersAsync(address, 1);
|
||||
ushort val = values[0];
|
||||
string newValue = val == 0 ? "底部进气" : "顶部进气";
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
// 更新选中项
|
||||
UpAndDown = newValue;
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"读取出口模式失败: {ex.Message}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async Task TogglePressAsync()
|
||||
{
|
||||
try
|
||||
@@ -346,11 +433,11 @@ namespace MembranePoreTester.ViewModels
|
||||
{
|
||||
try
|
||||
{
|
||||
bool status = await _plcService.ReadCoilAsync(_plcConfig.EnableCoil); // 读取 M21
|
||||
bool status = await _plcService.ReadCoilAsync(StationId == 1 ? _plcConfig.EnableCoil : StationId == 2 ? _plcConfig.EnableCoil2 : _plcConfig.EnableCoil3); // 读取 M21
|
||||
EnableStatus = status;
|
||||
|
||||
|
||||
bool pressStatus = await _plcService.ReadCoilAsync(_plcConfig.PressCoil);//这里也要更新加压的按钮状态
|
||||
bool pressStatus = await _plcService.ReadCoilAsync(StationId == 1 ? _plcConfig.PressCoil : StationId == 2 ? _plcConfig.PressCoil2 : _plcConfig.PressCoil3);//这里也要更新加压的按钮状态
|
||||
|
||||
_isPressing = pressStatus;
|
||||
|
||||
@@ -401,6 +488,37 @@ namespace MembranePoreTester.ViewModels
|
||||
}
|
||||
|
||||
|
||||
private async Task WriteInTakeModeAsync(string mode)
|
||||
{
|
||||
if (IsDisposed) return;
|
||||
|
||||
ushort val = mode.ToString().Contains("底部") ? (ushort)0 : (ushort)1;
|
||||
try
|
||||
{
|
||||
ushort address = 0;
|
||||
|
||||
if (StationId == 1)
|
||||
{
|
||||
address = _plcConfig.UpAndDown1;
|
||||
}
|
||||
else if (StationId == 2)
|
||||
{
|
||||
address = _plcConfig.UpAndDown2;
|
||||
}
|
||||
else if (StationId == 3)
|
||||
{
|
||||
address = _plcConfig.UpAndDown3;
|
||||
}
|
||||
|
||||
await _plcService.WriteSingleRegisterAsync(address, val);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"写出口模式失败: {ex.Message}");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private bool _isPoreDistributionActive;
|
||||
public bool IsPoreDistributionActive
|
||||
{
|
||||
@@ -426,10 +544,13 @@ namespace MembranePoreTester.ViewModels
|
||||
var station = new StationItem
|
||||
{
|
||||
Name = $"工位 {i}",
|
||||
BubblePointVM = new BubblePointViewModel { StationId = i },
|
||||
PoreDistributionVM = new PoreDistributionViewModel { StationId = i },
|
||||
BubblePointVM = new BubblePointViewModel(),
|
||||
PoreDistributionVM = new PoreDistributionViewModel(),
|
||||
StationId = i
|
||||
};
|
||||
// 在构造完成后显式传入 StationId 以初始化 VM
|
||||
station.BubblePointVM.Initialize(i);
|
||||
station.PoreDistributionVM.Initialize(i);
|
||||
Stations.Add(station);
|
||||
}
|
||||
|
||||
@@ -456,6 +577,11 @@ namespace MembranePoreTester.ViewModels
|
||||
bool highPressAlarm = await plc.ReadCoilAsync(config.HighPressAlarm);
|
||||
bool lowPressAlarm = await plc.ReadCoilAsync(config.LowPressAlarm);
|
||||
|
||||
|
||||
bool Midnight1 = await plc.ReadCoilAsync(config.Midnight1);
|
||||
bool Midnight2 = await plc.ReadCoilAsync(config.Midnight2);
|
||||
bool Midnight3 = await plc.ReadCoilAsync(config.Midnight3);
|
||||
|
||||
// 收集当前报警信息
|
||||
var newAlarms = new List<string>();
|
||||
if (smallFlowAlarm) newAlarms.Add("小流量计报警");
|
||||
@@ -463,6 +589,10 @@ namespace MembranePoreTester.ViewModels
|
||||
if (highPressAlarm) newAlarms.Add("高压超限");
|
||||
if (lowPressAlarm) newAlarms.Add("低压超限");
|
||||
|
||||
if (Midnight1) newAlarms.Add("1工位漏夜");
|
||||
if (Midnight2) newAlarms.Add("2工位漏夜");
|
||||
if (Midnight3) newAlarms.Add("3工位漏夜");
|
||||
|
||||
// 更新UI(避免频繁刷新集合导致界面闪烁,直接替换内容)
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
|
||||
@@ -731,6 +731,18 @@ namespace MembranePoreTester.ViewModels
|
||||
set => SetProperty(ref _stationId, value);
|
||||
}
|
||||
|
||||
// 初始化方法:在 MainViewModel 创建 StationItem 后调用,确保 StationId 已设置
|
||||
public void Initialize(int stationId)
|
||||
{
|
||||
StationId = stationId;
|
||||
// 延迟调用读取模式,确保PLC连接稳定
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(200);
|
||||
await ReadPressureModeAsync();
|
||||
});
|
||||
}
|
||||
|
||||
public void SaveToDatabase()
|
||||
{
|
||||
var entity = new PoreDistributionEntity
|
||||
|
||||
@@ -134,6 +134,8 @@
|
||||
<Border DockPanel.Dock="Top" Background="White" CornerRadius="6" Padding="10" Margin="0,0,0,10" BorderBrush="#E9ECF0" BorderThickness="1">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<ComboBox ItemsSource="{Binding PressureModeList}" SelectedItem="{Binding SelectedPressureMode}" Width="80"/>
|
||||
|
||||
<ComboBox ItemsSource="{Binding InTakeModeList}" SelectedItem="{Binding SelecteInTakeMode}" Width="80"/>
|
||||
<Button Content="▶ 启动" Command="{Binding StartCommand}" Width="80" Background="#4CAF50"/>
|
||||
<Button Content="⏹ 停止" Command="{Binding StopCommand}" Width="80" Background="#F44336"/>
|
||||
<Button Content="{Binding PressButtonText}" Command="{Binding PressCommand}" Width="80" Background="#FF9800"/>
|
||||
|
||||
@@ -22,6 +22,18 @@
|
||||
"EnableCoil": 21, // 使能线圈(M21),状态反馈(只读)
|
||||
"StopCoil": 7, // 停止线圈(M7),ON 停止测试
|
||||
|
||||
|
||||
"StartCoil2": 30, // 启动线圈(M20),ON 启动测试程序
|
||||
"EnableCoil2": 31, // 使能线圈(M21),状态反馈(只读)
|
||||
"StopCoil2": 32, // 停止线圈(M7),ON 停止测试
|
||||
|
||||
|
||||
"StartCoil3": 33, // 启动线圈(M20),ON 启动测试程序
|
||||
"EnableCoil3": 34, // 使能线圈(M21),状态反馈(只读)
|
||||
"StopCoil3": 35, // 停止线圈(M7),ON 停止测试
|
||||
|
||||
|
||||
|
||||
// 压力值系数(用于单位转换,例如 kPa 转 Pa 时设为 1000)
|
||||
"PressureFactor": 1000.0,
|
||||
|
||||
@@ -33,6 +45,8 @@
|
||||
|
||||
// ========== 运维参数设置(可读写) ==========
|
||||
"PressureUpperLimit": 300, // 加压上限(D300)
|
||||
"PressureUpperLimit2": 302, // 加压上限(D300)
|
||||
"PressureUpperLimit3": 304, // 加压上限(D300)
|
||||
"PressureRate": 280, // 加压速率(D280)
|
||||
"PressureCoeff": 282, // 加压系数(D282)
|
||||
|
||||
@@ -74,14 +88,22 @@
|
||||
"BigFlow2": 42, //
|
||||
"BigFlow3": 46, //
|
||||
|
||||
|
||||
|
||||
|
||||
"SmallFlowAlarm": 210,
|
||||
"BigFlowAlarm": 213,
|
||||
|
||||
"HighPressAlarm": 180, //高压超限
|
||||
"LowPressAlarm": 195 //低压超限
|
||||
"LowPressAlarm": 195, //低压超限
|
||||
|
||||
"Midnight1": 50, // 漏夜1
|
||||
|
||||
"Midnight2": 51, // 漏夜2
|
||||
|
||||
"Midnight3": 52, // 漏夜3
|
||||
|
||||
|
||||
"UpAndDown1": 18, // 漏夜3
|
||||
"UpAndDown2": 20, // 漏夜3
|
||||
"UpAndDown3": 22 // 漏夜3
|
||||
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user