|
|
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 Rs.MotionPlat.Vision;
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.IO;
|
|
|
using System.Linq;
|
|
|
using System.Text;
|
|
|
using System.Threading;
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
namespace Rs.MotionPlat.Flow.SubFlow
|
|
|
{
|
|
|
enum EStockPlaceFlowStep
|
|
|
{
|
|
|
待触发,
|
|
|
到料仓拍照位上方,
|
|
|
等待到料仓拍照位上方,
|
|
|
料仓穴位拍照,
|
|
|
到料仓放料位上方,
|
|
|
等待到料仓放料位上方,
|
|
|
到料仓放料位下方,
|
|
|
等待到料仓放料位下方,
|
|
|
料仓放料完成抬起,
|
|
|
等待料仓放料完成抬起,
|
|
|
料仓放料完成粘料检测
|
|
|
}
|
|
|
/// <summary>
|
|
|
/// 料仓放料流程
|
|
|
/// </summary>
|
|
|
public class StockPlaceFlow
|
|
|
{
|
|
|
public event Action<TestProduct> PlaceFinishedEvent;
|
|
|
bool finished = true;
|
|
|
double slotOffsetX = 0.0;
|
|
|
double slotOffsetY = 0.0;
|
|
|
EStockPlaceFlowStep flowStep = EStockPlaceFlowStep.待触发;
|
|
|
public StockPlaceFlow()
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
private static StockPlaceFlow instance;
|
|
|
public static StockPlaceFlow Instance
|
|
|
{
|
|
|
get
|
|
|
{
|
|
|
if (instance == null)
|
|
|
instance = new StockPlaceFlow();
|
|
|
return instance;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public string GetCurStep()
|
|
|
{
|
|
|
return flowStep.ToString();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 料仓放料
|
|
|
/// </summary>
|
|
|
/// <param name="tray">需要放入的料盘</param>
|
|
|
/// <param name="nozzleIndex">哪个吸嘴放</param>
|
|
|
/// <param name="className"></param>
|
|
|
public void Place(ETrayType trayType,int slotIndex,int nozzleIndex,bool needStop=true)
|
|
|
{
|
|
|
RsTray tray = null;
|
|
|
if (finished)
|
|
|
finished = false;
|
|
|
else
|
|
|
return;
|
|
|
switch (trayType)
|
|
|
{
|
|
|
case ETrayType.Ng:
|
|
|
tray = GlobalTray.NgTray;
|
|
|
break;
|
|
|
case ETrayType.ReTest:
|
|
|
tray = GlobalTray.RetestTray;
|
|
|
break;
|
|
|
case ETrayType.Grr:
|
|
|
tray = GlobalTray.GrrTray;
|
|
|
break;
|
|
|
case ETrayType.Ok:
|
|
|
tray = GlobalTray.OkTary;
|
|
|
break;
|
|
|
case ETrayType.Input:
|
|
|
tray = GlobalTray.InputTray;
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
flowStep = EStockPlaceFlowStep.待触发;
|
|
|
string logInfo = string.Empty;
|
|
|
TargetPosition targetPosition = new TargetPosition();
|
|
|
Nozzle curNozzle = NozzleManager.GetNozzle(nozzleIndex);
|
|
|
TraySlot curPlaceSlot = null;
|
|
|
DischargeFlow.Instance.ActionStart();
|
|
|
while (!finished)
|
|
|
{
|
|
|
if (MachineManage.Instance.MachineStatus == EMachineStatus.Stop && needStop)
|
|
|
{
|
|
|
Thread.Sleep(10);
|
|
|
continue;
|
|
|
}
|
|
|
switch (flowStep)
|
|
|
{
|
|
|
case EStockPlaceFlowStep.待触发:
|
|
|
slotOffsetX = 0;
|
|
|
slotOffsetY = 0;
|
|
|
if (GlobalVar.EnableBeforePlaceProductGrab)
|
|
|
{
|
|
|
flowStep = EStockPlaceFlowStep.到料仓拍照位上方;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
flowStep = EStockPlaceFlowStep.到料仓放料位上方;
|
|
|
}
|
|
|
break;
|
|
|
case EStockPlaceFlowStep.到料仓拍照位上方:
|
|
|
curPlaceSlot = tray.GetSlot(slotIndex);
|
|
|
if(curPlaceSlot!=null)
|
|
|
{
|
|
|
SlotPoint sp = TrayPointManager.GetSlotPoint(trayType, curPlaceSlot.Index);
|
|
|
if(sp!=null)
|
|
|
{
|
|
|
targetPosition.X = sp.X;
|
|
|
targetPosition.Y1 = GlobalVar.StockSideY1;
|
|
|
targetPosition.Y2 = sp.Y;
|
|
|
//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($"到{trayType}料仓拍照位上方,", targetPosition, GetClassName());
|
|
|
flowStep = EStockPlaceFlowStep.等待到料仓拍照位上方;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case EStockPlaceFlowStep.等待到料仓拍照位上方:
|
|
|
if (Ops.IsStop("LoadX", "LoadY1", "LoadY2"))
|
|
|
{
|
|
|
AxisPosPrint.PrintXY1Y2CurrentPos("轴loadx,loady1,loady2已停止运动,", GetClassName());
|
|
|
if (AxisArrived.LoadXY1Y2IsArrived(targetPosition.X, targetPosition.Y1, targetPosition.Y2))
|
|
|
{
|
|
|
AxisPosPrint.PrintXY1Y2CurrentPos($"已运动到{trayType}料仓拍照位上方,", GetClassName());
|
|
|
flowStep = EStockPlaceFlowStep.料仓穴位拍照;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
flowStep = EStockPlaceFlowStep.到料仓拍照位上方;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case EStockPlaceFlowStep.料仓穴位拍照:
|
|
|
VisionHelper.trayLocationVision.ClearQueue();
|
|
|
UpCameraHelper.Grab();
|
|
|
VisionResult vr = VisionHelper.Grab(Vision.EVisionScene.TrayLocation);
|
|
|
if((vr!=null && vr.Result) || GlobalVar.RunSpace)
|
|
|
{
|
|
|
if(GlobalVar.RunSpace)
|
|
|
{
|
|
|
flowStep = EStockPlaceFlowStep.到料仓放料位上方;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
curNozzle = NozzleManager.GetNozzle(nozzleIndex);
|
|
|
slotOffsetX = vr.OffsetX;
|
|
|
slotOffsetY = vr.OffsetY;
|
|
|
string sn = "";
|
|
|
if (curNozzle != null && curNozzle.Product != null && !string.IsNullOrEmpty(curNozzle.Product.SN))
|
|
|
{
|
|
|
sn = curNozzle.Product.SN;
|
|
|
}
|
|
|
string title = "index,sn,offsetx,offsety,time\r\n";
|
|
|
string content = $"{slotIndex},{sn},{slotOffsetX},{slotOffsetY},{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}\r\n";
|
|
|
string dataDir = $"d://data/placestock//{DateTime.Now.ToString("yyyy-MM-dd")}";
|
|
|
if (!Directory.Exists(dataDir))
|
|
|
{
|
|
|
Directory.CreateDirectory(dataDir);
|
|
|
}
|
|
|
string dataFilePath = $"{dataDir}//{GlobalVar.LotName}_{trayType}.csv";
|
|
|
if (!File.Exists(dataFilePath))
|
|
|
{
|
|
|
File.AppendAllText(dataFilePath, title);
|
|
|
}
|
|
|
File.AppendAllText(dataFilePath, content);
|
|
|
flowStep = EStockPlaceFlowStep.到料仓放料位上方;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
Msgbox.ShowTipDialog(EButtonType.Retry, "stock slot location fail", "", true);
|
|
|
}
|
|
|
break;
|
|
|
case EStockPlaceFlowStep.到料仓放料位上方:
|
|
|
//curNozzle = NozzleManager.GetToUnloadNozzle();
|
|
|
curNozzle = NozzleManager.GetNozzle(nozzleIndex);
|
|
|
if (curNozzle != null)
|
|
|
{
|
|
|
curPlaceSlot = tray.GetSlot(slotIndex);
|
|
|
if (curPlaceSlot != null)
|
|
|
{
|
|
|
targetPosition = NozzleManager.GetToTraySlot(trayType, curPlaceSlot.Index, curNozzle.NozzleIndex);
|
|
|
targetPosition.X += slotOffsetX;
|
|
|
targetPosition.Y2+= slotOffsetY;
|
|
|
//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("到料仓放料位上方,", targetPosition, GetClassName());
|
|
|
flowStep = EStockPlaceFlowStep.等待到料仓放料位上方;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case EStockPlaceFlowStep.等待到料仓放料位上方:
|
|
|
if (Ops.IsStop("LoadX", "LoadY1", "LoadY2"))
|
|
|
{
|
|
|
AxisPosPrint.PrintXY1Y2CurrentPos("轴loadx,loady1,loady2已停止运动,",GetClassName());
|
|
|
if (AxisArrived.LoadXY1Y2IsArrived(targetPosition.X, targetPosition.Y1, targetPosition.Y2))
|
|
|
{
|
|
|
AxisPosPrint.PrintXY1Y2CurrentPos("已运动到料仓放料位上方,", GetClassName());
|
|
|
flowStep = EStockPlaceFlowStep.到料仓放料位下方;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
flowStep = EStockPlaceFlowStep.到料仓放料位上方;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case EStockPlaceFlowStep.到料仓放料位下方:
|
|
|
targetPosition.StockZ = NozzleManager.GetNozzleToTrayTakeProductPos(trayType, curNozzle.NozzleIndex)-GlobalVar.PlaceProdcutToStockTrayOffsetHeight;
|
|
|
if (NozzleManager.Go(curNozzle, targetPosition.StockZ, GlobalVar.WholeSpeed))
|
|
|
{
|
|
|
logInfo = $"{GetClassName()}到料仓放料位下方";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
flowStep = EStockPlaceFlowStep.等待到料仓放料位下方;
|
|
|
}
|
|
|
break;
|
|
|
case EStockPlaceFlowStep.等待到料仓放料位下方:
|
|
|
if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}"))
|
|
|
{
|
|
|
logInfo = $"{GetClassName()}已运动到料仓放料位下方";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
//关闭真空吸
|
|
|
curNozzle.VacSuction(EIoOperate.Close, GetClassName());
|
|
|
//打开真空破
|
|
|
curNozzle.VacBreak(EIoOperate.Open, GetClassName());
|
|
|
//关闭真空
|
|
|
curNozzle.VacBreak(EIoOperate.Close, GetClassName());
|
|
|
flowStep = EStockPlaceFlowStep.料仓放料完成抬起;
|
|
|
}
|
|
|
break;
|
|
|
case EStockPlaceFlowStep.料仓放料完成抬起:
|
|
|
if (NozzleManager.GotoSafePos(curNozzle.NozzleIndex))
|
|
|
{
|
|
|
logInfo = $"{GetClassName()}料仓放料完成抬起";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
flowStep = EStockPlaceFlowStep.等待料仓放料完成抬起;
|
|
|
}
|
|
|
break;
|
|
|
case EStockPlaceFlowStep.等待料仓放料完成抬起:
|
|
|
if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}"))
|
|
|
{
|
|
|
logInfo = $"{GetClassName()}放料完成已抬起";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
flowStep = EStockPlaceFlowStep.料仓放料完成粘料检测;
|
|
|
}
|
|
|
break;
|
|
|
case EStockPlaceFlowStep.料仓放料完成粘料检测:
|
|
|
if (!curNozzle.HasProduct() || GlobalVar.RunSpace)
|
|
|
{
|
|
|
DischargeFlow.Instance.ActionEnd("拾取器将 1 个 DUT 卸载到output托盘(OK/NG)", "Picker unload 1 DUT to output trav (OK/NG)");
|
|
|
if(curNozzle.Product!=null)
|
|
|
{
|
|
|
curNozzle.Product.ToSlotIndex = curPlaceSlot.Index;
|
|
|
if (trayType != ETrayType.ReTest)
|
|
|
{
|
|
|
PlaceFinishedEvent?.Invoke(curNozzle.Product);
|
|
|
}
|
|
|
logInfo = $"{GetClassName()}检测到吸嘴{curNozzle.NozzleIndex}无粘料,吸嘴{curNozzle.NozzleIndex}把产品SN:{curNozzle.Product.SN}放入OK料盘{curPlaceSlot.Index}穴位";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
tray.ChangeStatus(curPlaceSlot.Index, ESlotStatus.Have);
|
|
|
curNozzle.Product.Save(trayType);
|
|
|
curNozzle.Product.ToString();
|
|
|
curNozzle.Clear();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
curNozzle.Clear();
|
|
|
tray.ChangeStatus(curPlaceSlot.Index, ESlotStatus.Have);
|
|
|
}
|
|
|
finished = true;
|
|
|
flowStep = EStockPlaceFlowStep.待触发;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
AlarmEntity alarmEntity = AlarmCollection.Get(AlarmConstID.排料吸嘴粘料报警).Transform(curNozzle.NozzleIndex);
|
|
|
if(alarmEntity != null)
|
|
|
{
|
|
|
Msgbox.ShowDialog(alarmEntity, EButtonType.Retry);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
Msg.ShowError("翻译文件中未找到 ‘排料吸嘴粘料报警’项");
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
string GetClassName()
|
|
|
{
|
|
|
return $"{nameof(StockPlaceFlow)}-";
|
|
|
}
|
|
|
}
|
|
|
}
|