From 8332fa05311955899cf9ed0006e4cdc65e33d024 Mon Sep 17 00:00:00 2001 From: xyy <544939200@qq.com> Date: Wed, 27 May 2026 14:04:14 +0800 Subject: [PATCH] --- ViewModels/ConfigViewModel.cs | 5 + ViewModels/D7896ViewModel.cs | 201 ++++++++++++++++++++-------------- Views/ConfigWindow.xaml | 4 +- Views/D7896View.xaml | 66 +++++++++-- 4 files changed, 187 insertions(+), 89 deletions(-) diff --git a/ViewModels/ConfigViewModel.cs b/ViewModels/ConfigViewModel.cs index 8c60260..3f23262 100644 --- a/ViewModels/ConfigViewModel.cs +++ b/ViewModels/ConfigViewModel.cs @@ -52,6 +52,11 @@ public partial class ConfigViewModel : ObservableObject } } + + + //public IAsyncRelayCommand SaveCommand => new AsyncRelayCommand(Save); + + [RelayCommand] private async Task Save() { diff --git a/ViewModels/D7896ViewModel.cs b/ViewModels/D7896ViewModel.cs index ef7ee84..c7c4286 100644 --- a/ViewModels/D7896ViewModel.cs +++ b/ViewModels/D7896ViewModel.cs @@ -141,16 +141,16 @@ public partial class D7896ViewModel : ObservableObject catch { } } - private async Task GetInitialResistanceAsync() - { - if (!await _plcService.IsConnectedAsync()) return 0; - try - { - float rawResistance = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.Resistance); - return rawResistance; - } - catch { return 0; } - } + //private async Task GetInitialResistanceAsync() + //{ + // if (!await _plcService.IsConnectedAsync()) return 0; + // try + // { + // float rawResistance = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.Resistance); + // return rawResistance; + // } + // catch { return 0; } + //} [RelayCommand] private async Task StartTestAsync() @@ -194,7 +194,7 @@ public partial class D7896ViewModel : ObservableObject await _th1963Ustd.ConnectAsync("192.168.1.12", 45454); // 改为实际IP await _th1963Ustd.ConfigureForHighSpeedDcvAsync(); - await _th1953Ustd.ConnectAsync("192.168.1.12", 45454); // 改为实际IP + await _th1953Ustd.ConnectAsync("192.168.1.13", 45454); // 改为实际IP await _th1953Ustd.ConfigureForHighSpeedDcvAsync(); } catch (Exception ex) @@ -207,15 +207,39 @@ public partial class D7896ViewModel : ObservableObject { StatusMessage = "正在加压..."; await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.InletValveCoil, true); - await Task.Delay(3000); - await UpdateRealTimeParametersAsync(); - if (ChamberPressure < PressureValue - 5) - MessageBox.Show($"压力未达到设定值 {PressureValue} kPa", "警告"); + + const int pressureStableTimeoutMs = 10000; // 30秒超时 + const double pressureTolerance = 5.0; // 允许误差 ±5 kPa + var startTime = DateTime.Now; + bool pressureReached = false; + + while ((DateTime.Now - startTime).TotalMilliseconds < pressureStableTimeoutMs) + { + await Task.Delay(500); // 每0.5秒检测一次 + await UpdateRealTimeParametersAsync(); + if (ChamberPressure >= PressureValue - pressureTolerance) + { + pressureReached = true; + break; + } + } + + if (!pressureReached) + { + // 加压失败,关闭进气阀,中止测试 + await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.InletValveCoil, false); + MessageBox.Show($"加压超时,压力未能达到 {PressureValue} kPa(当前 {ChamberPressure:F1} kPa)", "错误"); + return; + } + + // 压力已达到,可关闭进气阀(或保持,看系统需求) + await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.InletValveCoil, false); + StatusMessage = $"压力已稳定在 {ChamberPressure:F1} kPa"; } - double initialResistance = await GetInitialResistanceAsync(); - if (initialResistance > 0) - StatusMessage = $"初始电阻: {initialResistance:F4} Ω"; + //double initialResistance = await GetInitialResistanceAsync(); + //if (initialResistance > 0) + // StatusMessage = $"初始电阻: {initialResistance:F4} Ω"; Measurements.Clear(); IsTesting = true; @@ -248,12 +272,7 @@ public partial class D7896ViewModel : ObservableObject StatusMessage = $"正在执行第 {i} 次测量..."; // 准备批量采集参数(每通道采样点数,采样率1000点/秒,加热时间1秒 -> 1000点) - int samples = 800; // 1秒 * 1000点/秒 - - - - - + int samples = 200; // 1秒 * 1000点/秒 // 预配置两台表:进入等待触发状态 await _th1963Ustd.PrepareBatchAsync(samples); @@ -262,24 +281,33 @@ public partial class D7896ViewModel : ObservableObject // 启动加热脉冲 (PLC) await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.StartCommand, true); - // 等待极短时间确保电流稳定(如 5ms) - await Task.Delay(5); + + try { await Task.Delay(5, _testCts.Token); } catch (OperationCanceledException) { break; } // 同时发送触发信号给两台电压表 await Task.WhenAll(_th1963Ustd.TriggerAsync(), _th1953Ustd.TriggerAsync()); // 等待加热结束 - await Task.Delay((int)(heatingDuration * 1000)); + try { await Task.Delay((int)(heatingDuration * 1000), _testCts.Token); } catch (OperationCanceledException) { break; } // 停止加热 await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.StartCommand, false); // 等待采集完成(剩余时间) int remainingMs = (int)((totalDuration - heatingDuration) * 1000) + 100; - await Task.Delay(remainingMs); + try { await Task.Delay(remainingMs, _testCts.Token); } catch (OperationCanceledException) { break; } // 获取采集数据 double[] ustd = await _th1963Ustd.FetchBatchAsync(); double[] upt = await _th1953Ustd.FetchBatchAsync(); + for (int j = 0; j < 20; j++) + { + Logger.Log($"第{j}点: U_std={ustd[j]:F6} V, U_pt={upt[j]:F6} V"); + } + + + + + StandardResistorVoltage = ustd.Average(); PlatinumVoltage = upt.Average(); @@ -292,9 +320,23 @@ public partial class D7896ViewModel : ObservableObject { timeArray[idx] = idx * totalDuration / samples; } - // 计算本次测量的 λ 和 α - var (lambda, alpha, deltaT, coolingPoints) = ComputeThermalProperties(upt, ustd, timeArray, initialResistance, CurrentTestTemperature); + + + // 动态计算初始电阻 R0(取前 10 个点的平均值,这期间温升很小) + int warmupPoints = Math.Min(10, ustd.Length); + double sumR0 = 0; + for (int j = 0; j < warmupPoints; j++) + { + double current = ustd[j] / StandardResistor; + double resistance = upt[j] / current; + sumR0 += resistance; + } + double dynamicR0 = sumR0 / warmupPoints; + Logger.Log($"动态计算 R0 = {dynamicR0:F6} Ω"); + + // 计算本次测量的 λ 和 α + var (lambda, alpha, deltaT, coolingPoints) = ComputeThermalProperties(upt, ustd, timeArray, dynamicR0, CurrentTestTemperature); // 添加结果日志 Logger.Log($"测量 {i} 结果: λ={lambda:F6} W/(m·K), α={alpha:E6} m²/s"); @@ -318,14 +360,16 @@ public partial class D7896ViewModel : ObservableObject Logger.Log($"热扩散率 α: {alpha:E6} m²/s"); Logger.Log($"体积热容 VHC: {result.VolumetricHeatCapacity:F2} kJ/(m³·K)"); Logger.Log($"比热容 Cp: {result.SpecificHeatCapacity:F2} J/(kg·K) (密度 = {SampleDensity:F1} kg/m³)"); - Logger.Log($"初始电阻 R0: {initialResistance:F6} Ω"); + Logger.Log($"初始电阻 R0: {dynamicR0:F6} Ω"); Logger.Log($"测试温度: {CurrentTestTemperature:F2} °C"); Logger.Log($"铂丝平均电阻: {PlatinumResistance:F6} Ω"); Logger.Log($"样品池压力: {ChamberPressure:F2} kPa"); Logger.Log("==========================================="); if (i < _config.TestParameters.MeasurementCount && !_stopRequested) - await Task.Delay(_config.TestParameters.IntervalSeconds * 1000); + { + try { await Task.Delay(_config.TestParameters.IntervalSeconds * 1000, _testCts.Token); } catch (OperationCanceledException) { break; } + } } CalculateAverages(); @@ -552,47 +596,47 @@ public partial class D7896ViewModel : ObservableObject return timeArray.Length - 1; } - /// - /// 最小二乘法拟合斜率 (X轴为横坐标,Y轴为纵坐标) — 用于加热段 ln(t) vs ΔT - /// - private double LeastSquaresSlope(List points) - { - if (points.Count < 2) return 0.001; - double sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0; - foreach (var p in points) - { - sumX += p.X; - sumY += p.Y; - sumXY += p.X * p.Y; - sumX2 += p.X * p.X; - } - double n = points.Count; - double denominator = n * sumX2 - sumX * sumX; - if (Math.Abs(denominator) < 1e-10) return 0.001; - double slope = (n * sumXY - sumX * sumY) / denominator; - return slope; - } + ///// + ///// 最小二乘法拟合斜率 (X轴为横坐标,Y轴为纵坐标) — 用于加热段 ln(t) vs ΔT + ///// + //private double LeastSquaresSlope(List points) + //{ + // if (points.Count < 2) return 0.001; + // double sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0; + // foreach (var p in points) + // { + // sumX += p.X; + // sumY += p.Y; + // sumXY += p.X * p.Y; + // sumX2 += p.X * p.X; + // } + // double n = points.Count; + // double denominator = n * sumX2 - sumX * sumX; + // if (Math.Abs(denominator) < 1e-10) return 0.001; + // double slope = (n * sumXY - sumX * sumY) / denominator; + // return slope; + //} - /// - /// 最小二乘法拟合斜率 (X轴为时间t,Y轴为 ln(ΔT)) — 用于冷却段 - /// - private double LeastSquaresSlopeOnTime(List points) - { - if (points.Count < 2) return -1.0; - double sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0; - foreach (var p in points) - { - sumX += p.X; - sumY += p.Y; - sumXY += p.X * p.Y; - sumX2 += p.X * p.X; - } - double n = points.Count; - double denominator = n * sumX2 - sumX * sumX; - if (Math.Abs(denominator) < 1e-10) return -1.0; - double slope = (n * sumXY - sumX * sumY) / denominator; - return slope; - } + ///// + ///// 最小二乘法拟合斜率 (X轴为时间t,Y轴为 ln(ΔT)) — 用于冷却段 + ///// + //private double LeastSquaresSlopeOnTime(List points) + //{ + // if (points.Count < 2) return -1.0; + // double sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0; + // foreach (var p in points) + // { + // sumX += p.X; + // sumY += p.Y; + // sumXY += p.X * p.Y; + // sumX2 += p.X * p.X; + // } + // double n = points.Count; + // double denominator = n * sumX2 - sumX * sumX; + // if (Math.Abs(denominator) < 1e-10) return -1.0; + // double slope = (n * sumXY - sumX * sumY) / denominator; + // return slope; + //} private void GenerateTemperatureCurveFromData(double[] time, double[] deltaT, List coolingPoints) { @@ -692,16 +736,14 @@ public partial class D7896ViewModel : ObservableObject } } + + [RelayCommand] - private async Task StopTestCommandAsync() + private async Task StopTest() { - if (!IsTesting) - { - MessageBox.Show("没有正在进行的测试", "提示"); - return; - } + if (!IsTesting) return; _stopRequested = true; - _testCts?.Cancel(); + _testCts?.Cancel(); // 取消所有等待的 Delay StatusMessage = "正在停止测试..."; await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.StartCommand, false); if (UsePressure) @@ -714,7 +756,6 @@ public partial class D7896ViewModel : ObservableObject IsTesting = false; StatusMessage = "测试已停止。"; } - [RelayCommand] private async Task PressureCalibrationAsync() => await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.PressureCalibrationCoil, true); [RelayCommand] private async Task ResistanceZeroAsync() => await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.ResistanceZeroCoil, true); [RelayCommand] diff --git a/Views/ConfigWindow.xaml b/Views/ConfigWindow.xaml index f007ab8..b72233a 100644 --- a/Views/ConfigWindow.xaml +++ b/Views/ConfigWindow.xaml @@ -1,7 +1,7 @@  @@ -37,7 +37,7 @@ -