更新2026
This commit is contained in:
@@ -692,7 +692,8 @@
|
|||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Grid>
|
<Grid>
|
||||||
@@ -713,11 +714,39 @@
|
|||||||
<TextBlock Grid.Row="1"
|
<TextBlock Grid.Row="1"
|
||||||
x:Name="RealtimeSpeedText"
|
x:Name="RealtimeSpeedText"
|
||||||
Text="{Binding RealtimeSpeedText}"
|
Text="{Binding RealtimeSpeedText}"
|
||||||
Style="{StaticResource MetricValue}"
|
Style="{StaticResource MetricValue}"
|
||||||
FontSize="50"
|
FontSize="50"
|
||||||
Foreground="#0F766E"
|
Foreground="#0F766E"
|
||||||
VerticalAlignment="Center" />
|
VerticalAlignment="Center"
|
||||||
<Border Grid.Row="2" Style="{StaticResource InfoStrip}">
|
Margin="0,4,0,10" />
|
||||||
|
<Grid Grid.Row="2" Margin="0,2,0,10">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Text="实时扭矩" Style="{StaticResource MetricTitle}" HorizontalAlignment="Left" />
|
||||||
|
<Button Grid.Column="1"
|
||||||
|
Content="扭矩归零"
|
||||||
|
Command="{Binding ZeroTorqueCommand}"
|
||||||
|
FontSize="13"
|
||||||
|
Padding="8,3"
|
||||||
|
MinHeight="28"
|
||||||
|
Background="#64748B"
|
||||||
|
BorderBrush="#475569" />
|
||||||
|
<TextBlock Grid.Row="1"
|
||||||
|
Grid.ColumnSpan="2"
|
||||||
|
x:Name="RealtimeTorqueText"
|
||||||
|
Text="{Binding RealtimeTorqueText}"
|
||||||
|
Style="{StaticResource MetricValue}"
|
||||||
|
FontSize="50"
|
||||||
|
Foreground="#1D4ED8"
|
||||||
|
Margin="0,4,0,0" />
|
||||||
|
</Grid>
|
||||||
|
<Border Grid.Row="3" Style="{StaticResource InfoStrip}">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
@@ -746,61 +775,20 @@
|
|||||||
<Border Grid.Column="1" Style="{StaticResource PanelBorder}" Margin="10,0,0,0">
|
<Border Grid.Column="1" Style="{StaticResource PanelBorder}" Margin="10,0,0,0">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Grid>
|
<local:TorqueTrendControl Samples="{Binding TorqueSamples}"
|
||||||
<Grid.ColumnDefinitions>
|
MinHeight="210" />
|
||||||
<ColumnDefinition Width="*" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<TextBlock Text="实时扭矩" Style="{StaticResource MetricTitle}" HorizontalAlignment="Left" />
|
|
||||||
<Button Grid.Column="1"
|
|
||||||
Content="归零"
|
|
||||||
Command="{Binding ZeroTorqueCommand}"
|
|
||||||
FontSize="13"
|
|
||||||
Padding="8,3"
|
|
||||||
MinHeight="28"
|
|
||||||
Background="#64748B"
|
|
||||||
BorderBrush="#475569" />
|
|
||||||
</Grid>
|
|
||||||
<TextBlock Grid.Row="1"
|
<TextBlock Grid.Row="1"
|
||||||
x:Name="RealtimeTorqueText"
|
Text="{Binding TorqueCurveStatusText}"
|
||||||
Text="{Binding RealtimeTorqueText}"
|
FontSize="14"
|
||||||
Style="{StaticResource MetricValue}"
|
FontWeight="SemiBold"
|
||||||
FontSize="50"
|
Foreground="#52616F"
|
||||||
Foreground="#1D4ED8"
|
HorizontalAlignment="Center"
|
||||||
Margin="0,2,0,4" />
|
Margin="0,6,0,0" />
|
||||||
<Grid Grid.Row="2" MinHeight="96" Margin="0,2,0,0">
|
<TextBlock Grid.Row="2"
|
||||||
<Grid>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="*" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<Grid Grid.Row="1">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="17*"/>
|
|
||||||
<ColumnDefinition Width="50*"/>
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="*" />
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<local:TorqueTrendControl Samples="{Binding TorqueSamples}"
|
|
||||||
MinHeight="86" Grid.ColumnSpan="2" />
|
|
||||||
<TextBlock Grid.Row="1"
|
|
||||||
Text="{Binding TorqueCurveStatusText}"
|
|
||||||
FontSize="14"
|
|
||||||
FontWeight="SemiBold"
|
|
||||||
Foreground="#52616F"
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
Margin="115,4,0,0" Grid.Column="1" />
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
<TextBlock Grid.Row="3"
|
|
||||||
x:Name="FinalSpeedTorqueText"
|
x:Name="FinalSpeedTorqueText"
|
||||||
Text="{Binding FinalSpeedTorqueText}"
|
Text="{Binding FinalSpeedTorqueText}"
|
||||||
FontSize="17"
|
FontSize="17"
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
private const double TenthsRegisterScale = 10.0;
|
private const double TenthsRegisterScale = 10.0;
|
||||||
private const int MaxTorqueSampleCount = 300;
|
private const int MaxTorqueSampleCount = 300;
|
||||||
private const double MinimumTorqueChangeThreshold = 0.05;
|
private const double MinimumTorqueChangeThreshold = 0.05;
|
||||||
|
private const double MinimumSpeedChangeThreshold = 1.0;
|
||||||
private const string TorqueUnit = "mN.m";
|
private const string TorqueUnit = "mN.m";
|
||||||
private static readonly TimeSpan RealtimeRefreshInterval = TimeSpan.FromMilliseconds(100);
|
private static readonly TimeSpan RealtimeRefreshInterval = TimeSpan.FromMilliseconds(100);
|
||||||
private static readonly TimeSpan RealtimeDataFreshnessTimeout = TimeSpan.FromSeconds(3);
|
private static readonly TimeSpan RealtimeDataFreshnessTimeout = TimeSpan.FromSeconds(3);
|
||||||
@@ -250,7 +251,7 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
private string _speedTorquePeakTorqueText = $"0.00 {TorqueUnit}";
|
private string _speedTorquePeakTorqueText = $"0.00 {TorqueUnit}";
|
||||||
private string _speedTorqueMaxDisplacementText = "0.000 mm";
|
private string _speedTorqueMaxDisplacementText = "0.000 mm";
|
||||||
private string _speedTorqueFinalDisplacementText = "--";
|
private string _speedTorqueFinalDisplacementText = "--";
|
||||||
private string _torqueCurveStatusText = "保持时间曲线:未启动";
|
private string _torqueCurveStatusText = "转速/扭矩保持时间关系曲线:未启动";
|
||||||
private string _axialConfigSummaryText = "--";
|
private string _axialConfigSummaryText = "--";
|
||||||
private string _speedTorqueConfigSummaryText = "--";
|
private string _speedTorqueConfigSummaryText = "--";
|
||||||
private string _statusText = "完成测试后可导出报表。";
|
private string _statusText = "完成测试后可导出报表。";
|
||||||
@@ -779,7 +780,8 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
_axialForce = axialForce;
|
_axialForce = axialForce;
|
||||||
_realtimeTorque = realtimeTorque;
|
_realtimeTorque = realtimeTorque;
|
||||||
_realtimeSpeed = realtimeSpeed;
|
_realtimeSpeed = realtimeSpeed;
|
||||||
AppendTorqueSample(GetScaledTorque(), _realtimeSpeed, DateTime.Now);
|
DateTime sampledAt = DateTime.Now;
|
||||||
|
AppendTorqueSample(GetScaledTorque(), _realtimeSpeed, sampledAt);
|
||||||
if (_isDisplacementRunning)
|
if (_isDisplacementRunning)
|
||||||
{
|
{
|
||||||
_maxDisplacement = Math.Max(_maxDisplacement, Math.Abs(_relativeDisplacement));
|
_maxDisplacement = Math.Max(_maxDisplacement, Math.Abs(_relativeDisplacement));
|
||||||
@@ -794,8 +796,8 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
bool isVentValveOpen = ReadCoilValue(coilValues, VentValveCoil);
|
bool isVentValveOpen = ReadCoilValue(coilValues, VentValveCoil);
|
||||||
VentValveButtonText = isVentValveOpen ? "关闭气阀" : "通气阀";
|
VentValveButtonText = isVentValveOpen ? "关闭气阀" : "通气阀";
|
||||||
|
|
||||||
_lastSuccessfulRealtimeReadAt = DateTime.Now;
|
_lastSuccessfulRealtimeReadAt = sampledAt;
|
||||||
CaptureRealtimeSample(dialIndicator, coilValues);
|
CaptureRealtimeSample(dialIndicator, coilValues, sampledAt);
|
||||||
FinalizeNoLoadSpeedRunIfDue();
|
FinalizeNoLoadSpeedRunIfDue();
|
||||||
QueueSnapshotIfDue();
|
QueueSnapshotIfDue();
|
||||||
|
|
||||||
@@ -1360,11 +1362,17 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
CreateRecordPoint("转速/扭矩实时测试", "最终位移", finalDisplacement.HasValue ? $"{FormatDisplacement(finalDisplacement.Value)} mm" : "--", "mm", finalDisplacement.HasValue ? "记录" : "待停止"),
|
CreateRecordPoint("转速/扭矩实时测试", "最终位移", finalDisplacement.HasValue ? $"{FormatDisplacement(finalDisplacement.Value)} mm" : "--", "mm", finalDisplacement.HasValue ? "记录" : "待停止"),
|
||||||
CreateRecordPoint("转速/扭矩实时测试", "最终转速", finalSpeed.HasValue ? $"{FormatSpeed(finalSpeed.Value)} r/min" : "--", "r/min", finalSpeed.HasValue ? "记录" : "待停止"),
|
CreateRecordPoint("转速/扭矩实时测试", "最终转速", finalSpeed.HasValue ? $"{FormatSpeed(finalSpeed.Value)} r/min" : "--", "r/min", finalSpeed.HasValue ? "记录" : "待停止"),
|
||||||
CreateRecordPoint("转速/扭矩实时测试", "最终扭矩", finalTorque.HasValue ? $"{FormatTorque(finalTorque.Value)} {TorqueUnit}" : "--", TorqueUnit, finalTorque.HasValue ? "记录" : "待停止"),
|
CreateRecordPoint("转速/扭矩实时测试", "最终扭矩", finalTorque.HasValue ? $"{FormatTorque(finalTorque.Value)} {TorqueUnit}" : "--", TorqueUnit, finalTorque.HasValue ? "记录" : "待停止"),
|
||||||
CreateRecordPoint("转速/扭矩实时测试", "保持时间曲线判定", curve.Result, string.Empty, "记录"),
|
CreateRecordPoint("转速/扭矩实时测试", "转速/扭矩保持时间关系曲线判定", curve.Result, string.Empty, "记录"),
|
||||||
|
CreateRecordPoint("转速/扭矩实时测试", "扭矩变化阈值", $"{FormatTorque(curve.ChangeThresholdMilliNewtonMeters)} {TorqueUnit}", TorqueUnit),
|
||||||
|
CreateRecordPoint("转速/扭矩实时测试", "转速变化阈值", $"{FormatSpeed(curve.SpeedChangeThresholdRpm)} r/min", "r/min"),
|
||||||
CreateRecordPoint("转速/扭矩实时测试", "保持时间内最小扭矩", curve.Samples.Count >= 2 ? $"{FormatTorque(curve.MinTorqueMilliNewtonMeters)} {TorqueUnit}" : "--", TorqueUnit),
|
CreateRecordPoint("转速/扭矩实时测试", "保持时间内最小扭矩", curve.Samples.Count >= 2 ? $"{FormatTorque(curve.MinTorqueMilliNewtonMeters)} {TorqueUnit}" : "--", TorqueUnit),
|
||||||
CreateRecordPoint("转速/扭矩实时测试", "保持时间内最大扭矩", curve.Samples.Count >= 2 ? $"{FormatTorque(curve.MaxTorqueMilliNewtonMeters)} {TorqueUnit}" : "--", TorqueUnit),
|
CreateRecordPoint("转速/扭矩实时测试", "保持时间内最大扭矩", curve.Samples.Count >= 2 ? $"{FormatTorque(curve.MaxTorqueMilliNewtonMeters)} {TorqueUnit}" : "--", TorqueUnit),
|
||||||
CreateRecordPoint("转速/扭矩实时测试", "保持时间内平均扭矩", curve.Samples.Count >= 2 ? $"{FormatTorque(curve.AverageTorqueMilliNewtonMeters)} {TorqueUnit}" : "--", TorqueUnit),
|
CreateRecordPoint("转速/扭矩实时测试", "保持时间内平均扭矩", curve.Samples.Count >= 2 ? $"{FormatTorque(curve.AverageTorqueMilliNewtonMeters)} {TorqueUnit}" : "--", TorqueUnit),
|
||||||
CreateRecordPoint("转速/扭矩实时测试", "保持时间内波动值", curve.Samples.Count >= 2 ? $"{FormatTorque(curve.FluctuationMilliNewtonMeters)} {TorqueUnit}" : "--", TorqueUnit)
|
CreateRecordPoint("转速/扭矩实时测试", "保持时间内扭矩波动值", curve.Samples.Count >= 2 ? $"{FormatTorque(curve.FluctuationMilliNewtonMeters)} {TorqueUnit}" : "--", TorqueUnit),
|
||||||
|
CreateRecordPoint("转速/扭矩实时测试", "保持时间内最小转速", curve.Samples.Count >= 2 ? $"{FormatSpeed(curve.MinSpeedRpm)} r/min" : "--", "r/min"),
|
||||||
|
CreateRecordPoint("转速/扭矩实时测试", "保持时间内最大转速", curve.Samples.Count >= 2 ? $"{FormatSpeed(curve.MaxSpeedRpm)} r/min" : "--", "r/min"),
|
||||||
|
CreateRecordPoint("转速/扭矩实时测试", "保持时间内平均转速", curve.Samples.Count >= 2 ? $"{FormatSpeed(curve.AverageSpeedRpm)} r/min" : "--", "r/min"),
|
||||||
|
CreateRecordPoint("转速/扭矩实时测试", "保持时间内转速波动值", curve.Samples.Count >= 2 ? $"{FormatSpeed(curve.SpeedFluctuationRpm)} r/min" : "--", "r/min")
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1783,13 +1791,13 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sheet = workbook.Worksheets.Add("扭矩曲线");
|
var sheet = workbook.Worksheets.Add("转速扭矩曲线");
|
||||||
sheet.Cell(1, 1).Value = "扭矩保持时间曲线";
|
sheet.Cell(1, 1).Value = "转速/扭矩保持时间关系曲线";
|
||||||
sheet.Range(1, 1, 1, 7).Merge().Style.Font.SetBold().Font.SetFontSize(16);
|
sheet.Range(1, 1, 1, 12).Merge().Style.Font.SetBold().Font.SetFontSize(16);
|
||||||
|
|
||||||
sheet.Cell(3, 1).Value = "保持时间(s)";
|
sheet.Cell(3, 1).Value = "保持时间(s)";
|
||||||
sheet.Cell(3, 2).Value = curve.HoldTimeSeconds;
|
sheet.Cell(3, 2).Value = curve.HoldTimeSeconds;
|
||||||
sheet.Cell(4, 1).Value = $"判定阈值({TorqueUnit})";
|
sheet.Cell(4, 1).Value = $"扭矩变化阈值({TorqueUnit})";
|
||||||
sheet.Cell(4, 2).Value = curve.ChangeThresholdMilliNewtonMeters;
|
sheet.Cell(4, 2).Value = curve.ChangeThresholdMilliNewtonMeters;
|
||||||
sheet.Cell(5, 1).Value = "曲线判定";
|
sheet.Cell(5, 1).Value = "曲线判定";
|
||||||
sheet.Cell(5, 2).Value = curve.Result;
|
sheet.Cell(5, 2).Value = curve.Result;
|
||||||
@@ -1799,14 +1807,31 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
sheet.Cell(7, 2).Value = curve.Samples.Count >= 2 ? curve.MaxTorqueMilliNewtonMeters : string.Empty;
|
sheet.Cell(7, 2).Value = curve.Samples.Count >= 2 ? curve.MaxTorqueMilliNewtonMeters : string.Empty;
|
||||||
sheet.Cell(8, 1).Value = $"平均扭矩({TorqueUnit})";
|
sheet.Cell(8, 1).Value = $"平均扭矩({TorqueUnit})";
|
||||||
sheet.Cell(8, 2).Value = curve.Samples.Count >= 2 ? curve.AverageTorqueMilliNewtonMeters : string.Empty;
|
sheet.Cell(8, 2).Value = curve.Samples.Count >= 2 ? curve.AverageTorqueMilliNewtonMeters : string.Empty;
|
||||||
sheet.Cell(9, 1).Value = $"波动值({TorqueUnit})";
|
sheet.Cell(9, 1).Value = $"扭矩波动值({TorqueUnit})";
|
||||||
sheet.Cell(9, 2).Value = curve.Samples.Count >= 2 ? curve.FluctuationMilliNewtonMeters : string.Empty;
|
sheet.Cell(9, 2).Value = curve.Samples.Count >= 2 ? curve.FluctuationMilliNewtonMeters : string.Empty;
|
||||||
sheet.Range(3, 1, 9, 1).Style.Font.SetBold();
|
sheet.Range(3, 1, 9, 1).Style.Font.SetBold();
|
||||||
|
|
||||||
|
sheet.Cell(3, 4).Value = "X轴";
|
||||||
|
sheet.Cell(3, 5).Value = $"扭矩({TorqueUnit})";
|
||||||
|
sheet.Cell(4, 4).Value = "Y轴";
|
||||||
|
sheet.Cell(4, 5).Value = "转速(r/min)";
|
||||||
|
sheet.Cell(5, 4).Value = "转速变化阈值(r/min)";
|
||||||
|
sheet.Cell(5, 5).Value = curve.SpeedChangeThresholdRpm;
|
||||||
|
sheet.Cell(6, 4).Value = "最小转速(r/min)";
|
||||||
|
sheet.Cell(6, 5).Value = curve.Samples.Count >= 2 ? curve.MinSpeedRpm : string.Empty;
|
||||||
|
sheet.Cell(7, 4).Value = "最大转速(r/min)";
|
||||||
|
sheet.Cell(7, 5).Value = curve.Samples.Count >= 2 ? curve.MaxSpeedRpm : string.Empty;
|
||||||
|
sheet.Cell(8, 4).Value = "平均转速(r/min)";
|
||||||
|
sheet.Cell(8, 5).Value = curve.Samples.Count >= 2 ? curve.AverageSpeedRpm : string.Empty;
|
||||||
|
sheet.Cell(9, 4).Value = "转速波动值(r/min)";
|
||||||
|
sheet.Cell(9, 5).Value = curve.Samples.Count >= 2 ? curve.SpeedFluctuationRpm : string.Empty;
|
||||||
|
sheet.Range(3, 4, 9, 4).Style.Font.SetBold();
|
||||||
|
|
||||||
sheet.Cell(11, 1).Value = "时间(s)";
|
sheet.Cell(11, 1).Value = "时间(s)";
|
||||||
sheet.Cell(11, 2).Value = $"扭矩({TorqueUnit})";
|
sheet.Cell(11, 2).Value = $"扭矩({TorqueUnit})";
|
||||||
sheet.Range(11, 1, 11, 2).Style.Fill.SetBackgroundColor(XLColor.FromHtml("#D9EAF7"));
|
sheet.Cell(11, 3).Value = "转速(r/min)";
|
||||||
sheet.Range(11, 1, 11, 2).Style.Font.SetBold();
|
sheet.Range(11, 1, 11, 3).Style.Fill.SetBackgroundColor(XLColor.FromHtml("#D9EAF7"));
|
||||||
|
sheet.Range(11, 1, 11, 3).Style.Font.SetBold();
|
||||||
|
|
||||||
for (int i = 0; i < curve.Samples.Count; i++)
|
for (int i = 0; i < curve.Samples.Count; i++)
|
||||||
{
|
{
|
||||||
@@ -1814,6 +1839,7 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
int row = 12 + i;
|
int row = 12 + i;
|
||||||
sheet.Cell(row, 1).Value = sample.ElapsedSeconds;
|
sheet.Cell(row, 1).Value = sample.ElapsedSeconds;
|
||||||
sheet.Cell(row, 2).Value = sample.TorqueMilliNewtonMeters;
|
sheet.Cell(row, 2).Value = sample.TorqueMilliNewtonMeters;
|
||||||
|
sheet.Cell(row, 3).Value = sample.SpeedRpm;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curve.Samples.Count > 0)
|
if (curve.Samples.Count > 0)
|
||||||
@@ -1822,19 +1848,19 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
{
|
{
|
||||||
byte[] imageBytes = CreateTorqueCurveImage(curve, 760, 360);
|
byte[] imageBytes = CreateTorqueCurveImage(curve, 760, 360);
|
||||||
var imageStream = new MemoryStream(imageBytes);
|
var imageStream = new MemoryStream(imageBytes);
|
||||||
var picture = sheet.AddPicture(imageStream, "TorqueCurve").MoveTo(sheet.Cell(3, 4));
|
var picture = sheet.AddPicture(imageStream, "SpeedTorqueCurve").MoveTo(sheet.Cell(3, 7));
|
||||||
picture.Width = 760;
|
picture.Width = 760;
|
||||||
picture.Height = 360;
|
picture.Height = 360;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
sheet.Cell(3, 4).Value = "曲线图生成失败,原始曲线数据已完整保留";
|
sheet.Cell(3, 7).Value = "曲线图生成失败,原始曲线数据已完整保留";
|
||||||
Log.Warning(ex, "扭矩曲线图片生成失败,报表继续保留原始曲线数据");
|
Log.Warning(ex, "转速/扭矩关系曲线图片生成失败,报表继续保留原始曲线数据");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sheet.Cell(3, 4).Value = "无扭矩曲线数据";
|
sheet.Cell(3, 7).Value = "无转速/扭矩曲线数据";
|
||||||
}
|
}
|
||||||
|
|
||||||
sheet.Columns().AdjustToContents();
|
sheet.Columns().AdjustToContents();
|
||||||
@@ -1853,7 +1879,7 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
var textBrush = new SolidColorBrush(Color.FromRgb(51, 65, 85));
|
var textBrush = new SolidColorBrush(Color.FromRgb(51, 65, 85));
|
||||||
|
|
||||||
context.DrawRectangle(background, borderPen, new Rect(0, 0, width, height));
|
context.DrawRectangle(background, borderPen, new Rect(0, 0, width, height));
|
||||||
DrawChartText(context, "扭矩保持时间曲线", 18, textBrush, new System.Windows.Point(22, 16), true);
|
DrawChartText(context, "转速/扭矩保持时间关系曲线", 18, textBrush, new System.Windows.Point(22, 16), true);
|
||||||
DrawChartText(context, $"判定:{curve.Result}", 14, markerBrush, new System.Windows.Point(22, 44), true);
|
DrawChartText(context, $"判定:{curve.Result}", 14, markerBrush, new System.Windows.Point(22, 44), true);
|
||||||
|
|
||||||
Rect plot = new(62, 78, width - 92, height - 126);
|
Rect plot = new(62, 78, width - 92, height - 126);
|
||||||
@@ -1871,26 +1897,40 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
|
|
||||||
if (curve.Samples.Count > 0)
|
if (curve.Samples.Count > 0)
|
||||||
{
|
{
|
||||||
double min = curve.Samples.Min(sample => sample.TorqueMilliNewtonMeters);
|
double minTorque = curve.Samples.Min(sample => sample.TorqueMilliNewtonMeters);
|
||||||
double max = curve.Samples.Max(sample => sample.TorqueMilliNewtonMeters);
|
double maxTorque = curve.Samples.Max(sample => sample.TorqueMilliNewtonMeters);
|
||||||
double range = max - min;
|
double torqueRange = maxTorque - minTorque;
|
||||||
if (range < 0.01)
|
if (torqueRange < 0.01)
|
||||||
{
|
{
|
||||||
min -= 0.5;
|
minTorque -= 0.5;
|
||||||
max += 0.5;
|
maxTorque += 0.5;
|
||||||
range = 1;
|
torqueRange = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
double padding = range * 0.12;
|
double padding = torqueRange * 0.12;
|
||||||
min -= padding;
|
minTorque -= padding;
|
||||||
max += padding;
|
maxTorque += padding;
|
||||||
range = max - min;
|
torqueRange = maxTorque - minTorque;
|
||||||
}
|
}
|
||||||
|
|
||||||
double firstElapsed = curve.Samples[0].ElapsedSeconds;
|
double minSpeed = curve.Samples.Min(sample => sample.SpeedRpm);
|
||||||
double lastElapsed = Math.Max(curve.Samples[^1].ElapsedSeconds, curve.HoldTimeSeconds);
|
double maxSpeed = curve.Samples.Max(sample => sample.SpeedRpm);
|
||||||
double elapsedRange = Math.Max(lastElapsed - firstElapsed, 0.001);
|
double speedRange = maxSpeed - minSpeed;
|
||||||
|
if (speedRange < 1)
|
||||||
|
{
|
||||||
|
double padding = Math.Max(Math.Abs(minSpeed) * 0.05, 1);
|
||||||
|
minSpeed -= padding;
|
||||||
|
maxSpeed += padding;
|
||||||
|
speedRange = maxSpeed - minSpeed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double padding = speedRange * 0.05;
|
||||||
|
minSpeed -= padding;
|
||||||
|
maxSpeed += padding;
|
||||||
|
speedRange = maxSpeed - minSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
var geometry = new StreamGeometry();
|
var geometry = new StreamGeometry();
|
||||||
using (StreamGeometryContext geometryContext = geometry.Open())
|
using (StreamGeometryContext geometryContext = geometry.Open())
|
||||||
@@ -1898,8 +1938,8 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
for (int i = 0; i < curve.Samples.Count; i++)
|
for (int i = 0; i < curve.Samples.Count; i++)
|
||||||
{
|
{
|
||||||
TorqueSamplePayload sample = curve.Samples[i];
|
TorqueSamplePayload sample = curve.Samples[i];
|
||||||
double x = plot.Left + plot.Width * (sample.ElapsedSeconds - firstElapsed) / elapsedRange;
|
double x = plot.Left + plot.Width * (sample.TorqueMilliNewtonMeters - minTorque) / torqueRange;
|
||||||
double y = plot.Bottom - (sample.TorqueMilliNewtonMeters - min) / range * plot.Height;
|
double y = plot.Bottom - (sample.SpeedRpm - minSpeed) / speedRange * plot.Height;
|
||||||
var point = new System.Windows.Point(x, y);
|
var point = new System.Windows.Point(x, y);
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
@@ -1915,15 +1955,16 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
geometry.Freeze();
|
geometry.Freeze();
|
||||||
context.DrawGeometry(null, linePen, geometry);
|
context.DrawGeometry(null, linePen, geometry);
|
||||||
|
|
||||||
DrawChartText(context, max.ToString("0.##", CultureInfo.InvariantCulture), 12, textBrush, new System.Windows.Point(16, plot.Top - 8), false);
|
DrawChartText(context, maxSpeed.ToString("0", CultureInfo.InvariantCulture), 12, textBrush, new System.Windows.Point(16, plot.Top - 8), false);
|
||||||
DrawChartText(context, min.ToString("0.##", CultureInfo.InvariantCulture), 12, textBrush, new System.Windows.Point(16, plot.Bottom - 10), false);
|
DrawChartText(context, minSpeed.ToString("0", CultureInfo.InvariantCulture), 12, textBrush, new System.Windows.Point(16, plot.Bottom - 10), false);
|
||||||
DrawChartText(context, $"{firstElapsed:0.#}s", 12, textBrush, new System.Windows.Point(plot.Left, plot.Bottom + 10), false);
|
DrawChartText(context, minTorque.ToString("0.##", CultureInfo.InvariantCulture), 12, textBrush, new System.Windows.Point(plot.Left, plot.Bottom + 10), false);
|
||||||
DrawChartText(context, $"{lastElapsed:0.#}s", 12, textBrush, new System.Windows.Point(plot.Right - 28, plot.Bottom + 10), false);
|
DrawChartText(context, maxTorque.ToString("0.##", CultureInfo.InvariantCulture), 12, textBrush, new System.Windows.Point(plot.Right - 34, plot.Bottom + 10), false);
|
||||||
DrawChartText(context, TorqueUnit, 12, textBrush, new System.Windows.Point(18, plot.Top + 16), false);
|
DrawChartText(context, "转速(r/min)", 12, textBrush, new System.Windows.Point(12, plot.Top + 16), false);
|
||||||
|
DrawChartText(context, $"扭矩({TorqueUnit})", 12, textBrush, new System.Windows.Point(plot.Right - 78, plot.Bottom - 18), false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DrawChartText(context, "无扭矩曲线数据", 16, textBrush, new System.Windows.Point(plot.Left + 20, plot.Top + 20), false);
|
DrawChartText(context, "无转速/扭矩曲线数据", 16, textBrush, new System.Windows.Point(plot.Left + 20, plot.Top + 20), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2512,7 +2553,6 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
_speedTorqueStartedAt = DateTime.Now;
|
_speedTorqueStartedAt = DateTime.Now;
|
||||||
_activeSpeedTorqueRun = CreateTestRun("转速/扭矩测试", _speedTorqueStartedAt.Value);
|
_activeSpeedTorqueRun = CreateTestRun("转速/扭矩测试", _speedTorqueStartedAt.Value);
|
||||||
ClearTorqueSamples();
|
ClearTorqueSamples();
|
||||||
AppendTorqueSample(GetScaledTorque(), _realtimeSpeed, _speedTorqueStartedAt.Value);
|
|
||||||
_maxSpeedTorqueDisplacement = Math.Max(_maxSpeedTorqueDisplacement, Math.Abs(_speedTorqueDisplacement));
|
_maxSpeedTorqueDisplacement = Math.Max(_maxSpeedTorqueDisplacement, Math.Abs(_speedTorqueDisplacement));
|
||||||
UpdateSpeedTorqueDisplay();
|
UpdateSpeedTorqueDisplay();
|
||||||
StatusText = "转速/扭矩测试已启动,通气阀由手动按钮独立控制。";
|
StatusText = "转速/扭矩测试已启动,通气阀由手动按钮独立控制。";
|
||||||
@@ -3342,6 +3382,12 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
double elapsedSeconds = Math.Max(0, (sampledAt - _speedTorqueStartedAt.Value).TotalSeconds);
|
double elapsedSeconds = Math.Max(0, (sampledAt - _speedTorqueStartedAt.Value).TotalSeconds);
|
||||||
|
if (_parameterConfig.TorqueHoldTime <= 0
|
||||||
|
|| elapsedSeconds > _parameterConfig.TorqueHoldTime)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
TorqueSamples.Add(new TorqueSamplePayload
|
TorqueSamples.Add(new TorqueSamplePayload
|
||||||
{
|
{
|
||||||
ElapsedSeconds = elapsedSeconds,
|
ElapsedSeconds = elapsedSeconds,
|
||||||
@@ -3366,15 +3412,20 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
|
|
||||||
private void UpdateTorqueCurveStatus()
|
private void UpdateTorqueCurveStatus()
|
||||||
{
|
{
|
||||||
if (_isSpeedTorqueRunning && TorqueSamples.Count > 0)
|
if (_isSpeedTorqueRunning
|
||||||
|
&& _speedTorqueStartedAt.HasValue
|
||||||
|
&& _parameterConfig.TorqueHoldTime > 0)
|
||||||
{
|
{
|
||||||
double elapsed = TorqueSamples[^1].ElapsedSeconds;
|
double elapsed = Math.Max(0, (DateTime.Now - _speedTorqueStartedAt.Value).TotalSeconds);
|
||||||
TorqueCurveStatusText = $"实时曲线:采集中 {FormatConfigNumber(elapsed)} s;X轴转速 / Y轴扭矩";
|
if (elapsed < _parameterConfig.TorqueHoldTime)
|
||||||
return;
|
{
|
||||||
|
TorqueCurveStatusText = $"实时曲线:采集中 {FormatConfigNumber(elapsed)} / {FormatConfigNumber(_parameterConfig.TorqueHoldTime)} s;X轴扭矩 / Y轴转速";
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TorqueCurvePayload curve = CreateTorqueCurvePayload();
|
TorqueCurvePayload curve = CreateTorqueCurvePayload();
|
||||||
TorqueCurveStatusText = $"保持时间曲线:{curve.Result}";
|
TorqueCurveStatusText = $"转速/扭矩保持时间关系曲线:{curve.Result}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private TorqueCurvePayload CreateTorqueCurvePayload()
|
private TorqueCurvePayload CreateTorqueCurvePayload()
|
||||||
@@ -3394,54 +3445,17 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
})
|
})
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
double threshold = GetTorqueChangeThreshold();
|
_cachedTorqueCurve = BuildTorqueCurvePayload(
|
||||||
if (_parameterConfig.TorqueHoldTime <= 0)
|
samples,
|
||||||
{
|
_parameterConfig.TorqueHoldTime,
|
||||||
_cachedTorqueCurve = new TorqueCurvePayload
|
GetTorqueChangeThreshold(),
|
||||||
{
|
GetSpeedChangeThreshold());
|
||||||
HoldTimeSeconds = _parameterConfig.TorqueHoldTime,
|
|
||||||
ChangeThresholdMilliNewtonMeters = threshold,
|
|
||||||
Result = "未设置保持时间,未判定",
|
|
||||||
Samples = samples
|
|
||||||
};
|
|
||||||
return _cachedTorqueCurve;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (samples.Count < 2)
|
|
||||||
{
|
|
||||||
_cachedTorqueCurve = new TorqueCurvePayload
|
|
||||||
{
|
|
||||||
HoldTimeSeconds = _parameterConfig.TorqueHoldTime,
|
|
||||||
ChangeThresholdMilliNewtonMeters = threshold,
|
|
||||||
Result = "采样不足,未判定",
|
|
||||||
Samples = samples
|
|
||||||
};
|
|
||||||
return _cachedTorqueCurve;
|
|
||||||
}
|
|
||||||
|
|
||||||
double min = samples.Min(sample => sample.TorqueMilliNewtonMeters);
|
|
||||||
double max = samples.Max(sample => sample.TorqueMilliNewtonMeters);
|
|
||||||
double average = samples.Average(sample => sample.TorqueMilliNewtonMeters);
|
|
||||||
double fluctuation = max - min;
|
|
||||||
|
|
||||||
_cachedTorqueCurve = new TorqueCurvePayload
|
|
||||||
{
|
|
||||||
HoldTimeSeconds = _parameterConfig.TorqueHoldTime,
|
|
||||||
ChangeThresholdMilliNewtonMeters = threshold,
|
|
||||||
MinTorqueMilliNewtonMeters = min,
|
|
||||||
MaxTorqueMilliNewtonMeters = max,
|
|
||||||
AverageTorqueMilliNewtonMeters = average,
|
|
||||||
FluctuationMilliNewtonMeters = fluctuation,
|
|
||||||
Result = fluctuation > threshold ? "有变化" : "无明显变化",
|
|
||||||
Samples = samples
|
|
||||||
};
|
|
||||||
return _cachedTorqueCurve;
|
return _cachedTorqueCurve;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TorqueCurvePayload CreateTorqueCurvePayload(TestRunPayload run)
|
private static TorqueCurvePayload CreateTorqueCurvePayload(TestRunPayload run)
|
||||||
{
|
{
|
||||||
double holdTime = run.ParameterSnapshot.TorqueHoldTime;
|
double holdTime = run.ParameterSnapshot.TorqueHoldTime;
|
||||||
double threshold = Math.Max(MinimumTorqueChangeThreshold, Math.Abs(run.ParameterSnapshot.HoldTorque) * 0.01);
|
|
||||||
List<TorqueSamplePayload> samples = run.Samples
|
List<TorqueSamplePayload> samples = run.Samples
|
||||||
.Select(sample => new TorqueSamplePayload
|
.Select(sample => new TorqueSamplePayload
|
||||||
{
|
{
|
||||||
@@ -3452,12 +3466,26 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
.Where(sample => sample.ElapsedSeconds <= holdTime)
|
.Where(sample => sample.ElapsedSeconds <= holdTime)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
return BuildTorqueCurvePayload(
|
||||||
|
samples,
|
||||||
|
holdTime,
|
||||||
|
Math.Max(MinimumTorqueChangeThreshold, Math.Abs(run.ParameterSnapshot.HoldTorque) * 0.01),
|
||||||
|
Math.Max(MinimumSpeedChangeThreshold, Math.Abs(run.ParameterSnapshot.LoadSpeedSetting) * 0.01));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TorqueCurvePayload BuildTorqueCurvePayload(
|
||||||
|
List<TorqueSamplePayload> samples,
|
||||||
|
double holdTime,
|
||||||
|
double torqueThreshold,
|
||||||
|
double speedThreshold)
|
||||||
|
{
|
||||||
if (holdTime <= 0)
|
if (holdTime <= 0)
|
||||||
{
|
{
|
||||||
return new TorqueCurvePayload
|
return new TorqueCurvePayload
|
||||||
{
|
{
|
||||||
HoldTimeSeconds = holdTime,
|
HoldTimeSeconds = holdTime,
|
||||||
ChangeThresholdMilliNewtonMeters = threshold,
|
ChangeThresholdMilliNewtonMeters = torqueThreshold,
|
||||||
|
SpeedChangeThresholdRpm = speedThreshold,
|
||||||
Result = "未设置保持时间,未判定",
|
Result = "未设置保持时间,未判定",
|
||||||
Samples = samples
|
Samples = samples
|
||||||
};
|
};
|
||||||
@@ -3468,23 +3496,43 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
return new TorqueCurvePayload
|
return new TorqueCurvePayload
|
||||||
{
|
{
|
||||||
HoldTimeSeconds = holdTime,
|
HoldTimeSeconds = holdTime,
|
||||||
ChangeThresholdMilliNewtonMeters = threshold,
|
ChangeThresholdMilliNewtonMeters = torqueThreshold,
|
||||||
|
SpeedChangeThresholdRpm = speedThreshold,
|
||||||
Result = "采样不足,未判定",
|
Result = "采样不足,未判定",
|
||||||
Samples = samples
|
Samples = samples
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
double min = samples.Min(static sample => sample.TorqueMilliNewtonMeters);
|
double minTorque = samples.Min(static sample => sample.TorqueMilliNewtonMeters);
|
||||||
double max = samples.Max(static sample => sample.TorqueMilliNewtonMeters);
|
double maxTorque = samples.Max(static sample => sample.TorqueMilliNewtonMeters);
|
||||||
|
double torqueFluctuation = maxTorque - minTorque;
|
||||||
|
double minSpeed = samples.Min(static sample => sample.SpeedRpm);
|
||||||
|
double maxSpeed = samples.Max(static sample => sample.SpeedRpm);
|
||||||
|
double speedFluctuation = maxSpeed - minSpeed;
|
||||||
|
bool torqueChanged = torqueFluctuation > torqueThreshold;
|
||||||
|
bool speedChanged = speedFluctuation > speedThreshold;
|
||||||
|
string result = (torqueChanged, speedChanged) switch
|
||||||
|
{
|
||||||
|
(true, true) => "有变化(扭矩、转速)",
|
||||||
|
(true, false) => "有变化(扭矩)",
|
||||||
|
(false, true) => "有变化(转速)",
|
||||||
|
_ => "无明显变化"
|
||||||
|
};
|
||||||
|
|
||||||
return new TorqueCurvePayload
|
return new TorqueCurvePayload
|
||||||
{
|
{
|
||||||
HoldTimeSeconds = holdTime,
|
HoldTimeSeconds = holdTime,
|
||||||
ChangeThresholdMilliNewtonMeters = threshold,
|
ChangeThresholdMilliNewtonMeters = torqueThreshold,
|
||||||
MinTorqueMilliNewtonMeters = min,
|
SpeedChangeThresholdRpm = speedThreshold,
|
||||||
MaxTorqueMilliNewtonMeters = max,
|
MinTorqueMilliNewtonMeters = minTorque,
|
||||||
|
MaxTorqueMilliNewtonMeters = maxTorque,
|
||||||
AverageTorqueMilliNewtonMeters = samples.Average(static sample => sample.TorqueMilliNewtonMeters),
|
AverageTorqueMilliNewtonMeters = samples.Average(static sample => sample.TorqueMilliNewtonMeters),
|
||||||
FluctuationMilliNewtonMeters = max - min,
|
FluctuationMilliNewtonMeters = torqueFluctuation,
|
||||||
Result = max - min > threshold ? "有变化" : "无明显变化",
|
MinSpeedRpm = minSpeed,
|
||||||
|
MaxSpeedRpm = maxSpeed,
|
||||||
|
AverageSpeedRpm = samples.Average(static sample => sample.SpeedRpm),
|
||||||
|
SpeedFluctuationRpm = speedFluctuation,
|
||||||
|
Result = result,
|
||||||
Samples = samples
|
Samples = samples
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -3494,6 +3542,11 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
return Math.Max(MinimumTorqueChangeThreshold, Math.Abs(_parameterConfig.HoldTorque) * 0.01);
|
return Math.Max(MinimumTorqueChangeThreshold, Math.Abs(_parameterConfig.HoldTorque) * 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private double GetSpeedChangeThreshold()
|
||||||
|
{
|
||||||
|
return Math.Max(MinimumSpeedChangeThreshold, Math.Abs(_parameterConfig.LoadSpeedSetting) * 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
private int GetTorqueSampleLimit()
|
private int GetTorqueSampleLimit()
|
||||||
{
|
{
|
||||||
if (_parameterConfig.TorqueHoldTime <= 0)
|
if (_parameterConfig.TorqueHoldTime <= 0)
|
||||||
@@ -3506,12 +3559,15 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
return Math.Max(MaxTorqueSampleCount, requiredSamples);
|
return Math.Max(MaxTorqueSampleCount, requiredSamples);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CaptureRealtimeSample(double dialIndicator, IReadOnlyDictionary<ushort, bool> coilValues)
|
private void CaptureRealtimeSample(
|
||||||
|
double dialIndicator,
|
||||||
|
IReadOnlyDictionary<ushort, bool> coilValues,
|
||||||
|
DateTime sampledAt)
|
||||||
{
|
{
|
||||||
var sample = new RealtimeSamplePayload
|
var sample = new RealtimeSamplePayload
|
||||||
{
|
{
|
||||||
Sequence = ++_realtimeSampleSequence,
|
Sequence = ++_realtimeSampleSequence,
|
||||||
SampledAt = DateTime.Now,
|
SampledAt = sampledAt,
|
||||||
DialIndicatorMm = dialIndicator,
|
DialIndicatorMm = dialIndicator,
|
||||||
RelativeDisplacementMm = _relativeDisplacement,
|
RelativeDisplacementMm = _relativeDisplacement,
|
||||||
AxialAxisPositionMm = _axialAxisPosition,
|
AxialAxisPositionMm = _axialAxisPosition,
|
||||||
|
|||||||
@@ -214,6 +214,8 @@ public sealed class TorqueCurvePayload
|
|||||||
|
|
||||||
public double ChangeThresholdMilliNewtonMeters { get; init; }
|
public double ChangeThresholdMilliNewtonMeters { get; init; }
|
||||||
|
|
||||||
|
public double SpeedChangeThresholdRpm { get; init; }
|
||||||
|
|
||||||
public double MinTorqueMilliNewtonMeters { get; init; }
|
public double MinTorqueMilliNewtonMeters { get; init; }
|
||||||
|
|
||||||
public double MaxTorqueMilliNewtonMeters { get; init; }
|
public double MaxTorqueMilliNewtonMeters { get; init; }
|
||||||
@@ -222,6 +224,14 @@ public sealed class TorqueCurvePayload
|
|||||||
|
|
||||||
public double FluctuationMilliNewtonMeters { get; init; }
|
public double FluctuationMilliNewtonMeters { get; init; }
|
||||||
|
|
||||||
|
public double MinSpeedRpm { get; init; }
|
||||||
|
|
||||||
|
public double MaxSpeedRpm { get; init; }
|
||||||
|
|
||||||
|
public double AverageSpeedRpm { get; init; }
|
||||||
|
|
||||||
|
public double SpeedFluctuationRpm { get; init; }
|
||||||
|
|
||||||
public string Result { get; init; } = string.Empty;
|
public string Result { get; init; } = string.Empty;
|
||||||
|
|
||||||
public List<TorqueSamplePayload> Samples { get; init; } = [];
|
public List<TorqueSamplePayload> Samples { get; init; } = [];
|
||||||
|
|||||||
@@ -65,8 +65,8 @@ public sealed class TorqueTrendControl : FrameworkElement
|
|||||||
if (samples.Count == 0)
|
if (samples.Count == 0)
|
||||||
{
|
{
|
||||||
DrawText(drawingContext, "等待转速/扭矩数据", 15, Color.FromRgb(82, 97, 111), new Point(plot.Left + 8, plot.Top + 8));
|
DrawText(drawingContext, "等待转速/扭矩数据", 15, Color.FromRgb(82, 97, 111), new Point(plot.Left + 8, plot.Top + 8));
|
||||||
DrawText(drawingContext, $"扭矩 ({TorqueUnit})", 12, Color.FromRgb(82, 97, 111), new Point(6, plot.Top));
|
DrawText(drawingContext, $"转速 ({SpeedUnit})", 12, Color.FromRgb(82, 97, 111), new Point(6, plot.Top));
|
||||||
DrawText(drawingContext, $"转速 ({SpeedUnit})", 12, Color.FromRgb(82, 97, 111), new Point(plot.Right - 82, plot.Bottom + 5));
|
DrawText(drawingContext, $"扭矩 ({TorqueUnit})", 12, Color.FromRgb(82, 97, 111), new Point(plot.Right - 82, plot.Bottom + 5));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,20 +107,20 @@ public sealed class TorqueTrendControl : FrameworkElement
|
|||||||
speedRange = maxSpeed - minSpeed;
|
speedRange = maxSpeed - minSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawText(drawingContext, maxTorque.ToString("0.##", CultureInfo.InvariantCulture), 12, Color.FromRgb(82, 97, 111), new Point(8, plot.Top - 2));
|
DrawText(drawingContext, maxSpeed.ToString("0", CultureInfo.InvariantCulture), 12, Color.FromRgb(82, 97, 111), new Point(8, plot.Top - 2));
|
||||||
DrawText(drawingContext, minTorque.ToString("0.##", CultureInfo.InvariantCulture), 12, Color.FromRgb(82, 97, 111), new Point(8, plot.Bottom - 14));
|
DrawText(drawingContext, minSpeed.ToString("0", CultureInfo.InvariantCulture), 12, Color.FromRgb(82, 97, 111), new Point(8, plot.Bottom - 14));
|
||||||
DrawText(drawingContext, minSpeed.ToString("0", CultureInfo.InvariantCulture), 12, Color.FromRgb(82, 97, 111), new Point(plot.Left, plot.Bottom + 5));
|
DrawText(drawingContext, minTorque.ToString("0.##", CultureInfo.InvariantCulture), 12, Color.FromRgb(82, 97, 111), new Point(plot.Left, plot.Bottom + 5));
|
||||||
DrawText(drawingContext, maxSpeed.ToString("0", CultureInfo.InvariantCulture), 12, Color.FromRgb(82, 97, 111), new Point(plot.Right - 38, plot.Bottom + 5));
|
DrawText(drawingContext, maxTorque.ToString("0.##", CultureInfo.InvariantCulture), 12, Color.FromRgb(82, 97, 111), new Point(plot.Right - 38, plot.Bottom + 5));
|
||||||
DrawText(drawingContext, $"扭矩 ({TorqueUnit})", 11, Color.FromRgb(82, 97, 111), new Point(plot.Left + 4, plot.Top + 3));
|
DrawText(drawingContext, $"转速 ({SpeedUnit})", 11, Color.FromRgb(82, 97, 111), new Point(plot.Left + 4, plot.Top + 3));
|
||||||
DrawText(drawingContext, $"转速 ({SpeedUnit})", 11, Color.FromRgb(82, 97, 111), new Point(plot.Right - 82, plot.Bottom - 18));
|
DrawText(drawingContext, $"扭矩 ({TorqueUnit})", 11, Color.FromRgb(82, 97, 111), new Point(plot.Right - 82, plot.Bottom - 18));
|
||||||
|
|
||||||
var geometry = new StreamGeometry();
|
var geometry = new StreamGeometry();
|
||||||
using (StreamGeometryContext context = geometry.Open())
|
using (StreamGeometryContext context = geometry.Open())
|
||||||
{
|
{
|
||||||
for (int i = 0; i < samples.Count; i++)
|
for (int i = 0; i < samples.Count; i++)
|
||||||
{
|
{
|
||||||
double x = plot.Left + plot.Width * (samples[i].SpeedRpm - minSpeed) / speedRange;
|
double x = plot.Left + plot.Width * (samples[i].TorqueMilliNewtonMeters - minTorque) / torqueRange;
|
||||||
double y = plot.Bottom - (samples[i].TorqueMilliNewtonMeters - minTorque) / torqueRange * plot.Height;
|
double y = plot.Bottom - (samples[i].SpeedRpm - minSpeed) / speedRange * plot.Height;
|
||||||
Point point = new(x, y);
|
Point point = new(x, y);
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
@@ -139,7 +139,7 @@ public sealed class TorqueTrendControl : FrameworkElement
|
|||||||
drawingContext.DrawGeometry(null, linePen, geometry);
|
drawingContext.DrawGeometry(null, linePen, geometry);
|
||||||
|
|
||||||
TorqueSamplePayload current = samples[^1];
|
TorqueSamplePayload current = samples[^1];
|
||||||
double currentY = plot.Bottom - (current.TorqueMilliNewtonMeters - minTorque) / torqueRange * plot.Height;
|
double currentY = plot.Bottom - (current.SpeedRpm - minSpeed) / speedRange * plot.Height;
|
||||||
var currentPen = new Pen(new SolidColorBrush(Color.FromRgb(15, 118, 110)), 1.2);
|
var currentPen = new Pen(new SolidColorBrush(Color.FromRgb(15, 118, 110)), 1.2);
|
||||||
drawingContext.DrawLine(currentPen, new Point(plot.Left, currentY), new Point(plot.Right, currentY));
|
drawingContext.DrawLine(currentPen, new Point(plot.Left, currentY), new Point(plot.Right, currentY));
|
||||||
DrawText(
|
DrawText(
|
||||||
|
|||||||
Reference in New Issue
Block a user