diff --git a/CSI-L028瞬态热线法导热系数测试仪器电气清单.xlsx b/CSI-L028瞬态热线法导热系数测试仪器电气清单.xlsx index 1c07dd5..553dc65 100644 Binary files a/CSI-L028瞬态热线法导热系数测试仪器电气清单.xlsx and b/CSI-L028瞬态热线法导热系数测试仪器电气清单.xlsx differ diff --git a/Helpers/Logger.cs b/Helpers/Logger.cs new file mode 100644 index 0000000..0eba27b --- /dev/null +++ b/Helpers/Logger.cs @@ -0,0 +1,34 @@ +using System; +using System.IO; +using System.Diagnostics; + +namespace ASTM_D7896_Tester.Services +{ + public static class Logger + { + private static readonly object _lock = new object(); + private static string _logFilePath = "D7896_Test_Log.txt"; + + public static void Log(string message, bool toConsole = true, bool toFile = true) + { + string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); + string logLine = $"{timestamp} - {message}"; + + if (toConsole) + Debug.WriteLine(logLine); + + if (toFile) + { + lock (_lock) + { + File.AppendAllText(_logFilePath, logLine + Environment.NewLine); + } + } + } + + public static void LogData(string label, double value, string unit = "") + { + Log($"{label}: {value:F6} {unit}".Trim()); + } + } +} \ No newline at end of file diff --git a/ViewModels/D7896ViewModel.cs b/ViewModels/D7896ViewModel.cs index 7a9754d..fe5611c 100644 --- a/ViewModels/D7896ViewModel.cs +++ b/ViewModels/D7896ViewModel.cs @@ -23,7 +23,8 @@ public partial class D7896ViewModel : ObservableObject // 电压表服务 private Th1963LanService _th1963Ustd; // 6位半测量标准电阻电压 U_std - private FiveHalfDmmService _fiveHalfUpt; // 5位半测量铂丝电压 U_pt + private Th1963LanService _th1953Ustd; // 6位半测量标准电阻电压 U_std + //private FiveHalfDmmService _fiveHalfUpt; // 5位半测量铂丝电压 U_pt private CancellationTokenSource _testCts; // 用于停止测试 private bool _stopRequested; @@ -87,7 +88,8 @@ public partial class D7896ViewModel : ObservableObject [ObservableProperty] private double _sampleDensity = 1000.0; // 新增,密度默认值1000 kg/m³(水) - + double heatingDuration = 0.8; // 加热时间 0.8 秒(需与您的加热脉冲宽度一致) + double totalDuration = 1.6; // 总采样时间(加热 + 冷却) public D7896ViewModel() { _config = App.PlcConfig ?? new AppConfig(); @@ -108,8 +110,8 @@ public partial class D7896ViewModel : ObservableObject // 初始化电压表服务 // TH1963 IP 地址需要根据实际配置修改,建议从配置文件读取 _th1963Ustd = new Th1963LanService(); - // 5位半万用表串口名,例如 "COM3" - _fiveHalfUpt = new FiveHalfDmmService("COM6", 115200); + + _th1953Ustd = new Th1963LanService(); StartBackgroundMonitoring(); } @@ -123,17 +125,18 @@ public partial class D7896ViewModel : ObservableObject private async Task MonitorPlcValues() { if (!await _plcService.IsConnectedAsync()) return; + if (Application.Current == null || Application.Current.Dispatcher == null) return; try { float rawResistance = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.Resistance); double newResistance = rawResistance; - Application.Current.Dispatcher.Invoke(() => PlatinumResistance = newResistance); + Application.Current?.Dispatcher.Invoke(() => PlatinumResistance = newResistance); float rawPressure = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.Pressure); - Application.Current.Dispatcher.Invoke(() => ChamberPressure = rawPressure); + Application.Current?.Dispatcher.Invoke(() => ChamberPressure = rawPressure); float rawTemp = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.Temperature); - Application.Current.Dispatcher.Invoke(() => CurrentTestTemperature = rawTemp); + Application.Current?.Dispatcher.Invoke(() => CurrentTestTemperature = rawTemp); } catch { } } @@ -144,7 +147,7 @@ public partial class D7896ViewModel : ObservableObject try { float rawResistance = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.Resistance); - return rawResistance / 1000.0; + return rawResistance; } catch { return 0; } } @@ -187,10 +190,12 @@ public partial class D7896ViewModel : ObservableObject try { - if (!_fiveHalfUpt.IsOpen) _fiveHalfUpt.Open(); + await _th1963Ustd.ConnectAsync("192.168.1.12", 45454); // 改为实际IP await _th1963Ustd.ConfigureForHighSpeedDcvAsync(); - await _fiveHalfUpt.ConfigureHighSpeedDcvAsync(); + + await _th1953Ustd.ConnectAsync("192.168.1.13", 45454); // 改为实际IP + await _th1953Ustd.ConfigureForHighSpeedDcvAsync(); } catch (Exception ex) { @@ -219,6 +224,22 @@ public partial class D7896ViewModel : ObservableObject try { + + // 预热:进行一次虚拟测量 + await _th1963Ustd.ConfigureForHighSpeedDcvAsync(); + await _th1963Ustd.PrepareBatchAsync(10); + await _th1963Ustd.TriggerAsync(); + await Task.Delay(100); + await _th1963Ustd.FetchBatchAsync(); // 丢弃结果 + + + // 预热:进行一次虚拟测量 + await _th1953Ustd.ConfigureForHighSpeedDcvAsync(); + await _th1953Ustd.PrepareBatchAsync(10); + await _th1953Ustd.TriggerAsync(); + await Task.Delay(100); + await _th1953Ustd.FetchBatchAsync(); // 丢弃结果 + for (int i = 1; i <= _config.TestParameters.MeasurementCount; i++) { if (_stopRequested) break; @@ -227,41 +248,56 @@ public partial class D7896ViewModel : ObservableObject StatusMessage = $"正在执行第 {i} 次测量..."; // 准备批量采集参数(每通道采样点数,采样率1000点/秒,加热时间1秒 -> 1000点) - int samples = 1000; // 1秒 * 1000点/秒 + int samples = 800; // 1秒 * 1000点/秒 + + + + + // 预配置两台表:进入等待触发状态 await _th1963Ustd.PrepareBatchAsync(samples); - await _fiveHalfUpt.PrepareBatchAsync(samples); // 需要在FiveHalfDmmService中实现PrepareBatchAsync,见补充 + await _th1953Ustd.PrepareBatchAsync(samples); // 启动加热脉冲 (PLC) await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.StartCommand, true); - // 同时发送触发信号给两台电压表 - await Task.WhenAll(_th1963Ustd.TriggerAsync(), _fiveHalfUpt.TriggerAsync()); - // 等待加热脉冲持续1秒 - await Task.Delay(1); + // 等待极短时间确保电流稳定(如 5ms) + await Task.Delay(5); + // 同时发送触发信号给两台电压表 + await Task.WhenAll(_th1963Ustd.TriggerAsync(), _th1953Ustd.TriggerAsync()); + + // 等待加热结束 + await Task.Delay((int)(heatingDuration * 1000)); // 停止加热 await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.StartCommand, false); - // 等待采集完成(留出额外时间) - await Task.Delay(500); + // 等待采集完成(剩余时间) + int remainingMs = (int)((totalDuration - heatingDuration) * 1000) + 100; + await Task.Delay(remainingMs); // 获取采集数据 double[] ustd = await _th1963Ustd.FetchBatchAsync(); - double[] upt = await _fiveHalfUpt.FetchBatchAsync(); + double[] upt = await _th1953Ustd.FetchBatchAsync(); + StandardResistorVoltage = ustd.Average(); + PlatinumVoltage = upt.Average(); + // 添加日志:原始电压统计 + Logger.Log($"测量 {i}: U_std 点数={ustd.Length}, 平均值={ustd.Average():F6} V, 最大值={ustd.Max():F6} V"); + Logger.Log($"测量 {i}: U_pt 点数={upt.Length}, 平均值={upt.Average():F6} V, 最大值={upt.Max():F6} V"); - - // 构建时间数组(假设采样时间正好1秒,采样点数 = ustd.Length) double[] timeArray = new double[ustd.Length]; for (int idx = 0; idx < timeArray.Length; idx++) { - timeArray[idx] = idx / (double)samples; // 0 ~ 1 秒 + timeArray[idx] = idx * totalDuration / samples; } // 计算本次测量的 λ 和 α var (lambda, alpha, deltaT, coolingPoints) = ComputeThermalProperties(upt, ustd, timeArray, initialResistance, CurrentTestTemperature); + // 添加结果日志 + Logger.Log($"测量 {i} 结果: λ={lambda:F6} W/(m·K), α={alpha:E6} m²/s"); + // 生成温升曲线图 GenerateTemperatureCurveFromData(timeArray, deltaT, coolingPoints); @@ -276,6 +312,18 @@ public partial class D7896ViewModel : ObservableObject Application.Current.Dispatcher.Invoke(() => Measurements.Add(result)); StatusMessage = $"第 {i} 次测量完成,λ={lambda:F4} W/m·K"; + // 在 result.CalculateVhcAndCp(SampleDensity); 之后添加 + Logger.Log($"========== 第 {i} 次测量详细数据 =========="); + Logger.Log($"热导率 λ: {lambda:F6} W/(m·K)"); + 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($"测试温度: {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); } @@ -300,8 +348,9 @@ public partial class D7896ViewModel : ObservableObject await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.OutletValveCoil, false); } IsTesting = false; - _fiveHalfUpt.Close(); + //_fiveHalfUpt.Close(); _th1963Ustd.Dispose(); + _th1953Ustd.Dispose(); _testCts?.Dispose(); } } @@ -324,6 +373,10 @@ public partial class D7896ViewModel : ObservableObject ptResistance[i] = upt[i] / current[i]; deltaT[i] = (ptResistance[i] - initialResistance) / (AlphaPt * initialResistance); } + // 添加日志:中间数据统计 + Logger.Log($"电流平均值: {current.Average():F6} A, 最大值: {current.Max():F6} A"); + Logger.Log($"铂丝电阻平均值: {ptResistance.Average():F6} Ω, 初始电阻: {initialResistance:F6} Ω"); + Logger.Log($"温升最大值: {deltaT.Max():F4} ℃, 平均值: {deltaT.Average():F4} ℃"); // 2. ========== 加热段拟合 → 热导率 λ ========== double tStart = 0.1; @@ -342,14 +395,17 @@ public partial class D7896ViewModel : ObservableObject double slope = LeastSquaresSlope(heatingPoints); if (slope <= 0) slope = 0.0001; + Logger.Log($"加热段拟合斜率 B = {slope:F6} (ΔT vs ln(t))"); + double avgCurrentSq = current.Average(c => c * c); double avgResistance = ptResistance.Average(); double powerPerLength = (avgCurrentSq * avgResistance) / _config.TestParameters.PlatinumWireLength; double lambda = powerPerLength / (4 * Math.PI * slope); - + Logger.Log($"单位长度加热功率 Q = {powerPerLength:F6} W/m"); + Logger.Log($"热导率 λ = {lambda:F6} W/(m·K)"); // 3. ========== 冷却段拟合 → 热扩散率 α ========== - double coolingStart = 1.0; - double coolingEnd = 2.0; + double coolingStart = heatingDuration; // 0.8 秒 + double coolingEnd = totalDuration; // 1.6 秒 int coolingStartIdx = FindIndex(time, coolingStart); int coolingEndIdx = FindIndex(time, coolingEnd); if (coolingStartIdx < 0) coolingStartIdx = n / 2; @@ -369,6 +425,10 @@ public partial class D7896ViewModel : ObservableObject if (alpha <= 0 || double.IsNaN(alpha) || double.IsInfinity(alpha)) alpha = 0.12e-6; // 默认值 + Logger.Log($"冷却段拟合斜率 D = {coolingSlope:F6} (lnΔT vs t)"); + Logger.Log($"时间常数 τ = {tau:F6} s"); + Logger.Log($"热扩散率 α = {alpha:E6} m²/s"); + // 准备冷却曲线数据点(用于绘图) var coolingPoints = new List(); for (int i = coolingStartIdx; i <= coolingEndIdx; i++) @@ -478,14 +538,6 @@ public partial class D7896ViewModel : ObservableObject CurveTitle = $"已完成 {CurrentMeasurementIndex} 次测量"; } - private void GenerateTemperatureCurve(float lambda, float alpha) { /* 旧方法,不再使用 */ } - - private OxyColor GetColorForIndex(int index) - { - var colors = new[] { OxyColors.Red, OxyColors.Blue, OxyColors.Green, OxyColors.Orange, - OxyColors.Purple, OxyColors.Brown, OxyColors.Pink, OxyColors.Cyan, OxyColors.Magenta, OxyColors.Olive }; - return colors[(index - 1) % colors.Length]; - } private void CalculateAverages() { diff --git a/ViewModels/MeasurementResult.cs b/ViewModels/MeasurementResult.cs index c456edd..60016ef 100644 --- a/ViewModels/MeasurementResult.cs +++ b/ViewModels/MeasurementResult.cs @@ -1,4 +1,5 @@ using CommunityToolkit.Mvvm.ComponentModel; +using System.Diagnostics; // 添加命名空间 namespace ASTM_D7896_Tester.ViewModels; @@ -19,10 +20,20 @@ public partial class MeasurementResult : ObservableObject public void CalculateVhcAndCp(double density) { CalculateVhc(); // 先计算 VHC + + // 日志:记录计算前的参数 + Debug.WriteLine($"[MeasurementResult] 计算比热容 - 密度: {density} kg/m³, 体积热容: {VolumetricHeatCapacity} kJ/(m³·K)"); + if (density > 0) - SpecificHeatCapacity = VolumetricHeatCapacity * 1000 / density; // 注意单位转换 + { + SpecificHeatCapacity = VolumetricHeatCapacity * 1000 / density; + Debug.WriteLine($"[MeasurementResult] 计算得到比热容: {SpecificHeatCapacity} J/(kg·K)"); + } else + { SpecificHeatCapacity = 0; + Debug.WriteLine($"[MeasurementResult] 警告: 密度无效 (density={density}),比热容设为0"); + } } [ObservableProperty] @@ -30,10 +41,17 @@ public partial class MeasurementResult : ObservableObject public void CalculateVhc() { - if (ThermalDiffusivity > 0) - VolumetricHeatCapacity = ThermalConductivity / (ThermalDiffusivity * 1e-6) / 1000.0; - else - VolumetricHeatCapacity = 0; - } + Debug.WriteLine($"[MeasurementResult] 计算体积热容 - 热导率: {ThermalConductivity} W/(m·K), 热扩散率: {ThermalDiffusivity} ×10⁻⁶ m²/s"); + if (ThermalDiffusivity > 0) + { + VolumetricHeatCapacity = ThermalConductivity / (ThermalDiffusivity * 1e-6) / 1000.0; + Debug.WriteLine($"[MeasurementResult] 计算得到体积热容: {VolumetricHeatCapacity} kJ/(m³·K)"); + } + else + { + VolumetricHeatCapacity = 0; + Debug.WriteLine($"[MeasurementResult] 警告: 热扩散率为0,体积热容设为0"); + } + } } \ No newline at end of file diff --git a/Views/D7896View.xaml b/Views/D7896View.xaml index cdc334d..3484787 100644 --- a/Views/D7896View.xaml +++ b/Views/D7896View.xaml @@ -5,7 +5,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" - d:DesignHeight="768" d:DesignWidth="1024"> + d:DesignHeight="768" d:DesignWidth="1024" Loaded="UserControl_Loaded"> @@ -221,7 +221,7 @@ - + diff --git a/Views/D7896View.xaml.cs b/Views/D7896View.xaml.cs index 3ff7eab..a79b1b7 100644 --- a/Views/D7896View.xaml.cs +++ b/Views/D7896View.xaml.cs @@ -29,5 +29,10 @@ namespace ASTM_D7896_Tester.Views InitializeComponent(); DataContext = new D7896ViewModel(); } + + private void UserControl_Loaded(object sender, RoutedEventArgs e) + { + + } } } diff --git a/appsettings.json b/appsettings.json index f8b106e..6a51af3 100644 --- a/appsettings.json +++ b/appsettings.json @@ -25,7 +25,7 @@ "TestParameters": { "MeasurementCount": 10, "IntervalSeconds": 30, - "PlatinumWireLength": 0.07, + "PlatinumWireLength": 0.07, //铂丝长度(单位:米) "PlatinumWireDiameter": 0.00006, "ReportOutputPath": "Reports\\", "DefaultSampleVolume": 40.0,