예제 #1
0
        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));
        }
예제 #2
0
        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("标定完成");
            }));
        }
예제 #3
0
        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);
        }
예제 #4
0
        /// <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;
                }
            }
        }