diff --git a/Helpers/PlcConfiguration.cs b/Helpers/PlcConfiguration.cs index ea86359..63d3284 100644 --- a/Helpers/PlcConfiguration.cs +++ b/Helpers/PlcConfiguration.cs @@ -35,6 +35,9 @@ namespace MembranePoreTester.Communication public ushort PressureUpperLimit { get; set; } = 300; // 加压上限 D300 public ushort PressureRate { get; set; } = 280; // 加压速率 D280 + + public ushort HPCoeff11 { get; set; } = 74; // 1工位加压速率 + // 高压/低压系数(每个工位独立) public ushort HPCoeff1 { get; set; } = 3120; // 工位1 高压系数 public ushort LPCoeff1 { get; set; } = 3122; // 工位1 低压系数 diff --git a/Models/BubblePointRecord.cs b/Models/BubblePointRecord.cs index eb6ef0f..b1efbee 100644 --- a/Models/BubblePointRecord.cs +++ b/Models/BubblePointRecord.cs @@ -3,7 +3,7 @@ using System.Runtime.CompilerServices; namespace MembranePoreTester.Models { - public class BubblePointRecord: INotifyPropertyChanged + public class BubblePointRecord : INotifyPropertyChanged { public string SampleType { get; set; } // 平板膜/中空纤维膜 public string SampleSpec { get; set; } // 规格 @@ -49,6 +49,9 @@ namespace MembranePoreTester.Models public DateTime TestDate { get; set; } = DateTime.Now; public string Tester { get; set; } + public string SpeedRate1 { get; set; } + + public double MaxPoreSize => CalculateMaxPore(); private double CalculateMaxPore() diff --git a/ViewModels/BubblePointViewModel.cs b/ViewModels/BubblePointViewModel.cs index ab46089..818bf27 100644 --- a/ViewModels/BubblePointViewModel.cs +++ b/ViewModels/BubblePointViewModel.cs @@ -119,6 +119,7 @@ namespace MembranePoreTester.ViewModels if (StationId > 0 && !IsDisposed) { await ReadCurrentPlcAsync(); + await ReadSpeedRateAsync(); // 新增:读取加压速率 } }; _timer.Start(); @@ -132,6 +133,36 @@ namespace MembranePoreTester.ViewModels //); } + + // 新增:读取加压速率并赋值给 Record.SpeedRate1 + private async Task ReadSpeedRateAsync() + { + try + { + float speedRate = 0; + switch (StationId) + { + case 1: + speedRate = await _plcService. ReadFloatAsync(_plcConfig.HPCoeff11); + 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)); + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"读取加压速率失败: {ex.Message}"); + } + } + public override void Dispose() { _timer?.Stop(); diff --git a/ViewModels/MainViewModel.cs b/ViewModels/MainViewModel.cs index 64aea12..a0d450d 100644 --- a/ViewModels/MainViewModel.cs +++ b/ViewModels/MainViewModel.cs @@ -121,8 +121,16 @@ namespace MembranePoreTester.ViewModels { if (SetProperty(ref _pressureUpperLimit, value)) { + if (HighLowPressure == "低压") + { + if (value > 200) + { + MessageBox.Show("低压模式,加压上限不能超过200!"); + return; + } + } // 值改变时写入PLC - _ = WriteFloatAsync(_plcConfig.PressureUpperLimit, (float)value); + _ = _plcService.WriteMultipleRegistersAsync(_plcConfig.PressureUpperLimit, (float)value); } } } @@ -135,7 +143,7 @@ namespace MembranePoreTester.ViewModels if (SetProperty(ref _pressureRate, value)) { // 值改变时写入PLC - _ = WriteFloatAsync(_plcConfig.PressureRate, (float)value); + _ = _plcService.WriteMultipleRegistersAsync(_plcConfig.PressureRate, (float)value); } } } @@ -148,6 +156,9 @@ namespace MembranePoreTester.ViewModels float upperLimit = await _plcService.ReadFloatAsync(_plcConfig.PressureUpperLimit); float rate = await _plcService.ReadFloatAsync(_plcConfig.PressureRate); + + + Application.Current.Dispatcher.Invoke(() => { PressureUpperLimit = upperLimit; @@ -204,7 +215,7 @@ namespace MembranePoreTester.ViewModels // 启动定时器,每秒读取一次 M21 状态 _timer = new System.Windows.Threading.DispatcherTimer(); _timer.Interval = TimeSpan.FromSeconds(1); - _timer.Tick += async (s, e) => + _timer.Tick += async (s, e) => { await ReadEnableStatusAsync(); await ReadPressureParametersAsync(); // 新增:读取压力参数 diff --git a/ViewModels/PoreDistributionViewModel.cs b/ViewModels/PoreDistributionViewModel.cs index 9f6f7a9..4293bfd 100644 --- a/ViewModels/PoreDistributionViewModel.cs +++ b/ViewModels/PoreDistributionViewModel.cs @@ -104,14 +104,16 @@ namespace MembranePoreTester.ViewModels if (TestMode.Contains("湿膜")) { float rawFlow = await _plcService.ReadWetFlowAsync(); - flow = Math.Round(rawFlow, 2); + flow = Math.Round(ConvertFlowByMode(rawFlow), 2); } else { float rawFlow = await _plcService.ReadDryFlowAsync(); - flow = Math.Round(rawFlow, 2); + flow = Math.Round(ConvertFlowByMode(rawFlow), 2); } + + CurrentFlow = flow; // 3. 直接新增一行(不查找相同压力) var newPoint = new Models.DataPoint { @@ -340,12 +342,12 @@ namespace MembranePoreTester.ViewModels if (TestMode == "湿膜") { float rawWet = await _plcService.ReadWetFlowAsync(); - SelectedDataPoint.WetFlow = rawWet; + SelectedDataPoint.WetFlow = ConvertFlowByMode(rawWet); } else { float rawDry = await _plcService.ReadDryFlowAsync(); - SelectedDataPoint.DryFlow = rawDry; + SelectedDataPoint.DryFlow = ConvertFlowByMode(rawDry); } } else @@ -355,12 +357,12 @@ namespace MembranePoreTester.ViewModels if (TestMode == "湿膜") { float rawWet = await _plcService.ReadWetFlowAsync(); - newPoint.WetFlow = rawWet; + newPoint.WetFlow = ConvertFlowByMode(ConvertFlowByMode(rawWet)); } else { float rawDry = await _plcService.ReadDryFlowAsync(); - newPoint.DryFlow = rawDry; + newPoint.DryFlow = ConvertFlowByMode(rawDry); } Record.DataPoints.Add(newPoint); } @@ -405,6 +407,7 @@ namespace MembranePoreTester.ViewModels // 修改 Calculate 方法: private void Calculate() { + var cleanedPoints = CleanDataPoints(Record.DataPoints); if (Record.DataPoints.Count < 2) return; AveragePoreSize = PoreDistributionAnalysis.CalculateAveragePore( @@ -412,6 +415,30 @@ namespace MembranePoreTester.ViewModels RangePercentage = PoreDistributionAnalysis.CalculatePoreRangePercentage( Record.DataPoints, Record.PressureUnit, Record.Liquid, LowerPore, UpperPore); + + // 可选:提示用户过滤了多少无效点 + int invalidCount = Record.DataPoints.Count - cleanedPoints.Count; + if (invalidCount > 0) + { + MessageBox.Show($"已自动过滤 {invalidCount} 个无效数据点"); + System.Diagnostics.Debug.WriteLine($"已自动过滤 {invalidCount} 个无效数据点"); + } + } + + private List CleanDataPoints(IEnumerable points) + { + return points + .Where(p => p.Pressure > 0.001) // 移除压力接近0的点 + .Where(p => !(Math.Abs(p.WetFlow) < 0.001 && Math.Abs(p.DryFlow) < 0.001)) // 移除双零流量点 + .GroupBy(p => Math.Round(p.Pressure, 2)) // 按压力四舍五入分组(避免重复压力) + .Select(g => new Models.DataPoint + { + Pressure = g.Key, + WetFlow = g.Max(x => x.WetFlow), // 取最大值(避免0覆盖有效值) + DryFlow = g.Max(x => x.DryFlow) + }) + .OrderBy(p => p.Pressure) + .ToList(); } private void GenerateReport() @@ -681,6 +708,16 @@ namespace MembranePoreTester.ViewModels public ICommand ClearAllCommand { get; } + + private double _currentFlow; + public double CurrentFlow + { + get => _currentFlow; + set => SetProperty(ref _currentFlow, value); + } + + + // 修改命令初始化(构造函数中) @@ -695,5 +732,17 @@ namespace MembranePoreTester.ViewModels } } + + + + private double ConvertFlowByMode(double rawFlow) + { + // 如果当前选择的是小流量模式,则需要除以1000(因为PLC可能存储的是mL/min) + if (SelectedPressureMode != null && SelectedPressureMode.Text.Contains("小流量")) + return rawFlow / 1000.0; + else + return rawFlow; + } + } } \ No newline at end of file diff --git a/Views/BubblePointView.xaml b/Views/BubblePointView.xaml index fdc4376..b6f7037 100644 --- a/Views/BubblePointView.xaml +++ b/Views/BubblePointView.xaml @@ -24,6 +24,7 @@ + @@ -39,19 +40,23 @@ +