/// <summary> /// Perform the blind-search. /// </summary> /// <param name="horizontalArgs">The arguments of the horizontal axis.</param> /// <param name="verticalArgs">The arguments of the vertical axis.</param> /// <param name="adcUsed">Note: only one ADC channel can be used to sample.</param> /// <param name="scanResults">Return the intensity-to-position points.</param> /// <param name="progressReportHandle"></param> public void StartBlindSearch(BlindSearchArgs horizontalArgs, BlindSearchArgs verticalArgs, ADCChannels adcUsed, out List <Point3D> scanResults, IProgress <BlindSearchProgressReport> progressReportHandle = null) { //! The memory is cleared automatically, you don't have to clear it manually. // arguments checking. if (GlobalDefinition.NumberOfSetBits((int)adcUsed) != 1) { throw new ArgumentException("only 1 analog capture channel can be activated.", nameof(adcUsed)); } if (horizontalArgs.Gap < horizontalArgs.Interval) { throw new ArgumentException($"the capture interval of {horizontalArgs.Unit} should be less than the gap."); } if (verticalArgs.Gap < verticalArgs.Interval) { throw new ArgumentException($"the capture interval of {verticalArgs.Unit} should be less than the gap."); } scanResults = new List <Point3D>(); ConfigAdcTrigger(adcUsed); // report progress. progressReportHandle?.Report(new BlindSearchProgressReport(BlindSearchProgressReport.ProgressStage.SCAN, 0)); lock (_lockController) { Send(new CommandBlindSearch(horizontalArgs, verticalArgs)); } var err = WaitBySystemState(200, 120000, new List <UnitID>() { horizontalArgs.Unit, verticalArgs.Unit }); if (err.Error != Errors.ERR_NONE) { throw new SystemErrorException(err); } else { //var values = new List<double>(new double[100000]); // read the sampling points from the memory. var adcValues = ReadMemoryAll(new Progress <MemoryReadProgressReport>(e => { // report transmission progress. progressReportHandle?.Report(new BlindSearchProgressReport(BlindSearchProgressReport.ProgressStage.TRANS, e.Complete)); })).ToList(); var indexOfAdcValues = 0; var cycle = 0; double x = 0, y = 0; // rebuild the relationship between the position and the intensity. while (true) { var seq = cycle % 4; BlindSearchArgs activeParam; int moveDirection; switch (seq) { case 0: // move horizontal axis (x) to positive direction (right) activeParam = horizontalArgs; moveDirection = 1; break; case 1: activeParam = verticalArgs; moveDirection = 1; break; case 2: activeParam = horizontalArgs; moveDirection = -1; break; case 3: activeParam = verticalArgs; moveDirection = -1; break; default: throw new InvalidOperationException("unknown sequence in the blind search."); } var steps = moveDirection * (activeParam.Gap * (cycle / 2 + 1)); if (Math.Abs(steps) > activeParam.Range) { break; } // for the horizontal axis. if (activeParam == horizontalArgs) { var originPos = x; while (true) { scanResults.Add(indexOfAdcValues > (adcValues.Count - 1) ? new Point3D(x, y, 0) : new Point3D(x, y, adcValues[indexOfAdcValues++])); x += moveDirection * activeParam.Interval; if (!(Math.Abs(x - originPos) >= Math.Abs(steps))) { continue; } x = originPos + steps; break; } } else if (activeParam == verticalArgs) { var originPos = y; while (true) { scanResults.Add(indexOfAdcValues > (adcValues.Count - 1) ? new Point3D(x, y, 0) : new Point3D(x, y, adcValues[indexOfAdcValues++])); y += moveDirection * activeParam.Interval; if (!(Math.Abs(y - originPos) >= Math.Abs(steps))) { continue; } y = originPos + steps; break; } } cycle++; } //// output debug data. //StringBuilder sb = new StringBuilder(); //foreach(var point in ScanResults) //{ // sb.Append($"{point.X}\t{point.Y}\t{point.Z}\r\n"); //} if (scanResults.Count != adcValues.Count) { throw new ADCSamplingPointMissException(scanResults.Count, adcValues.Count); } } }
/// <summary> /// Perform the blind-search. /// </summary> /// <param name="HorizontalArgs">The arguments of the horizontal axis.</param> /// <param name="VerticalArgs">The arguments of the vertical axis.</param> /// <param name="AdcUsed">Note: only one ADC channel can be used to sample.</param> /// <param name="ScanResults">Return the intensity-to-position points.</param> public void StartBlindSearch(BlindSearchArgs HorizontalArgs, BlindSearchArgs VerticalArgs, ADCChannels AdcUsed, out List <Point3D> ScanResults) { //! The memory is cleared automatically, you don't have to clear it manually. // check argments. if (GlobalDefinition.NumberOfSetBits((int)AdcUsed) != 1) { throw new ArgumentException($"specify ONLY one channel of the ADC to capture the analog signal."); } if (HorizontalArgs.Gap < HorizontalArgs.Interval) { throw new ArgumentException($"the trigger interval of {HorizontalArgs.Unit} shoud be less than the value of the gap."); } if (VerticalArgs.Gap < VerticalArgs.Interval) { throw new ArgumentException($"the trigger interval of {VerticalArgs.Unit} shoud be less than the value of the gap."); } ScanResults = new List <Point3D>(); ConfigADCTrigger(AdcUsed); lock (lockController) { Send(new CommandBlindSearch(HorizontalArgs, VerticalArgs)); } var err = WaitBySystemState(200, 120000); if (err.Error != Errors.ERR_NONE) { throw new SystemErrorException(err); } else { //var values = new List<double>(new double[100000]); // read the sampling points from the memory. var adcValues = ReadMemoryAll(); int indexOfAdcValues = 0; int cycle = 0; double x = 0, y = 0; BlindSearchArgs activeParam = null; int moveDirection = 1; // rebuild the relationship between the position and the intensity. while (true) { var seq = cycle % 4; switch (seq) { case 0: // move horizontal axis (x) to positive direction (right) activeParam = HorizontalArgs; moveDirection = 1; break; case 1: activeParam = VerticalArgs; moveDirection = 1; break; case 2: activeParam = HorizontalArgs; moveDirection = -1; break; case 3: activeParam = VerticalArgs; moveDirection = -1; break; } var steps = moveDirection * (activeParam.Gap * (cycle / 2 + 1)); if (Math.Abs(steps) > activeParam.Range) { break; } // for the horizontal axis. if (activeParam == HorizontalArgs) { var originPos = x; while (true) { if (indexOfAdcValues > (adcValues.Count - 1)) { ScanResults.Add(new Point3D(x, y, 0)); } else { ScanResults.Add(new Point3D(x, y, adcValues[indexOfAdcValues++])); } x += moveDirection * activeParam.Interval; if (Math.Abs(x - originPos) >= Math.Abs(steps)) { x = originPos + steps; break; } } } else if (activeParam == VerticalArgs) { var originPos = y; while (true) { if (indexOfAdcValues > (adcValues.Count - 1)) { ScanResults.Add(new Point3D(x, y, 0)); } else { ScanResults.Add(new Point3D(x, y, adcValues[indexOfAdcValues++])); } y += moveDirection * activeParam.Interval; if (Math.Abs(y - originPos) >= Math.Abs(steps)) { y = originPos + steps; break; } } } cycle++; } // output debug data. StringBuilder sb = new StringBuilder(); foreach (var point in ScanResults) { sb.Append($"{point.X}\t{point.Y}\t{point.Z}\r\n"); } if (ScanResults.Count > adcValues.Count) { throw new ADCSamplingPointMissException(ScanResults.Count, adcValues.Count); } } }
/// <summary> /// Perform the fast-1D alignment with two analog capture channel activated. /// </summary> /// <param name="unit"></param> /// <param name="range"></param> /// <param name="interval"></param> /// <param name="speed"></param> /// <param name="analogCapture"></param> /// <param name="scanResults"></param> /// <param name="analogCapture2"></param> /// <param name="scanResults2"></param> public void StartFast1D(UnitID unit, int range, ushort interval, byte speed, ADCChannels analogCapture, out List <Point2D> scanResults, ADCChannels analogCapture2, out List <Point2D> scanResults2) { if (GlobalDefinition.NumberOfSetBits((int)analogCapture) != 1) { throw new ArgumentException("only 1 analog capture channel can be activated.", nameof(analogCapture)); } if ((analogCapture2 != 0) && GlobalDefinition.NumberOfSetBits((int)analogCapture2) != 1) { throw new ArgumentException("only 1 analog capture channel can be activated.", nameof(analogCapture2)); } var dir = range < 0 ? -1 : 1; scanResults = new List <Point2D>(); scanResults2 = null; if (analogCapture2 != 0) { scanResults2 = new List <Point2D>(); } ConfigAdcTrigger(analogCapture | analogCapture2); ClearMemory(); MoveTriggerAdc(unit, range, speed, interval); // read sampling points from the memory. var adcValues = ReadMemoryAll().ToList(); var x = 0; var indexOfAdcValues = 0; while (true) { scanResults.Add(indexOfAdcValues > (adcValues.Count - 1) ? new Point2D(x, 0) : new Point2D(x, adcValues[indexOfAdcValues++])); if (analogCapture2 != 0) { scanResults2?.Add(indexOfAdcValues > (adcValues.Count - 1) ? new Point2D(x, 0) : new Point2D(x, adcValues[indexOfAdcValues++])); } x += (dir * interval); if (Math.Abs(x) >= Math.Abs(range)) { break; } } #region Convert negative coordinates to positive coordinates. var minPos = scanResults.Min(p => p.X); foreach (var p in scanResults) { p.X -= minPos; } if (analogCapture2 != 0 && scanResults2 != null) { minPos = scanResults2.Min(p => p.X); foreach (var p in scanResults2) { p.X -= minPos; } } #endregion // ran too fast, some ADC value missed. var pointsDesired = Math.Abs((int)Math.Ceiling((double)range / interval)); if (pointsDesired != scanResults.Count) { throw new ADCSamplingPointMissException(pointsDesired, scanResults.Count); } }
/// <summary> /// Perform the fast-1D alignment. /// </summary> /// <param name="Unit"></param> /// <param name="Range"></param> /// <param name="Interval"></param> /// <param name="Speed"></param> /// <param name="AnalogCapture"></param> /// <param name="ScanResults"></param> public void StartFast1D(UnitID Unit, int Range, ushort Interval, byte Speed, ADCChannels AnalogCapture, out List <Point2D> ScanResults, ADCChannels AnalogCapture2, out List <Point2D> ScanResults2) { if (GlobalDefinition.NumberOfSetBits((int)AnalogCapture) != 1) { throw new ArgumentException($"specify ONLY one channel allowed for the analog capture."); } if (GlobalDefinition.NumberOfSetBits((int)AnalogCapture2) > 1) { throw new ArgumentException($"specify ONLY one channel allowed for the analog capture 2, or disable it."); } ScanResults = new List <Point2D>(); ScanResults2 = null; if (AnalogCapture2 != 0) { ScanResults2 = new List <Point2D>(); } ConfigADCTrigger(AnalogCapture | AnalogCapture2); ClearMemory(); MoveTriggerADC(Unit, Range, Speed, Interval); // read sampling points from the memory. var adcValues = ReadMemoryAll(); int x = 0; int indexOfAdcValues = 0; while (true) { if (indexOfAdcValues > (adcValues.Count - 1)) { ScanResults.Add(new Point2D(x, 0)); } else { ScanResults.Add(new Point2D(x, adcValues[indexOfAdcValues++])); } if (AnalogCapture2 != 0) { if (indexOfAdcValues > (adcValues.Count - 1)) { ScanResults2.Add(new Point2D(x, 0)); } else { ScanResults2.Add(new Point2D(x, adcValues[indexOfAdcValues++])); } } x += Interval; if (Math.Abs(x) >= Math.Abs(Range)) { break; } } // ran too fast, some ADC value missed. if (ScanResults.Count * Interval < Range) { throw new ADCSamplingPointMissException((int)Math.Ceiling((decimal)Range / Interval), ScanResults.Count); } }