private static void PerformAlignment(SystemServiceClient Service, Func <string, object>[] AlignmentHandlers, Options opts, string[] Profiles, SSC_PMRangeEnum PMRange, double BreakPowerDiff_dBm, double BreakPowerMax_dBm = double.MaxValue, int MaxCycle = 5) { if (AlignmentHandlers.Length != Profiles.Length) { throw new Exception("Handler和Profile的数量不一致。"); } var cycle = 0; var currPower = Service.__SSC_Powermeter_Read(opts.PowerMeterCaption); var lastPower = currPower; while (true) { Service.__SSC_Powermeter_SetRange(opts.PowerMeterCaption, PMRange); Thread.Sleep(200); for (var i = 0; i < AlignmentHandlers.Length; i++) { AlignmentHandlers[i](Profiles[i]); } Thread.Sleep(200); // 计算耦合后和耦合前的功率差值 currPower = Service.__SSC_Powermeter_Read(opts.PowerMeterCaption); var diffPower = currPower - lastPower; lastPower = currPower; if (double.IsNaN(BreakPowerDiff_dBm) == false) { if (diffPower <= BreakPowerDiff_dBm || currPower >= BreakPowerMax_dBm) { // if the delta power is less than 2dB, jump out of the loop. break; } cycle++; if (cycle > MaxCycle) { throw new Exception("初始光太小。"); } } else { break; } } // wait until the powermeter is stable. Thread.Sleep(500); }
/// <summary> /// Lens慢速线性扫描 /// </summary> /// <param name="Service"></param> /// <param name="opts"></param> private static void Step3(SystemServiceClient Service, Options opts) { var cycle = 0; Service.__SSC_Powermeter_SetRange(opts.PowerMeterCaption, SSC_PMRangeEnum.AUTO); Thread.Sleep(500); Service.__SSC_LogInfo("开始执行线性扫描...."); while (true) { // PowerMeterAutoRange(Service, PM_CAPTION); var pBeforeAlign = Service.__SSC_Powermeter_Read(opts.PowerMeterCaption); if (opts.UseHillClimbInLensAlign) { Service.__SSC_DoHillClimb(opts.ProfileNameLineScanLens); } else { Service.__SSC_DoProfileND(opts.ProfileNameLineScanLens); } Thread.Sleep(500); var pAfterAlign = Service.__SSC_Powermeter_Read(opts.PowerMeterCaption); Service.__SSC_LogInfo($"光功率:{pAfterAlign:F2}dBm"); var powerDiff = pAfterAlign - pBeforeAlign; Service.__SSC_LogInfo($"Power Diff: {powerDiff:F2}dB, {pAfterAlign:F2}dBm/{pBeforeAlign:F2}dBm"); //if (power > 0 && (powerDiff > -0.2 && powerDiff < 0.2)) if (powerDiff > opts.PowerThreLineScanN && powerDiff < opts.PowerThreLineScanP) { break; } if (pAfterAlign >= opts.PowerThreTerminate) { break; } cycle++; if (cycle > 10) { throw new Exception("慢速扫描执行失败,无法找到稳定光功率。"); } } }
/// <summary> /// 执行爬山算法微调 /// </summary> /// <param name="Apas"></param> /// <param name="opts"></param> private static void Step5(SystemServiceClient Apas, Options opts) { Apas.__SSC_LogInfo("开始执行最终位置优化..."); try { Apas.__SSC_Powermeter_SetRange(opts.PowerMeterCaption, SSC_PMRangeEnum.AUTO); if (opts.UseHillClimbInFinalFineTune) { Apas.__SSC_DoHillClimb(opts.ProfileNameFinalFineTune); } else { Apas.__SSC_DoProfileND(opts.ProfileNameFinalFineTune); } } catch (Exception) { } }
/// <summary> /// Receptacle和准直Lens同时调整。 /// </summary> /// <param name="Apas"></param> private static void Step4(SystemServiceClient Apas, Options opts) { var cycle = 0; Apas.__SSC_LogInfo("开始Rept和准直Lens双边调整..."); Apas.__SSC_Powermeter_SetRange(opts.PowerMeterCaption, SSC_PMRangeEnum.AUTO); while (true) { var pBeforeAlign = Apas.__SSC_Powermeter_Read(opts.PowerMeterCaption); #region 调整Receptacle if (opts.UseProfileNdInReceptLensDualScan == false) { Apas.__SSC_Powermeter_SetRange(opts.PowerMeterCaption, SSC_PMRangeEnum.RANGE4); Apas.__SSC_DoFastND(opts.ProfileNameDualLineScanRecept); } else { Apas.__SSC_Powermeter_SetRange(opts.PowerMeterCaption, SSC_PMRangeEnum.AUTO); Apas.__SSC_DoProfileND(opts.ProfileNameDualLineScanRecept); } #endregion Thread.Sleep(200); #region 调整Lens Apas.__SSC_Powermeter_SetRange(opts.PowerMeterCaption, SSC_PMRangeEnum.AUTO); if (opts.UseHillClimbInLensAlign) { Apas.__SSC_DoHillClimb(opts.ProfileNameDualLineScanLens); } else { Apas.__SSC_DoProfileND(opts.ProfileNameDualLineScanLens); } #endregion Thread.Sleep(500); var pAfterAlign = Apas.__SSC_Powermeter_Read(opts.PowerMeterCaption); var pDiff = pAfterAlign - pBeforeAlign; Apas.__SSC_LogInfo($"Power Diff: {pDiff:F2}dB, {pAfterAlign:F2}dBm, {pBeforeAlign:F2}dBm"); //if (power > 3.5 && (powerDiff > -0.2 && powerDiff < 0.2)) if (pDiff > opts.PowerThreDualLineScanN && pDiff < opts.PowerThreDualLineScanP) { break; } if (pAfterAlign >= opts.PowerThreTerminate) { break; } if (pDiff < -0.3) { break; // 如果耦合功率开始变小超过-0.3dBm,则停止扫描 } cycle++; if (cycle > 10) { var msg = "无法调整稳定功率位置。"; Apas.__SSC_LogError(msg); throw new Exception(msg); } } }
/// <summary> /// The section of the user process. /// 用户自定义流程函数。 /// Please write your process in the following method. /// 请在以下函数中定义您的工艺流程。 /// </summary> /// <param name="Apas"></param> /// <returns></returns> private static void UserProc(SystemServiceClient Apas, CamRemoteAccessContractClient Camera = null, Options opts = null) { try { Apas.__SSC_LogInfo($"目标功率:{opts.PowerThreTerminate:F2}dBm"); var sw = new Stopwatch(); var swTotal = new Stopwatch(); swTotal.Start(); // 初始化功率计状态 Apas.__SSC_LogInfo("初始化光功率计..."); Apas.__SSC_Powermeter_SetRange(opts.PowerMeterCaption, SSC_PMRangeEnum.AUTO); Apas.__SSC_Powermeter_SetUnit(opts.PowerMeterCaption, SSC_PMUnitEnum.dBm); // 等待功率计稳定 Thread.Sleep(500); // 读取初始功率 var power = Apas.__SSC_Powermeter_Read(opts.PowerMeterCaption); Apas.__SSC_LogInfo($"初始光 {power:F2}dBm"); // STEP 1: RECT Area Scan if (power < -25) { if (opts.IgnoreBlindSearch == false) { sw.Restart(); Step1(Apas, opts); sw.Stop(); Apas.__SSC_LogInfo($"耗时: {sw.Elapsed.TotalSeconds:F1}s"); } else { Apas.__SSC_LogWarn($"忽略BlindSearch,当前功率:{power:F2}dBm"); } } // Step 2: Fast Focus Scan if (power < 0) { if (opts.IgnoreFastFocusScan == false) { sw.Restart(); Step2(Apas, opts); sw.Stop(); Apas.__SSC_LogInfo($"耗时: {sw.Elapsed.TotalSeconds:F1}s"); } else { Apas.__SSC_LogWarn($"忽略快速焦距扫描,,当前功率:{power:F2}dBm"); } } // STEP 3: Profile ND to fine-tune. // 等待功率计稳定 Thread.Sleep(500); power = Apas.__SSC_Powermeter_Read(opts.PowerMeterCaption); if (opts.IgnoreLensProfileScan == false && power < opts.PowerThreTerminate) { sw.Restart(); Step3(Apas, opts); sw.Stop(); Apas.__SSC_LogInfo($"耗时: {sw.Elapsed.TotalSeconds:F1}s"); } else { Apas.__SSC_LogWarn($"忽略Lens线性Profile扫描,,当前功率:{power:F2}dBm"); } // STEP 4: 双边耦合 // 等待功率计稳定 Thread.Sleep(500); power = Apas.__SSC_Powermeter_Read(opts.PowerMeterCaption); if (opts.IgnoreReceptLensDualScan == false && power < opts.PowerThreTerminate) { sw.Restart(); Step4(Apas, opts); sw.Stop(); Apas.__SSC_LogInfo($"耗时: {sw.Elapsed.TotalSeconds:F1}s"); } else { Apas.__SSC_LogWarn($"忽略Receptacle-Lens双边扫描,,当前功率:{power:F2}dBm"); } // STEP 5: 最终位置优化 // 等待功率计稳定 Thread.Sleep(500); power = Apas.__SSC_Powermeter_Read(opts.PowerMeterCaption); if (opts.IgnoreFinalFineTune == false && power < opts.PowerThreTerminate) { sw.Restart(); Step5(Apas, opts); sw.Stop(); Apas.__SSC_LogInfo($"耗时: {sw.Elapsed.TotalSeconds:F1}s"); } else { Apas.__SSC_LogWarn($"忽略最终微调,,当前功率:{power:F2}dBm"); } swTotal.Stop(); Apas.__SSC_LogInfo($"总耗时: {swTotal.Elapsed.TotalSeconds:F1}s"); // 检查光功率是否达标 Apas.__SSC_Powermeter_SetRange(opts.PowerMeterCaption, SSC_PMRangeEnum.AUTO); Thread.Sleep(500); power = Apas.__SSC_Powermeter_Read(opts.PowerMeterCaption); Apas.__SSC_LogInfo($"最终光功率为 {power:F2}dBm"); if (TARGET_POWER_MIN_DBM <= power) { Apas.__SSC_LogInfo("脚本运行完成"); } else { var msg = $"无法耦合到目标功率 {TARGET_POWER_MIN_DBM}dBm"; Apas.__SSC_LogError(msg); throw new Exception(msg); } } catch (Exception ex) { //Apas.__SSC_LogError(ex.Message); throw new Exception(ex.Message); } // Thread.Sleep(100); }