From 92a480834a35bc192b247e7566972ff94a3e10a9 Mon Sep 17 00:00:00 2001 From: xyy <544939200@qq.com> Date: Wed, 17 Jun 2026 23:08:06 +0800 Subject: [PATCH] --- ...测试仪(4).gxw => CSI-Z173 吸入制剂药物测试仪.gxw | Bin 1040384 -> 1048064 bytes Models/CalibrationConfig.cs | 12 ++ Models/PlcConfiguration.cs | 5 + ViewModels/ConfigViewModel.cs | 24 +++ ViewModels/MainViewModel.cs | 170 +++++++++++++----- Views/ConfigWindow.xaml | 31 +++- Views/MainWindow.xaml | 2 +- 7 files changed, 196 insertions(+), 48 deletions(-) rename CSI-Z173 吸入制剂药物测试仪(4).gxw => CSI-Z173 吸入制剂药物测试仪.gxw (95%) diff --git a/CSI-Z173 吸入制剂药物测试仪(4).gxw b/CSI-Z173 吸入制剂药物测试仪.gxw similarity index 95% rename from CSI-Z173 吸入制剂药物测试仪(4).gxw rename to CSI-Z173 吸入制剂药物测试仪.gxw index 9d1246729c1eaad46ad336b2095bed2e20d63fc9..f2c0d082f755f1bde17ce92a91973116b679eb61 100644 GIT binary patch delta 14181 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

?<(?qhjDxT z4nutueb&!~z2krk2gOUjr*UxP^-l1ZV(d$W6$?JR!rD6>>L|yUaOaWd(ZCXU&}oNr zTuCTM?N~oM)Z^^*&Z0~|L*(@{L|%^}1;FE2+^GV5jB+nQE))WBFVPTrH0BME=T34x zcarn^6ifztl;aqH0`u;8wz!{``aVVfY;OR4?10*&Vb+Vc89|4iqaWT zlt8Bo1WF_nbh;xxrM=VR4?s`BNN1<3)6=2AKN0Z+NQA~t%dyH1w-f#x-W3Xa!yWEm z#1l}0-blc!1Uf=KPp8}I^>joOuUGL!oPKww;)1`X_bGm7Sm_8yTTrequCUt!|Dq+* zsf0VBPrnz8oZ(Kl8=7{aXA$^E7rsunC*bdJDSkin67Yt7ip$&49`=Aw!AKzB_JxUG Kt@=njM*bI(UkBp= delta 9238 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 PyupPBL=_j< diff --git a/ViewModels/ConfigViewModel.cs b/ViewModels/ConfigViewModel.cs index 082d20d..03da971 100644 --- a/ViewModels/ConfigViewModel.cs +++ b/ViewModels/ConfigViewModel.cs @@ -43,6 +43,17 @@ namespace AciTester.ViewModels var protect = await _plcService.ReadFloatAsync(_config.FlowProtectReg); _calib.FlowLowLimit = protect - 5; // 示例,实际根据协议解析 _calib.FlowHighLimit = protect + 5; + + + // 读取线圈状态(新增) + _calib.FlowCalibrationEnabled = await _plcService.ReadCoilAsync(_config.FlowCalibrationCoil); + _calib.PumpPressureCalibrationEnabled = await _plcService.ReadCoilAsync(_config.PumpPressureCalibCoil); + _calib.ImpactorPressureCalibrationEnabled = await _plcService.ReadCoilAsync(_config.ImpactorPressureCalibCoil); + + + + + } catch (System.Exception ex) { @@ -64,6 +75,19 @@ namespace AciTester.ViewModels await _plcService.WriteMultipleRegistersAsync(_config.PumpPressureCalibReg, _calib.PumpPressureCalibration); await _plcService.WriteMultipleRegistersAsync(_config.ImpactorPressureCalibReg, _calib.ImpactorPressureCalibration); // 写入流量保护值(需根据实际协议拆分高低限) + + + + + await _plcService.WriteCoilAsync(_config.FlowCalibrationCoil, _calib.FlowCalibrationEnabled); + await _plcService.WriteCoilAsync(_config.PumpPressureCalibCoil, _calib.PumpPressureCalibrationEnabled); + await _plcService.WriteCoilAsync(_config.ImpactorPressureCalibCoil, _calib.ImpactorPressureCalibrationEnabled); + + + + + + MessageBox.Show("配置保存成功", "提示"); // 可选:触发重新校准 await _plcService.WriteCoilAsync(_config.ImpactorPressureCalibCoil, true); diff --git a/ViewModels/MainViewModel.cs b/ViewModels/MainViewModel.cs index a6f3966..e2b1575 100644 --- a/ViewModels/MainViewModel.cs +++ b/ViewModels/MainViewModel.cs @@ -75,18 +75,20 @@ namespace AciTester.ViewModels _plcService = new ModbusTcpPlcService(_config); _reportService = new ExcelReportService(); + // NGI 装置三 - 依据《中国药典》2025年版通则0951 表3 + // 包含预分离器 + Stage 1 ~ 7 + MOC,共9个收集部件 Stages = new ObservableCollection - { - new StageData { StageName = "Stage 0", CutoffDiameter = 9.0 }, - new StageData { StageName = "Stage 1", CutoffDiameter = 5.8 }, - new StageData { StageName = "Stage 2", CutoffDiameter = 4.7 }, - new StageData { StageName = "Stage 3", CutoffDiameter = 3.3 }, - new StageData { StageName = "Stage 4", CutoffDiameter = 2.1 }, - new StageData { StageName = "Stage 5", CutoffDiameter = 1.1 }, - new StageData { StageName = "Stage 6", CutoffDiameter = 0.7 }, - new StageData { StageName = "Stage 7", CutoffDiameter = 0.4 }, - new StageData { StageName = "Filter", CutoffDiameter = 0.0 } - }; +{ + new StageData { StageName = "预分离器", CutoffDiameter = 12.80 }, // 不计入粒径分布 + new StageData { StageName = "Stage 1", CutoffDiameter = 14.30 }, + new StageData { StageName = "Stage 2", CutoffDiameter = 4.88 }, + new StageData { StageName = "Stage 3", CutoffDiameter = 2.185 }, + new StageData { StageName = "Stage 4", CutoffDiameter = 1.207 }, + new StageData { StageName = "Stage 5", CutoffDiameter = 0.608 }, + new StageData { StageName = "Stage 6", CutoffDiameter = 0.323 }, + new StageData { StageName = "Stage 7", CutoffDiameter = 0.206 }, + new StageData { StageName = "MOC", CutoffDiameter = 0.070 } +}; ConnectCommand = new AsyncRelayCommand(ConnectAsync); DisconnectCommand = new RelayCommand(Disconnect); @@ -438,11 +440,100 @@ namespace AciTester.ViewModels } } + //private void CalculateResult() + //{ + // double totalMass = 0; + // foreach (var stage in Stages) + // totalMass += stage.NetWeight; + + // if (totalMass <= 0) + // { + // MessageBox.Show("总质量为零,无法计算", "警告", MessageBoxButton.OK, MessageBoxImage.Warning); + // return; + // } + + // // 1. 计算各级占比和累积分布(8个层级) + // double[] diamArray = new double[8]; + // for (int i = 0; i < 8; i++) + // diamArray[i] = Stages[i].CutoffDiameter; + + // double[] percentages = new double[8]; + // double[] cumulatives = new double[8]; + // double sum = 0; + // for (int i = 0; i < 8; i++) + // { + // percentages[i] = Stages[i].NetWeight / totalMass * 100; + // sum += percentages[i]; + // cumulatives[i] = sum; + // } + + // // 2. 插值函数(与之前相同,但只使用8个点) + // double Interpolate(double targetCum) + // { + // if (targetCum <= cumulatives[0]) return diamArray[0]; + // if (targetCum >= cumulatives[7]) return diamArray[7]; + // for (int i = 0; i < 7; 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[7]; + // } + + // double d10 = Interpolate(10); + // double d50 = Interpolate(50); + // double d90 = Interpolate(90); + + // // 3. GSD (D84/D16) + // double d16 = Interpolate(16); + // double d84 = Interpolate(84); + // double gsd = (d16 > 0 && d84 > 0) ? d84 / d16 : 0; + + // // 4. 微细粒子剂量(FPD)和分数(FPF) + // // NGI中,截止直径 ≤ 5μm 的层级为 Stage 3~7 以及 MOC(Stage 3的D50=2.82μm,Stage 7=0.34μm,全部≤5μm) + // // 因此统计 Stage 3,4,5,6,7 和 MOC 的质量 + // double fineMass = 0; + // for (int i = 2; i < 8; i++) // i=2 对应Stage 3(数组索引从0开始) + // fineMass += Stages[i].NetWeight; + + // double fpd = fineMass * 1000; // mg + // double fpf = (fineMass / totalMass) * 100; + + // // 5. 赋值给 CurrentResult + // CurrentResult = new TestResult + // { + // TestTime = DateTime.Now, + // TotalMass = totalMass, + // FineParticleDose = fpd, + // FineParticleFraction = fpf, + // Stages = Stages.ToList(), + // FlowRate = CurrentFlow, + // Temperature = RealTime.Temperature, + // DifferentialPressure = RealTime.DifferentialPressure, + // D10 = d10, + // D50 = d50, + // D90 = d90, + // GSD = gsd + // }; + + // MessageBox.Show($"计算完成\n总质量: {totalMass:F4} g\n微细粒子剂量: {fpd:F2} mg\n微细粒子分数: {fpf:F2}%\nD50: {d50:F2} μm", + // "计算结果", MessageBoxButton.OK, MessageBoxImage.Information); + //} private void CalculateResult() { + // 排除预分离器(索引0),只计算 Stage 1 ~ MOC(索引1~8) double totalMass = 0; - foreach (var stage in Stages) - totalMass += stage.NetWeight; + for (int i = 1; i < 9; i++) + totalMass += Stages[i].NetWeight; if (totalMass <= 0) { @@ -450,30 +541,32 @@ 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++) + // 提取 Stage 1 ~ MOC 的直径和质量(索引1~8) + double[] diamArray = new double[8]; + double[] netWeights = new double[8]; + for (int i = 0; i < 8; i++) { - percentages[i] = Stages[i].NetWeight / totalMass * 100; + diamArray[i] = Stages[i + 1].CutoffDiameter; + netWeights[i] = Stages[i + 1].NetWeight; + } + + // 计算占比和累积分布 + double[] percentages = new double[8]; + double[] cumulatives = new double[8]; + double sum = 0; + for (int i = 0; i < 8; i++) + { + percentages[i] = netWeights[i] / totalMass * 100; sum += percentages[i]; cumulatives[i] = sum; } - // 2. 插值函数:给定累积百分比,返回对应的粒径(对数线性插值) + // 插值函数(只针对8个数据点) 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 (targetCum >= cumulatives[7]) return diamArray[7]; + for (int i = 0; i < 7; i++) { if (cumulatives[i] <= targetCum && cumulatives[i + 1] >= targetCum) { @@ -487,31 +580,27 @@ namespace AciTester.ViewModels return Math.Exp(logD); } } - return diamArray[8]; + return diamArray[7]; } double d10 = Interpolate(10); double d50 = Interpolate(50); double d90 = Interpolate(90); - // 3. 计算 GSD(几何标准偏差):GSD = D84 / D16(如果可用) + // GSD double d16 = Interpolate(16); double d84 = Interpolate(84); double gsd = (d16 > 0 && d84 > 0) ? d84 / d16 : 0; - // 4. 计算微细粒子剂量和分数(原有逻辑) + // FPD: Stage 3 ~ MOC(索引3~8) double fineMass = 0; - foreach (var stage in Stages) - { - if (stage.CutoffDiameter <= 5.0 && stage.CutoffDiameter > 0) - fineMass += stage.NetWeight; - } - fineMass += Stages[8].NetWeight; // Filter + for (int i = 3; i < 9; i++) + fineMass += Stages[i].NetWeight; - double fpd = fineMass * 1000; // mg + double fpd = fineMass * 1000; double fpf = (fineMass / totalMass) * 100; - // 5. 赋值给 CurrentResult + // 保存结果 CurrentResult = new TestResult { TestTime = DateTime.Now, @@ -522,7 +611,6 @@ namespace AciTester.ViewModels FlowRate = CurrentFlow, Temperature = RealTime.Temperature, DifferentialPressure = RealTime.DifferentialPressure, - // 新增粒径参数 D10 = d10, D50 = d50, D90 = d90, diff --git a/Views/ConfigWindow.xaml b/Views/ConfigWindow.xaml index d02631e..15be49e 100644 --- a/Views/ConfigWindow.xaml +++ b/Views/ConfigWindow.xaml @@ -1,7 +1,7 @@  @@ -11,31 +11,38 @@ - + + - + + + + + + + @@ -43,16 +50,28 @@ + - + + + + + + + + + + + +