This commit is contained in:
@@ -52,6 +52,11 @@ public partial class ConfigViewModel : ObservableObject
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//public IAsyncRelayCommand SaveCommand => new AsyncRelayCommand(Save);
|
||||
|
||||
|
||||
[RelayCommand]
|
||||
private async Task Save()
|
||||
{
|
||||
|
||||
@@ -141,16 +141,16 @@ public partial class D7896ViewModel : ObservableObject
|
||||
catch { }
|
||||
}
|
||||
|
||||
private async Task<double> GetInitialResistanceAsync()
|
||||
{
|
||||
if (!await _plcService.IsConnectedAsync()) return 0;
|
||||
try
|
||||
{
|
||||
float rawResistance = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.Resistance);
|
||||
return rawResistance;
|
||||
}
|
||||
catch { return 0; }
|
||||
}
|
||||
//private async Task<double> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 最小二乘法拟合斜率 (X轴为横坐标,Y轴为纵坐标) — 用于加热段 ln(t) vs ΔT
|
||||
/// </summary>
|
||||
private double LeastSquaresSlope(List<DataPoint> 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;
|
||||
}
|
||||
///// <summary>
|
||||
///// 最小二乘法拟合斜率 (X轴为横坐标,Y轴为纵坐标) — 用于加热段 ln(t) vs ΔT
|
||||
///// </summary>
|
||||
//private double LeastSquaresSlope(List<DataPoint> 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;
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// 最小二乘法拟合斜率 (X轴为时间t,Y轴为 ln(ΔT)) — 用于冷却段
|
||||
/// </summary>
|
||||
private double LeastSquaresSlopeOnTime(List<DataPoint> 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;
|
||||
}
|
||||
///// <summary>
|
||||
///// 最小二乘法拟合斜率 (X轴为时间t,Y轴为 ln(ΔT)) — 用于冷却段
|
||||
///// </summary>
|
||||
//private double LeastSquaresSlopeOnTime(List<DataPoint> 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<DataPoint> 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]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Window x:Class="ASTM_D7896_Tester.Views.ConfigWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="高级参数配置" Height="300" Width="400"
|
||||
Title="高级参数配置" Height="300" Width="450"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
<Grid Margin="20">
|
||||
<Grid.RowDefinitions>
|
||||
@@ -37,7 +37,7 @@
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Row="5" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,20,0,0">
|
||||
<Button Content="保存并关闭" Command="{Binding SaveAndCloseCommand}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}" Width="100" Margin="5"/>
|
||||
<Button Content="保存并关闭" Command="{Binding SaveCommand}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}" Width="100" Margin="5"/>
|
||||
<Button Content="取消" Click="CancelButton_Click" Width="100" Margin="5"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -214,15 +214,67 @@
|
||||
|
||||
<!-- 5. 测量数据表格(占用剩余高度) -->
|
||||
<Border Grid.Row="4" Background="White" CornerRadius="6" Padding="8" Margin="0,5" Effect="{StaticResource CardShadow}">
|
||||
<DataGrid ItemsSource="{Binding Measurements}" AutoGenerateColumns="False"
|
||||
<DataGrid ItemsSource="{Binding Measurements}" AutoGenerateColumns="False" HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
CanUserAddRows="False" IsReadOnly="True"
|
||||
HeadersVisibility="Column" GridLinesVisibility="Horizontal"
|
||||
RowHeight="28" MinHeight="150">
|
||||
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="序号" Binding="{Binding Index}" Width="60"/>
|
||||
<DataGridTextColumn Header="热导率 (W/m·K)" Binding="{Binding ThermalConductivity, StringFormat=F5}" Width="*"/>
|
||||
<DataGridTextColumn Header="热扩散率 (m²/s)" Binding="{Binding ThermalDiffusivity, StringFormat=F10}" Width="*"/>
|
||||
<DataGridTextColumn Header="体积热容 (kJ/m³·K)" Binding="{Binding VolumetricHeatCapacity, StringFormat=F2}" Width="*"/>
|
||||
<DataGridTextColumn Header="序号" Binding="{Binding Index}" Width="60">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="HorizontalAlignment" Value="Center"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
<DataGridTextColumn.HeaderStyle>
|
||||
<Style TargetType="DataGridColumnHeader">
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"/>
|
||||
</Style>
|
||||
</DataGridTextColumn.HeaderStyle>
|
||||
</DataGridTextColumn>
|
||||
|
||||
<DataGridTextColumn Header="热导率 (W/m·K)" Binding="{Binding ThermalConductivity, StringFormat=F5}" Width="*">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="HorizontalAlignment" Value="Center"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
<DataGridTextColumn.HeaderStyle>
|
||||
<Style TargetType="DataGridColumnHeader">
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"/>
|
||||
</Style>
|
||||
</DataGridTextColumn.HeaderStyle>
|
||||
</DataGridTextColumn>
|
||||
|
||||
<DataGridTextColumn Header="热扩散率 (m²/s)" Binding="{Binding ThermalDiffusivity, StringFormat=F10}" Width="*">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="HorizontalAlignment" Value="Center"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
<DataGridTextColumn.HeaderStyle>
|
||||
<Style TargetType="DataGridColumnHeader">
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"/>
|
||||
</Style>
|
||||
</DataGridTextColumn.HeaderStyle>
|
||||
</DataGridTextColumn>
|
||||
|
||||
<DataGridTextColumn Header="体积热容 (kJ/m³·K)" Binding="{Binding VolumetricHeatCapacity, StringFormat=F2}" Width="*">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="HorizontalAlignment" Value="Center"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
<DataGridTextColumn.HeaderStyle>
|
||||
<Style TargetType="DataGridColumnHeader">
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"/>
|
||||
</Style>
|
||||
</DataGridTextColumn.HeaderStyle>
|
||||
</DataGridTextColumn>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</Border>
|
||||
@@ -257,7 +309,7 @@
|
||||
IsEnabled="{Binding IsTesting, Converter={StaticResource InverseBooleanConverter}}"
|
||||
Background="{StaticResource PrimaryButtonBrush}"/>
|
||||
|
||||
<Button Content="■ 停止测试" Command="{Binding StopTestCommandAsync}" Width="130" Height="36" Margin="8" Background="Orange"/>
|
||||
<Button Content="■ 停止测试" Command="{Binding StopTestCommand}" Width="130" Height="36" Margin="8" Background="Orange"/>
|
||||
|
||||
|
||||
<Button Content="⟳ 重置" Command="{Binding ResetCommand}" Width="100" Height="36" Margin="8"/>
|
||||
@@ -275,7 +327,7 @@
|
||||
<ComboBox ItemsSource="{Binding ReferenceLiquids}" SelectedItem="{Binding SelectedReferenceLiquid}" Width="100" Margin="5,0"/>
|
||||
<TextBlock Text="参考热导率 (W/m·K):" VerticalAlignment="Center" Margin="10,0,5,0"/>
|
||||
<TextBox Text="{Binding ReferenceConductivity}" Width="70" Margin="0,0,10,0"/>
|
||||
<Button Content="开始校准" Command="{Binding PerformSystemCalibrationCommand}" Width="100"/>
|
||||
<!--<Button Content="开始校准" Command="{Binding PerformSystemCalibrationCommand}" Width="100"/>-->
|
||||
</WrapPanel>
|
||||
<TextBlock Text="{Binding CalibrationStatus}" FontSize="11" Foreground="Blue" Margin="0,5,0,0"/>
|
||||
</StackPanel>
|
||||
|
||||
Reference in New Issue
Block a user