using Rs.Controls; using Rs.Framework; using Rs.MotionPlat.Commom; using Rs.MotionPlat.Entitys; using Rs.MotionPlat.Flow.Common; using Rs.MotionPlat.Flow.SafePosFlow; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Rs.MotionPlat.Flow.SubFlow { enum EStockTakeFlowStep { 待触发, 到料仓取料位上方, 等待到料仓取料位上方, 到料仓取料位下方, 等待到料仓取料位下方, 料仓取料完成抬起, 等待料仓取料完成抬起, 料仓取料真空吸检测, } public enum EStockScanBarcodeMode { Multi, Single } /// /// 料仓取料流程 /// public class StockTakeFlow { bool finished = true; Nozzle curNozzle = null; TraySlot waitTakeProductSlot = null; EStockTakeFlowStep flowStep = EStockTakeFlowStep.待触发; private StockTakeFlow() { } private static StockTakeFlow instance; public static StockTakeFlow Instance { get { if (instance == null) instance = new StockTakeFlow(); return instance; } } public string GetCurStep() { return flowStep.ToString(); } /// /// 料仓取料 /// /// public void Take(ETrayType trayType, int slotIndex,int nozzleIndex, EStockScanBarcodeMode scanBarCodeMode= EStockScanBarcodeMode.Multi, ProductLocationResult locaResult=null,bool needStop=true) { if (finished) finished = false; else return; flowStep = EStockTakeFlowStep.待触发; string logInfo = string.Empty; TargetPosition targetPosition = new TargetPosition(); DischargeFlow.Instance.ActionStart(); while (!finished) { if (MachineManage.Instance.MachineStatus == EMachineStatus.Stop && needStop) { Thread.Sleep(10); continue; } switch (flowStep) { case EStockTakeFlowStep.待触发: flowStep = EStockTakeFlowStep.到料仓取料位上方; break; case EStockTakeFlowStep.到料仓取料位上方: //获取空闲吸嘴 curNozzle = NozzleManager.GetNozzle(nozzleIndex); if (curNozzle != null) { if (trayType== ETrayType.Input) { waitTakeProductSlot = GlobalTray.InputTray.GetSlot(slotIndex); } else if(trayType== ETrayType.Grr) { waitTakeProductSlot = GlobalTray.GrrTray.GetSlot(slotIndex); } targetPosition = NozzleManager.GetToTraySlot(trayType, waitTakeProductSlot.Index, curNozzle.NozzleIndex); if (scanBarCodeMode== EStockScanBarcodeMode.Single) { MessageQueue.Instance.Insert($"拍照偏移量 x:{locaResult.OffsetX},y:{locaResult.OffsetY}"); targetPosition.X += locaResult.OffsetX; targetPosition.Y2 += locaResult.OffsetY; } else { ProductLocationResult result = OneGrabSixteenManager.Instance.GetResultBySlotIndex(waitTakeProductSlot.Index); if (!GlobalVar.RunSpace) { //MessageQueue.Instance.Insert($"拍照偏移量 x:{result.OffsetX},y:{result.OffsetY}"); targetPosition.X += result.OffsetX; targetPosition.Y2 += result.OffsetY; } } //double curLoadX = Ops.GetCurPosition(AxisControl.LoadX); //if (curLoadX - GlobalVar.FixtureSafePosX > 50) //{ // DischargeModuleGoSafePosFlow.Instance.GoSafePostion(ESafePosSide.PlaceToStock); //} if (GroupAxisMove.XY1Y2MovePos(targetPosition, GlobalVar.WholeSpeed, EGoWhichSide.StockSide)) { AxisPosPrint.PrintXY1Y2TargetPos($"{WhatNozzleIndex()}到料仓{WhatTraySlot()}取料位上方,", targetPosition, GetClassName()); flowStep = EStockTakeFlowStep.等待到料仓取料位上方; } } break; case EStockTakeFlowStep.等待到料仓取料位上方: if (Ops.IsStop("LoadX", "LoadY1", "LoadY2") || GlobalVar.VirtualAxis) { AxisPosPrint.PrintXY1Y2CurrentPos("轴XY1Y2已停止运动,", GetClassName()); if (AxisArrived.LoadXY1Y2IsArrived(targetPosition.X, targetPosition.Y1, targetPosition.Y2)) { AxisPosPrint.PrintXY1Y2CurrentPos($"{WhatNozzleIndex()}已运动到料仓{WhatTraySlot()}取料位上方,", GetClassName()); flowStep = EStockTakeFlowStep.到料仓取料位下方; } else { flowStep = EStockTakeFlowStep.到料仓取料位上方; } } break; case EStockTakeFlowStep.到料仓取料位下方: targetPosition.StockZ = NozzleManager.GetNozzleToTrayTakeProductPos(trayType, curNozzle.NozzleIndex); if (NozzleManager.Go(curNozzle, targetPosition.StockZ, GlobalVar.WholeSpeed)) { logInfo = $"{GetClassName()}{WhatNozzleIndex()}到料仓{WhatTraySlot()}取料位下方,tz:{targetPosition.StockZ}"; MessageQueue.Instance.Insert(logInfo); flowStep = EStockTakeFlowStep.等待到料仓取料位下方; } break; case EStockTakeFlowStep.等待到料仓取料位下方: if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}")) { Thread.Sleep(100); logInfo = $"{GetClassName()}{WhatNozzleIndex()}已运动到料仓{WhatTraySlot()}取料位下方:{curNozzle.GetCurrentPos()}"; MessageQueue.Instance.Insert(logInfo); if (!GlobalVar.RunSpace) { //打开真空吸 curNozzle.VacSuction(EIoOperate.Open, GetClassName()); } flowStep = EStockTakeFlowStep.料仓取料完成抬起; } break; case EStockTakeFlowStep.料仓取料完成抬起: if (NozzleManager.GotoSafePos(curNozzle.NozzleIndex)) { logInfo =$"{GetClassName()} 料仓取料完成抬起"; MessageQueue.Instance.Insert(logInfo); flowStep = EStockTakeFlowStep.等待料仓取料完成抬起; } break; case EStockTakeFlowStep.等待料仓取料完成抬起: if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}")) { logInfo =$"{GetClassName()} 料仓取料完成已抬起:{curNozzle.GetCurrentPos()}"; MessageQueue.Instance.Insert(logInfo); flowStep = EStockTakeFlowStep.料仓取料真空吸检测; } break; case EStockTakeFlowStep.料仓取料真空吸检测: if (curNozzle.HasProduct()|| GlobalVar.RunSpace) { //curNozzle.Product = new TestProduct() { SN = VirtualBarCode.Code, TestNum = 0 }; if(GlobalVar.RunSpace) { curNozzle.Product = new TestProduct() { SN = VirtualBarCode.Code, FromSlotIndex = waitTakeProductSlot.Index, TestNum = 0, From = $"R{waitTakeProductSlot.Row + 1}C{waitTakeProductSlot.Column + 1}" }; } else { string sn = string.Empty; if(GlobalVar.EnableVirtualBarCode) { sn = VirtualBarCode.Code; } else { if (scanBarCodeMode == EStockScanBarcodeMode.Multi) { ProductLocationResult vResult = OneGrabSixteenManager.Instance.GetResultBySlotIndex(slotIndex); sn = vResult.SN; } else { sn = locaResult.SN; } } curNozzle.Product = new TestProduct() { SN = sn, TestNum = 0, FromSlotIndex = waitTakeProductSlot.Index, From = $"R{waitTakeProductSlot.Row + 1}C{waitTakeProductSlot.Column + 1}" }; //ProductLocationResult vResult = OneGrabSixteenManager.Instance.GetResultBySlotIndex(slotIndex); //if (vResult!=null || locaResult!=null) //{ // string sn = string.Empty; // if(GlobalVar.EnableVirtualBarCode) // { // sn = VirtualBarCode.Code; // } // else // { // if (scanBarCodeMode== EStockScanBarcodeMode.Multi) // sn = vResult.SN; // else // sn = locaResult.SN; // } //} } curNozzle.Status = ENozzleStatus.ToTest; //curNozzle.Status = ENozzleStatus.ToUnload; curNozzle.ChangeStatus(ESlotStatus.Have); GlobalTray.GetTray(trayType).ChangeStatus(waitTakeProductSlot.Index, ESlotStatus.NotHave); //GlobalTray.InputTray.ChangeStatus(waitTakeProductSlot.Index, ESlotStatus.NotHave); if(curNozzle.Product!=null) { logInfo = $"{GetClassName()} from r{waitTakeProductSlot.Row + 1}c{waitTakeProductSlot.Column + 1} 穴位索引:{WhatTraySlot()} 产品:{curNozzle.Product.SN}被{WhatNozzleIndex()}取料完成,"; MessageQueue.Instance.Insert(logInfo); } //flowStep = EStockTakeFlowStep.判断是否需要从料仓取料; finished = true; flowStep = EStockTakeFlowStep.待触发; DischargeFlow.Instance.ActionEnd("PnP 从输入托盘拾取 1 个 DUT", "PhP pick up 1 DUT from input tray"); } else { AlarmEntity alarmEntity = AlarmCollection.Get(AlarmConstID.排料吸嘴取料失败报警).Transform($"{curNozzle.NozzleIndex}",$"{waitTakeProductSlot.Row}",$"{waitTakeProductSlot.Column}",$"{waitTakeProductSlot.Index}"); EButtonType btnSelect = Msgbox.ShowDialog(alarmEntity,EButtonType.EndInput | EButtonType.Retry | EButtonType.Skip | EButtonType.Recheck,true); switch (btnSelect) { case EButtonType.EndInput: logInfo = GetClassName() + $"选择了结束上料"; MessageQueue.Instance.Insert(logInfo); GlobalVar.Clear = true; finished = true; flowStep = EStockTakeFlowStep.待触发; break; case EButtonType.Retry: logInfo = GetClassName() + $"选择了重试"; MessageQueue.Instance.Insert(logInfo); curNozzle.VacBreak(EIoOperate.Close, GetClassName()); curNozzle.VacSuction(EIoOperate.Close, GetClassName()); //先把产品放下 //StockPlaceFlow.Instance.Place(ETrayType.Input, waitTakeProductSlot.Index, curNozzle.NozzleIndex); flowStep = EStockTakeFlowStep.到料仓取料位下方; break; case EButtonType.Recheck: logInfo = GetClassName() + $"选择了重新检查真空"; MessageQueue.Instance.Insert(logInfo); flowStep = EStockTakeFlowStep.料仓取料真空吸检测; break; case EButtonType.Skip: logInfo = GetClassName() + $"选择了跳过"; curNozzle.VacBreak(EIoOperate.Close, GetClassName()); curNozzle.VacSuction(EIoOperate.Close, GetClassName()); MessageQueue.Instance.Insert(logInfo); finished = true; flowStep = EStockTakeFlowStep.待触发; break; default: break; } } break; } } } string GetClassName() { return $"{nameof(StockTakeFlow)}-"; } /// /// 获取几号吸嘴 /// /// private string WhatNozzleIndex() { return $"{curNozzle.NozzleIndex}号吸嘴"; } /// /// 获取料仓的几号穴位 /// /// private string WhatTraySlot() { return $"{waitTakeProductSlot.Index}号穴位"; } } }