528 lines
25 KiB
C#
528 lines
25 KiB
C#
using CordonelPreadjustmentUi.Const;
|
||
using CordonelPreadjustmentUi.Helper;
|
||
using CordonelPreadjustmentUi.Helper.Extensions;
|
||
using CordonelPreadjustmentUi.Processes.Itinerary;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
|
||
using Xylem.Common.Ui.CordonelPreadjustmentUi;
|
||
using static CordonelPreadjustmentUi.PreAdjustmentControl;
|
||
|
||
namespace CordonelPreadjustmentUi.Processes.Actions
|
||
{
|
||
public class SPAmplitudeTestProcess : BaseProcess
|
||
{
|
||
public SPAmplitudeTestProcess(string processName, StatusPanelItems panelState, string performMessage, string failedMessage, int? expectedTimeS) : base(processName, panelState, performMessage, failedMessage, expectedTimeS)
|
||
{
|
||
}
|
||
|
||
public override List<Task> StartWork()
|
||
{
|
||
return doWorkProcess(base.CurrentProcessProgress);
|
||
}
|
||
|
||
private List<Task> doWorkProcess(ProcessProgress pp)
|
||
{
|
||
var MetersToProcess = MeterStateCtls.Where(e => e.IsEnabled).ToList();
|
||
|
||
var listOfProcessTask = new List<Task>();
|
||
|
||
foreach (var meterctl in MetersToProcess)
|
||
{
|
||
listOfProcessTask.Add(new Task<bool>(() =>
|
||
{
|
||
|
||
pp.DebugMessage($"Performing {ProcessName} procedure", null, "CC");
|
||
|
||
#region Definitions and initializations
|
||
const Int32 FirstHitShiftValue = 4;
|
||
const Int32 FirstHitShiftValueEnd = 4;
|
||
const Int32 FirstHitUpdatePeriodeValue = 1;
|
||
const Int32 FirstHitUpdatePeriodeValueEnd = 10;
|
||
const Int32 WaitBeforeLogging = 5;
|
||
String DebugMessage = String.Empty;
|
||
|
||
var TofAvgMean = new MultiPathDataLogContainer<Double>(pp.Setting.NumberOfPaths);
|
||
var OptimalPoint = new MultiPathDataLogContainer<Int32>(pp.Setting.NumberOfPaths);
|
||
var TofAvgMeanTotal = new MultiPathDataLogContainer<List<Double>>(pp.Setting.NumberOfPaths);
|
||
TofAvgMeanTotal.Update(null, new List<Double>());
|
||
|
||
Boolean Ok = false;
|
||
#endregion
|
||
#region StartLogging
|
||
if (pp.Setting.AmpTestGenerateLogfiles)
|
||
{
|
||
String time = System.DateTime.Now.ToString(Formats.LogFileDateTimeString);
|
||
String Header = $"Genesis ZeroFlowOffsetCalibration {meterctl.Meter.Slot}; PCB ID = {meterctl.Meter.PcbId}; Date = {time}; Operator = {Environment.UserName}\n";
|
||
meterctl.Meter.DataLog(Header);
|
||
//GenesisZeroFlow._GenesisZeroFlow.SetLoggingPathAmplitudeTest(this.MeterNumber, $"{DataLogging.DefaultPath}AmplitudeTest_RawData_{TempPcbID}_{time}.txt");
|
||
meterctl.Meter.logAmpTest = true;
|
||
pp.DebugMessage($" Start logging", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId);
|
||
}
|
||
#endregion
|
||
|
||
|
||
Ok = false;
|
||
|
||
Ok = WriteRegisterSafe(meterctl.Meter, "First hit update period", Register.Genesisflow.FirstHitUpdatePeriod, FirstHitUpdatePeriodeValue);
|
||
if (CheckAbort(Ok, meterctl)) { return Ok; }
|
||
|
||
pp.StatusLabel = (PredefinedMessages.WaitUntilRegisterWriteFinished(pp.Setting.Culture));
|
||
Ok = false;
|
||
Ok = WriteRegisterSafe(meterctl.Meter, "WorkAround TriggerIdle", Register.Genesisflow.TriggerIdle, 1, false);
|
||
Thread.Sleep(150);
|
||
|
||
pp.StatusLabel = (PredefinedMessages.WaitUntilRegisterWriteFinished(pp.Setting.Culture));
|
||
Ok = false;
|
||
Ok = WriteRegisterSafe(meterctl.Meter, "first hit shift", Register.Genesisflow.FirstHitShift, FirstHitShiftValueEnd);
|
||
|
||
Thread.Sleep(150);
|
||
pp.StatusLabel = (PredefinedMessages.WaitUntilRegisterWriteFinished(pp.Setting.Culture));
|
||
Ok = false;
|
||
Ok = WriteRegisterSafe(meterctl.Meter, "WorkAround TriggerActive", Register.Genesisflow.TriggerActive, 1, false);
|
||
Thread.Sleep(150);
|
||
|
||
#region Set first hit level percentage from 5 to 35
|
||
pp.DebugMessage($"Start first hit level percentage sweep ", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId);
|
||
for (Int32 FirstHitLevelPercentage = pp.Setting.AmpTestPercentageStart; FirstHitLevelPercentage <= pp.Setting.AmpTestPercentageStop; FirstHitLevelPercentage++)
|
||
{
|
||
if (CheckAbort(Ok, meterctl)) { return Ok; }
|
||
|
||
pp.StatusLabel = $"{PredefinedMessages.WaitUntilPercentageSweepFinished(pp.Setting.Culture)} {FirstHitLevelPercentage.ToString(pp.Setting.Culture)}/{pp.Setting.AmpTestPercentageStop.ToString(pp.Setting.Culture)}";
|
||
#region Write to percentage register PATH0
|
||
|
||
Ok = false;
|
||
|
||
Ok = WriteRegisterSafe(meterctl.Meter, "Percentage", Register.Genesisflow.FirstHitPercent3, FirstHitLevelPercentage);
|
||
if (CheckAbort(Ok, meterctl)) { return Ok; }
|
||
#endregion
|
||
|
||
#region Wait for 1 second
|
||
for (Int32 i = 0; i < WaitBeforeLogging; i++)
|
||
{
|
||
Thread.Sleep(200);
|
||
}
|
||
#endregion
|
||
#region Record TOF
|
||
|
||
|
||
Ok = RecordData(pp, meterctl, Ok, FirstHitLevelPercentage);
|
||
|
||
bool retryRecord = false;
|
||
if (true)
|
||
{
|
||
if (!meterctl.Meter.listOfTotalTimeOfFlightSPerPath.Get(2).Any())
|
||
{
|
||
pp.StatusLabel = $"No Data for Path {2}. Start one recollect";
|
||
|
||
retryRecord = true;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//for (UInt16 Path = 0; Path < meterctl.Meter.listOfTotalTimeOfFlightSPerPath.GetPathCount(); Path++)
|
||
//{
|
||
// if (!meterctl.Meter.listOfTotalTimeOfFlightSPerPath.Get(Path).Any())
|
||
// {
|
||
// pp.StatusLabel = $"No Data for Path {Path}. Start one recollect";
|
||
|
||
// retryRecord = true;
|
||
// }
|
||
|
||
//}
|
||
}
|
||
|
||
if (retryRecord)
|
||
{
|
||
Ok = RecordData(pp, meterctl, Ok, FirstHitLevelPercentage);
|
||
}
|
||
|
||
|
||
pp.StatusLabel = $"{PredefinedMessages.WaitUntilPercentageSweepFinished(pp.Setting.Culture)} {FirstHitLevelPercentage.ToString(pp.Setting.Culture)}/{ pp.Setting.AmpTestPercentageStop.ToString(pp.Setting.Culture)}; 0s";
|
||
Ok = true;
|
||
#endregion
|
||
#region Calculate mean value
|
||
UInt16 Path = 2;
|
||
|
||
var meanVal = meterctl.Meter.listOfTotalTimeOfFlightSPerPath.Get(Path).ToList().Mean();
|
||
pp.DebugMessage($"Calculate mean value {meanVal} at {meterctl.Meter.Slot}; PATH{(Path + 1).ToString(pp.Setting.Culture)}", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId);
|
||
//earlier TofAvgMeanTotal
|
||
//TofAvgMean.Update(Path, meanVal);
|
||
|
||
if (meanVal == 0)
|
||
{
|
||
pp.DebugMessage($"Mean value is zero at {meterctl.Meter.Slot}; PATH{(Path + 1).ToString(pp.Setting.Culture)}; Value = {Math.Round(meanVal, 4).ToString("000.0000", pp.Setting.Culture)}", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId);
|
||
meterctl.Meter.calibrationResult.AddAdditionalLog($"" +
|
||
$"PATH {Path + 1}", Math.Round(meanVal, 4).ToString("000.0000", pp.Setting.Culture));
|
||
|
||
if (CheckAbort(false, meterctl)) { return false; }
|
||
}
|
||
|
||
pp.DebugMessage($"Mean value at {meterctl.Meter.Slot}; PATH{(Path + 1).ToString(pp.Setting.Culture)}; Value = {Math.Round(meanVal, 4).ToString("000.0000", pp.Setting.Culture)}", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId);
|
||
|
||
meterctl.Meter.calibrationResult.AddAdditionalLog($"Amp. Test Mean value PATH {Path + 1}", $"at {FirstHitLevelPercentage}={Math.Round(meanVal, 4).ToString("000.0000", pp.Setting.Culture)}");
|
||
var cTofAvgMeanTotal = TofAvgMeanTotal.Get(0).ToList();
|
||
|
||
cTofAvgMeanTotal.Add(meanVal);
|
||
TofAvgMeanTotal.Update(0, cTofAvgMeanTotal);
|
||
//meterctl.Meter.listOfTotalTimeOfFlightSPerPath.Update(Path,new List<Double>());
|
||
|
||
|
||
#endregion
|
||
}
|
||
#endregion
|
||
#region Write raw data to files
|
||
//if (this.GenerateLogFiles)
|
||
//{
|
||
// GenesisZeroFlow._GenesisZeroFlow.SetLoggingIndicatorAmpTest(this.MeterNumber, false);
|
||
// String temp = GenesisZeroFlow._GenesisZeroFlow.GetDataToLog()[this.MeterNumber];
|
||
// pp.DebugMessage =$"{meterctl.Meter.PcbId}\tAPPLICATION:\t\t Write data to files at {meterctl.Meter.Slot}\n";
|
||
// Logging.WriteToFile(temp, GenesisZeroFlow._GenesisZeroFlow.GetLoggingPathAmplitudeTest()[this.MeterNumber]);
|
||
//}
|
||
#endregion
|
||
#region Write mean values to file
|
||
//String DateTime = System.DateTime.Now.ToString(Formats.LogFileDateTimeString;
|
||
//if (this.GenerateMeanFiles)
|
||
//{
|
||
// for (UInt16 Path = Constants.PATH0; Path < Constants.NumberOfPaths; Path++)
|
||
// Logging.WriteToFile(GenesisZeroFlow._GenesisZeroFlow.GetAmpValuesToLog()[this.MeterNumber][Constants.PATH0], $@"..\ZeroflowCalibrationTool_MeanAmplitude_{meterctl.Meter.Slot}_PATH{Path + 1}_{TempPcbID}_{DateTime}.csv");
|
||
//}
|
||
|
||
|
||
//this.ClearData();
|
||
//#endregion
|
||
#region Calculate optimal point
|
||
|
||
var DistanceLeft = new MultiPathDataLogContainer<double>(pp.Setting.NumberOfPaths);
|
||
var DistanceRight = new MultiPathDataLogContainer<double>(pp.Setting.NumberOfPaths);
|
||
|
||
var CalculationFailed = new MultiPathDataLogContainer<bool>(pp.Setting.NumberOfPaths);
|
||
|
||
pp.DebugMessage($"Start calculating optimal points", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId);
|
||
|
||
for (UInt16 Path = 0; Path < TofAvgMeanTotal.GetPathCount(); Path++)
|
||
{
|
||
var tmpOptimalPoint = 0;
|
||
var tmpDistanceLeft = 0.0;
|
||
var tmpDistanceRight = 0.0;
|
||
|
||
var r = CalculateOptimalPoint(pp, meterctl.Meter.Slot, TofAvgMeanTotal.Get(Path).ToList(), out tmpDistanceLeft, out tmpDistanceRight, out tmpOptimalPoint);
|
||
OptimalPoint.Update(Path, tmpOptimalPoint);
|
||
DistanceLeft.Update(Path, tmpDistanceLeft);
|
||
DistanceRight.Update(Path, tmpDistanceRight);
|
||
|
||
CalculationFailed.Update(Path, r);
|
||
|
||
if (!r)
|
||
{
|
||
meterctl.Meter.calibrationResult.AddAdditionalLog($"Amp. Test OptimalPoint PATH {Path + 1}", OptimalPoint.Get(Path).ToString(pp.Setting.Culture));
|
||
pp.DebugMessage($"Optimal point calculation successful PATH{Path + 1}; Value = {OptimalPoint.Get(Path).ToString(pp.Setting.Culture)}", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId);
|
||
}
|
||
else
|
||
{
|
||
meterctl.Meter.calibrationResult.AddAdditionalLog($"Amp. Test OptimalPoint PATH {Path + 1}", "NaN");
|
||
pp.DebugMessage($"Optimal point calculation failed, PATH{Path + 1}", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId);
|
||
if (CheckAbort(!r, meterctl)) { return !r; }
|
||
}
|
||
|
||
}
|
||
#endregion
|
||
#region Check value
|
||
pp.DebugMessage($"Start optimal point values check", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId);
|
||
|
||
Boolean OptimalPointOK = true;
|
||
for (UInt16 Path = 0; Path < OptimalPoint.GetPathCount(); Path++)
|
||
{
|
||
if (!this.CheckOptimalPoint(pp, OptimalPoint.Get(Path), out DebugMessage, meterctl.Meter.Slot))
|
||
{
|
||
OptimalPointOK = false;
|
||
}
|
||
|
||
pp.DebugMessage($"{DebugMessage}, PATH{Path + 1}", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId);
|
||
}
|
||
|
||
if (CheckAbort(OptimalPointOK, meterctl)) { return OptimalPointOK; }
|
||
#endregion
|
||
#region Check distance
|
||
Boolean CheckDistOK = true;
|
||
for (UInt16 Path = 0; Path < DistanceLeft.GetPathCount(); Path++)
|
||
{
|
||
if (!this.CheckDistance(pp, DistanceLeft.Get(Path), DistanceRight.Get(Path), out DebugMessage, meterctl.Meter.Slot))
|
||
{
|
||
CheckDistOK = false;
|
||
}
|
||
|
||
pp.DebugMessage($"{DebugMessage}, PATH{Path + 1}", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId);
|
||
}
|
||
if (CheckAbort(CheckDistOK, meterctl)) { return CheckDistOK; }
|
||
|
||
#endregion
|
||
#region Set first hit level percentage registers
|
||
pp.DebugMessage($"Start writing to percentage registers", meterctl.Meter.Slot, "CC", meterctl.Meter.PcbId);
|
||
|
||
pp.StatusLabel = ($"{PredefinedMessages.WaitUntilRegisterWriteFinished(pp.Setting.Culture)}");
|
||
Ok = false;
|
||
String RegValue = Register.Genesisflow.FirstHitPercent2;
|
||
|
||
|
||
Ok = WriteRegisterSafe(meterctl.Meter, "Percentage", RegValue, OptimalPoint.Get(0));
|
||
if (CheckAbort(Ok, meterctl)) { return Ok; }
|
||
|
||
#endregion
|
||
|
||
//here
|
||
|
||
#region Set first hit update period to 10
|
||
pp.StatusLabel = (PredefinedMessages.WaitUntilRegisterWriteFinished(pp.Setting.Culture));
|
||
Ok = false;
|
||
Ok = WriteRegisterSafe(meterctl.Meter, "first hit update period", Register.Genesisflow.FirstHitUpdatePeriod, FirstHitUpdatePeriodeValueEnd);
|
||
if (CheckAbort(Ok, meterctl)) { return Ok; }
|
||
#endregion
|
||
|
||
#region Wait for 1 second
|
||
for (Int32 i = 0; i < WaitBeforeLogging; i++)
|
||
{
|
||
Thread.Sleep(300);
|
||
}
|
||
#endregion
|
||
|
||
|
||
|
||
#region Set first hit shift to 4
|
||
//Frost, Alex <AFrost@sentec.co.uk> Do 02.07.2020 17:12
|
||
//RE: Writing 4 to 'First hit shift'-register failed
|
||
//I think a workaround would be to go into idle mode before changing this register then back to active mode after.I haven’t tried this out yet
|
||
pp.StatusLabel = (PredefinedMessages.WaitUntilRegisterWriteFinished(pp.Setting.Culture));
|
||
Ok = false;
|
||
Ok = WriteRegisterSafe(meterctl.Meter, "WorkAround TriggerIdle", Register.Genesisflow.TriggerIdle, 1, false);
|
||
Thread.Sleep(150);
|
||
pp.StatusLabel = (PredefinedMessages.WaitUntilRegisterWriteFinished(pp.Setting.Culture));
|
||
Ok = false;
|
||
Ok = WriteRegisterSafe(meterctl.Meter, "first hit shift", Register.Genesisflow.FirstHitShift, FirstHitShiftValueEnd);
|
||
Thread.Sleep(150);
|
||
pp.StatusLabel = (PredefinedMessages.WaitUntilRegisterWriteFinished(pp.Setting.Culture));
|
||
Ok = false;
|
||
Ok = WriteRegisterSafe(meterctl.Meter, "WorkAround TriggerActive", Register.Genesisflow.TriggerActive, 1, false);
|
||
Thread.Sleep(150);
|
||
|
||
if (CheckAbort(Ok, meterctl)) { return Ok; }
|
||
#endregion
|
||
#endregion
|
||
return Ok;
|
||
}));
|
||
|
||
}
|
||
|
||
|
||
return listOfProcessTask;
|
||
|
||
}
|
||
|
||
private bool RecordData(ProcessProgress pp, MeterStateControl meterctl, bool Ok, int FirstHitLevelPercentage)
|
||
{
|
||
meterctl.Meter.listOfTotalTimeOfFlightSPerPath.Update(null, new List<Double>());
|
||
meterctl.Meter.logAmpTest = true;
|
||
|
||
pp.DebugMessage($"Start collecting data", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId);
|
||
var LinecounterFollowing = new MultiPathDataLogContainer<Int32>(pp.Setting.NumberOfPaths);
|
||
|
||
|
||
for (Int32 Seconds = 0; Seconds < pp.Setting.AmpTestTofRecordingTime; Seconds++) // eight seconds remove /2
|
||
{
|
||
if (Int32.Equals((Seconds % pp.Setting.AmpTestActivityCheckInverval), 0))
|
||
{
|
||
pp.StatusLabel = $"{PredefinedMessages.WaitUntilPercentageSweepFinished(pp.Setting.Culture)} {FirstHitLevelPercentage.ToString(pp.Setting.Culture)}/{ pp.Setting.AmpTestPercentageStop.ToString(pp.Setting.Culture)}; {(pp.Setting.AmpTestTofRecordingTime - Seconds).ToString(pp.Setting.Culture)}s";
|
||
|
||
Thread.Sleep(1000);
|
||
Ok = ActivityCheck(pp, meterctl.Meter.listOfTotalTimeOfFlightSPerPath, pp.Setting.AmpTestTofRecordingTime);
|
||
if (!Ok)
|
||
{
|
||
pp.DebugMessage($"Activity check failed", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId);
|
||
// if (CheckAbort(Ok, meterctl)) { return Ok; }
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
return Ok;
|
||
}
|
||
|
||
private Boolean CalculateOptimalPoint(ProcessProgress pp, int Slot, List<Double> TofAvg, out Double left, out Double right, out Int32 xAtOptimalPoint)
|
||
{
|
||
|
||
List<Double> ValuesLeft = new List<Double>();
|
||
List<Double> ValuesRight = new List<Double>();
|
||
List<Double> MinDistance = new List<Double>();
|
||
xAtOptimalPoint = 0;
|
||
Boolean SubError = true;
|
||
left = 0;
|
||
right = 0;
|
||
|
||
ValuesLeft = this.CalculateNearestDistanceLeft(pp, TofAvg, out left);
|
||
ValuesRight = this.CalculateNearestDistanceRight(pp, TofAvg, out right);
|
||
|
||
for (UInt16 i = 0; i < ValuesLeft.Count(); i++)
|
||
{
|
||
Double temp1 = ValuesLeft.ElementAt(i);
|
||
Double temp2 = ValuesRight.ElementAt(i);
|
||
Thread.Sleep(10);
|
||
MinDistance.Add(Math.Min(temp1, temp2));
|
||
}
|
||
|
||
//String mindistance = $"mindistance: PATH{path.ToString(GlobalCulture)}\n";
|
||
//for (Int16 i = 0; i < MinDistance.Count(); i++)
|
||
//{
|
||
// Double temp = MinDistance.ElementAt(i);
|
||
// Misc.WaitNMilliseconds(10);
|
||
// mindistance = $"{mindistance}{temp.ToString(GlobalCulture)}\n";
|
||
//}
|
||
//Logging.WriteToFile(mindistance, @"..\mindistance_PATH"+ path.ToString() + ".txt");
|
||
|
||
Double Maximum = 0;
|
||
|
||
for (Int16 i = 0; i < MinDistance.Count(); i++)
|
||
{
|
||
if ((!Int16.Equals(i, 0)) && (!Int16.Equals(i, (Int16)(TofAvg.Count() - 1))))
|
||
{
|
||
if (MinDistance.ElementAt(i) > Maximum)
|
||
{
|
||
Maximum = MinDistance.ElementAt(i);
|
||
xAtOptimalPoint = (Int32)i + pp.Setting.AmpTestPercentageStart;
|
||
;
|
||
SubError = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
return SubError;
|
||
}
|
||
private List<Double> CalculateNearestDistanceLeft(ProcessProgress pp, List<Double> TofAvg, out Double left)
|
||
{
|
||
List<Double> Distance = new List<Double>();
|
||
Double NearestDistance = 0;
|
||
Boolean Detected = false;
|
||
left = 0;
|
||
|
||
for (Int32 Percentage = pp.Setting.AmpTestFirstHitLevelPropMin; Percentage <= pp.Setting.AmpTestFirstHitLevelPropMax; Percentage++)
|
||
{
|
||
Detected = false;
|
||
for (Int32 PercentageFollowing = Percentage; PercentageFollowing <= pp.Setting.AmpTestFirstHitLevelPropMax; PercentageFollowing++)
|
||
{
|
||
if ((TofAvg.ElementAt(PercentageFollowing - pp.Setting.AmpTestFirstHitLevelPropMin) - TofAvg.ElementAt(Percentage - pp.Setting.AmpTestFirstHitLevelPropMin)) > pp.Setting.AmpTestTriggerValue)
|
||
{
|
||
NearestDistance = PercentageFollowing - Percentage;
|
||
Detected = true;
|
||
break;
|
||
}
|
||
}
|
||
if (!Detected)
|
||
{
|
||
NearestDistance = pp.Setting.AmpTestFirstHitLevelPropMax - Percentage;
|
||
}
|
||
|
||
Distance.Add(NearestDistance);
|
||
}
|
||
|
||
for (Int16 i = 0; i < (Int16)Distance.Count(); i++)
|
||
{
|
||
if (Distance.ElementAt(i) >= left)
|
||
{
|
||
left = Distance.ElementAt(i);
|
||
}
|
||
}
|
||
return Distance;
|
||
}
|
||
private List<Double> CalculateNearestDistanceRight(ProcessProgress pp, List<Double> TofAvg, out Double right)
|
||
{
|
||
List<Double> Distance = new List<Double>();
|
||
Double NearestDistance = 0;
|
||
Boolean Detected = false;
|
||
right = 0;
|
||
|
||
for (Int32 Percentage = pp.Setting.AmpTestFirstHitLevelPropMax; Percentage >= (pp.Setting.AmpTestFirstHitLevelPropMin); Percentage--)
|
||
{
|
||
Detected = false;
|
||
|
||
for (Int32 ProportionFollowing = Percentage; ProportionFollowing >= pp.Setting.AmpTestFirstHitLevelPropMin; ProportionFollowing--)
|
||
{
|
||
if ((TofAvg.ElementAt(ProportionFollowing - pp.Setting.AmpTestFirstHitLevelPropMin)) - (TofAvg.ElementAt(Percentage - pp.Setting.AmpTestFirstHitLevelPropMin)) < -pp.Setting.AmpTestTriggerValue)
|
||
{
|
||
NearestDistance = Percentage - ProportionFollowing;
|
||
Detected = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!Detected)
|
||
{
|
||
NearestDistance = Percentage - pp.Setting.AmpTestFirstHitLevelPropMin;
|
||
}
|
||
|
||
Distance.Add(NearestDistance);
|
||
}
|
||
|
||
|
||
Distance.Reverse();
|
||
|
||
for (Int16 i = 0; i < Distance.Count(); i++)
|
||
{
|
||
if (Distance.ElementAt(i) >= right)
|
||
{
|
||
right = Distance.ElementAt(i);
|
||
}
|
||
}
|
||
return Distance;
|
||
}
|
||
private Boolean CheckOptimalPoint(ProcessProgress pp, Int32 optimalPoint, out String debugMessage, int Slot)
|
||
{
|
||
Boolean Ok = true;
|
||
debugMessage = $"Optimal point check successful at {Slot}";
|
||
// ampTestLowerLimit, ampTestUpperLimit, ampTestDistance
|
||
if (optimalPoint > pp.Setting.AmpTestFirstHitLevelPropMax)
|
||
{
|
||
debugMessage = $"Optimal point maximum check failed at {Slot}";
|
||
Ok = false;
|
||
return Ok;
|
||
}
|
||
|
||
if (optimalPoint < pp.Setting.AmpTestFirstHitLevelPropMin)
|
||
{
|
||
debugMessage = $"Optimal point minimum check failed at {Slot}";
|
||
Ok = false;
|
||
return Ok;
|
||
}
|
||
|
||
return Ok;
|
||
}
|
||
private Boolean CheckDistance(ProcessProgress pp, Double left, Double right, out String debugMessage, int Slot)
|
||
{
|
||
Boolean Ok = true;
|
||
debugMessage = $"Distance check successful at {Slot}";
|
||
|
||
if (left < pp.Setting.AmpTestFirstHitLevelPropMin)
|
||
{
|
||
Ok = false;
|
||
debugMessage = $"Distance check failed at {Slot}";
|
||
return Ok;
|
||
}
|
||
|
||
if (right < pp.Setting.AmpTestFirstHitLevelPropMin)
|
||
{
|
||
Ok = false;
|
||
debugMessage = $"Distance check failed at {Slot}";
|
||
return Ok;
|
||
}
|
||
|
||
return Ok;
|
||
}
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
} |