static SingleAxisInfo GenerateSingleAxisInfo(SystemServiceClient Service, string aliger, string axisname, int speed = 100, int rank = 1) { axisname = axisname.ToUpper(); double positon = Service.__SSC_GetAbsPosition(aliger, axisname); return(new SingleAxisInfo(axisname, positon, speed, rank)); }
private void btn_AutoCalibrate_Click(object sender, EventArgs e) { Task.Run(new Action(() => { string Aliger = "CWDM4"; if (MessageBox.Show("请确认目标已处于视野左上方", "提示") != DialogResult.OK) { return; } int xOffset = (int)nmUD_XOffset.Value; int yOffset = (int)nmUD_YOffset.Value; for (int j = 0; j < 3; j++) { for (int i = 0; i < 3; i++) { if (i != 0) { service.__SSC_MoveAxis(Aliger, "Y", SSC_MoveMode.REL, 80, -yOffset); } Thread.Sleep(200); double x = service.__SSC_GetAbsPosition(Aliger, "X"); double y = service.__SSC_GetAbsPosition(Aliger, "Y"); //dGV_machinePoint.Rows[j * 3 + i].Cells[1].Value = x; //dGV_machinePoint.Rows[j * 3 + i].Cells[2].Value = y; UpdateDataGridView(dGV_machinePoint, j * 3 + i, x, y); Bitmap _image = camClient.GrabOneFrame("AWG"); visionFun.Bitmap2HObjectBpp32(_image, out HObject _himage); GetAwgPosition(_himage, out HTuple awgx, out HTuple awgy, out HObject cross); //dGV_pixelPoint.Rows[j * 3 + i].Cells[1].Value = awgx.D; //dGV_pixelPoint.Rows[j * 3 + i].Cells[2].Value = awgy.D; UpdateDataGridView(dGV_pixelPoint, j * 3 + i, awgx.D, awgy.D); UpdateDisplay(hDisplay1, _himage, cross); Thread.Sleep(300); } if (j != 2) { service.__SSC_MoveAxis(Aliger, "X", SSC_MoveMode.REL, 80, -xOffset); service.__SSC_MoveAxis(Aliger, "Y", SSC_MoveMode.REL, 80, 2 * yOffset); Thread.Sleep(100); } } MessageBox.Show("标定完成"); })); }
static HTuple model; //模板数据 #endregion #region User Process /// <summary> /// The section of the user process. /// 用户自定义流程函数。 /// /// Please write your process in the following method. /// 请在以下函数中定义您的工艺流程。 /// /// </summary> /// <param name="Service"></param> /// <returns></returns> static void UserProc(SystemServiceClient Service, CamRemoteAccessContractClient Camera = null) { string message = ""; int cycles = 0; bool goodAlign = false; string alignmentProfile = ""; double awgX = 0, awgY = 0, awgAngle = 0; double pdX = 0, pdY = 0, pdAngle = 0; double offsetX, offsetY, offsetAngle; Camera.SetExposure("AWG", 30000); Camera.SetExposure("Left", 16000); Init(); try { // 抬起针筒 Service.__SSC_WriteIO(Conditions.IO_INJECTOR, SSC_IOStatusEnum.Disabled); // 识别AWG角度 Service.__SSC_LogInfo("移动到AWG角度识别位置..."); Service.__SSC_MoveToPresetPosition(Conditions.ALIGNER, "awg拍照位置"); MoveToPosition(Service, "pd初始角度"); // Service.__SSC_MoveToPresetPosition(Conditions.ALIGNER, "pd初始角度"); Thread.Sleep(100); Service.__SSC_LogInfo("识别AWG角度..."); var image1 = Camera.GrabOneFrame("AWG"); HObject awgImage; visionFun.Bitmap2HObjectBpp32(image1, out awgImage); GetAwgOffset(awgImage, ref awgX, ref awgY, ref awgAngle, out Bitmap awgimage); Service.__SSC_ShowImage(awgimage); awgImage.Dispose(); awgimage.Dispose(); awgImage = null; awgimage = null; Service.__SSC_MoveAxis(Conditions.ALIGNER, "R", SSC_MoveMode.REL, 100, -awgAngle); Thread.Sleep(100); // 识别PD Array角度 Service.__SSC_LogInfo("移动到PD Array角度识别位置..."); Service.__SSC_MoveToPresetPosition(Conditions.ALIGNER, "pd拍照位置"); Thread.Sleep(100); Service.__SSC_LogInfo("识别PA Array角度..."); var image2 = Camera.GrabOneFrame("Left"); HObject pdImage; visionFun.Bitmap2HObjectBpp32(image2, out pdImage); GetPdOffset(pdImage, ref pdX, ref pdY, ref pdAngle, out Bitmap pdimage); Service.__SSC_ShowImage(pdimage); pdImage.Dispose(); pdimage.Dispose(); pdImage = null; pdimage = null; offsetX = -awgX - pdX; offsetY = -awgY - pdY; Service.__SSC_LogInfo($"x 方向总偏移量 {offsetX}"); Service.__SSC_LogInfo($"y 方向总偏移量 {offsetY}"); MoveToPosition(Service, "Awg耦合高位"); // Service.__SSC_MoveToPresetPosition(Conditions.ALIGNER, "耦合高位"); Thread.Sleep(100); Service.__SSC_MoveAxis(Conditions.ALIGNER, "X", SSC_MoveMode.REL, 100, -awgX); Thread.Sleep(100); Service.__SSC_MoveAxis(Conditions.ALIGNER, "X", SSC_MoveMode.REL, 100, -pdX); Thread.Sleep(100); Service.__SSC_MoveAxis(Conditions.ALIGNER, "Y", SSC_MoveMode.REL, 100, -awgY); Thread.Sleep(100); Service.__SSC_MoveAxis(Conditions.ALIGNER, "Y", SSC_MoveMode.REL, 100, -pdY); Thread.Sleep(100); var image3 = Camera.GrabOneFrame("Rear"); HObject awgImage1; visionFun.Bitmap2HObjectBpp32(image3, out awgImage1); GetAwgVerticalHeight(Service, awgImage1); Console.WriteLine("Press any key to go to 耦合位置."); Console.ReadKey(); Thread.Sleep(100); MoveToPosition(Service, "Awg耦合低位"); // Service.__SSC_MoveToPresetPosition(Conditions.ALIGNER, "耦合位置"); Console.WriteLine("Press any key to continue."); Console.ReadKey(); int xmaxpath = 0; double[] data = new double[4]; data[0] = Service.__SSC_MeasurableDevice_Read($"{EQUIP_CAPTION},0"); data[1] = Service.__SSC_MeasurableDevice_Read($"{EQUIP_CAPTION},1"); data[2] = Service.__SSC_MeasurableDevice_Read($"{EQUIP_CAPTION},2"); data[3] = Service.__SSC_MeasurableDevice_Read($"{EQUIP_CAPTION},3"); message = "预对准初始响应度:"; for (int i = 0; i < 4; i++) { message += $"[{i}]{data[i]} "; } Service.__SSC_LogInfo(message); if (data[0] < Conditions.Resp_After_VisionAlign) { Service.__SSC_LogError("视觉对准初始光功率过低,请检查产品。"); return; } #region 粗耦合 // 如果初始响应度大于阈值,跳过粗找光。 if (data[0] < Conditions.Resp_After_RoughAlign) { cycles = 0; goodAlign = false; Service.__SSC_LogInfo("开始粗找光..."); while (cycles < 5) { cycles++; alignmentProfile = "x&y_roughScan"; Service.__SSC_LogInfo($"执行Profile-ND,参数[{alignmentProfile}],Cycle {cycles}/5..."); Service.__SSC_DoProfileND(alignmentProfile); var resp = Service.__SSC_MeasurableDevice_Read($"{EQUIP_CAPTION},0"); Service.__SSC_LogInfo($"响应度:{resp}/目标值: {Conditions.Resp_After_RoughAlign}"); if (resp >= Conditions.Resp_After_RoughAlign) { goodAlign = true; break; } } if (!goodAlign) { Service.__SSC_LogError("CH1响应度无法达到规格。"); return; } } #endregion #region 精细耦合 cycles = 0; goodAlign = false; Service.__SSC_LogInfo("开始细找光..."); while (cycles < 5) { cycles++; alignmentProfile = "x&y_detailScan"; Service.__SSC_LogInfo($"执行Profile-ND,参数[{alignmentProfile}],Cycle {cycles}/5..."); Service.__SSC_DoProfileND(alignmentProfile); var resp = Service.__SSC_MeasurableDevice_Read($"{EQUIP_CAPTION},0"); Service.__SSC_LogInfo($"响应度:{resp}/目标值: {Conditions.Resp_After_AccuracyAlign}"); if (resp >= Conditions.Resp_After_AccuracyAlign) { goodAlign = true; break; } } if (!goodAlign) { Service.__SSC_LogError("CH1响应度无法达到规格。"); return; } #endregion #region 角度调整 cycles = 0; goodAlign = false; Service.__SSC_LogInfo("开始角度调整..."); while (cycles < 5) { cycles++; alignmentProfile = "mercury"; Service.__SSC_LogInfo($"执行Angle Tuning,参数[{alignmentProfile}],Cycle {cycles}/5..."); var diff = (double)Service.__SSC_DoAngleTuning(alignmentProfile); Service.__SSC_LogInfo($"1-4通道峰值位置误差:{diff.ToString("F3")}um/目标值: {Conditions.Resp_After_AngleTuning_PeakPosDiff}"); if (Math.Abs(diff) <= Conditions.Resp_After_AngleTuning_PeakPosDiff) { goodAlign = true; break; } } if (!goodAlign) { Service.__SSC_LogError("1-4通道峰值位置误差无法达到规格!"); } #endregion #region 角度调整后精细耦合 cycles = 0; goodAlign = false; Service.__SSC_LogInfo("开始Final找光..."); while (cycles < 5) { cycles++; alignmentProfile = "x&y_detailScan"; Service.__SSC_LogInfo($"执行Profile-ND,参数[{alignmentProfile}],Cycle {cycles}/5..."); Service.__SSC_DoProfileND(alignmentProfile); var resp = Service.__SSC_MeasurableDevice_Read($"{EQUIP_CAPTION},0"); Service.__SSC_LogInfo($"响应度:{resp}/目标值: {Conditions.Resp_Final}"); if (resp >= Conditions.Resp_Final) { goodAlign = true; break; } } if (!goodAlign) { Service.__SSC_LogError("CH1响应度无法达到规格。"); return; } #endregion #region 检查四个通道响应度 double[] finalResp = new double[4]; for (int i = 0; i < 4; i++) { finalResp[i] = Service.__SSC_MeasurableDevice_Read($"{EQUIP_CAPTION},{i}"); } if (finalResp.Min() < Conditions.Resp_Final) { Service.__SSC_LogError($"最小响应度低于规格,规格:{Conditions.Resp_Final}"); return; } else if (finalResp.Max() - finalResp.Min() > Conditions.Resp_Final_Diff) { Service.__SSC_LogError($"通道平衡无法达到规格,规格:{Conditions.Resp_Final_Diff}"); return; } else { Service.__SSC_LogInfo("耦合完成!"); } #endregion #region 保存当前位置 Service.__SSC_LogInfo("保存当前位置..."); var final_x = Service.__SSC_GetAbsPosition(Conditions.ALIGNER, "X"); var final_y = Service.__SSC_GetAbsPosition(Conditions.ALIGNER, "Y"); var final_z = Service.__SSC_GetAbsPosition(Conditions.ALIGNER, "Z"); Service.__SSC_LogInfo($"X: {final_x}, Y: {final_y}, Z: {final_z}"); #endregion Console.WriteLine("请点胶"); Console.ReadKey(); Service.__SSC_MoveAxis(Conditions.ALIGNER, "Z", SSC_MoveMode.REL, 100, -10000); Thread.Sleep(100); Console.WriteLine("点胶完成,按任意键继续"); Console.ReadKey(); Service.__SSC_MoveAxis(Conditions.ALIGNER, "Z", SSC_MoveMode.REL, 100, 9500); Thread.Sleep(100); Service.__SSC_MoveAxis(Conditions.ALIGNER, "Z", SSC_MoveMode.REL, 20, 500); Thread.Sleep(100); return; #region 点胶 Service.__SSC_LogInfo("开始点胶..."); // 上提Z轴,AWG退到安全位置 Service.__SSC_MoveAxis(Conditions.ALIGNER, "Z", SSC_MoveMode.REL, 20, -1000); // 移动到点胶位置 Service.__SSC_MoveToPresetPosition(Conditions.ALIGNER, "点胶位置"); Thread.Sleep(200); // 降下针筒 Service.__SSC_WriteIO(Conditions.IO_INJECTOR, SSC_IOStatusEnum.Enabled); Thread.Sleep(200); // 启动点胶机 Service.__SSC_LogInfo("点胶..."); // 抬起针筒 Service.__SSC_WriteIO(Conditions.IO_INJECTOR, SSC_IOStatusEnum.Disabled); #endregion #region 恢复AWG位置,重新对准 Service.__SSC_LogInfo("恢复AWG位置..."); Service.__SSC_MoveAxis(Conditions.ALIGNER, "X", SSC_MoveMode.ABS, 100, final_x); Service.__SSC_MoveAxis(Conditions.ALIGNER, "Y", SSC_MoveMode.ABS, 100, final_y); Service.__SSC_MoveAxis(Conditions.ALIGNER, "Z", SSC_MoveMode.ABS, 100, final_z); #endregion } catch (Exception ex) { Service.__SSC_LogError(ex.Message); } System.Threading.Thread.Sleep(100); }
/// <summary> /// Fast Focus Scan. /// </summary> /// <param name="Service"></param> private static void Step2(SystemServiceClient Service, Options opts) { var powerZHistory = new List <PointF>(); var powerXYHistory = new Queue <double>(); var cycle = 0; double zMoved = 0, nextZMoveStep = opts.FocusScanStep; Service.__SSC_LogInfo("开始执行快速扫描...."); var range = SSC_PMRangeEnum.RANGE3; var originZPos = Service.__SSC_GetAbsPosition(LMC_LENS, LMC_LENS_AXIS_Z); var power = Service.__SSC_Powermeter_Read(opts.PowerMeterCaption); while (true) { #region XY Scan powerXYHistory.Clear(); cycle = 0; while (true) { // XY Scan PerformAlignment(Service, new Func <string, object>[] { Service.__SSC_DoFastND, Service.__SSC_DoFastND }, opts, new[] { opts.ProfileNameFocusScanLens, opts.ProfileNameFocusScanRecept }, range, 0.2, power, 10); power = Service.__SSC_Powermeter_Read(opts.PowerMeterCaption); Service.__SSC_LogInfo($"光功率:{power:F2}dBm"); if (power > opts.PowerThreFocusScan) { Service.__SSC_LogInfo("功率达到阈值,耦合结束。"); return; } powerXYHistory.Enqueue(power); if (powerXYHistory.Count > 5) { powerXYHistory.Dequeue(); } if (powerXYHistory.Count > 2) { DataAnalysis.CheckSlope(powerXYHistory.ToArray(), out var trend); Service.__SSC_LogInfo($"功率变化趋势:{trend}"); if (trend == DataAnalysis.SlopeTrendEnum.Ripple) { break; } } cycle++; if (cycle > 20) { // throw new Exception("快速扫描失败,无法找到稳定光功率。"); break; } } #endregion power = Service.__SSC_Powermeter_Read(opts.PowerMeterCaption); var currZPos = Service.__SSC_GetAbsPosition(LMC_LENS, LMC_LENS_AXIS_Z); Service.__SSC_LogInfo($"XY平面功率: {currZPos - originZPos:F4}um, {power:F2}dBm"); if (power > 0) // exit if the power > 0dBm { break; } powerZHistory.Add(new PointF((float)currZPos, (float)power)); if (powerZHistory.Count >= 2) { power = powerZHistory[powerZHistory.Count - 1].Y; var lastlastPower = powerZHistory[powerZHistory.Count - 2].Y; var diff = power - lastlastPower; Service.__SSC_LogInfo($"功率差: {diff:F2}dBm/{power:F2}dBm/{lastlastPower:F2}dBm"); if (diff < -1) { Service.__SSC_LogInfo("功率降低,开始反向搜索..."); nextZMoveStep *= -1; nextZMoveStep /= 2; if (Math.Abs(nextZMoveStep) < opts.FocusScanFinalStep) { Service.__SSC_LogInfo("搜索步进收敛至最小,结束搜索!"); break; } } } Service.__SSC_MoveAxis(LMC_LENS, LMC_LENS_AXIS_Z, SSC_MoveMode.REL, 20, nextZMoveStep); // accum the total distance of the Z axis moved, // be sure it never move out of the RANGE. zMoved += nextZMoveStep; if (zMoved > opts.FocusScanRange) { Service.__SSC_LogWarn("焦点扫描Z轴范围达到最大值。"); break; } } }