You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

574 lines
31 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using Rs.AutoDischarge.V3.Flow;
using Rs.Camera;
using Rs.Controls;
using Rs.Framework;
using Rs.Motion;
using Rs.MotionPlat.Commom;
using Rs.MotionPlat.Entitys;
using Rs.MotionPlat.Entitys.Trays;
using Rs.MotionPlat.Flow.Camera;
using Rs.MotionPlat.Flow.NgFlow;
using Rs.MotionPlat.Flow.SafePosFlow;
using Rs.MotionPlat.Flow.SubFlow;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static Rs.MotionPlat.Commom.SchedulingMessageBox;
namespace Rs.MotionPlat.Flow
{
enum ERearrangeFlowStep
{
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
}
public class RearrangeFlow
{
private string logInfo = string.Empty;
private static RearrangeFlow instance;
public static RearrangeFlow Instance
{
get
{
if (instance == null)
{
instance = new RearrangeFlow();
}
return instance;
}
}
ERearrangeFlowStep flowStep = ERearrangeFlowStep.;
Nozzle curNozzle;
TurnoverInfo curTask;
SlotPoint curSlotPoint;
SlotPoint nozzleDist;
double targetX = 0.0;
double targetY = 0.0;
int FetchNum = 0;//取料次数
ErrorCode errCode = ErrorCode.Ok;
string alarmInfo = string.Empty;
ETrayType traytype;
public void Rearrange()
{
bool finished = false;
flowStep = ERearrangeFlowStep.;
while (!finished)
{
switch (flowStep)
{
case ERearrangeFlowStep.:
if (RearrangeTask.HasTask() && WorkEnvironment.Instance.EnvironmentOk)
{
DischargeFlow.Instance.Stop();
logInfo = $"接收重排任务";
MessageQueue.Instance.Insert(logInfo);
flowStep = ERearrangeFlowStep.;
}
break;
case ERearrangeFlowStep.:
curTask = RearrangeTask.GetTask();
curNozzle = NozzleManager.GetIdelNozzle(true);
if (curTask != null && curNozzle != null)
{
if (DischargeFlow.Instance.XYCanGoLocalArea() || GlobalVar.VirtualAxis)
{
curSlotPoint = null;
traytype = ETrayType.Ok;
switch (curTask.FromType)
{
case TurnoverType.Passed:
traytype = ETrayType.Ok;
break;
case TurnoverType.Failed:
traytype = ETrayType.Ng;
break;
case TurnoverType.Multifunction:
traytype = ETrayType.Multi;
break;
default:
break;
}
logInfo = $"吸嘴{curNozzle.NozzleIndex} 去{traytype}盘 {curTask.FromIndex + 1} 号穴位取料";
curSlotPoint = TrayPointManager.GetSlotPoint(traytype, curTask.FromIndex + 1);
MessageQueue.Instance.Insert(logInfo);
if (curSlotPoint != null)
{
nozzleDist = TrayPointManager.GetDistToNozzle1(curNozzle.NozzleIndex);
targetX = curSlotPoint.X + nozzleDist.X;
targetY = curSlotPoint.Y + nozzleDist.Y;
errCode = AxisControl.LoadX.MovePos(targetX, GlobalVar.WholeSpeed);
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
{
errCode = AxisControl.GetAxis($"NozzleR{curNozzle.NozzleIndex}").MovePos(SysConfigParam.GetValue<Double>($"NozzleR{curNozzle.NozzleIndex}StartPos"), (int)(GlobalVar.WholeSpeed));
errCode = AxisControl.LoadY.MovePos(targetY, (int)(GlobalVar.WholeSpeed));
if (errCode == ErrorCode.Ok | GlobalVar.VirtualAxis)
{
flowStep = ERearrangeFlowStep.;
}
}
}
}
else
{
logInfo = "loady move isn't safe";
Msg.ShowError(logInfo);
MessageQueue.Instance.Warn(logInfo);
}
}
break;
case ERearrangeFlowStep.:
if (Ops.IsStop("LoadX", "LoadY", $"NozzleR{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
{
logInfo = "已运动到取料位上方";
Thread.Sleep(100);
MessageQueue.Instance.Insert(logInfo);
flowStep = ERearrangeFlowStep.;
}
break;
case ERearrangeFlowStep.:
if (AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").HomeStatus == EHomeStatus.Finished || GlobalVar.VirtualAxis)
{
logInfo = "准备运动到取料位下方";
MessageQueue.Instance.Insert(logInfo);
errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(GetVacOffsetHeight(FetchNum) + SysConfigParam.GetValue<double>($"TrayNozzle{curNozzle.NozzleIndex}TakeHeight"), GlobalVar.WholeSpeed);
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
{
flowStep = ERearrangeFlowStep.;
}
}
else
{
logInfo = $"NozzleZ{curNozzle.NozzleIndex} 轴状态未回原,请手动回原后点击确定";
Msg.ShowError(logInfo);
LogHelper.Error(logInfo);
}
break;
case ERearrangeFlowStep.:
if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
{
logInfo = "已运动到取料位下方";
MessageQueue.Instance.Insert(logInfo);
flowStep = ERearrangeFlowStep.;
}
break;
case ERearrangeFlowStep.:
VacManager.DischargeVacSuction(EVacOperator.Open, true, curNozzle.NozzleIndex);
flowStep = ERearrangeFlowStep.;
break;
case ERearrangeFlowStep.:
errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(0, GlobalVar.WholeSpeed);
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
{
logInfo = "取料完成准备抬起";
MessageQueue.Instance.Insert(logInfo);
flowStep = ERearrangeFlowStep.;
}
break;
case ERearrangeFlowStep.:
if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
{
logInfo = "取料完成已运动到抬起位,准备真空检测";
MessageQueue.Instance.Insert(logInfo);
flowStep = ERearrangeFlowStep.;
}
break;
case ERearrangeFlowStep.:
if (Ops.IsOn($"{curNozzle.NozzleIndex}号吸嘴真空吸检测") || GlobalVar.RunSpace || GlobalVar.VirtualAxis)
{
FetchNum = 0;
logInfo = $"吸嘴{curNozzle.NozzleIndex}真空检测 OK";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
curNozzle.Status = ENozzleStatus.ToUnload;
curNozzle.FromType = curTask.FromType;
curNozzle.ToType = curTask.ToType;
curNozzle.ToIndex = curTask.ToIndex;
curTask.SuckerNo = curNozzle.NozzleIndex;
curNozzle.TurnoverGUID = curTask.GUID;
if (curTask.FromType == TurnoverType.Passed)
{
curNozzle.FromFloor = StockManager.Instance.GetStock(ETrayType.Ok).GetFloor();// StockManager.Instance.GetTray(EStockType.Ok).GetFloor();
curNozzle.SN = GlobalTray.OkTary.GetSlot(curTask.FromIndex+1).SN;
curNozzle.FromIndex = curTask.FromIndex;
GlobalTray.OkTary.ChangeStatus(curNozzle.FromIndex + 1, ESlotStatus.NotHave);
}
else if (curTask.FromType == TurnoverType.Failed)
{
curNozzle.FromFloor = StockManager.Instance.GetStock(ETrayType.Ng).GetFloor();//StockManager.Instance.GetTray(EStockType.Ng).GetFloor();
curNozzle.SN = GlobalTray.NgTray.GetSlot(curTask.FromIndex + 1).SN;
curNozzle.FromIndex = curTask.FromIndex;
GlobalTray.NgTray.ChangeStatus(curNozzle.FromIndex + 1, ESlotStatus.NotHave);
}
else if (curTask.FromType == TurnoverType.Multifunction)
{
curNozzle.FromFloor = StockManager.Instance.GetStock(ETrayType.Multi).GetFloor();//StockManager.Instance.GetTray(EStockType.Ng).GetFloor();
curNozzle.SN = GlobalTray.MultiTray.GetSlot(curTask.FromIndex + 1).SN;
curNozzle.FromIndex = curTask.FromIndex;
GlobalTray.MultiTray.ChangeStatus(curNozzle.FromIndex + 1, ESlotStatus.NotHave);
}
curNozzle.Update();
curTask.Dealed = true;
if (RearrangeTask.HasTask() && NozzleManager.GetNozzlesByStatus(ENozzleStatus.IDLE).Count > 0)
{
logInfo = $"检测到还有条任务未执行,继续执行";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
flowStep = ERearrangeFlowStep.;
}
else
{
flowStep = ERearrangeFlowStep.;
}
}
else
{
if (FetchNum == 0)
{
//这个时候Z&R回原一次然后再重新取料
ZRHomeFlow.Instance.GoHome(curNozzle.NozzleIndex);
}
FetchNum++;
if (FetchNum >= GlobalVar.DischargeRetakeNum)
{
DischargeDumpFlow.Instance.Start(curTask.FromType, curNozzle.NozzleIndex, curNozzle.FromIndex);
alarmInfo = string.Format(AlarmCollection.GetAlarm(AlarmConstID.tray), curNozzle.NozzleIndex, curNozzle.FromIndex + 1);
flowStep = ERearrangeFlowStep.;
}
else
{
flowStep = ERearrangeFlowStep.;
}
}
break;
//TestCenterMessageBox.Show(AlarmConstID.TrayTakeFailAlarm, alarmInfo, btnText, buttonText);
case ERearrangeFlowStep.:
ETipButton btnText = (ETipButton.Retry | ETipButton.Skip | ETipButton.Yes);
Dictionary<ETipButton, string> buttonText = new Dictionary<ETipButton, string>();
buttonText.Add(ETipButton.Retry, "重试|Retry");
buttonText.Add(ETipButton.Skip, "跳过|Skip");
buttonText.Add(ETipButton.Yes, "移动到安全位|MoveToSafePos");
int alarmid = AlarmConstID.tray;
SchedulingMessageBox box = MsgBox.ShowDialog(alarmid, alarmInfo, btnText, buttonText);
switch (box.Button)
{
case ETipButton.Retry:
logInfo = GetClassName() + $"选择了重试,继续取料";
MessageQueue.Instance.Insert(logInfo);
if (curTask.FromType == TurnoverType.ToBeTested)
{
//检测料盘是否在上料位,在上料位则继续取料,不在上料位,则通知料仓把料盘送到上料位
if (!StockManager.Instance.GetStock(ETrayType.Input).HasTray())
{
logInfo = GetClassName() + $"检测到料盘不在就绪状态,上料盘";
MessageQueue.Instance.Insert(logInfo);
StockManager.Instance.GetStock(ETrayType.Input).Load(EStockTrayLoadMode.AfterBacked, null);//.Load(EStockType.Input, EStockTrayLoadMode.AfterBacked);
}
}
FetchNum = 0;
flowStep = ERearrangeFlowStep.;
break;
case ETipButton.Skip:
SlotProductHasOrNotResult haveProduct = null;
logInfo = GetClassName() + "选择了跳过";
MessageQueue.Instance.Insert(logInfo);
if (!StockManager.Instance.GetStock(traytype).HasTray())
{
logInfo = GetClassName() + $"检测到料盘不在上料位";
MessageQueue.Instance.Insert(logInfo);
StockManager.Instance.GetStock(traytype).Load(EStockTrayLoadMode.AfterBacked, null);//.Load(EStockType.Input, EStockTrayLoadMode.AfterBacked);
logInfo = GetClassName() + $"上料完成,通知相机拍照,检测产品是否已拿走";
MessageQueue.Instance.Insert(logInfo);
}
haveProduct = UpCameraCheckFlow.Instance.CheckStockTrayHasProduct(traytype, curNozzle.FromIndex + 1, true);
if (!haveProduct.HasProduct)
{
logInfo = GetClassName() + "检测到产品已拿走,流程继续";
MessageQueue.Instance.Insert(logInfo);
FetchNum = 0;
//执行料仓Tray取料NG时的处理流程流程处理结束后流程继续
GlobalTray.GetTray(traytype).ChangeStatus(curNozzle.FromIndex + 1, ESlotStatus.NotHave);
if (RearrangeTask.HasTask() && NozzleManager.GetNozzlesByStatus(ENozzleStatus.IDLE).Count > 0)
{
flowStep = ERearrangeFlowStep.;
}
else
{
flowStep = ERearrangeFlowStep.;
}
}
else
{
alarmInfo = $"检测到{curNozzle.FromIndex + 1}号穴位产品未取出,请处理";
flowStep = ERearrangeFlowStep.;
}
break;
case ETipButton.Yes://移动到安全位
//通知料仓把料盘退回到安全位
if (curTask.FromType == TurnoverType.ToBeTested)
{
logInfo = GetClassName() + $"通知料仓把料盘退回到安全位";
MessageQueue.Instance.Insert(logInfo);
StockManager.Instance.GetStock(ETrayType.Input).Unload(EStockTrayUnLoadMode.Back, null);//.UnLoad(EStockType.Input, EStockTrayUnLoadMode.Back);
//StockManager.Instance.Wait(EStockType.Input);
logInfo = GetClassName() + $"料仓已退回到安全位";
MessageQueue.Instance.Insert(logInfo);
}
else if (curTask.FromType == TurnoverType.Turnover)
{
logInfo = GetClassName() + $"通知排料头回安全位";
MessageQueue.Instance.Insert(logInfo);
DischargeModuleGoSafePosFlow.Instance.GoSafePostion();
logInfo = GetClassName() + $"排料头已回到安全位";
MessageQueue.Instance.Insert(logInfo);
}
alarmInfo = $"已运动到安全位,{curNozzle.NozzleIndex}号排料吸嘴取{curNozzle.FromIndex}号穴位产品次失败,请处理";
flowStep = ERearrangeFlowStep.;
break;
default:
break;
}
break;
case ERearrangeFlowStep.:
if (DischargeFlow.Instance.XYCanGoLocalArea() || GlobalVar.VirtualAxis)
{
targetX = 0.0;
targetY = 0.0;
///获取需要放料的吸嘴
curSlotPoint = null;
curNozzle = NozzleManager.GetToUnloadNozzle();
if (curNozzle != null)
{
curSlotPoint = GetSlotPoint(curNozzle.ToType);
}
if (curSlotPoint != null)
{
nozzleDist = TrayPointManager.GetDistToNozzle1(curNozzle.NozzleIndex);
targetX = curSlotPoint.X + nozzleDist.X;
targetY = curSlotPoint.Y + nozzleDist.Y;
errCode = AxisControl.LoadX.MovePos(targetX, GlobalVar.WholeSpeed);
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
{
errCode = AxisControl.LoadY.MovePos(targetY, GlobalVar.WholeSpeed);
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
{
errCode = AxisControl.GetAxis($"NozzleR{curNozzle.NozzleIndex}").MoveOffset(0, GlobalVar.WholeSpeed);
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
{
flowStep = ERearrangeFlowStep.;
}
}
}
}
}
else
{
Msg.ShowError("loady move isn't safe");
}
break;
case ERearrangeFlowStep.:
if (Ops.IsStop("LoadX", "LoadY", $"NozzleR{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
{
Thread.Sleep(100);
logInfo = "已运动到放料位上方";
MessageQueue.Instance.Insert(logInfo);
flowStep = ERearrangeFlowStep.;
}
break;
case ERearrangeFlowStep.:
logInfo = "到放料位下方";
MessageQueue.Instance.Insert(logInfo);
errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(SysConfigParam.GetValue<double>($"TurnoverNozzle{curNozzle.NozzleIndex}TakeHeight") + 3, GlobalVar.WholeSpeed);
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
{
flowStep = ERearrangeFlowStep.;
}
break;
case ERearrangeFlowStep.:
if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
{
VacManager.DischargeVacSuction(EVacOperator.Close, true, curNozzle.NozzleIndex);
VacManager.DischargeVacBreak(EVacOperator.Open, true, curNozzle.NozzleIndex);
VacManager.DischargeVacBreak(EVacOperator.Close, false, curNozzle.NozzleIndex);
flowStep = ERearrangeFlowStep.;
}
break;
case ERearrangeFlowStep.:
errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(0, GlobalVar.WholeSpeed);
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
{
logInfo = "放料完成抬起";
MessageQueue.Instance.Insert(logInfo);
flowStep = ERearrangeFlowStep.;
}
break;
case ERearrangeFlowStep.:
if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
{
logInfo = "放料完成已运动到抬起位,准备真空检测";
MessageQueue.Instance.Insert(logInfo);
flowStep = ERearrangeFlowStep.;
}
break;
case ERearrangeFlowStep.:
flowStep = ERearrangeFlowStep.;
break;
case ERearrangeFlowStep.:
logInfo = "放料任务完成";
MessageQueue.Instance.Insert(logInfo);
AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").Home();
if (curNozzle.ToType == TurnoverType.Passed)
{
GlobalTray.OkTary.ChangeStatus(curNozzle.ToIndex + 1, ESlotStatus.Have);
}
else if (curNozzle.ToType == TurnoverType.Failed)
{
GlobalTray.NgTray.ChangeStatus(curNozzle.ToIndex + 1, ESlotStatus.Have);
}
else if (curNozzle.ToType == TurnoverType.Multifunction)
{
GlobalTray.MultiTray.ChangeStatus(curNozzle.ToIndex + 1, ESlotStatus.Have);
}
curNozzle.Reset();
Thread.Sleep(100);
RearrangeTask.AddWaitReportTask(curNozzle);
if (NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload).Count > 0)
{
flowStep = ERearrangeFlowStep.;
}
else
{
if (RearrangeTask.HasTask())
{
flowStep = ERearrangeFlowStep.;
}
else
{
flowStep = ERearrangeFlowStep.;
}
}
break;
case ERearrangeFlowStep.:
logInfo = "任务结束到安全位";
MessageQueue.Instance.Insert(logInfo);
errCode = AxisControl.LoadX.MovePos(SysConfigParam.GetValue<double>("LoadXStartPos"), GlobalVar.WholeSpeed);
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
{
errCode = AxisControl.LoadY.MovePos(SysConfigParam.GetValue<double>("LoadYStartPos"), GlobalVar.WholeSpeed);
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
{
flowStep = ERearrangeFlowStep.;
}
}
break;
case ERearrangeFlowStep.:
if (Ops.IsStop("LoadX", "LoadY") || GlobalVar.VirtualAxis)
{
logInfo = "任务结束已回到安全位";
MessageQueue.Instance.Insert(logInfo);
if (RearrangeTask.ReportCenter() > 0)
{
logInfo = "通知中控任务完成";
MessageQueue.Instance.Insert(logInfo);
RearrangeTask.RemoveAll();
logInfo = "任务完成,清除任务";
MessageQueue.Instance.Insert(logInfo);
}
MachineManage.Instance.SetLoadUnloadStatus(ERunState.Waiting);
finished = true;
}
break;
default:
break;
}
}
}
private double GetVacOffsetHeight(int fetchNum)
{
if (fetchNum == 0) return 0;
//先判断是奇数还是偶数
int count = 0;
int oddOrEven = fetchNum & 0x01;
double offsetDisct = 0.0;
if (oddOrEven == 1)
{
count = (fetchNum / 2) + 1;
offsetDisct = -0.1 * count;
}
else if (oddOrEven == 0)
{
count = (fetchNum / 2);
offsetDisct = 0.1 * count;
}
return offsetDisct;
}
private SlotPoint GetSlotPoint(TurnoverType trayType)
{
SlotPoint pt = new SlotPoint();
switch (trayType)
{
case TurnoverType.Passed:
logInfo = "到Pass盘放料位上方";
pt = TrayPointManager.GetSlotPoint( ETrayType.Ok, curNozzle.ToIndex + 1);
break;
case TurnoverType.Failed:
logInfo = "到Ng盘放料位上方";
pt = TrayPointManager.GetSlotPoint( ETrayType.Ng, curNozzle.ToIndex + 1);
break;
case TurnoverType.Multifunction:
logInfo = "到Multi盘放料位上方";
pt = TrayPointManager.GetSlotPoint( ETrayType.Multi, curNozzle.ToIndex + 1);
break;
default:
break;
}
return pt;
}
private string GetClassName()
{
return string.Empty;
}
}
}