From 4489514b5d0633ce7785bb944c7fe16e11033021 Mon Sep 17 00:00:00 2001 From: xyy <544939200@qq.com> Date: Tue, 16 Jun 2026 21:18:46 +0800 Subject: [PATCH] --- Models/StageData.cs | 42 ++++++++++++++------ Models/TestResult.cs | 6 +++ Services/ExcelReportService.cs | 30 +++++++++++---- Services/ModbusTcpPlcService.cs | 12 ++++-- ViewModels/MainViewModel.cs | 68 ++++++++++++++++++++++++++++++--- Views/ConfigWindow.xaml | 4 +- Views/MainWindow.xaml | 48 +++++++++++++++-------- 7 files changed, 163 insertions(+), 47 deletions(-) diff --git a/Models/StageData.cs b/Models/StageData.cs index 044ae25..3797efe 100644 --- a/Models/StageData.cs +++ b/Models/StageData.cs @@ -1,20 +1,38 @@ using CommunityToolkit.Mvvm.ComponentModel; -namespace AciTester.Models; - -public partial class StageData : ObservableObject +namespace AciTester.Models { - [ObservableProperty] - private string stageName = string.Empty; + public partial class StageData : ObservableObject + { + [ObservableProperty] + private string stageName; - [ObservableProperty] - private double cutoffDiameter; // 截止直径 (μm) + [ObservableProperty] + private double cutoffDiameter; - [ObservableProperty] - private double initialWeight; // 测前质量 (g) + private double _initialWeight; + public double InitialWeight + { + get => _initialWeight; + set + { + if (SetProperty(ref _initialWeight, value)) + OnPropertyChanged(nameof(NetWeight)); // 关键:通知净重变化 + } + } - [ObservableProperty] - private double finalWeight; // 测后质量 (g) + private double _finalWeight; + public double FinalWeight + { + get => _finalWeight; + set + { + if (SetProperty(ref _finalWeight, value)) + OnPropertyChanged(nameof(NetWeight)); // 关键:通知净重变化 + } + } - public double NetWeight => finalWeight - initialWeight; + // 计算属性,不存储 + public double NetWeight => FinalWeight - InitialWeight; + } } \ No newline at end of file diff --git a/Models/TestResult.cs b/Models/TestResult.cs index a14bc00..8b212ee 100644 --- a/Models/TestResult.cs +++ b/Models/TestResult.cs @@ -11,4 +11,10 @@ public class TestResult public float Temperature { get; set; } public float DifferentialPressure { get; set; } + + // 新增粒径参数 + public double D10 { get; set; } + public double D50 { get; set; } // 即 MMAD + public double D90 { get; set; } + public double GSD { get; set; } } \ No newline at end of file diff --git a/Services/ExcelReportService.cs b/Services/ExcelReportService.cs index ddc0a09..d625914 100644 --- a/Services/ExcelReportService.cs +++ b/Services/ExcelReportService.cs @@ -28,7 +28,7 @@ namespace AciTester.Services sheet.Cells["A5"].Value = "总质量F(g):"; sheet.Cells["B5"].Value = result.TotalMass; - // 在报告生成时添加 + // 测试环境 sheet.Cells["A6"].Value = "测试环境:"; sheet.Cells["B6"].Value = $"流量: {result.FlowRate:F2} L/min, 温度: {result.Temperature:F1}℃, 压差: {result.DifferentialPressure:F2} kPa"; @@ -38,14 +38,28 @@ namespace AciTester.Services sheet.Cells["A8"].Value = "微细粒子分数(FPF)"; sheet.Cells["B8"].Value = $"{result.FineParticleFraction:F2}%"; - // 各级数据表 - sheet.Cells["A10"].Value = "层级"; - sheet.Cells["B10"].Value = "截止直径(μm)"; - sheet.Cells["C10"].Value = "净重(g)"; - sheet.Cells["D10"].Value = "占比(%)"; - sheet.Cells["A10:D10"].Style.Font.Bold = true; + // ============ 新增:粒径分布参数 ============ + sheet.Cells["A9"].Value = "粒径分布参数"; + sheet.Cells["A9"].Style.Font.Bold = true; - int row = 11; + sheet.Cells["A10"].Value = "D10 (μm)"; + sheet.Cells["B10"].Value = result.D10; + sheet.Cells["A11"].Value = "D50 (μm) (MMAD)"; + sheet.Cells["B11"].Value = result.D50; + sheet.Cells["A12"].Value = "D90 (μm)"; + sheet.Cells["B12"].Value = result.D90; + sheet.Cells["A13"].Value = "GSD (几何标准偏差)"; + sheet.Cells["B13"].Value = result.GSD; + + // 各级数据表(起始行号调整为15) + int dataStartRow = 15; + sheet.Cells[dataStartRow, 1].Value = "层级"; + sheet.Cells[dataStartRow, 2].Value = "截止直径(μm)"; + sheet.Cells[dataStartRow, 3].Value = "净重(g)"; + sheet.Cells[dataStartRow, 4].Value = "占比(%)"; + sheet.Cells[dataStartRow, 1, dataStartRow, 4].Style.Font.Bold = true; + + int row = dataStartRow + 1; double total = result.TotalMass; foreach (var stage in result.Stages) { diff --git a/Services/ModbusTcpPlcService.cs b/Services/ModbusTcpPlcService.cs index d38421d..9e0005e 100644 --- a/Services/ModbusTcpPlcService.cs +++ b/Services/ModbusTcpPlcService.cs @@ -88,10 +88,14 @@ namespace AciTester.Services public async Task ReadCoilAsync(ushort coilAddress) { - await EnsureConnectedAsync(); - await Task.Delay(100); - bool[] result = await _master?.ReadCoilsAsync(_config.SlaveId, coilAddress, 1); - return result[0]; + try + { + await EnsureConnectedAsync(); + await Task.Delay(100); + bool[] result = await _master?.ReadCoilsAsync(_config.SlaveId, coilAddress, 1); + return result[0]; + } + catch { return false; } } public bool IsConnected => _tcpClient != null && _tcpClient.Connected; diff --git a/ViewModels/MainViewModel.cs b/ViewModels/MainViewModel.cs index 349aa53..a6f3966 100644 --- a/ViewModels/MainViewModel.cs +++ b/ViewModels/MainViewModel.cs @@ -140,6 +140,7 @@ namespace AciTester.ViewModels }; } + public IAsyncRelayCommand StopTestCommand { get; } public IAsyncRelayCommand ConnectCommand { get; } public IRelayCommand DisconnectCommand { get; } @@ -403,7 +404,8 @@ namespace AciTester.ViewModels IsTesting = true; _testCts = new CancellationTokenSource(); - //StopTestCommand.NotifyCanExecuteChanged(); + + StopTestCommand.NotifyCanExecuteChanged(); try { await _plcService.WriteCoilAsync(_config.PumpCoil, true); @@ -448,17 +450,68 @@ namespace AciTester.ViewModels return; } + // 1. 计算各级占比和累积分布 + // 注意:Stages[0] ~ Stages[7] 对应 Stage0~Stage7,Stages[8] 是 Filter + // 截止直径数组(与 Stages 的顺序一致) + double[] diamArray = new double[9]; + for (int i = 0; i < 9; i++) + diamArray[i] = Stages[i].CutoffDiameter; + + // 占比和累积分布 + double[] percentages = new double[9]; + double[] cumulatives = new double[9]; + double sum = 0; + for (int i = 0; i < 9; i++) + { + percentages[i] = Stages[i].NetWeight / totalMass * 100; + sum += percentages[i]; + cumulatives[i] = sum; + } + + // 2. 插值函数:给定累积百分比,返回对应的粒径(对数线性插值) + double Interpolate(double targetCum) + { + if (targetCum <= cumulatives[0]) return diamArray[0]; + if (targetCum >= cumulatives[8]) return diamArray[8]; + for (int i = 0; i < 8; i++) + { + if (cumulatives[i] <= targetCum && cumulatives[i + 1] >= targetCum) + { + double d1 = diamArray[i]; + double d2 = diamArray[i + 1]; + double c1 = cumulatives[i]; + double c2 = cumulatives[i + 1]; + double logD1 = Math.Log(d1); + double logD2 = Math.Log(d2); + double logD = logD1 + (targetCum - c1) * (logD2 - logD1) / (c2 - c1); + return Math.Exp(logD); + } + } + return diamArray[8]; + } + + double d10 = Interpolate(10); + double d50 = Interpolate(50); + double d90 = Interpolate(90); + + // 3. 计算 GSD(几何标准偏差):GSD = D84 / D16(如果可用) + double d16 = Interpolate(16); + double d84 = Interpolate(84); + double gsd = (d16 > 0 && d84 > 0) ? d84 / d16 : 0; + + // 4. 计算微细粒子剂量和分数(原有逻辑) double fineMass = 0; foreach (var stage in Stages) { if (stage.CutoffDiameter <= 5.0 && stage.CutoffDiameter > 0) fineMass += stage.NetWeight; } - fineMass += Stages[8].NetWeight; + fineMass += Stages[8].NetWeight; // Filter - double fpd = fineMass * 1000; + double fpd = fineMass * 1000; // mg double fpf = (fineMass / totalMass) * 100; + // 5. 赋值给 CurrentResult CurrentResult = new TestResult { TestTime = DateTime.Now, @@ -468,10 +521,15 @@ namespace AciTester.ViewModels Stages = Stages.ToList(), FlowRate = CurrentFlow, Temperature = RealTime.Temperature, - DifferentialPressure = RealTime.DifferentialPressure + DifferentialPressure = RealTime.DifferentialPressure, + // 新增粒径参数 + D10 = d10, + D50 = d50, + D90 = d90, + GSD = gsd }; - MessageBox.Show($"计算完成\n总质量: {totalMass:F4} g\n微细粒子剂量: {fpd:F2} mg\n微细粒子分数: {fpf:F2}%", + MessageBox.Show($"计算完成\n总质量: {totalMass:F4} g\n微细粒子剂量: {fpd:F2} mg\n微细粒子分数: {fpf:F2}%\nD50: {d50:F2} μm", "计算结果", MessageBoxButton.OK, MessageBoxImage.Information); } diff --git a/Views/ConfigWindow.xaml b/Views/ConfigWindow.xaml index 74e877d..d02631e 100644 --- a/Views/ConfigWindow.xaml +++ b/Views/ConfigWindow.xaml @@ -18,10 +18,10 @@ - + diff --git a/Views/MainWindow.xaml b/Views/MainWindow.xaml index b583d80..8f997b6 100644 --- a/Views/MainWindow.xaml +++ b/Views/MainWindow.xaml @@ -237,14 +237,14 @@