|
|
using HalconDotNet;
|
|
|
using NPOI.SS.Formula.Eval;
|
|
|
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.Common;
|
|
|
using Rs.MotionPlat.Flow.SafePosFlow;
|
|
|
using Rs.MotionPlat.Flow.SubFlow;
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Diagnostics;
|
|
|
using System.Diagnostics.Eventing.Reader;
|
|
|
using System.IO;
|
|
|
using System.Linq;
|
|
|
using System.Runtime.CompilerServices;
|
|
|
using System.Text;
|
|
|
using System.Threading;
|
|
|
using System.Threading.Tasks;
|
|
|
using System.Windows.Forms;
|
|
|
using static Rs.MotionPlat.Commom.SchedulingMessageBox;
|
|
|
|
|
|
namespace Rs.MotionPlat.Flow
|
|
|
{
|
|
|
public enum EDischargeFlowStep
|
|
|
{
|
|
|
等待任务,
|
|
|
/*取料*/
|
|
|
到取料位上方,
|
|
|
等待到取料位上方,
|
|
|
到取料位下方,
|
|
|
等待到取料位下方,
|
|
|
开真空,
|
|
|
取料完成后真空检测,
|
|
|
取料失败报警,
|
|
|
取料完成抬起,
|
|
|
等待取料完成抬起,
|
|
|
/*拍照*/
|
|
|
到下相机拍照起始位,
|
|
|
等待到下相机拍照起始位,
|
|
|
到下相机拍照结束位,
|
|
|
等待到下相机拍照结束位,
|
|
|
等待相机拍照完成,
|
|
|
等待视觉处理结果,
|
|
|
/*放料*/
|
|
|
到放料位上方,
|
|
|
等待到放料位上方,
|
|
|
丢料检测,
|
|
|
到放料位下方,
|
|
|
等待到放料位下方,
|
|
|
到放料关破真空位,
|
|
|
等待到放料关破真空位,
|
|
|
周转盘放料位真空检测,
|
|
|
放料完成抬起,
|
|
|
等待放料完成抬起,
|
|
|
放料真空检测,
|
|
|
粘料检测,
|
|
|
周转盘放料真空报警,
|
|
|
放料任务完成,
|
|
|
任务结束到安全位,
|
|
|
等待任务结束到安全位,
|
|
|
IDLE
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 排料流程
|
|
|
/// </summary>
|
|
|
public class DischargeFlow : BaseFlow
|
|
|
{
|
|
|
private DischargeFlow() { }
|
|
|
|
|
|
private static DischargeFlow instance;
|
|
|
|
|
|
public event Action<List<MatchResult>> OnMatchResult;
|
|
|
public event Action<List<VisionResult>> OnUpCameraGrabResult;
|
|
|
public event Action<VisionResult,bool> OnShowGrabResult;
|
|
|
public event Action<SlotProductHasOrNotResult> OnStockTrayProductHasOrNotResult;
|
|
|
public event Action<SlotProductHasOrNotResult> OnTurnoverTrayProductHasOrNotResult;
|
|
|
public static DischargeFlow Instance
|
|
|
{
|
|
|
get
|
|
|
{
|
|
|
if (instance == null)
|
|
|
{
|
|
|
instance = new DischargeFlow();
|
|
|
}
|
|
|
return instance;
|
|
|
}
|
|
|
}
|
|
|
private AlarmEntity alarmEntity;
|
|
|
Stopwatch timeout = new Stopwatch();
|
|
|
EDischargeFlowStep flowStep = EDischargeFlowStep.等待任务;
|
|
|
EDischargeFlowStep restoreFlowStep = EDischargeFlowStep.IDLE;
|
|
|
HObject[] imgs = new HObject[2];
|
|
|
List<MatchResult> mrs = new List<MatchResult>();
|
|
|
int reFetchNum = 0;//重取料次数
|
|
|
bool bFetchBack = false;
|
|
|
double targetX = 0.0;
|
|
|
double targetY = 0.0;
|
|
|
double targetZ = 0.0;
|
|
|
double targetR = 0.0;
|
|
|
//double targetPos = 0.0;
|
|
|
TraySlot tray = new TraySlot();
|
|
|
// List<TurnoverInfo> totalTask = new List<TurnoverInfo>();
|
|
|
List<TurnoverInfo> dealTask = new List<TurnoverInfo>();
|
|
|
//TurnoverInfo curTurnoverTask = new TurnoverInfo();
|
|
|
TurnoverInfo curTask = new TurnoverInfo();
|
|
|
List<Nozzle> idleNozzle = new List<Nozzle>();
|
|
|
Nozzle curNozzle = new Nozzle();
|
|
|
/// <summary>
|
|
|
/// 当前穴位的点位
|
|
|
/// </summary>
|
|
|
SlotPoint curSlotPoint = new SlotPoint();
|
|
|
SlotPoint nozzleDist = new SlotPoint();
|
|
|
//List<Nozzle> unloadNozzles = new List<Nozzle>();
|
|
|
TraySlot downSlot = new TraySlot();
|
|
|
OffsetPoint turnoverOffsetPoint = new OffsetPoint();
|
|
|
int needGrabNum = 0;//需要拍照的吸嘴数量
|
|
|
int reGrabCount = 0;//重拍次数
|
|
|
ErrorCode errCode = ErrorCode.Ok;
|
|
|
List<TurnoverInfo> testLoadList = new List<TurnoverInfo>();
|
|
|
List<TurnoverInfo> testUnLoadList = new List<TurnoverInfo>();
|
|
|
/// <summary>
|
|
|
/// 从料仓到周转盘
|
|
|
/// </summary>
|
|
|
private bool StockTrayToTurnoverTray = true;
|
|
|
SchedulingMessageBox msgBox;
|
|
|
/// <summary>
|
|
|
/// 未执行的任务数量
|
|
|
/// </summary>
|
|
|
private int undoTaskNum = 0;
|
|
|
int scanNum = 0;
|
|
|
|
|
|
public override void Run()
|
|
|
{
|
|
|
switch (flowStep)
|
|
|
{
|
|
|
case EDischargeFlowStep.等待任务:
|
|
|
if (LoadAndUnloadTask.Instance.GetTaskNum(ETaskType.Load) > 0
|
|
|
|| LoadAndUnloadTask.Instance.GetTaskNum(ETaskType.Unload) > 0
|
|
|
|| LoadAndUnloadTask.Instance.GetTaskNum(ETaskType.Change) > 0)
|
|
|
{
|
|
|
StockTrayToTurnoverTray = true;
|
|
|
logInfo = GetClassName() + $"接收到排料任务";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
if (GlobalVar.CleanOut && GlobalVar.DischargeNozzleHasProduct)
|
|
|
{
|
|
|
foreach (TurnoverInfo ti in LoadAndUnloadTask.Instance.GetUnDealedTask())
|
|
|
{
|
|
|
ti.Dealed = true;
|
|
|
}
|
|
|
mrs = new List<MatchResult>();
|
|
|
for (int i = 0; i < 8; i++)
|
|
|
{
|
|
|
mrs.Add(new MatchResult());
|
|
|
}
|
|
|
flowStep = EDischargeFlowStep.到放料位上方;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (GlobalVar.FirstDischarge)
|
|
|
{
|
|
|
GlobalVar.FirstDischarge = false;
|
|
|
//设备遗留产品检测
|
|
|
//吸嘴全部用真空吸检测,周转盘用上相机检测,SOCKET用镭射头检测
|
|
|
flowStep = EDischargeFlowStep.到取料位上方;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
flowStep = EDischargeFlowStep.到取料位上方;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|
|
|
break;
|
|
|
case EDischargeFlowStep.到取料位上方:
|
|
|
//先取上料任务,再取下料任务,最后取换料任务
|
|
|
if(StockTrayToTurnoverTray)
|
|
|
{
|
|
|
if (LoadAndUnloadTask.Instance.GetTaskNum(ETaskType.Load) > 0)
|
|
|
{
|
|
|
curTask = LoadAndUnloadTask.Instance.GetLoadTask();
|
|
|
}
|
|
|
else if (LoadAndUnloadTask.Instance.GetTaskNum(ETaskType.Unload) > 0)
|
|
|
{
|
|
|
curTask = LoadAndUnloadTask.Instance.GetUnLoadTask();
|
|
|
}
|
|
|
else if (LoadAndUnloadTask.Instance.GetTaskNum(ETaskType.Change) > 0)
|
|
|
{
|
|
|
curTask = LoadAndUnloadTask.Instance.GetChangeTask();
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (LoadAndUnloadTask.Instance.GetTaskNum(ETaskType.Unload) > 0)
|
|
|
{
|
|
|
curTask = LoadAndUnloadTask.Instance.GetUnLoadTask();
|
|
|
}
|
|
|
else if (LoadAndUnloadTask.Instance.GetTaskNum(ETaskType.Load) > 0)
|
|
|
{
|
|
|
curTask = LoadAndUnloadTask.Instance.GetLoadTask();
|
|
|
}
|
|
|
else if (LoadAndUnloadTask.Instance.GetTaskNum(ETaskType.Change) > 0)
|
|
|
{
|
|
|
curTask = LoadAndUnloadTask.Instance.GetChangeTask();
|
|
|
}
|
|
|
}
|
|
|
curNozzle = NozzleManager.GetIdelNozzle();
|
|
|
if (curTask!=null && curNozzle != null)
|
|
|
{
|
|
|
if (XYCanGoLocalArea() || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
curSlotPoint = null;
|
|
|
curNozzle.FromType=curTask.FromType;
|
|
|
if (curTask.FromType == TurnoverType.Turnover)
|
|
|
{
|
|
|
curSlotPoint = TrayPointManager.GetSlotPoint( ETrayType.Turnover, curTask.FromIndex + 1);
|
|
|
curNozzle.FromIndex = curTask.FromIndex;
|
|
|
logInfo = GetClassName()+ $"排料{curNozzle.NozzleIndex}号吸嘴到{curTask.FromType.ToString()}盘{curNozzle.FromIndex + 1}号穴位取料";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
}
|
|
|
else if (curTask.FromType == TurnoverType.ToBeTested)
|
|
|
{
|
|
|
TraySlot slot = GlobalTray.Input1Tray.GetSlot(ESlotStatus.Have);
|
|
|
if (slot != null)
|
|
|
{
|
|
|
curSlotPoint = TrayPointManager.GetSlotPoint( ETrayType.Input1, slot.Index);
|
|
|
curNozzle.FromIndex= slot.Index-1;
|
|
|
logInfo =GetClassName()+ $"排料{curNozzle.NozzleIndex}号吸嘴到{curTask.FromType.ToString()}盘{curNozzle.FromIndex+1}号穴位取料";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
GlobalTray.Input1Tray.ChangeStatus(ESlotStatus.Have);
|
|
|
//slot = GlobalTray.Input2Tray.GetSlot(ESlotStatus.Have);
|
|
|
//if (slot != null)
|
|
|
//{
|
|
|
// curSlotPoint = TrayPointManager.GetSlotPoint(ETrayType.Input2, slot.Index);
|
|
|
// curNozzle.FromIndex = slot.Index - 1;
|
|
|
// logInfo = GetClassName() + $"排料{curNozzle.NozzleIndex}号吸嘴到{curTask.FromType.ToString()}盘{curNozzle.FromIndex + 1}号穴位取料";
|
|
|
// MessageQueue.Instance.Insert(logInfo);
|
|
|
//}
|
|
|
//else
|
|
|
//{
|
|
|
// slot = GlobalTray.Input3Tray.GetSlot(ESlotStatus.Have);
|
|
|
// if (slot != null)
|
|
|
// {
|
|
|
// curSlotPoint = TrayPointManager.GetSlotPoint(ETrayType.Input3, slot.Index);
|
|
|
// curNozzle.FromIndex = slot.Index - 1;
|
|
|
// logInfo = GetClassName() + $"排料{curNozzle.NozzleIndex}号吸嘴到{curTask.FromType.ToString()}盘{curNozzle.FromIndex + 1}号穴位取料";
|
|
|
// MessageQueue.Instance.Insert(logInfo);
|
|
|
// }
|
|
|
// else
|
|
|
// {
|
|
|
// //这里报警,input已经没有产品了
|
|
|
// }
|
|
|
//}
|
|
|
}
|
|
|
}
|
|
|
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)
|
|
|
{
|
|
|
//if(Ops.IsHomedAndNearStartPos($"NozzleR{NozzleIndex}"))
|
|
|
{
|
|
|
errCode = AxisControl.LoadY.MovePos(targetY, (int)(GlobalVar.WholeSpeed));
|
|
|
if(errCode== ErrorCode.Ok|| GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
targetR = SysConfigParam.GetValue<Double>($"NozzleR{curNozzle.NozzleIndex}StartPos");
|
|
|
errCode = AxisControl.GetAxis($"NozzleR{curNozzle.NozzleIndex}").MovePos(targetR, GlobalVar.WholeSpeed);
|
|
|
if (errCode == ErrorCode.Ok | GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
if (GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
Thread.Sleep(GlobalVar.VirtualAxisMoveTime);
|
|
|
}
|
|
|
flowStep = EDischargeFlowStep.等待到取料位上方;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//MsgBox.ShowAxisAlarmDialog($"NozzleR{curNozzle.NozzleIndex}", errCode);
|
|
|
alarmEntity = AlarmCollection.Get($"NozzleR{curNozzle.NozzleIndex}运动异常").Transform(errCode.ToString());
|
|
|
AlarmMessageBox.ShowDialog(alarmEntity, ETipButton.Ok, null);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//MsgBox.ShowAxisAlarmDialog(AxisControl.LoadY, errCode);
|
|
|
AlarmMessageBox.ShowDialog(true, ETipButton.Ok, null, AlarmConstID.LoadY运动异常, errCode.ToString());
|
|
|
}
|
|
|
}
|
|
|
//else
|
|
|
// {
|
|
|
// Msg.ShowError($"吸头 NozzleR{NozzleIndex} 不在起始位,请手动手动回原后运动到起始位");
|
|
|
// }
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//MsgBox.ShowAxisAlarmDialog(AxisControl.LoadX, errCode);
|
|
|
AlarmMessageBox.ShowDialog(true, ETipButton.Ok, null, AlarmConstID.LoadX运动异常,errCode.ToString());
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//logInfo = "x y r move is unsafe";
|
|
|
//Msg.ShowError(logInfo);
|
|
|
MessageQueue.Instance.Warn($"LoadY运动不安全,请检查TurnoverY的位置");
|
|
|
AlarmMessageBox.ShowDialog(true, ETipButton.Ok, null, AlarmConstID.运动不安全, $"{AxisAlias.LoadY}", $"{ AxisAlias.TurnoverY}");
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
case EDischargeFlowStep.等待到取料位上方:
|
|
|
if (Ops.IsStop("LoadX", "LoadY", $"NozzleR{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
if (AxisArrived.LoadXYIsArrived(targetX, targetY))
|
|
|
{
|
|
|
logInfo = GetClassName() + $"已运动到{WitchTrayWitchSlot(curNozzle.FromType, curNozzle.FromIndex)}取料位上方";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
flowStep = EDischargeFlowStep.到取料位下方;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
flowStep = EDischargeFlowStep.到取料位上方;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
case EDischargeFlowStep.到取料位下方:
|
|
|
if (AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").HomeStatus == EHomeStatus.Finished || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
if (curTask.FromType == TurnoverType.Turnover)
|
|
|
{
|
|
|
targetZ = GetVacOffsetHeight(reFetchNum) + SysConfigParam.GetValue<double>($"TurnoverNozzle{curNozzle.NozzleIndex}TakeHeight");
|
|
|
//在周转盘取料,提前把真空吸打开
|
|
|
VacManager.DischargeVacSuction(EVacOperator.Open, false, curNozzle.NozzleIndex);
|
|
|
VacManager.TurnoverTrayVacSuction(EVacOperator.Close, false, curNozzle.FromIndex + 1);
|
|
|
}
|
|
|
else if (curTask.FromType == TurnoverType.ToBeTested)
|
|
|
{
|
|
|
targetZ = GetVacOffsetHeight(reFetchNum) + SysConfigParam.GetValue<double>($"TrayNozzle{curNozzle.NozzleIndex}TakeHeight");
|
|
|
}
|
|
|
errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(targetZ, GlobalVar.WholeSpeed);
|
|
|
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
logInfo = GetClassName() + $"到{WitchTrayWitchSlot(curNozzle.FromType, curNozzle.FromIndex)}号穴位取料位下方";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
if (GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
Thread.Sleep(GlobalVar.VirtualAxisMoveTime);
|
|
|
}
|
|
|
flowStep = EDischargeFlowStep.等待到取料位下方;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//MsgBox.ShowAxisAlarmDialog($"NozzleZ{curNozzle.NozzleIndex}", errCode);
|
|
|
//AlarmMessageBox.ShowDialog(true,ETipButton.Ok,null,)
|
|
|
alarmEntity = AlarmCollection.Get($"NozzleZ{curNozzle.NozzleIndex}运动异常").Transform(errCode.ToString());
|
|
|
AlarmMessageBox.ShowDialog(alarmEntity, ETipButton.Ok, null);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
logInfo = GetClassName()+ $"NozzleZ{curNozzle.NozzleIndex} 轴状态未回原,请手动回原后点击确定";
|
|
|
MessageQueue.Instance.Warn(logInfo);
|
|
|
//MsgBox.ShowDialog(AlarmConstID.AxisNotAtHomeAlarm, logInfo, ETipButton.Ok);
|
|
|
AlarmMessageBox.ShowDialog(true, ETipButton.Ok, null, AlarmConstID.轴不在原点, $"NozzleZ{curNozzle.NozzleIndex}");
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
case EDischargeFlowStep.等待到取料位下方:
|
|
|
if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
if (AxisArrived.LoadXYIsArrived(targetX, targetY))
|
|
|
{
|
|
|
logInfo = GetClassName() + $"已运动到{WitchTrayWitchSlot(curNozzle.FromType, curNozzle.FromIndex)}号穴位取料位下方";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
if (curTask.FromType == TurnoverType.Turnover)
|
|
|
{
|
|
|
VacManager.TurnoverTrayVacBreak(EVacOperator.Open, true, curNozzle.FromIndex + 1);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
VacManager.DischargeVacSuction(EVacOperator.Open, true, curNozzle.NozzleIndex);
|
|
|
}
|
|
|
flowStep = EDischargeFlowStep.取料完成抬起;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
flowStep = EDischargeFlowStep.到取料位上方;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case EDischargeFlowStep.取料完成抬起:
|
|
|
errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(0, GlobalVar.WholeSpeed);
|
|
|
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
if(GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
Thread.Sleep(GlobalVar.VirtualAxisMoveTime);
|
|
|
}
|
|
|
logInfo = GetClassName()+ $"取{WitchTrayWitchSlot(curNozzle.FromType, curNozzle.FromIndex)}号穴位产品完成抬起";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
flowStep = EDischargeFlowStep.等待取料完成抬起;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
alarmEntity = AlarmCollection.Get($"NozzleZ{curNozzle.NozzleIndex}运动异常").Transform(errCode.ToString());
|
|
|
AlarmMessageBox.ShowDialog(alarmEntity, ETipButton.Ok, null);
|
|
|
}
|
|
|
break;
|
|
|
case EDischargeFlowStep.等待取料完成抬起:
|
|
|
if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
logInfo = GetClassName()+$"取{WitchTrayWitchSlot(curNozzle.FromType, curNozzle.FromIndex)}号穴位产品完成已抬起";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
flowStep = EDischargeFlowStep.取料完成后真空检测;
|
|
|
}
|
|
|
break;
|
|
|
case EDischargeFlowStep.取料完成后真空检测:
|
|
|
if (Ops.IsOn($"{curNozzle.NozzleIndex}号吸嘴真空吸检测") || GlobalVar.RunSpace)
|
|
|
{
|
|
|
reFetchNum = 0;
|
|
|
logInfo = GetClassName()+$"排料吸嘴{curNozzle.NozzleIndex}号真空检测OK";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
GlobalTray.DischargeNozzle.ChangeStatus(curNozzle.NozzleIndex, ESlotStatus.Have);
|
|
|
UpdateNozzleStatus(curNozzle, curTask);
|
|
|
undoTaskNum = LoadAndUnloadTask.Instance.GetTaskNum(curTask.taskMode);
|
|
|
if (undoTaskNum > 0 && NozzleManager.GetNozzlesByStatus(ENozzleStatus.IDLE).Count > 0)
|
|
|
{
|
|
|
logInfo =GetClassName()+ $"还有{undoTaskNum}条任务未执行,并且有空闲吸嘴,继续取料";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
flowStep = EDischargeFlowStep.到取料位上方;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
flowStep = EDischargeFlowStep.到下相机拍照起始位;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if(reFetchNum==0)
|
|
|
{
|
|
|
//这个时候Z&R回原一次,然后再重新取料
|
|
|
ZRHomeFlow.Instance.GoHome(curNozzle.NozzleIndex);
|
|
|
}
|
|
|
reFetchNum++;
|
|
|
if (reFetchNum >= GlobalVar.DischargeRetakeNum)
|
|
|
{
|
|
|
DischargeDumpFlow.Instance.Start(curTask.FromType, curNozzle.NozzleIndex, curNozzle.FromIndex);
|
|
|
//alarmInfo = $"排料{curNozzle.NozzleIndex}号吸嘴取{curNozzle.FromIndex+1}号穴位产品{reFetchNum}次失败";
|
|
|
if(curTask.FromType== TurnoverType.ToBeTested)
|
|
|
{
|
|
|
//alarmInfo = string.Format(AlarmCollection.GetAlarm(AlarmConstID.料仓tray盘取料报警), curNozzle.NozzleIndex, curNozzle.FromIndex + 1);
|
|
|
alarmEntity = AlarmCollection.Get(AlarmConstID.料仓tray盘取料报警).Transform(curNozzle.NozzleIndex, (curNozzle.FromIndex + 1));
|
|
|
}
|
|
|
else if(curTask.FromType== TurnoverType.Turnover)
|
|
|
{
|
|
|
//alarmInfo = string.Format(AlarmCollection.GetAlarm(AlarmConstID.排料头在周转盘取料失败报警), curNozzle.NozzleIndex, curNozzle.FromIndex + 1);
|
|
|
alarmEntity = AlarmCollection.Get(AlarmConstID.排料头在周转盘取料失败报警).Transform(curNozzle.NozzleIndex, curNozzle.FromIndex + 1);
|
|
|
}
|
|
|
flowStep = EDischargeFlowStep.取料失败报警;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
flowStep = EDischargeFlowStep.到取料位下方;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case EDischargeFlowStep.取料失败报警:
|
|
|
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");
|
|
|
if (curTask.FromType == TurnoverType.ToBeTested)
|
|
|
{
|
|
|
buttonText.Add(ETipButton.No, "结束上料|EndInput");
|
|
|
btnText |= ETipButton.No;
|
|
|
}
|
|
|
ETipButton button = AlarmMessageBox.ShowDialog(alarmEntity, btnText, buttonText);
|
|
|
//switch (box.Button)
|
|
|
switch(button)
|
|
|
{
|
|
|
case ETipButton.Retry:
|
|
|
logInfo = GetClassName() + $"选择了重试,继续取料";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
reFetchNum = 0;
|
|
|
flowStep = EDischargeFlowStep.到取料位上方;
|
|
|
break;
|
|
|
case ETipButton.Skip:
|
|
|
SlotProductHasOrNotResult haveProduct = null;
|
|
|
logInfo = GetClassName() + "选择了跳过";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
if(curTask.FromType== TurnoverType.ToBeTested)
|
|
|
{
|
|
|
haveProduct = UpCameraCheckFlow.Instance.CheckStockTrayHasProduct(ETrayType.Input1, curNozzle.FromIndex+1, true);
|
|
|
OnStockTrayProductHasOrNotResult?.Invoke(haveProduct);
|
|
|
}
|
|
|
else if(curTask.FromType== TurnoverType.Turnover)
|
|
|
{
|
|
|
haveProduct = UpCameraCheckFlow.Instance.CheckTurnoverTrayHasProduct(null, curTask.FromIndex + 1);
|
|
|
OnStockTrayProductHasOrNotResult?.Invoke(haveProduct);
|
|
|
}
|
|
|
if(!haveProduct.HasProduct)
|
|
|
{
|
|
|
logInfo = GetClassName() + "检测到产品已拿走,流程继续";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
reFetchNum = 0;
|
|
|
//执行料仓Tray取料NG时的处理流程,流程处理结束后,流程继续
|
|
|
if (curTask.FromType == TurnoverType.Turnover)
|
|
|
{
|
|
|
TurnoverTrayManager.Instance.Slot(curTask.FromIndex + 1).ClearProduct();
|
|
|
GlobalTray.TurnoverTray.ChangeStatus(curTask.FromIndex + 1, ESlotStatus.NotHave);
|
|
|
curTask.Dealed = true;
|
|
|
}
|
|
|
else if (curTask.FromType == TurnoverType.ToBeTested)
|
|
|
{
|
|
|
GlobalTray.Input1Tray.ChangeStatus(curNozzle.FromIndex+1, ESlotStatus.NotHave);
|
|
|
}
|
|
|
undoTaskNum = LoadAndUnloadTask.Instance.GetTaskNum(curTask.taskMode);
|
|
|
if (undoTaskNum > 0 && NozzleManager.GetNozzlesByStatus(ENozzleStatus.IDLE).Count > 0)
|
|
|
{
|
|
|
logInfo = GetClassName()+ $"跳过后检测到还有{undoTaskNum}条任务未执行,继续取料";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
flowStep = EDischargeFlowStep.到取料位上方;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
flowStep = EDischargeFlowStep.到下相机拍照起始位;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//alarmInfo = $"检测到{curNozzle.FromIndex+1}号穴位产品未取出,请处理";
|
|
|
alarmEntity = AlarmCollection.Get(AlarmConstID.料仓产品未取出).Transform(curNozzle.FromIndex + 1);
|
|
|
flowStep = EDischargeFlowStep.取料失败报警;
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
case ETipButton.Yes://移动到安全位
|
|
|
//通知料仓把料盘退回到安全位
|
|
|
if(curTask.FromType== TurnoverType.Turnover)
|
|
|
{
|
|
|
logInfo = GetClassName() + $"通知排料头回安全位";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
DischargeModuleGoSafePosFlow.Instance.GoSafePostion();
|
|
|
logInfo = GetClassName() + $"排料头已回到安全位";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
}
|
|
|
alarmEntity = AlarmCollection.Get(AlarmConstID.料仓tray盘取料报警).Transform(curNozzle.NozzleIndex, (curNozzle.FromIndex + 1));
|
|
|
flowStep = EDischargeFlowStep.取料失败报警;
|
|
|
break;
|
|
|
case ETipButton.No://结束上料
|
|
|
logInfo = GetClassName() + $"选择了结束上料,通知中控结束上料";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
reFetchNum = 0;
|
|
|
TestCenter.Instance.EndInput();
|
|
|
LoadAndUnloadTask.Instance.ClearUndoTask();
|
|
|
if (NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload).Count > 0)
|
|
|
{
|
|
|
flowStep = EDischargeFlowStep.到下相机拍照起始位;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (LoadAndUnloadTask.Instance.GetUnDealedTask().Count > 0)
|
|
|
{
|
|
|
ScanBarCode();
|
|
|
StockTrayToTurnoverTray = !StockTrayToTurnoverTray;
|
|
|
flowStep = EDischargeFlowStep.到取料位上方;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
ScanBarCode();
|
|
|
flowStep = EDischargeFlowStep.任务结束到安全位;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
break;
|
|
|
case EDischargeFlowStep.到下相机拍照起始位:
|
|
|
if (XYCanGoTurnoverTray() || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
if (NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload).Count > 0)
|
|
|
{
|
|
|
logInfo = GetClassName() + $"到下相机拍照起始位";
|
|
|
Ops.On("下相机光源");
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
if(!GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
ImageProcess.ClearAutoTrigger();
|
|
|
HikCamera.Instance.SetExposure("locationCamera", GlobalVar.FlyGrabExposureTime);
|
|
|
HikCamera.Instance.SetGain("locationCamera", GlobalVar.FlyGrabGain);
|
|
|
}
|
|
|
if (NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload)[0].ToType == TurnoverType.Turnover)
|
|
|
{
|
|
|
needGrabNum = NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload).Count();
|
|
|
targetX = SysConfigParam.GetValue<double>($"Nozzle{needGrabNum}CenterX") - 30;
|
|
|
targetY = SysConfigParam.GetValue<double>($"Nozzle2CenterY");
|
|
|
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)
|
|
|
{
|
|
|
flowStep = EDischargeFlowStep.等待到下相机拍照起始位;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
targetX = SysConfigParam.GetValue<double>("Nozzle1CenterX") + 30;
|
|
|
targetY = SysConfigParam.GetValue<double>($"Nozzle1CenterY");
|
|
|
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)
|
|
|
{
|
|
|
flowStep = EDischargeFlowStep.等待到下相机拍照起始位;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//PromptMessageBox.ShowAxisAlarmDialog(AxisControl.LoadY, errCode);
|
|
|
alarmEntity = AlarmCollection.Get(AlarmConstID.LoadY运动异常).Transform(errCode.ToString());
|
|
|
AlarmMessageBox.ShowDialog(alarmEntity, ETipButton.Ok, null);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//PromptMessageBox.ShowAxisAlarmDialog(AxisControl.LoadX, errCode);
|
|
|
alarmEntity = AlarmCollection.Get(AlarmConstID.LoadX运动异常).Transform(errCode.ToString());
|
|
|
AlarmMessageBox.ShowDialog(alarmEntity, ETipButton.Ok, null);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
logInfo = GetClassName() + $"检测到排料吸嘴没有需要下料的产品,任务结束回安全位";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
flowStep = EDischargeFlowStep.任务结束到安全位;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
case EDischargeFlowStep.等待到下相机拍照起始位:
|
|
|
if (Ops.IsStop("LoadX", "LoadY") || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
if(AxisArrived.LoadXYIsArrived(targetX,targetY))
|
|
|
{
|
|
|
logInfo = GetClassName() + $"已运动到下相机拍照起始位";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
if (!GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
HikCamera.Instance.SetTrigger("locationCamera", ETriggerMode.Auto);
|
|
|
}
|
|
|
|
|
|
List<double> grabPoints = new List<double>();
|
|
|
//获取有几个吸嘴需要拍照
|
|
|
needGrabNum = NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload).Count();
|
|
|
if (NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload)[0].ToType == TurnoverType.Turnover)
|
|
|
{
|
|
|
for (int i = needGrabNum; i >= 1; i--)
|
|
|
{
|
|
|
grabPoints.Add(SysConfigParam.GetValue<double>($"Nozzle{i}CenterX"));
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
for (int i = 1; i < needGrabNum + 1; i++)
|
|
|
{
|
|
|
grabPoints.Add(SysConfigParam.GetValue<double>($"Nozzle{i}CenterX"));
|
|
|
}
|
|
|
}
|
|
|
//LogHelper.Debug(GetClassName()+$"拍照点位:{grabPoints.ToJoinString(",")}");
|
|
|
errCode = AxisControl.LoadX.SetPosCompare(2, grabPoints.ToArray());
|
|
|
flowStep = EDischargeFlowStep.到下相机拍照结束位;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
flowStep = EDischargeFlowStep.到下相机拍照起始位;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
case EDischargeFlowStep.到下相机拍照结束位:
|
|
|
if (XYCanGoTurnoverTray() || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
logInfo = GetClassName() + $"到下相机拍照结束位";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
//IoManager.Instance.WriteOut("下左相机光源触发", 1);
|
|
|
//Thread.Sleep(50);
|
|
|
if (NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload)[0].ToType == TurnoverType.Turnover)
|
|
|
{
|
|
|
targetX = SysConfigParam.GetValue<double>($"Nozzle1CenterX") + 10;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
targetX = SysConfigParam.GetValue<double>($"Nozzle{needGrabNum}CenterX") - 10;
|
|
|
}
|
|
|
errCode = AxisControl.LoadX.MovePos(targetX, GlobalVar.FlyCameraSpeed);
|
|
|
if (errCode== ErrorCode.Ok || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
flowStep = EDischargeFlowStep.等待到下相机拍照结束位;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//PromptMessageBox.ShowAxisAlarmDialog(AxisControl.LoadX, errCode);
|
|
|
alarmEntity = AlarmCollection.Get(AlarmConstID.LoadX运动异常).Transform(errCode.ToString());
|
|
|
AlarmMessageBox.ShowDialog(alarmEntity, ETipButton.Ok, null);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
case EDischargeFlowStep.等待到下相机拍照结束位:
|
|
|
if (Ops.IsStop("LoadX") || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
if(AxisArrived.LoadXYIsArrived(targetX,targetY))
|
|
|
{
|
|
|
logInfo = GetClassName() + $"已运动到下相机拍照结束位";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
if (!GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
AxisControl.LoadX.ClearCompare(1);
|
|
|
}
|
|
|
Ops.Off("下相机光源");
|
|
|
timeout.Restart();
|
|
|
flowStep = EDischargeFlowStep.等待相机拍照完成;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
flowStep = EDischargeFlowStep.到下相机拍照结束位;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case EDischargeFlowStep.等待相机拍照完成:
|
|
|
if(timeout.ElapsedMilliseconds<3000)
|
|
|
{
|
|
|
imgs = ImageProcess.GetAutoImage();
|
|
|
if ((imgs != null && imgs.Length == needGrabNum) || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
logInfo = GetClassName() + $"相机拍照完成,准备处理照片";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
if (NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload)[0].ToType == TurnoverType.Turnover)
|
|
|
{
|
|
|
imgs = imgs.Reverse().ToArray();
|
|
|
}
|
|
|
if (GlobalVar.RunSpace)
|
|
|
{
|
|
|
if(GlobalVar.EnableScanBarCodeByDownCamera)
|
|
|
{
|
|
|
foreach (Nozzle nl in NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload))
|
|
|
{
|
|
|
if (string.IsNullOrEmpty(nl.SN))
|
|
|
{
|
|
|
nl.SN = VirtualBarCode.Code;// (nl.FromIndex + 1).ToString().PadLeft(18, '0');
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
mrs = new List<MatchResult>();
|
|
|
for (int i = 0; i < needGrabNum; i++)
|
|
|
{
|
|
|
mrs.Add(new MatchResult());
|
|
|
}
|
|
|
flowStep = EDischargeFlowStep.到放料位上方;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//拍照完成
|
|
|
flowStep = EDischargeFlowStep.等待视觉处理结果;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
MessageQueue.Instance.Warn("下相机拍照超时,重拍");
|
|
|
flowStep = EDischargeFlowStep.到下相机拍照起始位;
|
|
|
}
|
|
|
break;
|
|
|
case EDischargeFlowStep.等待视觉处理结果:
|
|
|
if (mrs != null && mrs.Count > 0)
|
|
|
{
|
|
|
mrs.Clear();
|
|
|
GC.Collect();
|
|
|
}
|
|
|
mrs = VisionProcess.Instance.MatchDownCam(imgs);
|
|
|
if (mrs != null && mrs.Count == imgs.Length && (mrs.Where(m=>m.IsOK==true).Count()==imgs.Length || GlobalVar.DownCameraFlyRegrabNum==0))
|
|
|
{
|
|
|
logInfo = GetClassName() + $"图片处理完成,准备放料";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
int count = 0;
|
|
|
if(GlobalVar.EnableScanBarCodeByDownCamera)
|
|
|
{
|
|
|
foreach (Nozzle nozzle in NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload))
|
|
|
{
|
|
|
nozzle.SN = mrs[count].SN;
|
|
|
count++;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//int ni = 1;
|
|
|
//foreach (MatchResult item in mrs)
|
|
|
//{
|
|
|
// NozzleManager.GetNozzle(ni).SN = item.SN;
|
|
|
// ni++;
|
|
|
//}
|
|
|
reGrabCount = 0;
|
|
|
OnMatchResult?.Invoke(mrs);
|
|
|
flowStep = EDischargeFlowStep.到放料位上方;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
int ni = 1;
|
|
|
List<int> errCodeList = new List<int>();
|
|
|
foreach (MatchResult item in mrs)
|
|
|
{
|
|
|
if(item.IsOK)
|
|
|
{
|
|
|
if(GlobalVar.EnableScanBarCodeByDownCamera)
|
|
|
{
|
|
|
NozzleManager.GetNozzle(ni).SN = item.SN;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
errCodeList.Add(ni);
|
|
|
NozzleManager.GetNozzle(ni).SN = null;
|
|
|
}
|
|
|
ni++;
|
|
|
}
|
|
|
OnMatchResult?.Invoke(mrs);
|
|
|
if(reGrabCount < GlobalVar.DownCameraFlyRegrabNum)
|
|
|
{
|
|
|
reGrabCount++;
|
|
|
flowStep = EDischargeFlowStep.到下相机拍照起始位;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if(GlobalVar.LocationFailAutoSkip)
|
|
|
{
|
|
|
reGrabCount = 0;
|
|
|
flowStep = EDischargeFlowStep.到放料位上方;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
reGrabCount = 0;
|
|
|
//alarmInfo = $"{string.Join(",", errCodeList)}号排料吸嘴拍照失败";
|
|
|
alarmEntity = AlarmCollection.Get(AlarmConstID.下相机拍照定位失败).Transform(errCodeList.ToJoinString(","));
|
|
|
//DialogResult dr = Msg.ShowQuestion(, System.Windows.Forms.MessageBoxButtons.RetryCancel);
|
|
|
//TestCenterMessageBox.Show(AlarmConstID.DownCameraFlyFailAlarm, alarmInfo, ETipButton.Retry | ETipButton.Cancel);
|
|
|
//box = MsgBox.ShowDialog(AlarmConstID.DownCameraFlyFailAlarm, alarmInfo, ETipButton.Retry | ETipButton.Cancel);// TestCenterMessageBox.WaitResult(AlarmConstID.DownCameraFlyFailAlarm);
|
|
|
ETipButton box = AlarmMessageBox.ShowDialog(alarmEntity, ETipButton.Retry | ETipButton.Cancel, null, true);
|
|
|
// if (box.Button == ETipButton.Cancel)
|
|
|
if(box== ETipButton.Cancel)
|
|
|
{
|
|
|
flowStep = EDischargeFlowStep.到放料位上方;
|
|
|
}
|
|
|
//else if (box.Button == ETipButton.Retry)
|
|
|
else if(box== ETipButton.Retry)
|
|
|
{
|
|
|
Thread.Sleep(500);
|
|
|
flowStep = EDischargeFlowStep.到下相机拍照起始位;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case EDischargeFlowStep.到放料位上方:
|
|
|
{
|
|
|
bool canGo = false;
|
|
|
if (curNozzle.ToType == TurnoverType.Turnover)
|
|
|
{
|
|
|
canGo = XYCanGoTurnoverTray();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
canGo = XYCanGoLocalArea();
|
|
|
}
|
|
|
if (canGo || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
turnoverOffsetPoint.Reset();
|
|
|
tray = null;
|
|
|
targetX = 0.0;
|
|
|
targetY = 0.0;
|
|
|
///获取需要放料的吸嘴
|
|
|
curSlotPoint = null;
|
|
|
curNozzle = NozzleManager.GetToUnloadNozzle();
|
|
|
if (curNozzle != null)
|
|
|
{
|
|
|
if (curNozzle.ToType == TurnoverType.Turnover)
|
|
|
{
|
|
|
logInfo = GetClassName() + $"排料吸嘴{curNozzle.NozzleIndex}号到{curNozzle.ToType}盘{curNozzle.ToIndex + 1}号穴位上方";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
curSlotPoint = TrayPointManager.GetSlotPoint(ETrayType.Turnover, curNozzle.ToIndex + 1);
|
|
|
turnoverOffsetPoint = TurnoverSlotOffset.GetOffsetPoint(curNozzle.ToIndex + 1);
|
|
|
}
|
|
|
else if (curNozzle.ToType == TurnoverType.ToBeTested)
|
|
|
{
|
|
|
downSlot = GlobalTray.Input1Tray.GetSlot(ESlotStatus.NotHave);
|
|
|
if (downSlot != null)
|
|
|
{
|
|
|
curNozzle.ToIndex = downSlot.Index - 1;
|
|
|
curSlotPoint = TrayPointManager.GetSlotPoint(ETrayType.Input1, downSlot.Index);
|
|
|
logInfo = GetClassName() + $"排料吸嘴{curNozzle.NozzleIndex}号到{curNozzle.ToType}盘{curNozzle.ToIndex + 1}号穴位上方";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
|
|
|
}
|
|
|
}
|
|
|
else if (curNozzle.ToType == TurnoverType.Passed)
|
|
|
{
|
|
|
downSlot = GlobalTray.Good1Tray.GetSlot(ESlotStatus.NotHave);
|
|
|
if (downSlot != null)
|
|
|
{
|
|
|
curNozzle.ToIndex = downSlot.Index - 1;
|
|
|
curSlotPoint = TrayPointManager.GetSlotPoint(ETrayType.Good1, downSlot.Index);
|
|
|
logInfo = GetClassName() + $"排料吸嘴{curNozzle.NozzleIndex}号到{curNozzle.ToType}盘{curNozzle.ToIndex + 1}号穴位上方";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
GlobalTray.Good1Tray.ChangeStatus(ESlotStatus.NotHave);
|
|
|
//downSlot = GlobalTray.Good2Tray.GetSlot(ESlotStatus.NotHave);
|
|
|
//if (downSlot != null)
|
|
|
//{
|
|
|
// curNozzle.ToIndex = downSlot.Index - 1;
|
|
|
// curSlotPoint = TrayPointManager.GetSlotPoint(ETrayType.Good2, downSlot.Index);
|
|
|
// logInfo = GetClassName() + $"排料吸嘴{curNozzle.NozzleIndex}号到{curNozzle.ToType}盘{curNozzle.ToIndex + 1}号穴位上方";
|
|
|
// MessageQueue.Instance.Insert(logInfo);
|
|
|
//}
|
|
|
//else
|
|
|
//{
|
|
|
// downSlot = GlobalTray.Good3Tray.GetSlot(ESlotStatus.NotHave);
|
|
|
// if (downSlot != null)
|
|
|
// {
|
|
|
// curNozzle.ToIndex = downSlot.Index - 1;
|
|
|
// curSlotPoint = TrayPointManager.GetSlotPoint(ETrayType.Good3, downSlot.Index);
|
|
|
// logInfo = GetClassName() + $"排料吸嘴{curNozzle.NozzleIndex}号到{curNozzle.ToType}盘{curNozzle.ToIndex + 1}号穴位上方";
|
|
|
// MessageQueue.Instance.Insert(logInfo);
|
|
|
// }
|
|
|
// else
|
|
|
// {
|
|
|
// //在这里报警,产品没有地方放了
|
|
|
// }
|
|
|
//}
|
|
|
}
|
|
|
}
|
|
|
else if (curNozzle.ToType == TurnoverType.Failed)
|
|
|
{
|
|
|
downSlot = GlobalTray.RejectTray.GetSlot(ESlotStatus.NotHave);
|
|
|
if (downSlot != null)
|
|
|
{
|
|
|
curNozzle.ToIndex = downSlot.Index - 1;
|
|
|
curSlotPoint = TrayPointManager.GetSlotPoint(ETrayType.Reject, downSlot.Index);
|
|
|
logInfo = GetClassName() + $"排料吸嘴{curNozzle.NozzleIndex}号到{curNozzle.ToType}盘{curNozzle.ToIndex + 1}号穴位上方";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//在这里报警,产品没有地方放了
|
|
|
}
|
|
|
}
|
|
|
else if (curNozzle.ToType == TurnoverType.Multifunction)
|
|
|
{
|
|
|
//如果吸嘴是1,并且最后一列
|
|
|
downSlot = GlobalTray.MultiTray.GetSlot(ESlotStatus.NotHave);
|
|
|
if (downSlot != null)
|
|
|
{
|
|
|
curNozzle.ToIndex = downSlot.Index - 1;
|
|
|
curSlotPoint = TrayPointManager.GetSlotPoint(ETrayType.Multi, downSlot.Index);
|
|
|
logInfo = GetClassName() + $"排料吸嘴{curNozzle.NozzleIndex}号到{curNozzle.ToType}盘{curNozzle.ToIndex + 1}号穴位上方,SN={curNozzle.SN}";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//在这里报警,产品没有地方放了
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (curSlotPoint != null)
|
|
|
{
|
|
|
nozzleDist = TrayPointManager.GetDistToNozzle1(curNozzle.NozzleIndex);
|
|
|
if (mrs!=null && mrs.Count>0 && mrs.Count>=curNozzle.NozzleIndex && mrs[curNozzle.NozzleIndex - 1].OffsetRow < 3 && mrs[curNozzle.NozzleIndex - 1].OffsetCol < 3)
|
|
|
{
|
|
|
targetX = mrs[curNozzle.NozzleIndex - 1].OffsetCol + curSlotPoint.X + nozzleDist.X + turnoverOffsetPoint.X;
|
|
|
targetY = mrs[curNozzle.NozzleIndex - 1].OffsetRow + curSlotPoint.Y + nozzleDist.Y + turnoverOffsetPoint.Y;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
targetX = curSlotPoint.X + nozzleDist.X + turnoverOffsetPoint.X;
|
|
|
targetY = curSlotPoint.Y + nozzleDist.Y + turnoverOffsetPoint.Y;
|
|
|
}
|
|
|
//在这里保存图片,图片的名称以 时间+穴位定义
|
|
|
if(curNozzle.ToType== TurnoverType.Turnover)
|
|
|
{
|
|
|
//判断文件夹是否存在
|
|
|
string dirname = $"d://images/{DateTime.Now.ToString("yyyyMMdd")}/load";
|
|
|
if (!Directory.Exists(dirname))
|
|
|
{
|
|
|
Directory.CreateDirectory(dirname);
|
|
|
}
|
|
|
if(mrs != null && mrs.Count > 0 && mrs.Count >= curNozzle.NozzleIndex && mrs[curNozzle.NozzleIndex - 1].Himage!=null)
|
|
|
{
|
|
|
HOperatorSet.WriteImage(mrs[curNozzle.NozzleIndex - 1].Himage, "bmp", 0, $"{dirname}//{DateTime.Now.ToString("yyyyMMddHHmmssfff")}_{curNozzle.ToIndex + 1}");
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//判断文件夹是否存在
|
|
|
string dirname = $"d://images/{DateTime.Now.ToString("yyyyMMdd")}/unload";
|
|
|
if (!Directory.Exists(dirname))
|
|
|
{
|
|
|
Directory.CreateDirectory(dirname);
|
|
|
}
|
|
|
if (mrs != null && mrs.Count > 0 && mrs.Count >= curNozzle.NozzleIndex && mrs[curNozzle.NozzleIndex - 1].Himage != null)
|
|
|
{
|
|
|
HOperatorSet.WriteImage(mrs[curNozzle.NozzleIndex - 1].Himage, "bmp", 0, $"{dirname}//{DateTime.Now.ToString("yyyyMMddHHmmssfff")}_{curNozzle.FromIndex + 1}");
|
|
|
}
|
|
|
}
|
|
|
logInfo =GetClassName()+ $"运动到放料位上方 X:{targetX}Y:{targetY}";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
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((mrs[curNozzle.NozzleIndex - 1].OffsetA) + turnoverOffsetPoint.A, GlobalVar.WholeSpeed);
|
|
|
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
if (GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
Thread.Sleep(GlobalVar.VirtualAxisMoveTime);
|
|
|
}
|
|
|
flowStep = EDischargeFlowStep.等待到放料位上方;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//AlarmMessageBox.ShowDialog(true, ETipButton.Ok, null, AlarmConstID.轴运动异常, $"NozzleR{curNozzle.NozzleIndex}", errCode.ToString());
|
|
|
//MsgBox.ShowAxisAlarmDialog($"NozzleR{curNozzle.NozzleIndex}", errCode);
|
|
|
|
|
|
alarmEntity = AlarmCollection.Get($"NozzleR{curNozzle.NozzleIndex}运动异常").Transform(errCode.ToString());
|
|
|
AlarmMessageBox.ShowDialog(alarmEntity, ETipButton.Ok, null);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//MsgBox.ShowAxisAlarmDialog(AxisControl.LoadY, errCode);
|
|
|
//AlarmMessageBox.ShowDialog(true, ETipButton.Ok, null, AlarmConstID.轴运动异常, $"{AxisAlias.LoadY}", errCode.ToString());
|
|
|
alarmEntity = AlarmCollection.Get(AlarmConstID.LoadY运动异常).Transform(errCode.ToString());
|
|
|
AlarmMessageBox.ShowDialog(alarmEntity, ETipButton.Ok, null);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//MsgBox.ShowAxisAlarmDialog(AxisControl.LoadX, errCode);
|
|
|
alarmEntity = AlarmCollection.Get(AlarmConstID.LoadX运动异常).Transform(errCode.ToString());
|
|
|
AlarmMessageBox.ShowDialog(alarmEntity, ETipButton.Ok, null);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
alarmInfo = "loady r move isn't safe";
|
|
|
MessageQueue.Instance.Warn(alarmInfo);
|
|
|
//MsgBox.ShowDialog(AlarmConstID.MoveUnsafeAlarm, alarmInfo, ETipButton.Ok);
|
|
|
AlarmMessageBox.ShowDialog(true, ETipButton.Ok, null, AlarmConstID.运动不安全, $"{AxisAlias.LoadY}", $"{AxisAlias.TurnoverY }");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
break;
|
|
|
case EDischargeFlowStep.等待到放料位上方:
|
|
|
if (Ops.IsStop("LoadX", "LoadY",$"NozzleR{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
if(AxisArrived.LoadXYIsArrived(targetX, targetY))
|
|
|
{
|
|
|
//当放料到tray盘区域时,并且周转再盘已经没有要下料的穴位时,通知周转模组可以运动了
|
|
|
//if (curNozzle.ToType != TurnoverType.Turnover && TurnoverTrayManager.Instance.GetSlots(ETurnoverTraySlotType.Tested, ETurnoverTraySlotStatus.Have).Count() == 0)
|
|
|
//{
|
|
|
// LogHelper.Debug("通知周转模组可以运动");
|
|
|
// TurnoverFlow.Instance.CanMoveFromTestTrayToTurnoverTray();
|
|
|
//}
|
|
|
logInfo = GetClassName() + $"排料吸嘴{curNozzle.NozzleIndex}号已运动到{WitchTrayWitchSlot(curNozzle.ToType, curNozzle.ToIndex)}放料位上方";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
flowStep = EDischargeFlowStep.丢料检测;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
flowStep = EDischargeFlowStep.到放料位上方;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case EDischargeFlowStep.丢料检测:
|
|
|
if (!curNozzle.HasProduct()&&!GlobalVar.RunSpace)
|
|
|
{
|
|
|
bool exit = false;
|
|
|
while (!exit)
|
|
|
{
|
|
|
//弹框报警
|
|
|
//alarmInfo = $"{curNozzle.NozzleIndex}吸嘴真空吸异常,可能丢料,请检查吸嘴的状态";
|
|
|
if(curNozzle.ToType== TurnoverType.Turnover)
|
|
|
{
|
|
|
//alarmInfo = string.Format(AlarmCollection.GetAlarm(AlarmConstID.排料投在周转盘放料时丢料报警), curNozzle.NozzleIndex);
|
|
|
alarmEntity = AlarmCollection.Get(AlarmConstID.排料投在周转盘放料时丢料报警).Transform(curNozzle.NozzleIndex);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//alarmInfo = string.Format(AlarmCollection.GetAlarm(AlarmConstID.料仓tray盘放料时丢料报警), curNozzle.NozzleIndex,curNozzle.ToType.ToString());
|
|
|
alarmEntity = AlarmCollection.Get(AlarmConstID.料仓tray盘放料时丢料报警).Transform(curNozzle.NozzleIndex, curNozzle.ToType.ToString());
|
|
|
}
|
|
|
//alarmid = AlarmConstID.料仓tray盘放料时丢料报警;
|
|
|
//if (curNozzle.ToType == TurnoverType.Turnover)
|
|
|
//{
|
|
|
// //alarmid = AlarmConstID.排料投在周转盘放料时丢料报警;
|
|
|
|
|
|
//}
|
|
|
//else
|
|
|
//{
|
|
|
|
|
|
//}
|
|
|
//TestCenterMessageBox.Show(AlarmConstID.DischargeNozzleLostProductAlarm, alarmInfo, MessageButtonManager.GetSkip_MoveToSafe_Button(), MessageButtonManager.GetSkip_MoveToSafe_ButtonText());
|
|
|
//msgBox = MsgBox.ShowDialog(alarmid, alarmInfo, MessageButtonManager.GetSkip_MoveToSafe_Button(), MessageButtonManager.GetSkip_MoveToSafe_ButtonText());// TestCenterMessageBox.WaitResult(AlarmConstID.DischargeNozzleLostProductAlarm);
|
|
|
ETipButton buttonRet = AlarmMessageBox.ShowDialog(alarmEntity, MessageButtonManager.GetSkip_MoveToSafe_Button(), MessageButtonManager.GetSkip_MoveToSafe_ButtonText());
|
|
|
//switch (msgBox.Button)
|
|
|
switch(buttonRet)
|
|
|
{
|
|
|
case ETipButton.Skip:
|
|
|
if (!curNozzle.HasProduct())
|
|
|
{
|
|
|
curNozzle.Reset();
|
|
|
curNozzle.VacSuction(EIoOperate.Close);
|
|
|
curNozzle.VacBreak(EIoOperate.Open);
|
|
|
curNozzle.VacBreak(EIoOperate.Close);
|
|
|
exit = true;
|
|
|
flowStep = EDischargeFlowStep.放料任务完成;
|
|
|
}
|
|
|
break;
|
|
|
case ETipButton.Yes:
|
|
|
DischargeModuleGoSafePosFlow.Instance.GoSafePostion();
|
|
|
DischargeModuleGoSafePosFlow.Instance.Wait();
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
flowStep = EDischargeFlowStep.到放料位下方;
|
|
|
}
|
|
|
break;
|
|
|
case EDischargeFlowStep.到放料位下方:
|
|
|
|
|
|
if (curNozzle.ToType == TurnoverType.Turnover)
|
|
|
{
|
|
|
targetZ = SysConfigParam.GetValue<double>($"TurnoverNozzle{curNozzle.NozzleIndex}TakeHeight");
|
|
|
/*提前打开周转盘真空吸*/
|
|
|
VacManager.TurnoverTrayVacSuction(EVacOperator.Open, false, curNozzle.ToIndex + 1);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
targetZ = SysConfigParam.GetValue<double>($"TrayNozzle{curNozzle.NozzleIndex}TakeHeight") + GlobalVar.DischargeNozzleDumpStockTrayOffsetHeight;
|
|
|
}
|
|
|
errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(targetZ, GlobalVar.WholeSpeed);
|
|
|
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
logInfo = GetClassName() + $"排料吸嘴{curNozzle.NozzleIndex}号到{WitchTrayWitchSlot(curNozzle.ToType, curNozzle.ToIndex)}放料位下方";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
VirtualAxisSleep();
|
|
|
flowStep = EDischargeFlowStep.等待到放料位下方;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//PromptMessageBox.ShowAxisAlarmDialog($"NozzleZ{curNozzle.NozzleIndex}", errCode);
|
|
|
alarmEntity = AlarmCollection.Get($"NozzleZ{curNozzle.NozzleIndex}运动异常").Transform(errCode.ToString());
|
|
|
AlarmMessageBox.ShowDialog(alarmEntity, ETipButton.Ok, null);
|
|
|
}
|
|
|
break;
|
|
|
case EDischargeFlowStep.等待到放料位下方:
|
|
|
if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
if(AxisArrived.LoadXYIsArrived(targetX,targetY))
|
|
|
{
|
|
|
logInfo = GetClassName() + $"排料吸嘴{curNozzle.NozzleIndex}号已运动到{WitchTrayWitchSlot(curNozzle.ToType, curNozzle.ToIndex)}放料位下方";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
if (curNozzle.ToType == TurnoverType.Turnover)
|
|
|
{
|
|
|
/*关闭排料吸嘴真空吸*/
|
|
|
//logInfo = GetClassName() + $"关闭{curNozzle.NozzleIndex}号排料吸嘴真空吸";
|
|
|
//MessageQueue.Instance.Insert(logInfo);
|
|
|
//Ops.Off($"{curNozzle.NozzleIndex}号吸嘴真空吸电磁阀");//关闭真空
|
|
|
//Thread.Sleep(GlobalVar.LoadNozzleCloseVacSuctionDelaytime);
|
|
|
VacManager.DischargeVacSuction(EVacOperator.Close, true, curNozzle.NozzleIndex);
|
|
|
/*打开排料吸嘴真空破*/
|
|
|
//logInfo = GetClassName() + $"打开{curNozzle.NozzleIndex}号排料吸嘴真空破";
|
|
|
//MessageQueue.Instance.Insert(logInfo);
|
|
|
//Ops.On($"{curNozzle.NozzleIndex}号吸嘴真空破电磁阀");
|
|
|
//Thread.Sleep(GlobalVar.LoadNozzleOpenVacBreakDelaytime);
|
|
|
VacManager.DischargeVacBreak(EVacOperator.Open, true, curNozzle.NozzleIndex);
|
|
|
flowStep = EDischargeFlowStep.到放料关破真空位;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
GlobalTray.DischargeNozzle.ChangeStatus(curNozzle.NozzleIndex, ESlotStatus.NotHave);
|
|
|
/*关闭排料吸嘴真空吸*/
|
|
|
//logInfo = GetClassName() + $"关闭{curNozzle.NozzleIndex}号排料吸嘴真空吸";
|
|
|
//MessageQueue.Instance.Insert(logInfo);
|
|
|
//Ops.Off($"{curNozzle.NozzleIndex}号吸嘴真空吸电磁阀");
|
|
|
//Thread.Sleep(GlobalVar.LoadNozzleCloseVacSuctionDelaytime);
|
|
|
VacManager.DischargeVacSuction(EVacOperator.Close, true, curNozzle.NozzleIndex);
|
|
|
/*打开排料吸嘴真空破*/
|
|
|
//logInfo = GetClassName() + $"打开{curNozzle.NozzleIndex}号排料吸嘴真空破";
|
|
|
//MessageQueue.Instance.Insert(logInfo);
|
|
|
//Ops.On($"{curNozzle.NozzleIndex}号吸嘴真空破电磁阀");
|
|
|
//Thread.Sleep(GlobalVar.LoadNozzleOpenVacBreakDelaytime);
|
|
|
VacManager.DischargeVacBreak(EVacOperator.Open, true, curNozzle.NozzleIndex);
|
|
|
/*关闭排料吸嘴真空破*/
|
|
|
//logInfo = GetClassName() + $"关闭{curNozzle.NozzleIndex}号排料吸嘴真空破";
|
|
|
//MessageQueue.Instance.Insert(logInfo);
|
|
|
//Ops.Off($"{curNozzle.NozzleIndex}号吸嘴真空破电磁阀");
|
|
|
//Thread.Sleep(GlobalVar.LoadNozzleCloseVacBreakDelaytime);
|
|
|
VacManager.DischargeVacBreak(EVacOperator.Close, false, curNozzle.NozzleIndex);
|
|
|
flowStep = EDischargeFlowStep.放料完成抬起;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
flowStep = EDischargeFlowStep.到放料位上方;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case EDischargeFlowStep.到放料关破真空位:
|
|
|
targetZ = SysConfigParam.GetValue<double>($"TurnoverNozzle{curNozzle.NozzleIndex}TakeHeight")+GlobalVar.DischargeNozzleDumpTurnoverTrayOffset;
|
|
|
errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(targetZ, GlobalVar.WholeSpeed);
|
|
|
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
logInfo = GetClassName() + $"排料吸嘴{curNozzle.NozzleIndex}号周转盘放料完成,准备抬起{GlobalVar.DischargeNozzleDumpTurnoverTrayOffset}mm后关闭破真空";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
flowStep = EDischargeFlowStep.等待到放料关破真空位;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
PromptMessageBox.ShowAxisAlarmDialog($"NozzleZ{curNozzle.NozzleIndex}", errCode);
|
|
|
}
|
|
|
break;
|
|
|
case EDischargeFlowStep.等待到放料关破真空位:
|
|
|
if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
/*关闭排料吸嘴真空破*/
|
|
|
//Ops.Off($"{curNozzle.NozzleIndex}号吸嘴真空破电磁阀");
|
|
|
//Thread.Sleep(GlobalVar.LoadNozzleCloseVacBreakDelaytime);
|
|
|
VacManager.DischargeVacBreak(EVacOperator.Close,false,curNozzle.NozzleIndex);
|
|
|
logInfo = GetClassName() + $"关闭排料{curNozzle.NozzleIndex}号吸嘴真空破";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
flowStep = EDischargeFlowStep.放料完成抬起;
|
|
|
}
|
|
|
break;
|
|
|
case EDischargeFlowStep.放料完成抬起:
|
|
|
errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(0, GlobalVar.WholeSpeed);
|
|
|
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
logInfo = GetClassName() + $"排料吸嘴{curNozzle.NozzleIndex}号{WitchTrayWitchSlot(curNozzle.ToType, curNozzle.ToIndex)}放料完成抬起";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
if (GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
Thread.Sleep(GlobalVar.VirtualAxisMoveTime);
|
|
|
}
|
|
|
flowStep = EDischargeFlowStep.等待放料完成抬起;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//PromptMessageBox.ShowAxisAlarmDialog($"NozzleZ{curNozzle.NozzleIndex}", errCode);
|
|
|
alarmEntity = AlarmCollection.Get($"NozzleZ{curNozzle.NozzleIndex}运动异常").Transform(errCode.ToString());
|
|
|
AlarmMessageBox.ShowDialog(alarmEntity, ETipButton.Ok, null);
|
|
|
}
|
|
|
break;
|
|
|
case EDischargeFlowStep.等待放料完成抬起:
|
|
|
if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
logInfo = GetClassName()+$"排料吸嘴{curNozzle.NozzleIndex}号{WitchTrayWitchSlot(curNozzle.ToType, curNozzle.ToIndex)}放料完成已起位";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
if(curNozzle.ToType== TurnoverType.Turnover)
|
|
|
{
|
|
|
flowStep = EDischargeFlowStep.放料真空检测;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
flowStep = EDischargeFlowStep.粘料检测;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
break;
|
|
|
case EDischargeFlowStep.放料真空检测:
|
|
|
if (curNozzle.ToType == TurnoverType.Turnover)
|
|
|
{
|
|
|
if (Ops.IsOn($"周转盘{curNozzle.ToIndex + 1}号穴位真空吸检测") || GlobalVar.RunSpace)
|
|
|
{
|
|
|
|
|
|
logInfo = GetClassName() + $"周转盘{curNozzle.ToIndex + 1}号穴位真空吸检测OK";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
flowStep = EDischargeFlowStep.放料任务完成;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//打开真空吸
|
|
|
curNozzle.VacSuction(EIoOperate.Open);
|
|
|
//如果粘料
|
|
|
if (curNozzle.HasProduct())
|
|
|
{
|
|
|
bool skip = false;
|
|
|
while (!skip)
|
|
|
{
|
|
|
//粘料报警,提示用户粘料,移动到安全位,或者点击跳过
|
|
|
//alarmInfo = $"排料{curNozzle.NozzleIndex}号吸嘴可能粘料,请查看吸嘴状态后处理";
|
|
|
//alarmInfo = string.Format(AlarmCollection.GetAlarm(AlarmConstID.排料头粘料报警), curNozzle.NozzleIndex);
|
|
|
alarmEntity = AlarmCollection.Get(AlarmConstID.排料头粘料报警).Transform(curNozzle.NozzleIndex);
|
|
|
MessageQueue.Instance.Warn(GetClassName() + alarmEntity.CN);
|
|
|
//TestCenterMessageBox.Show(AlarmConstID.NozzleTackinessAlarm, alarmInfo, MessageButtonManager.GetSkip_MoveToSafe_Button(), MessageButtonManager.GetSkip_MoveToSafe_ButtonText());
|
|
|
//msgBox = MsgBox.ShowDialog(AlarmConstID.排料头粘料报警, alarmInfo, MessageButtonManager.GetSkip_MoveToSafe_Button(), MessageButtonManager.GetSkip_MoveToSafe_ButtonText());// TestCenterMessageBox.WaitResult(AlarmConstID.NozzleTackinessAlarm);
|
|
|
ETipButton btnRet = AlarmMessageBox.ShowDialog(alarmEntity, MessageButtonManager.GetSkip_MoveToSafe_Button(), MessageButtonManager.GetSkip_MoveToSafe_ButtonText());
|
|
|
//switch (msgBox.Button)
|
|
|
switch(btnRet)
|
|
|
{
|
|
|
case ETipButton.Skip:
|
|
|
logInfo = GetClassName() + "选择了跳过按钮";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
if (!curNozzle.HasProduct())
|
|
|
{
|
|
|
curNozzle.VacSuction(EIoOperate.Close);
|
|
|
curNozzle.Reset();
|
|
|
skip = true;
|
|
|
flowStep = EDischargeFlowStep.放料任务完成;
|
|
|
}
|
|
|
break;
|
|
|
case ETipButton.Yes:
|
|
|
logInfo = GetClassName() + "选择了移动到安全位按钮";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
DischargeModuleGoSafePosFlow.Instance.GoSafePostion();
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//如果没有粘料,说明产品放下去了,这个时候用相机检测产品是否在穴位种
|
|
|
VisionResult vr = UpCameraScanBarCodeFlow.Instance.ScanSingle(curNozzle.ToIndex + 1, true,true,false);
|
|
|
//VisionResult vr = UpCameraScanBarCodeFlow.Instance.WaitSingle();
|
|
|
if (UpCameraScanBarCodeFlow.Instance.CheckResult(vr))
|
|
|
{
|
|
|
logInfo = GetClassName() + $"排料吸嘴{curNozzle.NozzleIndex}号SN={curNozzle.SN}放{WitchTrayWitchSlot(curNozzle.ToType, curNozzle.ToIndex)}";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
curNozzle.VacSuction(EIoOperate.Close);
|
|
|
flowStep = EDischargeFlowStep.放料任务完成;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//异常处理
|
|
|
bool exit = false;
|
|
|
Dictionary<ETipButton, string> buttons = new Dictionary<ETipButton, string>()
|
|
|
{
|
|
|
{ ETipButton.Retry,"重拍|Regrab" },
|
|
|
{ETipButton.Skip,"跳过|Skip" },
|
|
|
{ETipButton.Yes,"移动到安全位|MoveToSafePos" }
|
|
|
};
|
|
|
while (!exit)
|
|
|
{
|
|
|
//alarmInfo = $"周转盘{curNozzle.ToIndex + 1}号穴位真空吸异常";
|
|
|
alarmInfo = string.Format(AlarmCollection.GetAlarm(AlarmConstID.排料头放料到周转盘后周转盘真空吸报警), curNozzle.NozzleIndex, curNozzle.ToIndex + 1);
|
|
|
MessageQueue.Instance.Warn(GetClassName() + alarmInfo);
|
|
|
//TestCenterMessageBox.Show(AlarmConstID.TurnoverDumpFailAlarm, alarmInfo, ETipButton.Retry | ETipButton.Skip | ETipButton.Yes, buttons);
|
|
|
msgBox = PromptMessageBox.ShowDialog(AlarmConstID.排料头放料到周转盘后周转盘真空吸报警, alarmInfo, ETipButton.Retry | ETipButton.Skip | ETipButton.Yes, buttons);// TestCenterMessageBox.WaitResult(AlarmConstID.TurnoverDumpFailAlarm);
|
|
|
if (msgBox != null)
|
|
|
{
|
|
|
switch (msgBox.Button)
|
|
|
{
|
|
|
case ETipButton.Retry://重拍
|
|
|
logInfo = GetClassName() + $"选择了重拍";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
vr = UpCameraScanBarCodeFlow.Instance.ScanSingle(curNozzle.ToIndex + 1, true,true,true);
|
|
|
//vr = UpCameraScanBarCodeFlow.Instance.WaitSingle();
|
|
|
if (UpCameraScanBarCodeFlow.Instance.CheckResult(vr))
|
|
|
{
|
|
|
logInfo = GetClassName() + $"排料吸嘴{curNozzle.NozzleIndex}号SN={curNozzle.SN}放{WitchTrayWitchSlot(curNozzle.ToType, curNozzle.ToIndex)}";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
curNozzle.VacSuction(EIoOperate.Close);
|
|
|
exit = true;
|
|
|
flowStep = EDischargeFlowStep.放料任务完成;
|
|
|
}
|
|
|
break;
|
|
|
case ETipButton.Skip://跳过
|
|
|
logInfo = GetClassName() + $"选择了跳过";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
if (!UpCameraCheckFlow.Instance.CheckTurnoverTrayHasProduct(null, curNozzle.ToIndex + 1).HasProduct)
|
|
|
{
|
|
|
VacManager.TurnoverTrayVacSuction(EVacOperator.Close, true, curNozzle.ToIndex + 1);
|
|
|
curNozzle.Reset();
|
|
|
flowStep = EDischargeFlowStep.放料任务完成;
|
|
|
exit = true;
|
|
|
}
|
|
|
break;
|
|
|
case ETipButton.Yes://移动到安全位
|
|
|
logInfo = GetClassName() + $"选择了移动到安全位";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
DischargeModuleGoSafePosFlow.Instance.GoSafePostion();
|
|
|
DischargeModuleGoSafePosFlow.Instance.Wait();
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case EDischargeFlowStep.粘料检测:
|
|
|
//打开真空吸
|
|
|
curNozzle.VacSuction(EIoOperate.Open);
|
|
|
if(!GlobalVar.RunSpace && curNozzle.HasProduct())
|
|
|
{
|
|
|
bool skip = false;
|
|
|
while(!skip)
|
|
|
{
|
|
|
//粘料报警,提示用户粘料,移动到安全位,或者点击跳过
|
|
|
//alarmInfo = $"排料{curNozzle.NozzleIndex}号吸嘴可能粘料,请查看吸嘴状态后处理";
|
|
|
//alarmInfo = string.Format(AlarmCollection.GetAlarm(AlarmConstID.排料头粘料报警), curNozzle.NozzleIndex);
|
|
|
alarmEntity = AlarmCollection.Get(AlarmConstID.排料头粘料报警).Transform(curNozzle.NozzleIndex);
|
|
|
MessageQueue.Instance.Warn(GetClassName()+ alarmEntity.CN);
|
|
|
//TestCenterMessageBox.Show(AlarmConstID.NozzleTackinessAlarm, alarmInfo, MessageButtonManager.GetSkip_MoveToSafe_Button(), MessageButtonManager.GetSkip_MoveToSafe_ButtonText());
|
|
|
//msgBox = MsgBox.ShowDialog(AlarmConstID.排料头粘料报警, alarmInfo, MessageButtonManager.GetSkip_MoveToSafe_Button(), MessageButtonManager.GetSkip_MoveToSafe_ButtonText());// TestCenterMessageBox.WaitResult(AlarmConstID.NozzleTackinessAlarm);
|
|
|
ETipButton btnRet = AlarmMessageBox.ShowDialog(alarmEntity, MessageButtonManager.GetSkip_MoveToSafe_Button(), MessageButtonManager.GetSkip_MoveToSafe_ButtonText());
|
|
|
//switch (msgBox.Button)
|
|
|
switch(btnRet)
|
|
|
{
|
|
|
case ETipButton.Skip:
|
|
|
logInfo = GetClassName() + "选择了跳过按钮";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
if (!curNozzle.HasProduct())
|
|
|
{
|
|
|
curNozzle.VacSuction(EIoOperate.Close);
|
|
|
curNozzle.Reset();
|
|
|
skip = true;
|
|
|
flowStep = EDischargeFlowStep.放料任务完成;
|
|
|
}
|
|
|
break;
|
|
|
case ETipButton.Yes:
|
|
|
logInfo = GetClassName() + "选择了移动到安全位按钮";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
DischargeModuleGoSafePosFlow.Instance.GoSafePostion();
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
logInfo = GetClassName() + $"排料吸嘴{curNozzle.NozzleIndex}号SN={curNozzle.SN}放{WitchTrayWitchSlot(curNozzle.ToType, curNozzle.ToIndex)}";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
curNozzle.VacSuction(EIoOperate.Close);
|
|
|
flowStep = EDischargeFlowStep.放料任务完成;
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
case EDischargeFlowStep.放料任务完成:
|
|
|
|
|
|
//AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").Home();
|
|
|
//MessageQueue.Instance.Insert($"{curNozzle.NozzleIndex}号排料吸嘴回原");
|
|
|
//Ops.HomeAndGoStartPos($"NozzleR{NozzleIndex}");
|
|
|
if (curNozzle.Status == ENozzleStatus.ToUnload)
|
|
|
{
|
|
|
GlobalTray.DischargeNozzle.ChangeStatus(curNozzle.NozzleIndex, ESlotStatus.NotHave);
|
|
|
logInfo = GetClassName() + $"排料吸嘴{curNozzle.NozzleIndex}号{WitchTrayWitchSlot(curNozzle.ToType, curNozzle.ToIndex)}放料任务完成";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
if (curNozzle.ToType == TurnoverType.Turnover)
|
|
|
{
|
|
|
GlobalTray.TurnoverTray.ChangeStatus(curNozzle.ToIndex + 1, ESlotStatus.Have);
|
|
|
TurnoverTrayManager.Instance.Slot(curNozzle.ToIndex + 1).AddProduct(curNozzle);
|
|
|
|
|
|
}
|
|
|
else if (curNozzle.ToType == TurnoverType.ToBeTested)
|
|
|
{
|
|
|
//curNozzle.ToFloor = StockManager.Instance.GetStock(ETrayType.Input).GetFloor();
|
|
|
GlobalTray.Input1Tray.ChangeStatus(curNozzle.ToIndex+1, ESlotStatus.Have);
|
|
|
TrayStatusManager.Fill(ETrayType.Input1, curNozzle.ToIndex + 1);
|
|
|
}
|
|
|
else if (curNozzle.ToType == TurnoverType.Passed)
|
|
|
{
|
|
|
//curNozzle.ToFloor = StockManager.Instance.GetStock(ETrayType.Ok).GetFloor();
|
|
|
GlobalTray.Good1Tray.ChangeStatus(curNozzle.ToIndex + 1, ESlotStatus.Have);
|
|
|
TrayStatusManager.Fill(ETrayType.Good1, curNozzle.ToIndex + 1);
|
|
|
}
|
|
|
else if (curNozzle.ToType == TurnoverType.Failed)
|
|
|
{
|
|
|
//curNozzle.ToFloor = StockManager.Instance.GetStock(ETrayType.Ng).GetFloor();
|
|
|
GlobalTray.RejectTray.ChangeStatus(curNozzle.ToIndex + 1, ESlotStatus.Have);
|
|
|
TrayStatusManager.Fill(ETrayType.Reject, curNozzle.ToIndex + 1);
|
|
|
}
|
|
|
else if (curNozzle.ToType == TurnoverType.Multifunction)
|
|
|
{
|
|
|
//curNozzle.ToFloor = StockManager.Instance.GetStock(ETrayType.Multi).GetFloor();
|
|
|
GlobalTray.MultiTray.ChangeStatus(curNozzle.ToIndex + 1, ESlotStatus.Have);
|
|
|
TrayStatusManager.Fill(ETrayType.Multi, curNozzle.ToIndex + 1);
|
|
|
}
|
|
|
LoadAndUnloadTask.Instance.AddTurnoverResult(curNozzle);
|
|
|
|
|
|
}
|
|
|
curNozzle.Reset();
|
|
|
if (NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload).Count > 0)
|
|
|
{
|
|
|
flowStep = EDischargeFlowStep.到放料位上方;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//release memory
|
|
|
//foreach (var item in mrs)
|
|
|
//{
|
|
|
// item.Dispose();
|
|
|
//}
|
|
|
//mrs.Clear();
|
|
|
if(mrs!=null&&mrs.Count>0)
|
|
|
{
|
|
|
Array.Clear(imgs, 0, imgs.Length);
|
|
|
mrs.Clear();
|
|
|
GC.Collect();
|
|
|
}
|
|
|
|
|
|
//GC.Collect();
|
|
|
if(curNozzle.ToType== TurnoverType.Turnover)
|
|
|
{
|
|
|
ScanBarCode();
|
|
|
}
|
|
|
|
|
|
if (LoadAndUnloadTask.Instance.GetUnDealedTask().Count > 0)
|
|
|
{
|
|
|
StockTrayToTurnoverTray = !StockTrayToTurnoverTray;
|
|
|
flowStep = EDischargeFlowStep.到取料位上方;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
flowStep = EDischargeFlowStep.任务结束到安全位;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
case EDischargeFlowStep.任务结束到安全位:
|
|
|
//检测一下是否需要换盘
|
|
|
{
|
|
|
#region 通知中控排料任务结束
|
|
|
if(curNozzle.ToType!= TurnoverType.Turnover && !GlobalVar.CleanOut)
|
|
|
{
|
|
|
if (TestCenter.Instance.LoadResult())
|
|
|
{
|
|
|
logInfo = GetClassName() + $"通知中控任务完成";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
LoadAndUnloadTask.Instance.Clear();
|
|
|
logInfo = GetClassName() + $"任务完成,清除任务";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
MachineManage.Instance.SetLoadUnloadStatus(ERunState.Waiting);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
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)
|
|
|
{
|
|
|
if (GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
Thread.Sleep(GlobalVar.VirtualAxisMoveTime);
|
|
|
}
|
|
|
logInfo = GetClassName() + $"排料任务结束到安全位";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
flowStep = EDischargeFlowStep.等待任务结束到安全位;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//MsgBox.ShowAxisAlarmDialog(AxisControl.LoadY, errCode);
|
|
|
alarmEntity = AlarmCollection.Get(AlarmConstID.LoadY运动异常).Transform(errCode.ToString());
|
|
|
AlarmMessageBox.ShowDialog(alarmEntity, ETipButton.Ok, null);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//MsgBox.ShowAxisAlarmDialog(AxisControl.LoadX, errCode);
|
|
|
alarmEntity = AlarmCollection.Get(AlarmConstID.LoadX运动异常).Transform(errCode.ToString());
|
|
|
AlarmMessageBox.ShowDialog(alarmEntity, ETipButton.Ok, null);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
case EDischargeFlowStep.等待任务结束到安全位:
|
|
|
if(Ops.IsStop("LoadX", "LoadY") || GlobalVar.VirtualAxis)
|
|
|
{
|
|
|
if (curNozzle.ToType == TurnoverType.Turnover)
|
|
|
{
|
|
|
if (TestCenter.Instance.LoadResult())
|
|
|
{
|
|
|
logInfo = GetClassName() + $"通知中控任务完成";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
LoadAndUnloadTask.Instance.Clear();
|
|
|
logInfo = GetClassName() + $"任务完成,清除任务";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
MachineManage.Instance.SetLoadUnloadStatus(ERunState.Waiting);
|
|
|
}
|
|
|
}
|
|
|
TurnoverFlow.Instance.CanMoveFromTestTrayToTurnoverTray();
|
|
|
logInfo = GetClassName()+ $"任务结束已回到安全位";
|
|
|
MessageQueue.Instance.Insert(logInfo);
|
|
|
flowStep = EDischargeFlowStep.等待任务;
|
|
|
}
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 判断排料轴是否可以干其他的活
|
|
|
/// </summary>
|
|
|
public void WaitCanMove()
|
|
|
{
|
|
|
while(true)
|
|
|
{
|
|
|
if(flowStep== EDischargeFlowStep.等待任务)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
Thread.Sleep(10);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public void ScanBarCode()
|
|
|
{
|
|
|
SchedulingMessageBox box = new SchedulingMessageBox();
|
|
|
if(GlobalVar.RunSpace)
|
|
|
{
|
|
|
List<TurnoverTraySlot> slots = TurnoverTrayManager.Instance.GetSlots(ETurnoverTraySlotType.WaitTest, ETurnoverTraySlotStatus.Have);
|
|
|
foreach (var slot in slots)
|
|
|
{
|
|
|
LoadAndUnloadTask.Instance.CopyBarcodeToTask(slot.Index - 1, VirtualBarCode.Code);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (LoadAndUnloadTask.Instance.GetUndealedLoadToTurnoverTask().Count == 0)
|
|
|
{
|
|
|
if (GlobalVar.GRR)
|
|
|
{
|
|
|
scanNum++;
|
|
|
}
|
|
|
if (scanNum == 1 || !GlobalVar.GRR)
|
|
|
{
|
|
|
if (GlobalVar.EnableVirtuleBarCode)
|
|
|
{
|
|
|
List<TurnoverTraySlot> slots = TurnoverTrayManager.Instance.GetSlots(ETurnoverTraySlotType.WaitTest, ETurnoverTraySlotStatus.Have);
|
|
|
foreach (var slot in slots)
|
|
|
{
|
|
|
LoadAndUnloadTask.Instance.CopyBarcodeToTask(slot.Index - 1, VirtualBarCode.Code);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//没有需要给周转盘上料的任务后,就开始上相机扫码
|
|
|
//判断周转盘第一行有没有产品,如果有产品则拍第一行
|
|
|
if (TurnoverTrayManager.Instance.HasProduct(ETrayRow.One))
|
|
|
{
|
|
|
//找拍照起点和终点
|
|
|
SlotPoint grabStartPoint = TrayPointManager.GetSlotPoint(ETrayType.Turnover, 1);
|
|
|
SlotPoint grabEndPoint = TrayPointManager.GetSlotPoint(ETrayType.Turnover, 8);
|
|
|
List<VisionResult> result = UpCameraScanBarCodeFlow.Instance.ScanMulti(1, false);
|
|
|
//List<VisionResult> result = UpCameraScanBarCodeFlow.Instance.Wait();
|
|
|
foreach (var vr in result)
|
|
|
{
|
|
|
if (TurnoverTrayManager.Instance.Slot(vr.SlotIndex).IsHasProduct)
|
|
|
{
|
|
|
if (vr.SearchModelOK)//定位成功
|
|
|
{
|
|
|
if (!GlobalVar.EnableScanBarCodeByDownCamera)
|
|
|
{
|
|
|
if (GlobalVar.RunSpace)
|
|
|
{
|
|
|
LoadAndUnloadTask.Instance.CopyBarcodeToTask(vr.SlotIndex - 1, VirtualBarCode.Code);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (vr.ScanBarCodeOK)
|
|
|
{
|
|
|
OnShowGrabResult?.Invoke(vr, true);
|
|
|
//复制二维码
|
|
|
LoadAndUnloadTask.Instance.CopyBarcodeToTask(vr.SlotIndex - 1, vr.SN);
|
|
|
TurnoverTrayManager.Instance.Slot(vr.SlotIndex).SN = vr.SN;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
int failNum = 1;
|
|
|
while (true)
|
|
|
{
|
|
|
if (failNum < 4)
|
|
|
{
|
|
|
//如果扫码失败再重扫一次
|
|
|
VisionResult vrsigle =UpCameraScanBarCodeFlow.Instance.ScanSingle(vr.SlotIndex, true,false,true);
|
|
|
//VisionResult vrsigle = UpCameraScanBarCodeFlow.Instance.WaitSingle();
|
|
|
if (vrsigle.ScanBarCodeOK)
|
|
|
{
|
|
|
OnShowGrabResult?.Invoke(vrsigle, true);
|
|
|
LoadAndUnloadTask.Instance.CopyBarcodeToTask(vr.SlotIndex - 1, vrsigle.SN);
|
|
|
TurnoverTrayManager.Instance.Slot(vr.SlotIndex).SN = vrsigle.SN;
|
|
|
break;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
failNum++;
|
|
|
OnShowGrabResult?.Invoke(vrsigle, true);
|
|
|
//复制二维码
|
|
|
//LoadAndUnloadTask.Instance.CopyBarcodeToTask(vr.SlotIndex - 1, "");
|
|
|
Thread.Sleep(500);
|
|
|
}
|
|
|
if(vrsigle != null)
|
|
|
{
|
|
|
vrsigle=null;
|
|
|
GC.Collect();
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
alarmInfo = string.Format(AlarmCollection.GetAlarm(AlarmConstID.扫码失败), vr.SlotIndex);
|
|
|
Dictionary<ETipButton, string> buttonTexts = new Dictionary<ETipButton, string>() {
|
|
|
{ ETipButton.Retry,"重试|Retry"},
|
|
|
{ ETipButton.Cancel,"自动移走|Auto remove"}
|
|
|
};
|
|
|
box = PromptMessageBox.ShowDialog(AlarmConstID.扫码失败, alarmInfo, ETipButton.Retry | ETipButton.Cancel, buttonTexts);
|
|
|
if (box.Button == ETipButton.Retry)
|
|
|
{
|
|
|
failNum = 1;
|
|
|
}
|
|
|
else if(box.Button== ETipButton.Cancel)
|
|
|
{
|
|
|
//OnShowGrabResult?.Invoke(vrsigle, true);
|
|
|
//复制二维码
|
|
|
LoadAndUnloadTask.Instance.CopyBarcodeToTask(vr.SlotIndex - 1, "");
|
|
|
TurnoverTrayManager.Instance.Slot(vr.SlotIndex).SN = "";
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//定位失败,或者超出指定范围
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
OnShowGrabResult?.Invoke(vr, false);
|
|
|
}
|
|
|
//vr.Dispose();
|
|
|
}
|
|
|
if (result != null && result.Count > 0)
|
|
|
{
|
|
|
result.Clear();
|
|
|
GC.Collect();
|
|
|
}
|
|
|
//OnUpCameraGrabResult?.Invoke(result);
|
|
|
}
|
|
|
//判断周转盘第三行有没有产品,如果有产品则拍第三行
|
|
|
if (TurnoverTrayManager.Instance.HasProduct(ETrayRow.Three))
|
|
|
{
|
|
|
//找拍照起点和终点
|
|
|
SlotPoint grabStartPoint = TrayPointManager.GetSlotPoint(ETrayType.Turnover, 17);
|
|
|
SlotPoint grabEndPoint = TrayPointManager.GetSlotPoint(ETrayType.Turnover, 24);
|
|
|
List<VisionResult> result = UpCameraScanBarCodeFlow.Instance.ScanMulti(24, true);
|
|
|
// List<VisionResult> result = UpCameraScanBarCodeFlow.Instance.Wait();
|
|
|
foreach (var vr in result)
|
|
|
{
|
|
|
if (TurnoverTrayManager.Instance.Slot(vr.SlotIndex).IsHasProduct)
|
|
|
{
|
|
|
|
|
|
if (vr.SearchModelOK)//定位成功
|
|
|
{
|
|
|
if (!GlobalVar.EnableScanBarCodeByDownCamera)
|
|
|
{
|
|
|
if (GlobalVar.RunSpace)
|
|
|
{
|
|
|
LoadAndUnloadTask.Instance.CopyBarcodeToTask(vr.SlotIndex - 1, VirtualBarCode.Code);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (vr.ScanBarCodeOK)
|
|
|
{
|
|
|
OnShowGrabResult?.Invoke(vr, true);
|
|
|
//复制二维码
|
|
|
LoadAndUnloadTask.Instance.CopyBarcodeToTask(vr.SlotIndex - 1, vr.SN);
|
|
|
TurnoverTrayManager.Instance.Slot(vr.SlotIndex).SN = vr.SN;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
int failNum = 1;
|
|
|
while (true)
|
|
|
{
|
|
|
if (failNum < 4)
|
|
|
{
|
|
|
|
|
|
//如果扫码失败再重扫一次
|
|
|
VisionResult vrsigle =UpCameraScanBarCodeFlow.Instance.ScanSingle(vr.SlotIndex, true,false,true);
|
|
|
//VisionResult vrsigle = UpCameraScanBarCodeFlow.Instance.WaitSingle();
|
|
|
if (vrsigle.ScanBarCodeOK)
|
|
|
{
|
|
|
OnShowGrabResult?.Invoke(vrsigle, true);
|
|
|
LoadAndUnloadTask.Instance.CopyBarcodeToTask(vr.SlotIndex - 1, vrsigle.SN);
|
|
|
TurnoverTrayManager.Instance.Slot(vr.SlotIndex).SN = vrsigle.SN;
|
|
|
break;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
failNum++;
|
|
|
OnShowGrabResult?.Invoke(vrsigle, true);
|
|
|
//复制二维码
|
|
|
//LoadAndUnloadTask.Instance.CopyBarcodeToTask(vr.SlotIndex - 1, "");
|
|
|
Thread.Sleep(500);
|
|
|
}
|
|
|
if(vrsigle != null)
|
|
|
{
|
|
|
vrsigle = null;
|
|
|
GC.Collect();
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//box = MsgBox.ShowDialog(AlarmConstID.ScanBarCodeFailAlarm, $"{vr.SlotIndex}穴位扫码失败", ETipButton.Retry | ETipButton.Skip);
|
|
|
alarmInfo = string.Format(AlarmCollection.GetAlarm(AlarmConstID.扫码失败), vr.SlotIndex);
|
|
|
Dictionary<ETipButton, string> buttonTexts = new Dictionary<ETipButton, string>() {
|
|
|
{ ETipButton.Retry,"重试|Retry"},
|
|
|
{ ETipButton.Cancel,"自动移走|Auto remove"}
|
|
|
};
|
|
|
box = PromptMessageBox.ShowDialog(AlarmConstID.扫码失败, alarmInfo, ETipButton.Retry | ETipButton.Cancel, buttonTexts);
|
|
|
if (box.Button == ETipButton.Retry)
|
|
|
{
|
|
|
failNum = 1;
|
|
|
}
|
|
|
else if (box.Button == ETipButton.Cancel)
|
|
|
{
|
|
|
//OnShowGrabResult?.Invoke(vrsigle, true);
|
|
|
//复制二维码
|
|
|
LoadAndUnloadTask.Instance.CopyBarcodeToTask(vr.SlotIndex - 1, "");
|
|
|
TurnoverTrayManager.Instance.Slot(vr.SlotIndex).SN = "";
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//定位失败,或者超出指定范围
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
OnShowGrabResult?.Invoke(vr, false);
|
|
|
}
|
|
|
//vr.Dispose();
|
|
|
}
|
|
|
if (result != null && result.Count > 0)
|
|
|
{
|
|
|
result.Clear();
|
|
|
GC.Collect();
|
|
|
}
|
|
|
//OnUpCameraGrabResult?.Invoke(result);
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 取料完成后更新吸嘴状态
|
|
|
/// </summary>
|
|
|
private void UpdateNozzleStatus(Nozzle nozzle,TurnoverInfo turnoverInfo)
|
|
|
{
|
|
|
nozzle.Status = ENozzleStatus.ToUnload;
|
|
|
//nozzle.FromType = turnoverInfo.FromType;
|
|
|
nozzle.ToType = turnoverInfo.ToType;
|
|
|
nozzle.ToIndex = turnoverInfo.ToIndex;
|
|
|
turnoverInfo.SuckerNo = nozzle.NozzleIndex;
|
|
|
nozzle.TurnoverGUID = turnoverInfo.GUID;
|
|
|
if (turnoverInfo.FromType == TurnoverType.Turnover)
|
|
|
{
|
|
|
TurnoverTrayManager.Instance.Slot(turnoverInfo.FromIndex + 1).ClearProduct();
|
|
|
nozzle.FromFloor = turnoverInfo.FromFloor;
|
|
|
nozzle.SN = turnoverInfo.SN;
|
|
|
//nozzle.FromIndex = turnoverInfo.FromIndex;
|
|
|
GlobalTray.TurnoverTray.ChangeStatus(nozzle.FromIndex + 1, ESlotStatus.NotHave);
|
|
|
}
|
|
|
else if (turnoverInfo.FromType == TurnoverType.ToBeTested)
|
|
|
{
|
|
|
//nozzle.FromFloor = StockManager.Instance.GetStock(ETrayType.Input).GetFloor();
|
|
|
nozzle.SN = "";
|
|
|
//nozzle.FromIndex = GlobalTray.InputTray.GetSlot(ESlotStatus.Have).Index - 1;
|
|
|
GlobalTray.Input1Tray.ChangeStatus(nozzle.FromIndex+1, ESlotStatus.NotHave);
|
|
|
TrayStatusManager.Clear(ETrayType.Input1, nozzle.FromIndex + 1);
|
|
|
}
|
|
|
nozzle.Update();
|
|
|
turnoverInfo.Dealed = true;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取吸嘴取料取不起来时,吸嘴在原取料位的偏移
|
|
|
/// 奇数向下偏移
|
|
|
/// 偶数向上偏移
|
|
|
/// </summary>
|
|
|
/// <param name="fetchNum"></param>
|
|
|
/// <returns></returns>
|
|
|
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;
|
|
|
}
|
|
|
/// <summary>
|
|
|
/// 检测排料Y轴是否可以到周转盘
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
private bool CanGoTurnoverTray()
|
|
|
{
|
|
|
//获取周转Y轴的位置,当排料Y轴去周转盘的时候,检测是否安全
|
|
|
double turnoverYPos = Ops.GetCurPosition("TurnoverY");
|
|
|
if (turnoverYPos - SysConfigParam.GetValue<double>("PressY") < -1)
|
|
|
return false;
|
|
|
return true;
|
|
|
}
|
|
|
/// <summary>
|
|
|
/// 检测XY是否可以去周转盘
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
public bool XYCanGoTurnoverTray()
|
|
|
{
|
|
|
if (!CanGoTurnoverTray())
|
|
|
return false;
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 判断XY是否可以在本区域运动
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
public bool XYCanGoLocalArea()
|
|
|
{
|
|
|
//获取周转Y轴的位置,当排料Y轴去周转盘的时候,检测是否安全
|
|
|
double turnoverYPos = Ops.GetCurPosition("TurnoverY");
|
|
|
if (turnoverYPos - SysConfigParam.GetValue<double>("TurnoverDumpY") < -0.5)
|
|
|
return false;
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
public string GetCurStep()
|
|
|
{
|
|
|
return flowStep.ToString();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 到哪个盘哪个穴位
|
|
|
/// </summary>
|
|
|
/// <param name="trayType"></param>
|
|
|
/// <param name="slotIndex"></param>
|
|
|
/// <returns></returns>
|
|
|
public string WitchTrayWitchSlot(TurnoverType trayType,int slotIndex)
|
|
|
{
|
|
|
return $"{trayType}盘{slotIndex+1}穴位";
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 复位流程步序
|
|
|
/// </summary>
|
|
|
private void ResetFlow()
|
|
|
{
|
|
|
flowStep = EDischargeFlowStep.等待任务;
|
|
|
|
|
|
}
|
|
|
|
|
|
///// <summary>
|
|
|
///// 检测XY是否在目标位置上
|
|
|
///// </summary>
|
|
|
///// <param name="xTargetPos"></param>
|
|
|
///// <param name="yTargetPos"></param>
|
|
|
///// <returns></returns>
|
|
|
//private bool XYIsInTargetPos(double xTargetPos, double yTargetPos)
|
|
|
//{
|
|
|
// Stopwatch timer = new Stopwatch();
|
|
|
// timer.Start();
|
|
|
// while (timer.ElapsedMilliseconds<3000)
|
|
|
// {
|
|
|
// double xCurPos = Ops.GetCurPosition(AxisControl.LoadX);
|
|
|
// double yCurPos = Ops.GetCurPosition(AxisControl.LoadY);
|
|
|
// if ((Math.Abs(xTargetPos - xCurPos) < AxisControl.LoadX.Config.Tolerance
|
|
|
// && Math.Abs(yTargetPos - yCurPos) <AxisControl.LoadY.Config.Tolerance) || GlobalVar.VirtualAxis)
|
|
|
// {
|
|
|
// timer.Stop();
|
|
|
// return true;
|
|
|
// }
|
|
|
// }
|
|
|
// timer.Stop();
|
|
|
// return false;
|
|
|
//}
|
|
|
}
|
|
|
|
|
|
}
|