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.

2188 lines
129 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 HalconDotNet;
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.Space;
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;
}
}
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 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 (WorkEnvironment.Instance.EnvironmentOk)
{
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);
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 = null;
if (Ops.IsOff("2号料仓缺盘光电检测"))
{
slot = GlobalTray.InputTray.GetSlot(ESlotStatus.Have,true);
}
else
{
slot = GlobalTray.InputTray.GetSlot(ESlotStatus.Have);
}
if (slot != null)
{
curSlotPoint = TrayPointManager.GetSlotPoint( ETrayType.Input, slot.Index);
curNozzle.FromIndex= slot.Index-1;
logInfo =GetClassName()+ $"排料{curNozzle.NozzleIndex}号吸嘴到{curTask.FromType.ToString()}盘{curNozzle.FromIndex+1}号穴位取料";
MessageQueue.Instance.Insert(logInfo);
}
else
{
//上料完成后判断是否时最后一盘料
//while (true)
{
if (Ops.IsOff("2号料仓缺盘光电检测"))
{
logInfo = "Input料仓最后一盘料请确认是否继续上料?";
msgBox = MsgBox.ShowDialog(111, logInfo, (ETipButton.Yes | ETipButton.No),new Dictionary<ETipButton, string>() { { ETipButton.Yes, "是|Yes" },{ETipButton.No, "结束上料|EndInput" } });
if (msgBox.Button == ETipButton.Yes)
{
flowStep = EDischargeFlowStep.;
}
else
{
//endInputClicked = true;
//结束上料
TestCenter.Instance.EndInput();
LoadAndUnloadTask.Instance.ClearUndoTask();
if (NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload).Count > 0)
{
flowStep = EDischargeFlowStep.;
}
else
{
if (LoadAndUnloadTask.Instance.GetUnDealedTask().Count > 0)
{
StockTrayToTurnoverTray = !StockTrayToTurnoverTray;
flowStep = EDischargeFlowStep.;
}
else
{
flowStep = EDischargeFlowStep.;
}
}
break;
}
}
else
{
logInfo = GetClassName() + $"{curTask.FromType.ToString()}盘无料,准备切换料盘";
MessageQueue.Instance.Insert(logInfo);
TakeTrayFlow.Instance.Take(ETrayType.Input, ETrayType.Empty1,
() =>
{
Task.Run(() =>
{
StockManager.Instance.GetStock(ETrayType.Input).Load(EStockTrayLoadMode.Whole, null);
});
}, null,
() =>
{
Task.Run(() =>
{
StockManager.Instance.GetStock(ETrayType.Empty1).Unload(EStockTrayUnLoadMode.Whole, null);
});
});
StockManager.Instance.GetStock(ETrayType.Input).WaitFinished();
}
}
break;
}
}
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)
{
targetPos = SysConfigParam.GetValue<Double>($"NozzleR{curNozzle.NozzleIndex}StartPos");
errCode = AxisControl.GetAxis($"NozzleR{curNozzle.NozzleIndex}").MovePos(targetPos, GlobalVar.WholeSpeed);
if (errCode == ErrorCode.Ok | GlobalVar.VirtualAxis)
{
if (GlobalVar.VirtualAxis)
{
Thread.Sleep(GlobalVar.VirtualAxisMoveTime);
}
flowStep = EDischargeFlowStep.;
}
else
{
MsgBox.ShowAxisAlarmDialog($"NozzleR{curNozzle.NozzleIndex}", errCode);
}
}
else
{
MsgBox.ShowAxisAlarmDialog(AxisControl.LoadY, errCode);
}
}
//else
// {
// Msg.ShowError($"吸头 NozzleR{NozzleIndex} 不在起始位,请手动手动回原后运动到起始位");
// }
}
else
{
MsgBox.ShowAxisAlarmDialog(AxisControl.LoadX, errCode);
}
}
}
else
{
logInfo = "x y r move is unsafe";
Msg.ShowError(logInfo);
MessageQueue.Instance.Warn(logInfo);
}
}
break;
case EDischargeFlowStep.:
if (Ops.IsStop("LoadX", "LoadY", $"NozzleR{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
{
logInfo = GetClassName()+$"已运动到{WitchTrayWitchSlot(curNozzle.FromType,curNozzle.FromIndex)}取料位上方";
MessageQueue.Instance.Insert(logInfo);
flowStep = EDischargeFlowStep.;
}
break;
case EDischargeFlowStep.:
if (AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").HomeStatus == EHomeStatus.Finished || GlobalVar.VirtualAxis)
{
if (curTask.FromType == TurnoverType.Turnover)
{
targetPos = 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)
{
targetPos = GetVacOffsetHeight(reFetchNum) + SysConfigParam.GetValue<double>($"TrayNozzle{curNozzle.NozzleIndex}TakeHeight");
}
errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(targetPos, 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);
}
}
else
{
logInfo = GetClassName()+ $"NozzleZ{curNozzle.NozzleIndex} 不在原点,请手动回原后点击确定";
MessageQueue.Instance.Warn(logInfo);
MsgBox.ShowDialog(AlarmConstID.AxisNotAtHomeAlarm, logInfo, ETipButton.Ok);
}
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.:
/*打开排料吸嘴真空吸*/
//Ops.On($"{curNozzle.NozzleIndex}号吸嘴真空吸电磁阀");
//Thread.Sleep(GlobalVar.LoadNozzleOpenVacSuctionDelaytime);
//logInfo = GetClassName()+ $"打开{curNozzle.NozzleIndex}号排料吸嘴真空吸";
//MessageQueue.Instance.Insert(logInfo);
if (curTask.FromType == TurnoverType.Turnover)
{
/*关闭周转盘真空吸*/
//logInfo = GetClassName() + $"关闭周转盘{curTask.FromIndex + 1}号穴位真空吸";
//Ops.Off($"周转盘{curTask.FromIndex + 1}号穴位真空吸");
//Thread.Sleep(GlobalVar.TurnoverTrayCloseVacSuctionDelaytime);
//MessageQueue.Instance.Insert(logInfo);
//VacManager.TurnoverTrayVacSuction(EVacOperator.Close, true, curNozzle.FromIndex+1);
/*打开周转盘真空破*/
//logInfo = GetClassName() + $"打开周转盘{curTask.FromIndex + 1}号穴位真空破";
//Ops.On($"周转盘{curTask.FromIndex + 1}号穴位真空破");
//Thread.Sleep(GlobalVar.TurnoverTrayOpenVacBreakDelaytime);
//MessageQueue.Instance.Insert(logInfo);
VacManager.TurnoverTrayVacBreak( EVacOperator.Open,true,curNozzle.FromIndex + 1);
/*关闭周转盘真空破*/
//logInfo = GetClassName() + $"关闭周转盘{curTask.FromIndex + 1}号穴位真空破";
//Ops.Off($"周转盘{curTask.FromIndex + 1}号穴位真空破");
//Thread.Sleep(GlobalVar.TurnoverTrayCloseVacBreakDelaytime);
//MessageQueue.Instance.Insert(logInfo);
}
else
{
VacManager.DischargeVacSuction(EVacOperator.Open, true, curNozzle.NozzleIndex);
}
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
{
MsgBox.ShowAxisAlarmDialog($"NozzleZ{curNozzle.NozzleIndex}", errCode);
}
break;
case EDischargeFlowStep.:
if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
{
logInfo = GetClassName()+$"取{WitchTrayWitchSlot(curNozzle.FromType, curNozzle.FromIndex)}号穴位产品完成已抬起";
MessageQueue.Instance.Insert(logInfo);
if (curTask.FromType == TurnoverType.Turnover)
{
///周转盘取料抬起后把真空破关闭,这里关破真空不等待
VacManager.TurnoverTrayVacBreak(EVacOperator.Close,false, curNozzle.FromIndex + 1);
}
flowStep = EDischargeFlowStep.;
}
break;
case EDischargeFlowStep.:
if (Ops.IsOn($"{curNozzle.NozzleIndex}号吸嘴真空吸检测") || GlobalVar.RunSpace || GlobalVar.VirtualAxis)
{
reFetchNum = 0;
logInfo = GetClassName()+$"排料吸嘴{curNozzle.NozzleIndex}号真空检测OK";
MessageQueue.Instance.Insert(logInfo);
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);
}
else if(curTask.FromType== TurnoverType.Turnover)
{
alarmInfo = string.Format(AlarmCollection.GetAlarm(AlarmConstID.), 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;
}
//TestCenterMessageBox.Show(AlarmConstID.TrayTakeFailAlarm, alarmInfo, btnText, buttonText);
int alarmid = AlarmConstID.;
if (curTask.FromType == TurnoverType.ToBeTested)
{
alarmid = AlarmConstID.tray;
}
SchedulingMessageBox box = MsgBox.ShowDialog(alarmid, alarmInfo, btnText, buttonText);// TestCenterMessageBox.WaitResult(AlarmConstID.TrayTakeFailAlarm);
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);
}
}
reFetchNum = 0;
flowStep = EDischargeFlowStep.;
break;
case ETipButton.Skip:
SlotProductHasOrNotResult haveProduct = null;
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);
logInfo = GetClassName() + $"上料完成,通知相机拍照,检测产品是否已拿走";
MessageQueue.Instance.Insert(logInfo);
}
haveProduct = UpCameraCheckFlow.Instance.CheckStockTrayHasProduct(ETrayType.Input, curNozzle.FromIndex+1, true);
OnStockTrayProductHasOrNotResult?.Invoke(haveProduct);
}
else if(curTask.FromType== TurnoverType.Turnover)
{
if(GlobalVar.EnableExceptionHandlingNozzle)
{
//首先把排料吸头移动到安全位
if(!DischargeModuleGoSafePosFlow.Instance.IsInSafePostion())
{
DischargeModuleGoSafePosFlow.Instance.GoSafePostion();
}
logInfo = GetClassName()+$"通知强力吸头到{ETrayType.Turnover}盘{curTask.FromIndex}穴位取异常料";
MessageQueue.Instance.Insert(logInfo);
WarningSuckerNgFlow.Instance.DealNgProduct(ETrayType.Turnover, curTask.FromIndex);
WarningSuckerNgFlow.Instance.Wait();
logInfo = GetClassName()+$"{ETrayType.Turnover}盘{curTask.FromIndex}穴位异常料处理完成";
MessageQueue.Instance.Insert(logInfo);
}
else
{
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)
{
GlobalTray.TurnoverTray.ChangeStatus(curTask.FromIndex + 1, ESlotStatus.NotHave);
curTask.Dealed = true;
}
else if (curTask.FromType == TurnoverType.ToBeTested)
{
GlobalTray.InputTray.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}号穴位产品未取出,请处理";
flowStep = EDischargeFlowStep.;
}
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 = 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)
{
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() + $"到下相机拍照起始位";
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();
errCode = AxisControl.LoadX.MovePos(SysConfigParam.GetValue<double>($"Nozzle{needGrabNum}CenterX") - 30, GlobalVar.WholeSpeed);
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
{
errCode = AxisControl.LoadY.MovePos(SysConfigParam.GetValue<double>($"Nozzle8CenterY"), GlobalVar.WholeSpeed);
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
{
flowStep = EDischargeFlowStep.;
}
}
}
else
{
errCode = AxisControl.LoadX.MovePos(SysConfigParam.GetValue<double>("Nozzle1CenterX") + 30, GlobalVar.WholeSpeed);
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
{
errCode = AxisControl.LoadY.MovePos(SysConfigParam.GetValue<double>("Nozzle1CenterY"), GlobalVar.WholeSpeed);
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
{
flowStep = EDischargeFlowStep.;
}
else
{
MsgBox.ShowAxisAlarmDialog(AxisControl.LoadY, errCode);
}
}
else
{
MsgBox.ShowAxisAlarmDialog(AxisControl.LoadX, errCode);
}
}
}
else
{
logInfo = GetClassName() + $"检测到排料吸嘴没有需要下料的产品,任务结束回安全位";
MessageQueue.Instance.Insert(logInfo);
flowStep = EDischargeFlowStep.;
}
}
break;
case EDischargeFlowStep.:
if (Ops.IsStop("LoadX", "LoadY") || GlobalVar.VirtualAxis)
{
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"));
}
}
errCode = AxisControl.LoadX.SetPosCompare(1, grabPoints.ToArray());
if(errCode== ErrorCode.Ok || GlobalVar.VirtualAxis)
{
flowStep = EDischargeFlowStep.;
}
else
{
MsgBox.ShowAxisAlarmDialog(AxisControl.LoadX, errCode);
}
}
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)
{
errCode = AxisControl.LoadX.MovePos(SysConfigParam.GetValue<double>($"Nozzle1CenterX") + 10, GlobalVar.FlyCameraSpeed);
}
else
{
errCode = AxisControl.LoadX.MovePos(SysConfigParam.GetValue<double>($"Nozzle{needGrabNum}CenterX") - 10, GlobalVar.FlyCameraSpeed);
}
if(errCode== ErrorCode.Ok || GlobalVar.VirtualAxis)
{
flowStep = EDischargeFlowStep.;
}
else
{
MsgBox.ShowAxisAlarmDialog(AxisControl.LoadX, errCode);
}
}
break;
case EDischargeFlowStep.:
if (Ops.IsStop("LoadX") || GlobalVar.VirtualAxis)
{
logInfo = GetClassName() + $"已运动到下相机拍照结束位";
MessageQueue.Instance.Insert(logInfo);
if(!GlobalVar.VirtualAxis)
{
AxisControl.LoadX.ClearCompare(1);
}
//IoManager.Instance.WriteOut("下左相机光源触发", 0);
timeout.Restart();
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
{
reGrabCount = 0;
alarmInfo = $"{string.Join(",", errCodeList)}号排料吸嘴拍照失败";
//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);
if (box.Button== ETipButton.Cancel)
{
flowStep = EDischargeFlowStep.;
}
else if (box.Button == 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.InputTray.GetSlot(ESlotStatus.NotHave);
if (downSlot != null)
{
curNozzle.ToIndex = downSlot.Index - 1;
curSlotPoint = TrayPointManager.GetSlotPoint(ETrayType.Input, downSlot.Index);
logInfo = GetClassName() + $"排料吸嘴{curNozzle.NozzleIndex}号到{curNozzle.ToType}盘{curNozzle.ToIndex + 1}号穴位上方";
MessageQueue.Instance.Insert(logInfo);
}
else
{
Task.Run(() => {
StockManager.Instance.GetStock(ETrayType.Input).Unload(EStockTrayUnLoadMode.Whole, null);
});
TakeTrayFlow.Instance.Take(ETrayType.Empty2, ETrayType.Input,
() =>
{
Task.Run(() =>
{
StockManager.Instance.GetStock(ETrayType.Empty2).Load(EStockTrayLoadMode.Whole, null);
});
},
null,
() =>
{
Task.Run(() => {
StockManager.Instance.GetStock(ETrayType.Input).Load(EStockTrayLoadMode.AfterTakeTray, () => {
GlobalTray.GetTray(ETrayType.Input).ChangeStatus(ESlotStatus.NotHave);
});
});
});
StockManager.Instance.GetStock(ETrayType.Input).WaitFinished();
}
}
else if (curNozzle.ToType == TurnoverType.Passed)
{
if (GlobalVar.InputTrayLoop)
{
downSlot = GlobalTray.InputTray.GetSlot(ESlotStatus.NotHave);
}
else
{
downSlot = GlobalTray.OkTary.GetSlot(ESlotStatus.NotHave);
}
if (downSlot != null)
{
curNozzle.ToIndex = downSlot.Index - 1;
if (GlobalVar.InputTrayLoop)
{
curSlotPoint = TrayPointManager.GetSlotPoint(ETrayType.Input, downSlot.Index);
}
else
{
curSlotPoint = TrayPointManager.GetSlotPoint(ETrayType.Ok, downSlot.Index);
}
logInfo = GetClassName() + $"排料吸嘴{curNozzle.NozzleIndex}号到{curNozzle.ToType}盘{curNozzle.ToIndex + 1}号穴位上方";
MessageQueue.Instance.Insert(logInfo);
}
else
{
Task.Run(() => {
StockManager.Instance.GetStock(ETrayType.Ok).Unload(EStockTrayUnLoadMode.Whole, null);
});
TakeTrayFlow.Instance.Take(ETrayType.Empty2, ETrayType.Ok,
() =>
{
Task.Run(() =>
{
StockManager.Instance.GetStock(ETrayType.Empty2).Load(EStockTrayLoadMode.Whole, null);
});
},
null,
() =>
{
Task.Run(() => {
StockManager.Instance.GetStock(ETrayType.Ok).Load(EStockTrayLoadMode.AfterTakeTray, null);
});
});
StockManager.Instance.GetStock(ETrayType.Ok).WaitFinished();
}
}
else if (curNozzle.ToType == TurnoverType.Failed)
{
downSlot = GlobalTray.NgTray.GetSlot(ESlotStatus.NotHave);
if (downSlot != null)
{
curNozzle.ToIndex = downSlot.Index - 1;
curSlotPoint = TrayPointManager.GetSlotPoint(ETrayType.Ng, downSlot.Index);
logInfo = GetClassName() + $"排料吸嘴{curNozzle.NozzleIndex}号到{curNozzle.ToType}盘{curNozzle.ToIndex + 1}号穴位上方";
MessageQueue.Instance.Insert(logInfo);
}
else
{
Task.Run(() => {
StockManager.Instance.GetStock(ETrayType.Ng).Unload(EStockTrayUnLoadMode.Whole, null);
});
TakeTrayFlow.Instance.Take(ETrayType.Empty2, ETrayType.Ng,
() =>
{
Task.Run(() => {
StockManager.Instance.GetStock(ETrayType.Empty2).Load(EStockTrayLoadMode.Whole, null);
});
},
null,
() =>
{
Task.Run(() => {
StockManager.Instance.GetStock(ETrayType.Ng).Load(EStockTrayLoadMode.AfterTakeTray, null);
});
});
StockManager.Instance.GetStock(ETrayType.Ng).WaitFinished();
}
}
else if (curNozzle.ToType == TurnoverType.Multifunction)
{
//如果吸嘴是1并且最后一列
downSlot = GlobalTray.MultiTray.GetSlot(ESlotStatus.NotHave);
#region 为了解决第一个吸嘴到不了最后一列的问题
if (curNozzle.NozzleIndex == 1 && downSlot != null && (downSlot.Column == 0))
{
if (downSlot.Column == 0)
{
downSlot = GlobalTray.MultiTray.GetSlot(downSlot.Index + 1);
}
}
#endregion
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
{
Task.Run(() => {
StockManager.Instance.GetStock(ETrayType.Multi).Unload(EStockTrayUnLoadMode.Whole, null);
});
TakeTrayFlow.Instance.Take(ETrayType.Empty2, ETrayType.Multi,
() =>
{
Task.Run(() => {
StockManager.Instance.GetStock(ETrayType.Empty2).Load(EStockTrayLoadMode.Whole, null);
});
},
null,
() =>
{
Task.Run(() => {
StockManager.Instance.GetStock(ETrayType.Multi).Load(EStockTrayLoadMode.AfterTakeTray, null);
});
});
StockManager.Instance.GetStock(ETrayType.Multi).WaitFinished();
}
}
}
if (curSlotPoint != null)
{
nozzleDist = TrayPointManager.GetDistToNozzle1(curNozzle.NozzleIndex);
if (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;
}
logInfo = $"运动到放料位上方 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
{
MsgBox.ShowAxisAlarmDialog($"NozzleR{curNozzle.NozzleIndex}", errCode);
}
}
else
{
MsgBox.ShowAxisAlarmDialog(AxisControl.LoadY, errCode);
}
}
else
{
MsgBox.ShowAxisAlarmDialog(AxisControl.LoadX, errCode);
}
}
}
else
{
alarmInfo = "x y r move isn't safe";
MessageQueue.Instance.Warn(alarmInfo);
MsgBox.ShowDialog(AlarmConstID.MoveUnsafeAlarm, alarmInfo, ETipButton.Ok);
}
}
break;
case EDischargeFlowStep.:
if (Ops.IsStop("LoadX", "LoadY",$"NozzleR{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
{
//当放料到tray盘区域时并且周转再盘已经没有要下料的穴位时通知周转模组可以运动了
if(curNozzle.ToType!= TurnoverType.Turnover && TurnoverTrayManager.Instance.GetSlots(ETurnoverTraySlotType.Tested, ETurnoverTraySlotStatus.Have).Count()==0)
{
TurnoverFlow.Instance.CanMoveFromTestTrayToTurnoverTray();
}
logInfo = GetClassName()+$"排料吸嘴{curNozzle.NozzleIndex}号已运动到{WitchTrayWitchSlot(curNozzle.ToType,curNozzle.ToIndex)}放料位上方";
MessageQueue.Instance.Insert(logInfo);
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);
}
else
{
alarmInfo = string.Format(AlarmCollection.GetAlarm(AlarmConstID.tray), curNozzle.NozzleIndex,curNozzle.ToType.ToString());
}
alarmid = AlarmConstID.tray;
if (curNozzle.ToType == TurnoverType.Turnover)
{
alarmid = AlarmConstID.;
}
//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);
switch (msgBox.Button)
{
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.;
}
//if (GlobalVar.RunSpace || GlobalVar.VirtualAxis)
//{
// flowStep = EDischargeFlowStep.到放料位下方;
//}
//else
//{
// #region 临时屏蔽
// // //获取所有需要放料的吸嘴,检测真空是否还在,如果真空异常则报警
// // List<Nozzle> lostNozzles = new List<Nozzle>();
// // List<Nozzle> toUnloadNozzles = NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload);
// // if (toUnloadNozzles.Count > 0)
// // {
// // foreach (var nozzle in toUnloadNozzles)
// // {
// // if (!nozzle.HasProduct())
// // {
// // //lostNozzles.Add(nozzle);
// // while (!bSkip)
// // {
// // }
// // }
// // }
// // if (lostNozzles.Count > 0)
// // {
// // bool bSkip = false;
// // while (!bSkip)
// // {
// // //弹框报警
// // alarmInfo = $"检测到{lostNozzles.Select(ln => ln.NozzleIndex).ToJoinString()}吸嘴真空吸异常,可能丢料,请检查吸嘴的状态";
// // TestCenterMessageBox.Show(AlarmConstID.DischargeNozzleLostProductAlarm, alarmInfo, MessageButtonManager.GetSkip_MoveToSafe_Button(), MessageButtonManager.GetSkip_MoveToSafe_ButtonText());
// // msgBox = TestCenterMessageBox.WaitResult(AlarmConstID.DischargeNozzleLostProductAlarm);
// // switch (msgBox.Button)
// // {
// // case ETipButton.Skip:
// // bSkip = true;
// // lostNozzles.ForEach(ln => ln.Reset());
// // break;
// // case ETipButton.Yes:
// // DischargeModuleGoSafePosFlow.Instance.GoSafePostion();
// // break;
// // default:
// // break;
// // }
// // }
// // }
// // else
// // {
// // if (curNozzle.Status == ENozzleStatus.ToUnload)
// // {
// // flowStep = EDischargeFlowStep.到放料位下方;
// // }
// // else
// // {
// // flowStep = EDischargeFlowStep.放料任务完成;
// // }
// // }
// // }
// // else
// // {
// // flowStep = EDischargeFlowStep.放料任务完成;
// // }
// #endregion
//}
break;
//case EDischargeFlowStep.到放料位下方:
// DischargeDumpFlow.Instance.Start(curNozzle.ToType, curNozzle.NozzleIndex, curNozzle.ToIndex);
// flowStep = EDischargeFlowStep.等待放料完成抬起;
// break;
case EDischargeFlowStep.:
if (curNozzle.ToType == TurnoverType.Turnover)
{
targetPos = SysConfigParam.GetValue<double>($"TurnoverNozzle{curNozzle.NozzleIndex}TakeHeight");
/*提前打开周转盘真空吸*/
VacManager.TurnoverTrayVacSuction(EVacOperator.Open, false, curNozzle.ToIndex + 1);
}
else
{
targetPos = SysConfigParam.GetValue<double>($"TrayNozzle{curNozzle.NozzleIndex}TakeHeight") + GlobalVar.DischargeNozzleDumpStockTrayOffsetHeight;
}
errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(targetPos, 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
{
MsgBox.ShowAxisAlarmDialog($"NozzleZ{curNozzle.NozzleIndex}", errCode);
}
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)
{
/*关闭排料吸嘴真空吸*/
//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
{
/*关闭排料吸嘴真空吸*/
//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.;
}
}
break;
case EDischargeFlowStep.:
targetPos = SysConfigParam.GetValue<double>($"TurnoverNozzle{curNozzle.NozzleIndex}TakeHeight")+GlobalVar.DischargeNozzleDumpTurnoverTrayOffset;
errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(targetPos, GlobalVar.WholeSpeed);
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
{
logInfo = GetClassName() + $"排料吸嘴{curNozzle.NozzleIndex}号周转盘放料完成,准备抬起{GlobalVar.DischargeNozzleDumpTurnoverTrayOffset}mm后关闭破真空";
MessageQueue.Instance.Insert(logInfo);
flowStep = EDischargeFlowStep.;
}
else
{
MsgBox.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
{
MsgBox.ShowAxisAlarmDialog($"NozzleZ{curNozzle.NozzleIndex}", errCode);
}
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);
MessageQueue.Instance.Warn(GetClassName() + alarmInfo);
//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);
switch (msgBox.Button)
{
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
{
//如果没有粘料,说明产品放下去了,这个时候用相机检测产品是否在穴位种
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 = MsgBox.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);
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 (GlobalVar.EnableExceptionHandlingNozzle)
{
//排料轴先回到安全位,等待异常处理吸嘴过来处理这颗异常料
DischargeModuleGoSafePosFlow.Instance.GoSafePostion();
WarningSuckerNgFlow.Instance.DealNgProduct(ETrayType.Turnover, curNozzle.ToIndex + 1);
VacManager.TurnoverTrayVacSuction(EVacOperator.Close, true, curNozzle.ToIndex + 1);
curNozzle.Reset();
flowStep = EDischargeFlowStep.;
exit = true;
}
else
{
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(curNozzle.HasProduct())
{
bool skip = false;
while(!skip)
{
//粘料报警,提示用户粘料,移动到安全位,或者点击跳过
//alarmInfo = $"排料{curNozzle.NozzleIndex}号吸嘴可能粘料,请查看吸嘴状态后处理";
alarmInfo = string.Format(AlarmCollection.GetAlarm(AlarmConstID.), curNozzle.NozzleIndex);
MessageQueue.Instance.Warn(GetClassName()+ alarmInfo);
//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);
switch (msgBox.Button)
{
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)
{
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.InputTray.ChangeStatus(curNozzle.ToIndex+1, ESlotStatus.Have);
TrayStatusManager.Fill(ETrayType.Input, curNozzle.ToIndex + 1);
}
else if (curNozzle.ToType == TurnoverType.Passed)
{
if (GlobalVar.InputTrayLoop)
{
curNozzle.ToFloor = StockManager.Instance.GetStock(ETrayType.Input).GetFloor();
GlobalTray.InputTray.ChangeStatus(curNozzle.ToIndex + 1, ESlotStatus.Have);
TrayStatusManager.Fill(ETrayType.Input, curNozzle.ToIndex + 1);
}
else
{
curNozzle.ToFloor = StockManager.Instance.GetStock(ETrayType.Ok).GetFloor();
GlobalTray.OkTary.ChangeStatus(curNozzle.ToIndex + 1, ESlotStatus.Have);
TrayStatusManager.Fill(ETrayType.Ok, curNozzle.ToIndex + 1);
}
}
else if (curNozzle.ToType == TurnoverType.Failed)
{
curNozzle.ToFloor = StockManager.Instance.GetStock(ETrayType.Ng).GetFloor();
GlobalTray.NgTray.ChangeStatus(curNozzle.ToIndex + 1, ESlotStatus.Have);
TrayStatusManager.Fill(ETrayType.Ng, 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)
{
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
TraySlot slot = GlobalTray.InputTray.GetSlot(ESlotStatus.Have);
if (slot != null)
{
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);
}
}
else
{
MsgBox.ShowAxisAlarmDialog(AxisControl.LoadX, errCode);
}
}
else
{
//if(!endInputClicked)
{
//这里检测到料盘种已经没有产品了,需要切盘
bool skip = false;
while (!skip)
{
if (Ops.IsOn("2号料仓缺盘光电检测"))
{
logInfo = GetClassName() + $"{curTask.FromType.ToString()}盘无料,准备切换料盘";
MessageQueue.Instance.Insert(logInfo);
TakeTrayFlow.Instance.Take(ETrayType.Input, ETrayType.Empty1,
() =>
{
Task.Run(() =>
{
StockManager.Instance.GetStock(ETrayType.Input).Load(EStockTrayLoadMode.Whole, null);
});
}, null,
() =>
{
Task.Run(() =>
{
StockManager.Instance.GetStock(ETrayType.Empty1).Unload(EStockTrayUnLoadMode.Whole, null);
});
});
StockManager.Instance.GetStock(ETrayType.Input).WaitFinished();
skip = true;
//logInfo = "Input料仓最后一盘料请确认是否继续上料?";
//msgBox = MsgBox.ShowDialog(111, logInfo, (ETipButton.Yes | ETipButton.No), new Dictionary<ETipButton, string>() { { ETipButton.Yes, "是|Yes" }, { ETipButton.No, "结束上料|EndInput" } });
//if (msgBox.Button == ETipButton.Yes)
//{
// //flowStep = EDischargeFlowStep.到取料位上方;
//}
//else
//{
// //结束上料
// endInputClicked = true;
// TestCenter.Instance.EndInput();
// skip = true;
//}
}
else
{
}
}
}
flowStep = EDischargeFlowStep.;
}
}
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. && Ops.AllZHomed())
{
return;
}
Thread.Sleep(10);
}
}
private 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)
{
//如果扫码失败再重扫一次
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(1000);
}
if(vrsigle != null)
{
vrsigle=null;
GC.Collect();
}
}
else
{
alarmInfo = string.Format(AlarmCollection.GetAlarm(AlarmConstID.), vr.SlotIndex);
box = MsgBox.ShowDialog(AlarmConstID., alarmInfo, ETipButton.Retry | ETipButton.Cancel);
if (box.Button == ETipButton.Retry)
{
failNum = 1;
}
else
{
//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)
{
//如果扫码失败再重扫一次
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(1000);
}
if(vrsigle != null)
{
vrsigle = null;
GC.Collect();
}
}
else
{
box = MsgBox.ShowDialog(AlarmConstID.ScanBarCodeFailAlarm, $"{vr.SlotIndex}穴位扫码失败", ETipButton.Retry | ETipButton.Skip);
if (box.Button == ETipButton.Retry)
{
failNum = 1;
}
else if (box.Button == ETipButton.Skip)
{
//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.InputTray.ChangeStatus(nozzle.FromIndex+1, ESlotStatus.NotHave);
TrayStatusManager.Clear(ETrayType.Input, 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}穴位";
}
}
}