更新20260605
This commit is contained in:
@@ -301,8 +301,8 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Services
|
||||
}
|
||||
|
||||
var pressureRaw = UshortToInt(data[0], data[1]);
|
||||
var friction1Raw = UshortToInt(data[6], data[7]);
|
||||
var friction2Raw = UshortToInt(data[2], data[3]);
|
||||
var friction1Raw = UshortToInt(data[2], data[3]);
|
||||
var friction2Raw = UshortToInt(data[6], data[7]);
|
||||
|
||||
var conversion = ConvertAdcReadings(pressureRaw, friction1Raw, friction2Raw);
|
||||
LogAdcDiagnostic(pressureRaw, friction1Raw, friction2Raw, conversion);
|
||||
@@ -525,10 +525,9 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.Services
|
||||
|
||||
var pressure = ConvertAdc(pressureRaw, pressureZero, pressureCoefficient);
|
||||
|
||||
// Keep the old instrument channel wiring: ADC 6/7 uses zero 1 with coefficient 2,
|
||||
// and ADC 2/3 uses zero 2 with coefficient 1.
|
||||
var friction1 = ConvertAdc(friction1Raw, frictionZero1, frictionCoefficient2);
|
||||
var friction2 = ConvertAdc(friction2Raw, frictionZero2, frictionCoefficient1);
|
||||
// Keep each settings row paired with the same ADC channel used by the legacy zero-capture button.
|
||||
var friction1 = ConvertAdc(friction1Raw, frictionZero1, frictionCoefficient1);
|
||||
var friction2 = ConvertAdc(friction2Raw, frictionZero2, frictionCoefficient2);
|
||||
var friction = (friction1 + friction2) * -1.0;
|
||||
return AdcConversionResult.Valid(pressure, friction1, friction2, friction);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
||||
private const string LegacyPlcPortName = "COM7";
|
||||
private const string LegacyAdcPortName = "COM8";
|
||||
private static readonly TimeSpan ResetButtonPendingTimeout = TimeSpan.FromMilliseconds(800);
|
||||
private static readonly TimeSpan RealtimeCurveTraceInterval = TimeSpan.FromSeconds(1);
|
||||
|
||||
private readonly SlipResistanceDeviceService deviceService = new();
|
||||
private readonly SlipExcelExportService excelExportService = new();
|
||||
@@ -56,6 +57,7 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
||||
private string activeAdcPortName = string.Empty;
|
||||
private int activeBaudRate;
|
||||
private List<SlipDataPoint> lastCompletedRun = [];
|
||||
private DateTime lastRealtimeCurveTraceLoggedAt = DateTime.MinValue;
|
||||
|
||||
[ObservableProperty]
|
||||
private string testNumber = $"SLIP-{DateTime.Now:yyyyMMdd-HHmm}";
|
||||
@@ -672,6 +674,7 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
||||
displacementPoints.Clear();
|
||||
runStopwatch.Restart();
|
||||
UploadProgress = 0;
|
||||
lastRealtimeCurveTraceLoggedAt = DateTime.MinValue;
|
||||
CurrentStatus = "测试运行:按标准采集垂直载荷、摩擦力、位移与摩擦系数";
|
||||
Log.Information("测试开始:TestNumber={TestNumber}, TargetLoad={TargetLoad}, TestSpeed={TestSpeed}", TestNumber, TargetLoadText, TestSpeedText);
|
||||
}
|
||||
@@ -699,11 +702,13 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
||||
displacementPoints.Add(new ObservablePoint(time, point.DisplacementMm));
|
||||
|
||||
UploadProgress = Math.Min(99, currentRun.Count);
|
||||
TraceRealtimeCurvePoint(point);
|
||||
}
|
||||
|
||||
private void CompleteRun()
|
||||
{
|
||||
runStopwatch.Stop();
|
||||
LogRealtimeCurveSummary("测试停止");
|
||||
if (currentRun.Count < 3)
|
||||
{
|
||||
Log.Warning("测试停止但采样点不足:TestNumber={TestNumber}, PointCount={PointCount}", TestNumber, currentRun.Count);
|
||||
@@ -718,11 +723,18 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
||||
.ToList();
|
||||
if (dynamicWindow.Count < MinimumDynamicWindowPointCount)
|
||||
{
|
||||
var firstWindowPoint = dynamicWindow.FirstOrDefault();
|
||||
var lastWindowPoint = dynamicWindow.LastOrDefault();
|
||||
Log.Warning(
|
||||
"测试停止但动摩擦窗口采样点不足:TestNumber={TestNumber}, PointCount={PointCount}, DynamicWindowPointCount={DynamicWindowPointCount}",
|
||||
"测试停止但动摩擦窗口采样点不足:TestNumber={TestNumber}, PointCount={PointCount}, DynamicWindow=0.300-0.600s, DynamicWindowPointCount={DynamicWindowPointCount}, RequiredPointCount={RequiredPointCount}, ActualWindowStart={ActualWindowStart}, ActualWindowEnd={ActualWindowEnd}, FirstSampleTime={FirstSampleTime:F3}s, LastSampleTime={LastSampleTime:F3}s",
|
||||
TestNumber,
|
||||
currentRun.Count,
|
||||
dynamicWindow.Count);
|
||||
dynamicWindow.Count,
|
||||
MinimumDynamicWindowPointCount,
|
||||
FormatNullable(firstWindowPoint?.TimeSeconds),
|
||||
FormatNullable(lastWindowPoint?.TimeSeconds),
|
||||
currentRun[0].TimeSeconds,
|
||||
currentRun[^1].TimeSeconds);
|
||||
CurrentStatus = "测试已停止,0.3 s~0.6 s 有效采样点不足,未生成结果";
|
||||
return;
|
||||
}
|
||||
@@ -733,6 +745,28 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
||||
var dynamicCoefficientValue = CalculateCoefficient(dynamicForce, dynamicLoad);
|
||||
var verdict = NeedsRetest(staticCoefficientValue, dynamicCoefficientValue) ? "需重测" : "有效";
|
||||
var nextIndex = Samples.Count == 0 ? 1 : Samples.Max(sample => sample.Index) + 1;
|
||||
var peakIndex = currentRun.IndexOf(peak) + 1;
|
||||
var dynamicStart = dynamicWindow[0].TimeSeconds;
|
||||
var dynamicEnd = dynamicWindow[^1].TimeSeconds;
|
||||
|
||||
Log.Information(
|
||||
"静/动摩擦计算明细:TestNumber={TestNumber}, PointCount={PointCount}, StaticSearchWindow=0.000-{StaticSearchEnd:F3}s, StaticPointIndex={StaticPointIndex}, StaticTime={StaticTime:F3}s, StaticFriction={StaticFriction:F3}N, StaticLoad={StaticLoad:F3}N, StaticCoefficient={StaticCoefficient:F5}, DynamicWindow={DynamicWindowStart:F3}-{DynamicWindowEnd:F3}s, DynamicActualWindow={DynamicActualStart:F3}-{DynamicActualEnd:F3}s, DynamicPointCount={DynamicPointCount}, DynamicAvgFriction={DynamicAvgFriction:F3}N, DynamicAvgLoad={DynamicAvgLoad:F3}N, DynamicCoefficient={DynamicCoefficient:F5}",
|
||||
TestNumber,
|
||||
currentRun.Count,
|
||||
DynamicWindowStartSeconds,
|
||||
peakIndex,
|
||||
peak.TimeSeconds,
|
||||
peak.HorizontalFrictionN,
|
||||
peak.VerticalLoadN,
|
||||
staticCoefficientValue,
|
||||
DynamicWindowStartSeconds,
|
||||
DynamicWindowEndSeconds,
|
||||
dynamicStart,
|
||||
dynamicEnd,
|
||||
dynamicWindow.Count,
|
||||
dynamicForce,
|
||||
dynamicLoad,
|
||||
dynamicCoefficientValue);
|
||||
|
||||
Samples.Insert(0, new TestSample(
|
||||
nextIndex,
|
||||
@@ -834,6 +868,111 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
||||
private static double CalculateCoefficient(double frictionForce, double verticalLoad) =>
|
||||
Math.Abs(verticalLoad) > 0.0001 ? frictionForce / verticalLoad : 0;
|
||||
|
||||
private void LogRealtimeCurveSummary(string stage)
|
||||
{
|
||||
var expectedCount = currentRun.Count;
|
||||
var countsMatch =
|
||||
verticalLoadPoints.Count == expectedCount
|
||||
&& horizontalFrictionPoints.Count == expectedCount
|
||||
&& frictionCoefficientPoints.Count == expectedCount
|
||||
&& displacementPoints.Count == expectedCount;
|
||||
var lastPoint = currentRun.Count > 0 ? currentRun[^1] : null;
|
||||
|
||||
Log.Information(
|
||||
"实时曲线同步汇总:Stage={Stage}, TestNumber={TestNumber}, DataPointCount={DataPointCount}, ChartCounts=[Vertical:{VerticalCount}, Friction:{FrictionCount}, Coefficient:{CoefficientCount}, Displacement:{DisplacementCount}], CountsMatch={CountsMatch}, LastDataPoint={LastDataPoint}, ChartLast=[Vertical:{VerticalChart}, Friction:{FrictionChart}, Coefficient:{CoefficientChart}, Displacement:{DisplacementChart}]",
|
||||
stage,
|
||||
TestNumber,
|
||||
expectedCount,
|
||||
verticalLoadPoints.Count,
|
||||
horizontalFrictionPoints.Count,
|
||||
frictionCoefficientPoints.Count,
|
||||
displacementPoints.Count,
|
||||
countsMatch,
|
||||
FormatDataPoint(lastPoint),
|
||||
FormatChartPoint(verticalLoadPoints.Count > 0 ? verticalLoadPoints[^1] : null),
|
||||
FormatChartPoint(horizontalFrictionPoints.Count > 0 ? horizontalFrictionPoints[^1] : null),
|
||||
FormatChartPoint(frictionCoefficientPoints.Count > 0 ? frictionCoefficientPoints[^1] : null),
|
||||
FormatChartPoint(displacementPoints.Count > 0 ? displacementPoints[^1] : null));
|
||||
}
|
||||
|
||||
private void TraceRealtimeCurvePoint(SlipDataPoint point)
|
||||
{
|
||||
var expectedCount = currentRun.Count;
|
||||
var countsMatch =
|
||||
verticalLoadPoints.Count == expectedCount
|
||||
&& horizontalFrictionPoints.Count == expectedCount
|
||||
&& frictionCoefficientPoints.Count == expectedCount
|
||||
&& displacementPoints.Count == expectedCount;
|
||||
var valuesMatch =
|
||||
countsMatch
|
||||
&& ChartPointMatches(verticalLoadPoints[^1], point.TimeSeconds, point.VerticalLoadN)
|
||||
&& ChartPointMatches(horizontalFrictionPoints[^1], point.TimeSeconds, point.HorizontalFrictionN)
|
||||
&& ChartPointMatches(frictionCoefficientPoints[^1], point.TimeSeconds, point.FrictionCoefficient)
|
||||
&& ChartPointMatches(displacementPoints[^1], point.TimeSeconds, point.DisplacementMm);
|
||||
|
||||
if (!countsMatch || !valuesMatch)
|
||||
{
|
||||
Log.Warning(
|
||||
"实时曲线数据不同步:TestNumber={TestNumber}, PointIndex={PointIndex}, ExpectedCount={ExpectedCount}, Counts=[Vertical:{VerticalCount}, Friction:{FrictionCount}, Coefficient:{CoefficientCount}, Displacement:{DisplacementCount}], ValuesMatch={ValuesMatch}, DataPoint=[Time:{Time:F3}s, Vertical:{Vertical:F3}N, Friction:{Friction:F3}N, Coefficient:{Coefficient:F5}, Displacement:{Displacement:F3}mm], ChartLast=[Vertical:{VerticalChart}, Friction:{FrictionChart}, Coefficient:{CoefficientChart}, Displacement:{DisplacementChart}]",
|
||||
TestNumber,
|
||||
expectedCount,
|
||||
expectedCount,
|
||||
verticalLoadPoints.Count,
|
||||
horizontalFrictionPoints.Count,
|
||||
frictionCoefficientPoints.Count,
|
||||
displacementPoints.Count,
|
||||
valuesMatch,
|
||||
point.TimeSeconds,
|
||||
point.VerticalLoadN,
|
||||
point.HorizontalFrictionN,
|
||||
point.FrictionCoefficient,
|
||||
point.DisplacementMm,
|
||||
FormatChartPoint(verticalLoadPoints.Count > 0 ? verticalLoadPoints[^1] : null),
|
||||
FormatChartPoint(horizontalFrictionPoints.Count > 0 ? horizontalFrictionPoints[^1] : null),
|
||||
FormatChartPoint(frictionCoefficientPoints.Count > 0 ? frictionCoefficientPoints[^1] : null),
|
||||
FormatChartPoint(displacementPoints.Count > 0 ? displacementPoints[^1] : null));
|
||||
return;
|
||||
}
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
if (expectedCount > 3 && now - lastRealtimeCurveTraceLoggedAt < RealtimeCurveTraceInterval)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lastRealtimeCurveTraceLoggedAt = now;
|
||||
Log.Debug(
|
||||
"实时曲线点同步:TestNumber={TestNumber}, PointIndex={PointIndex}, Time={Time:F3}s, Vertical={Vertical:F3}N, Friction={Friction:F3}N, Coefficient={Coefficient:F5}, Displacement={Displacement:F3}mm, InDynamicWindow={InDynamicWindow}, ChartCount={ChartCount}",
|
||||
TestNumber,
|
||||
expectedCount,
|
||||
point.TimeSeconds,
|
||||
point.VerticalLoadN,
|
||||
point.HorizontalFrictionN,
|
||||
point.FrictionCoefficient,
|
||||
point.DisplacementMm,
|
||||
point.TimeSeconds >= DynamicWindowStartSeconds && point.TimeSeconds <= DynamicWindowEndSeconds,
|
||||
expectedCount);
|
||||
}
|
||||
|
||||
private static bool ChartPointMatches(ObservablePoint chartPoint, double expectedX, double expectedY) =>
|
||||
NearlyEquals(chartPoint.X, expectedX) && NearlyEquals(chartPoint.Y, expectedY);
|
||||
|
||||
private static bool NearlyEquals(double? actual, double expected) =>
|
||||
actual.HasValue && Math.Abs(actual.Value - expected) < 0.000001;
|
||||
|
||||
private static string FormatChartPoint(ObservablePoint? point) =>
|
||||
point is null
|
||||
? "null"
|
||||
: $"({FormatNullable(point.X)},{FormatNullable(point.Y)})";
|
||||
|
||||
private static string FormatNullable(double? value) =>
|
||||
value.HasValue ? value.Value.ToString("F3", CultureInfo.InvariantCulture) : "null";
|
||||
|
||||
private static string FormatDataPoint(SlipDataPoint? point) =>
|
||||
point is null
|
||||
? "null"
|
||||
: $"Time={point.TimeSeconds.ToString("F3", CultureInfo.InvariantCulture)}s, Vertical={point.VerticalLoadN.ToString("F3", CultureInfo.InvariantCulture)}N, Friction={point.HorizontalFrictionN.ToString("F3", CultureInfo.InvariantCulture)}N, Coefficient={point.FrictionCoefficient.ToString("F5", CultureInfo.InvariantCulture)}, Displacement={point.DisplacementMm.ToString("F3", CultureInfo.InvariantCulture)}mm";
|
||||
|
||||
private async Task RunDeviceCommand(Task command, string successMessage)
|
||||
{
|
||||
try
|
||||
|
||||
Reference in New Issue
Block a user