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.

1249 lines
65 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.Camera;
using Rs.Controls;
using Rs.Framework;
using Rs.Motion;
using Rs.MotionPlat.Commom;
using Rs.MotionPlat.Flow.Space;
using Rs.MotionPlat.MsgBox;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Rs.MotionPlat.Flow
{
public enum EWorkFlowStep
{
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
Input,
Input,
Ok,
Ok,
Ng,
Ng,
Multi,
Multi,
IDLE
}
public class WorkFlow : BaseFlow
{
private bool grabOK = false;
private static WorkFlow instance;
public event Action<List<MatchResult>> OnMatchResult;
public static WorkFlow Instance
{
get
{
if (instance == null)
{
instance = new WorkFlow();
}
return instance;
}
}
enum ELoadUnloadAction
{
/// <summary>
/// 上料
/// </summary>
LOAD,
/// <summary>
/// 下料
/// </summary>
UNLOAD
}
private WorkFlow()
{
//HikCamera.Instance.GrabOkEvent += (camIndex,img) => {
// grabOK = true;
//};
}
EWorkFlowStep flowStep = EWorkFlowStep.;
EWorkFlowStep restoreFlowStep = EWorkFlowStep.IDLE;
HObject[] imgs = new HObject[2];
List<MatchResult> mrs = new List<MatchResult>();
int FetchNum = 0;//取料次数
bool bFetchBack = false;
double targetX = 0.0;
double targetY = 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();
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>();
public override void Run()
{
switch (flowStep)
{
case EWorkFlowStep.:
if (LoadAndUnloadTask.Instance.Count > 0 && WorkEnvironment.Instance.EnvironmentOk)
{
if(LoadAndUnloadTask.Instance.CanRunTask())
{
if(LoadAndUnloadTask.Instance.GetTaskNum(ETaskMode.TestLoad)>0)
{
logInfo = $"接收到测试工位上料任务";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
flowStep = EWorkFlowStep.;
}
else if(LoadAndUnloadTask.Instance.GetTaskNum( ETaskMode.TestUnload)>0)
{
logInfo = $"接收到测试工位下料任务";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
flowStep = EWorkFlowStep.;
}
else
{
logInfo = $"接收到排料任务";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
flowStep = EWorkFlowStep.;
}
}
}
break;
case EWorkFlowStep.:
//先取下料任务,再取上料任务,最后取换料任务
if(LoadAndUnloadTask.Instance.GetTaskNum(ETaskMode.Unload)>0)
{
curTask = LoadAndUnloadTask.Instance.GetUnLoadTask();
}
else if(LoadAndUnloadTask.Instance.GetTaskNum( ETaskMode.Load)>0)
{
curTask = LoadAndUnloadTask.Instance.GetLoadTask();
}
else if (LoadAndUnloadTask.Instance.GetTaskNum(ETaskMode.Change) > 0)
{
curTask = LoadAndUnloadTask.Instance.GetChangeTask();
}
curNozzle = NozzleManager.GetIdelNozzle();
if (curTask!=null && curNozzle != null)
{
if (XYCanMove() || GlobalVar.VirtualAxis)
{
curSlotPoint = null;
if (curTask.FromType == TurnoverType.Turnover)
{
logInfo = $"吸嘴 {curNozzle.NozzleIndex} 去周转盘 {curTask.FromIndex + 1} 号穴位取料";
curSlotPoint = TrayPointManager.GetSlotPoint(GlobalVar.CurRecipe, "Turnover", curTask.FromIndex + 1, EPointType.RUN);
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
}
else if (curTask.FromType == TurnoverType.ToBeTested)
{
TraySlot slot = GlobalTray.InputTray.GetSlot(ESlotStatus.Have);
if (slot != null)
{
logInfo = $"吸嘴{curNozzle.NozzleIndex} 去Input盘 {slot.Index} 号穴位取料";
curSlotPoint = TrayPointManager.GetSlotPoint(GlobalVar.CurRecipe, "Input", slot.Index, EPointType.BASE);
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
}
else
{
// Msg.ShowInfo("Input料盘缺料请手动切盘后点击确定");
// GlobalTray.InputTray.ResetTray();
// GlobalTray.InputTray.Fill();
logInfo = "检测到Input料盘无料准备上料盘";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
TakeTrayFlow.Instance.Take(EStockType.Input, EStockType.Empty1, ELoadUnloadType.Unload);
restoreFlowStep = EWorkFlowStep.;
flowStep = EWorkFlowStep.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.GetAxis($"NozzleR{curNozzle.NozzleIndex}").MovePos(SysConfigParam.GetValue<Double>($"NozzleR{curNozzle.NozzleIndex}StartPos"), (int)(GlobalVar.WholeSpeed));
errCode = AxisControl.LoadY.MovePos(targetY, (int)(GlobalVar.WholeSpeed));
if (errCode == ErrorCode.Ok | GlobalVar.VirtualAxis)
{
flowStep = EWorkFlowStep.;
}
}
//else
// {
// Msg.ShowError($"吸头 NozzleR{NozzleIndex} 不在起始位,请手动手动回原后运动到起始位");
// }
}
}
}
else
{
logInfo = "x y move isn't safe";
Msg.ShowError(logInfo);
LogHelper.Error(logInfo);
MessageQueue.Instance.Warn(logInfo);
}
}
break;
case EWorkFlowStep.:
if (Ops.IsStop("LoadX", "LoadY", $"NozzleR{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
{
logInfo = "已运动到取料位上方";
Thread.Sleep(100);
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
flowStep = EWorkFlowStep.;
}
break;
case EWorkFlowStep.:
if(GlobalVar.VirtualAxis)
{
Thread.Sleep(GlobalVar.VirtualAxisMoveTime);
flowStep = EWorkFlowStep.;
}
else
{
if (AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").HomeStatus == EHomeStatus.Finished)
{
logInfo = "准备运动到取料位下方";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
if (curTask.FromType == TurnoverType.Turnover)
{
errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(GetVacOffsetHeight(FetchNum) + SysConfigParam.GetValue<double>($"TurnoverNozzle{curNozzle.NozzleIndex}TakeHeight"), GlobalVar.WholeSpeed);
}
else if (curTask.FromType == TurnoverType.ToBeTested)
{
errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(GetVacOffsetHeight(FetchNum) + SysConfigParam.GetValue<double>($"TrayNozzle{curNozzle.NozzleIndex}TakeHeight"), GlobalVar.WholeSpeed);
}
if (errCode == ErrorCode.Ok)
{
flowStep = EWorkFlowStep.;
}
}
else
{
logInfo = $"NozzleZ{curNozzle.NozzleIndex} 不在原点,请手动回原后点击确定";
Msg.ShowError(logInfo);
LogHelper.Error(logInfo);
}
}
break;
case EWorkFlowStep.:
if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
{
logInfo = "已运动到取料位下方";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
flowStep = EWorkFlowStep.;
}
break;
case EWorkFlowStep.:
if(GlobalVar.VirtualAxis)
{
flowStep = EWorkFlowStep.;
}
else
{
Ops.On($"{curNozzle.NozzleIndex}号吸嘴真空吸电磁阀");
Thread.Sleep(GlobalVar.LoadNozzleOpenVacSuctionDelaytime);
logInfo = $"打开{curNozzle.NozzleIndex}号吸嘴真空吸";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
if (curTask.FromType == TurnoverType.Turnover)
{
logInfo = $"关闭周转盘{curTask.FromIndex + 1}号穴位真空吸";
Ops.Off($"周转盘{curTask.FromIndex + 1}号穴位真空吸");
Thread.Sleep(GlobalVar.TurnoverTrayCloseVacSuctionDelaytime);
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
logInfo = $"打开周转盘{curTask.FromIndex + 1}号穴位真空破";
Ops.On($"周转盘{curTask.FromIndex + 1}号穴位真空破");
Thread.Sleep(GlobalVar.TurnoverTrayOpenVacBreakDelaytime);
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
logInfo = $"关闭周转盘{curTask.FromIndex + 1}号穴位真空破";
Ops.Off($"周转盘{curTask.FromIndex + 1}号穴位真空破");
Thread.Sleep(GlobalVar.TurnoverTrayCloseVacBreakDelaytime);
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
}
flowStep = EWorkFlowStep.;
}
break;
case EWorkFlowStep.:
errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(0, GlobalVar.WholeSpeed);
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
{
logInfo = "取料完成准备抬起";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug (logInfo);
flowStep = EWorkFlowStep.;
}
break;
case EWorkFlowStep.:
if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
{
logInfo = "取料完成已运动到抬起位,准备真空检测";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
flowStep = EWorkFlowStep.;
}
break;
case EWorkFlowStep.:
if (Ops.IsOn($"{curNozzle.NozzleIndex}号吸嘴真空吸检测") || GlobalVar.RunSpace || GlobalVar.VirtualAxis)
{
FetchNum = 0;
logInfo = $"吸嘴{curNozzle.NozzleIndex}真空检测 OK";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
curNozzle.Status = ENozzleStatus.ToUnload;
curNozzle.FromType = curTask.FromType;
curNozzle.ToType = curTask.ToType;
curNozzle.ToIndex = curTask.ToIndex;
curTask.SuckerNo = curNozzle.NozzleIndex ;
curNozzle.TurnoverGUID = curTask.GUID;
if (curTask.FromType == TurnoverType.Turnover)
{
curNozzle.FromFloor = curTask.FromFloor;
curNozzle.SN = curTask.SN;
curNozzle.FromIndex = curTask.FromIndex;
GlobalTray.TurnoverTray.ChangeStatus(curTask.FromIndex+1, ESlotStatus.NotHave);
}
else if (curTask.FromType == TurnoverType.ToBeTested)
{
curNozzle.FromFloor = StockManager.Instance.GetTray(EStockType.Input).GetFloor();
curNozzle.SN = "";
curNozzle.FromIndex = GlobalTray.InputTray.GetSlot(ESlotStatus.Have).Index-1;
GlobalTray.InputTray.ChangeStatus(GlobalTray.InputTray.GetSlot(ESlotStatus.Have).Index, ESlotStatus.NotHave);
}
curNozzle.Update();
curTask.Dealed = true;
int undoTaskNum = LoadAndUnloadTask.Instance.GetTaskNum(curTask.taskMode);
if (undoTaskNum > 0 && NozzleManager.GetNozzlesByStatus(ENozzleStatus.IDLE).Count > 0)
{
logInfo = $"检测到还有{undoTaskNum}条任务未执行,继续执行";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
flowStep = EWorkFlowStep.;
}
else
{
flowStep = EWorkFlowStep.;
}
}
else
{
FetchNum++;
if (FetchNum == 6)
{
//DialogResult dr = Msg.ShowError($"吸嘴{curNozzle.NozzleIndex}取料{FetchNum}次失败报警,请处理后点击确定", MessageBoxButtons.RetryCancel);
CloseResult cr = new TakeFailMsg().ShowMsg($"吸嘴{curNozzle.NozzleIndex}取料{FetchNum}次失败报警,请处理后点击确定");
if (cr.Result == ECloseButton.Retry)
{
FetchNum = 0;
flowStep = EWorkFlowStep.;
}
else if (cr.Result == ECloseButton.Skip)//switch
{
FetchNum = 0;
if (curTask.FromType == TurnoverType.Turnover)
{
GlobalTray.TurnoverTray.ChangeStatus(curTask.FromIndex + 1, ESlotStatus.NotHave);
}
else if (curTask.FromType == TurnoverType.ToBeTested)
{
GlobalTray.InputTray.ChangeStatus(GlobalTray.InputTray.GetSlot(ESlotStatus.Have).Index, ESlotStatus.NotHave);
}
if (LoadAndUnloadTask.Instance.GetTaskNum(curTask.taskMode) > 0 && NozzleManager.GetNozzlesByStatus(ENozzleStatus.IDLE).Count > 0)
{
flowStep = EWorkFlowStep.;
}
else
{
flowStep = EWorkFlowStep.;
}
}
else if(cr.Result== ECloseButton.EndInput)
{
FetchNum = 0;
TestCenter.Instance.EndInput();
LoadAndUnloadTask.Instance.ClearUndoTask();
if(NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload).Count>0)
{
flowStep = EWorkFlowStep.;
}
else
{
flowStep = EWorkFlowStep.;
}
}
else if (cr.Result == ECloseButton.Continue)
{
FetchNum = 0;
curNozzle.Status = ENozzleStatus.ToUnload;
curNozzle.FromType = curTask.FromType;
curNozzle.FromFloor = curTask.FromFloor;
curNozzle.ToType = curTask.ToType;
curNozzle.ToIndex = curTask.ToIndex;
curTask.SuckerNo = curNozzle.NozzleIndex;
curNozzle.TurnoverGUID = curTask.GUID;
if (curTask.FromType == TurnoverType.Turnover)
{
curNozzle.SN = curTask.SN;
curNozzle.FromIndex = curTask.FromIndex;
GlobalTray.TurnoverTray.ChangeStatus(curTask.FromIndex + 1, ESlotStatus.NotHave);
}
else if (curTask.FromType == TurnoverType.ToBeTested)
{
curNozzle.FromIndex = GlobalTray.InputTray.GetSlot(ESlotStatus.Have).Index;
GlobalTray.InputTray.ChangeStatus(GlobalTray.InputTray.GetSlot(ESlotStatus.Have).Index, ESlotStatus.NotHave);
}
curNozzle.Update();
curTask.Dealed = true;
if (LoadAndUnloadTask.Instance.GetTaskNum(curTask.taskMode) > 0 && NozzleManager.GetNozzlesByStatus(ENozzleStatus.IDLE).Count > 0)
{
flowStep = EWorkFlowStep.;
}
else
{
if(GlobalVar.VirtualAxis)
{
foreach (Nozzle nl in NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload))
{
if (string.IsNullOrEmpty(nl.SN))
nl.SN = nl.FromIndex.ToString().PadLeft(18, '0');
//nl.SN = GuidHelper.Create();
}
mrs = new List<MatchResult>();
for (int i = 0; i < needGrabNum; i++)
{
mrs.Add(new MatchResult());
}
flowStep = EWorkFlowStep.;
}
else
{
flowStep = EWorkFlowStep.;
}
}
}
}
else
{
flowStep = EWorkFlowStep.;
}
}
break;
case EWorkFlowStep.:
if (XYCanMove() || GlobalVar.VirtualAxis)
{
logInfo = "到下相机拍照起始位";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(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();
AxisControl.LoadX.MovePos(SysConfigParam.GetValue<double>($"Nozzle{needGrabNum}CenterX") - 30, GlobalVar.WholeSpeed);
AxisControl.LoadY.MovePos(SysConfigParam.GetValue<double>($"Nozzle8CenterY"), GlobalVar.WholeSpeed);
}
else
{
AxisControl.LoadX.MovePos(SysConfigParam.GetValue<double>("Nozzle1CenterX") + 30, GlobalVar.WholeSpeed);
AxisControl.LoadY.MovePos(SysConfigParam.GetValue<double>("Nozzle1CenterY"), GlobalVar.WholeSpeed);
}
flowStep = EWorkFlowStep.;
}
break;
case EWorkFlowStep.:
if (Ops.IsStop("LoadX", "LoadY") || GlobalVar.VirtualAxis)
{
logInfo = "已运动到下相机拍照起始位";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
Thread.Sleep(100);
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 = EWorkFlowStep.;
}
}
break;
case EWorkFlowStep.:
if (XYCanMove() || GlobalVar.VirtualAxis)
{
logInfo = "到下相机拍照结束位";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
IoManager.Instance.WriteOut("下左相机光源触发", 1);
Thread.Sleep(50);
if (NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload)[0].ToType == TurnoverType.Turnover)
{
AxisControl.LoadX.MovePos(SysConfigParam.GetValue<double>($"Nozzle1CenterX") + 10, GlobalVar.FlyCameraSpeed);
}
else
{
AxisControl.LoadX.MovePos(SysConfigParam.GetValue<double>($"Nozzle{needGrabNum}CenterX") - 10, GlobalVar.FlyCameraSpeed);
}
flowStep = EWorkFlowStep.;
}
break;
case EWorkFlowStep.:
Stopwatch stopwatch = new Stopwatch();
if (Ops.IsStop("LoadX") || GlobalVar.VirtualAxis)
{
logInfo = "已运动到下相机拍照结束位";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
if(!GlobalVar.VirtualAxis)
{
AxisControl.LoadX.ClearCompare(1);
}
IoManager.Instance.WriteOut("下左相机光源触发", 0);
flowStep = EWorkFlowStep.;
stopwatch.Start();
}
break;
case EWorkFlowStep.:
imgs = ImageProcess.GetAutoImage();
if ((imgs != null && imgs.Length == needGrabNum)|| GlobalVar.VirtualAxis)
{
logInfo = "相机拍照完成,准备处理照片";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
if (NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload)[0].ToType == TurnoverType.Turnover)
{
imgs = imgs.Reverse().ToArray();
}
if (GlobalVar.RunSpace)
{
foreach(Nozzle nl in NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload))
{
if(string.IsNullOrEmpty(nl.SN))
nl.SN = (nl.FromIndex+1).ToString().PadLeft(18, '0');
//nl.SN = GuidHelper.Create();
}
flowStep = EWorkFlowStep.;
mrs = new List<MatchResult>();
for(int i=0;i<needGrabNum;i++)
{
mrs.Add(new MatchResult());
}
}
else
{
//拍照完成
flowStep = EWorkFlowStep.;
}
}
break;
case EWorkFlowStep.:
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 = "图片处理完成,准备放料";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
//foreach (Nozzle nozzle in NozzleManager.GetNozzles())
//{
// nozzle.SN = Guid.NewGuid().ToString();
//}
int ni = 1;
foreach (MatchResult item in mrs)
{
NozzleManager.GetNozzle(ni).SN = item.SN;
//File.AppendAllText("D://OFFSET.TXT",$"SN:{item.SN},X:{item.OffsetRow},Y:{item.OffsetCol},R:{AngleTool.Rad2Deg(item.Angle)}\r\n");
ni++;
}
reGrabCount = 0;
//CameraOkEvent?.Invoke(imgs, mrs);
OnMatchResult?.Invoke(mrs);
//TestCenter.Instance.EndInput();
flowStep = EWorkFlowStep.;
//Thread.Sleep(2000);
}
else
{
int ni = 1;
List<int> errCodeList = new List<int>();
foreach (MatchResult item in mrs)
{
if(item.IsOK)
{
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 = EWorkFlowStep.;
}
else
{
reGrabCount = 0;
DialogResult dr = Msg.ShowQuestion($"吸嘴{string.Join(",", errCodeList)}扫描失败,点击取消则不再扫码", System.Windows.Forms.MessageBoxButtons.RetryCancel);
if (dr == DialogResult.Cancel)
{
flowStep = EWorkFlowStep.;
}
else if (dr == DialogResult.Retry)
{
Thread.Sleep(1000);
flowStep = EWorkFlowStep.;
}
}
}
break;
case EWorkFlowStep.:
if (XYCanMove() || 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 = "到周转盘放料位上方";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
curSlotPoint = TrayPointManager.GetSlotPoint(GlobalVar.CurRecipe, "Turnover", curNozzle.ToIndex + 1, EPointType.RUN);
turnoverOffsetPoint = TurnoverSlotOffset.GetOffsetPoint(curNozzle.ToIndex + 1);
}
else if (curNozzle.ToType == TurnoverType.ToBeTested)
{
logInfo = "到input盘放料位上方";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
downSlot = GlobalTray.InputTray.GetSlot(ESlotStatus.NotHave);
if (downSlot != null)
{
curSlotPoint = TrayPointManager.GetSlotPoint(GlobalVar.CurRecipe, "Input", downSlot.Index, EPointType.BASE);
}
else
{
Msg.ShowInfo("Input已满请手动切盘后点击确定");
GlobalTray.InputTray.ResetTray();
GlobalTray.InputTray.Clear();
//StockManager.Instance.UnLoad(EStockType.Multi);
//restoreFlowStep = EWorkFlowStep.到放料位上方;
//flowStep = EWorkFlowStep.等待Multi料仓收料完成;
}
}
else if (curNozzle.ToType == TurnoverType.Passed)
{
logInfo = "到Pass盘放料位上方";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
//OK料仓切盘
downSlot = GlobalTray.OkTary.GetSlot(ESlotStatus.NotHave);
if (downSlot != null)
{
curSlotPoint = TrayPointManager.GetSlotPoint(GlobalVar.CurRecipe, "OK", downSlot.Index, EPointType.RUN);
}
else
{
//Msg.ShowInfo("OK料盘已满请手动切盘后点击确定");
//GlobalTray.OkTary.ResetTray();
//GlobalTray.OkTary.Clear();
//TakeTrayFlow.Instance.Take(EStockType.Input, EStockType.Empty1, ELoadUnloadType.Unload);
TakeTrayFlow.Instance.Take(EStockType.Empty2, EStockType.Ok);
StockManager.Instance.UnLoad(EStockType.Ok);
restoreFlowStep = EWorkFlowStep.;
flowStep = EWorkFlowStep.Ok;
}
}
else if (curNozzle.ToType == TurnoverType.Failed)
{
logInfo = "到Ng盘放料位上方";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
downSlot = GlobalTray.NgTray.GetSlot(ESlotStatus.NotHave);
if (downSlot != null)
{
curSlotPoint = TrayPointManager.GetSlotPoint(GlobalVar.CurRecipe, "NG", downSlot.Index, EPointType.RUN);
}
else
{
//Msg.ShowInfo("NG料盘已满请手动切盘后点击确定");
//GlobalTray.NgTray.ResetTray();
//GlobalTray.NgTray.Clear();
TakeTrayFlow.Instance.Take(EStockType.Empty2, EStockType.Ng);
StockManager.Instance.UnLoad(EStockType.Ng);
restoreFlowStep = EWorkFlowStep.;
flowStep = EWorkFlowStep.Ng;
}
}
else if (curNozzle.ToType == TurnoverType.Multifunction)
{
logInfo = "到Multi盘放料位上方";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
downSlot = GlobalTray.MultiTray.GetSlot(ESlotStatus.NotHave);
if (downSlot != null)
{
curSlotPoint = TrayPointManager.GetSlotPoint(GlobalVar.CurRecipe, "Multi", downSlot.Index, EPointType.RUN);
}
else
{
//Msg.ShowInfo("多功能料盘已满,请手动切盘后点击确定!");
//GlobalTray.MultiTray.ResetTray();
//GlobalTray.MultiTray.Clear();
TakeTrayFlow.Instance.Take(EStockType.Empty2, EStockType.Multi);
StockManager.Instance.UnLoad(EStockType.Multi);
restoreFlowStep = EWorkFlowStep.;
flowStep = EWorkFlowStep.Multi;
}
}
}
if (curSlotPoint!=null)
{
nozzleDist = TrayPointManager.GetDistToNozzle1(curNozzle.NozzleIndex);
if(mrs[curNozzle.NozzleIndex - 1].OffsetRow <5 && mrs[curNozzle.NozzleIndex - 1].OffsetCol<5)
{
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;
}
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)
{
flowStep = EWorkFlowStep.;
}
}
}
}
}
else
{
Msg.ShowError("x y move isn't safe");
}
break;
case EWorkFlowStep.:
if (Ops.IsStop("LoadX", "LoadY",$"NozzleR{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
{
Thread.Sleep(100);
logInfo = "已运动到放料位上方";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
flowStep = EWorkFlowStep.;
}
break;
case EWorkFlowStep.:
logInfo = "到放料位下方";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
if (curNozzle.ToType == TurnoverType.Turnover)
{
errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(SysConfigParam.GetValue<double>($"TurnoverNozzle{curNozzle.NozzleIndex}TakeHeight"), GlobalVar.WholeSpeed);
}
else
{
errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(SysConfigParam.GetValue<double>($"TurnoverNozzle{curNozzle.NozzleIndex}TakeHeight") +3, GlobalVar.WholeSpeed);
}
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
{
flowStep = EWorkFlowStep.;
}
break;
case EWorkFlowStep.:
if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
{
logInfo = "已运动到放料位下方";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
if (curNozzle.ToType== TurnoverType.Turnover)
{
Ops.On($"周转盘{curNozzle.ToIndex + 1}号穴位真空吸");
Thread.Sleep(GlobalVar.TurnoverTrayOpenVacSuctionDelaytime);
Ops.Off($"{curNozzle.NozzleIndex}号吸嘴真空吸电磁阀");//关闭真空
Thread.Sleep(GlobalVar.LoadNozzleCloseVacSuctionDelaytime);
Ops.On($"{curNozzle.NozzleIndex}号吸嘴真空破电磁阀");
Thread.Sleep(GlobalVar.LoadNozzleOpenVacBreakDelaytime);
Ops.Off($"{curNozzle.NozzleIndex}号吸嘴真空破电磁阀");
Thread.Sleep(GlobalVar.LoadNozzleCloseVacBreakDelaytime);
flowStep = EWorkFlowStep.;
}
else
{
Ops.Off($"{curNozzle.NozzleIndex}号吸嘴真空吸电磁阀");
Thread.Sleep(GlobalVar.LoadNozzleCloseVacSuctionDelaytime);
Ops.On($"{curNozzle.NozzleIndex}号吸嘴真空破电磁阀");
Thread.Sleep(GlobalVar.LoadNozzleOpenVacBreakDelaytime);
Ops.Off($"{curNozzle.NozzleIndex}号吸嘴真空破电磁阀");
Thread.Sleep(GlobalVar.LoadNozzleCloseVacBreakDelaytime);
flowStep = EWorkFlowStep.;
}
}
break;
//case EWorkFlowStep.到放料破真空位:
// errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(SysConfigParam.GetValue<double>($"TurnoverNozzle{curNozzle.NozzleIndex}TakeHeight")+1, GlobalVar.WholeSpeed);
// if (errCode == ErrorCode.Ok)
// {
// flowStep = EWorkFlowStep.等待到放料破真空位;
// }
// break;
//case EWorkFlowStep.等待到放料破真空位:
// if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}"))
// {
// flowStep = EWorkFlowStep.周转盘放料位真空检测;
// }
// break;
//case EWorkFlowStep.周转盘放料位真空检测:
// if (curNozzle.ToType == TurnoverType.Turnover)
// {
// Thread.Sleep(100);
// if(Ops.IsOn($"周转盘{curNozzle.ToIndex + 1}号穴位真空吸检测") || GlobalVar.RunSpace)
// {
// flowStep = EWorkFlowStep.放料完成抬起;
// }
// else
// {
// DialogResult dr = Msg.ShowError($"周转盘{curNozzle.ToIndex + 1}号穴位真空吸异常,点击确定后跳过");
// if (dr == DialogResult.OK)
// {
// flowStep = EWorkFlowStep.放料完成抬起;
// }
// }
// }
// break;
case EWorkFlowStep.:
errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(0, GlobalVar.WholeSpeed);
if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis)
{
logInfo = "放料完成抬起";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
flowStep = EWorkFlowStep.;
}
break;
case EWorkFlowStep.:
if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis)
{
logInfo = "放料完成已运动到抬起位,准备真空检测";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
flowStep = EWorkFlowStep.;
}
break;
case EWorkFlowStep.:
if (curNozzle.ToType == TurnoverType.Turnover)
{
if (Ops.IsOn($"周转盘{curNozzle.ToIndex + 1}号穴位真空吸检测") || GlobalVar.RunSpace)
{
logInfo = $"周转盘{curNozzle.ToIndex + 1}号穴位真空吸检测 OK";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
flowStep = EWorkFlowStep.;
}
else
{
logInfo = $"放料时周转盘{curNozzle.ToIndex + 1}号穴位真空吸异常";
MessageQueue.Instance.Warn(logInfo);
LogHelper.Debug(logInfo);
DialogResult dr = Msg.ShowError($"周转盘{curNozzle.ToIndex + 1}号穴位真空吸异常,点击确定后跳过");
if (dr == DialogResult.OK)
{
flowStep = EWorkFlowStep.;
}
}
}
else
{
flowStep = EWorkFlowStep.;
}
break;
case EWorkFlowStep.:
logInfo = "放料任务完成";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").Home();
//Ops.HomeAndGoStartPos($"NozzleR{NozzleIndex}");
if (curNozzle.ToType == TurnoverType.Turnover)
{
GlobalTray.TurnoverTray.ChangeStatus(curNozzle.ToIndex + 1, ESlotStatus.Have);
}
else if (curNozzle.ToType == TurnoverType.ToBeTested)
{
curNozzle.ToIndex = downSlot.Index-1;
curNozzle.ToFloor = StockManager.Instance.GetTray(EStockType.Input).GetFloor();
GlobalTray.InputTray.ChangeStatus(downSlot.Index, ESlotStatus.Have);
}
else if (curNozzle.ToType == TurnoverType.Passed)
{
curNozzle.ToIndex = downSlot.Index-1;
curNozzle.ToFloor = StockManager.Instance.GetTray(EStockType.Ok).GetFloor();
GlobalTray.OkTary.ChangeStatus(downSlot.Index, ESlotStatus.Have);
}
else if (curNozzle.ToType == TurnoverType.Failed)
{
curNozzle.ToIndex = downSlot.Index-1;
curNozzle.ToFloor = StockManager.Instance.GetTray(EStockType.Ng).GetFloor();
GlobalTray.NgTray.ChangeStatus(downSlot.Index, ESlotStatus.Have);
}
else if (curNozzle.ToType == TurnoverType.Multifunction)
{
curNozzle.ToIndex = downSlot.Index-1;
curNozzle.ToFloor = StockManager.Instance.GetTray(EStockType.Multi).GetFloor();
GlobalTray.MultiTray.ChangeStatus(downSlot.Index, ESlotStatus.Have);
}
curNozzle.Reset();
Thread.Sleep(100);
LoadAndUnloadTask.Instance.AddTurnoverResult(curNozzle);
if (NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload).Count > 0)
{
flowStep = EWorkFlowStep.;
}
else
{
if (LoadAndUnloadTask.Instance.GetUnDealedTask().Count > 0)
{
flowStep = EWorkFlowStep.;
}
else
{
flowStep = EWorkFlowStep.;
}
}
break;
case EWorkFlowStep.:
logInfo = "任务结束到安全位";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
errCode = AxisControl.LoadX.MovePos(SysConfigParam.GetValue<double>("LoadXStartPos"), GlobalVar.WholeSpeed);
if(errCode== ErrorCode.Ok || GlobalVar.VirtualAxis)
{
errCode = AxisControl.LoadY.MovePos(SysConfigParam.GetValue<double>("LoadYStartPos"), GlobalVar.WholeSpeed);
if(errCode== ErrorCode.Ok || GlobalVar.VirtualAxis)
{
flowStep = EWorkFlowStep.;
}
}
break;
case EWorkFlowStep.:
if(Ops.IsStop("LoadX", "LoadY") || GlobalVar.VirtualAxis)
{
logInfo = "任务结束已回到安全位";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
if (TestCenter.Instance.LoadResult())
{
logInfo = "通知中控任务完成";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
LoadAndUnloadTask.Instance.Clear();
logInfo = "任务完成,清除任务";
MessageQueue.Instance.Insert(logInfo);
LogHelper.Debug(logInfo);
}
MachineManage.Instance.SetLoadUnloadStatus(ERunState.Waiting);
flowStep = EWorkFlowStep.;
}
break;
case EWorkFlowStep.:
testLoadList = LoadAndUnloadTask.Instance.GetTestLoadTasks();
TurnoverFlow.Instance.PressLoad(testLoadList);
flowStep = EWorkFlowStep.;
break;
case EWorkFlowStep.:
if (TurnoverFlow.Instance.LoadFinished())
{
TestCenter.Instance.LoadTestLoadResult();
//切换穴位状态
foreach (TurnoverInfo turnoverInfo in testLoadList)
{
GlobalTray.TurnoverTray.ChangeStatus(turnoverInfo.FromIndex+1, ESlotStatus.NotHave);
}
LoadAndUnloadTask.Instance.Clear();
MachineManage.Instance.SetLoadUnloadStatus(ERunState.Waiting);
//for (int i = 1; i < 9; i++)
//{
// GlobalTray.TurnoverTray.ChangeStatus(i, ESlotStatus.NotHave);
//}
//for (int i = 17; i < 25; i++)
//{
// GlobalTray.TurnoverTray.ChangeStatus(i, ESlotStatus.NotHave);
//}
flowStep = EWorkFlowStep.;
}
break;
case EWorkFlowStep.:
testUnLoadList = LoadAndUnloadTask.Instance.GetTestUnLoadTasks();
TurnoverFlow.Instance.PressUnload(testUnLoadList);
flowStep = EWorkFlowStep.;
break;
case EWorkFlowStep.:
if (TurnoverFlow.Instance.UnloadFinished())
{
//logInfo = string.Join(",",testUnLoadList.Select(t=>t.ToIndex).ToList());
TestCenter.Instance.LoadTestUnLoadResult();
//切换穴位状态
foreach (TurnoverInfo turnoverInfo in testUnLoadList)
{
GlobalTray.TurnoverTray.ChangeStatus(turnoverInfo.ToIndex+1, ESlotStatus.Have);
}
LoadAndUnloadTask.Instance.Clear();
//for (int i = 9; i < 17; i++)
//{
// GlobalTray.TurnoverTray.ChangeStatus(i, ESlotStatus.Have);
//}
//for (int i = 25; i < 33; i++)
//{
// GlobalTray.TurnoverTray.ChangeStatus(i, ESlotStatus.Have);
//}
MachineManage.Instance.SetLoadUnloadStatus(ERunState.Waiting);
flowStep = EWorkFlowStep.;
}
break;
case EWorkFlowStep.Input:
if(TakeTrayFlow.Instance.TakeStatus== ETakeStatus.TakeOK)
{
StockManager.Instance.UnLoad(EStockType.Empty1);
StockManager.Instance.Load(EStockType.Input);
flowStep = EWorkFlowStep.Input;
}
break;
case EWorkFlowStep.Input:
if(StockManager.Instance.GetStockStatus(EStockType.Input)== AutoDischarge.V3.Flow.ETrayStatus.Loaded)
{
flowStep = restoreFlowStep;
restoreFlowStep = EWorkFlowStep.IDLE;
}
break;
case EWorkFlowStep.Ok:
if(StockManager.Instance.GetStockStatus( EStockType.Ok)== AutoDischarge.V3.Flow.ETrayStatus.Unloaded)
{
flowStep = EWorkFlowStep.Ok;
TakeTrayFlow.Instance.Take(EStockType.Empty2, EStockType.Ok);
}
break;
case EWorkFlowStep.Ok:
if(TakeTrayFlow.Instance.TakeStatus== ETakeStatus.TakeOK && StockManager.Instance.GetStockStatus( EStockType.Ok)== AutoDischarge.V3.Flow.ETrayStatus.Loaded)
{
flowStep = restoreFlowStep;
restoreFlowStep = EWorkFlowStep.IDLE;
}
break;
case EWorkFlowStep.Ng:
if (StockManager.Instance.GetStockStatus(EStockType.Ng) == AutoDischarge.V3.Flow.ETrayStatus.Unloaded)
{
flowStep = EWorkFlowStep.Ng;
TakeTrayFlow.Instance.Take(EStockType.Empty2, EStockType.Ng);
}
break;
case EWorkFlowStep.Ng:
if (TakeTrayFlow.Instance.TakeStatus == ETakeStatus.TakeOK && StockManager.Instance.GetStockStatus(EStockType.Ng) == AutoDischarge.V3.Flow.ETrayStatus.Loaded)
{
flowStep = restoreFlowStep;
restoreFlowStep = EWorkFlowStep.IDLE;
}
break;
case EWorkFlowStep.Multi:
if (StockManager.Instance.GetStockStatus(EStockType.Multi) == AutoDischarge.V3.Flow.ETrayStatus.Unloaded)
{
flowStep = EWorkFlowStep.Multi;
TakeTrayFlow.Instance.Take(EStockType.Empty2, EStockType.Multi);
}
break;
case EWorkFlowStep.Multi:
if (TakeTrayFlow.Instance.TakeStatus == ETakeStatus.TakeOK && StockManager.Instance.GetStockStatus(EStockType.Multi) == AutoDischarge.V3.Flow.ETrayStatus.Loaded)
{
flowStep = restoreFlowStep;
restoreFlowStep = EWorkFlowStep.IDLE;
}
break;
default:
break;
}
}
private double GetVacOffsetHeight(int fetchNum)
{
switch (fetchNum)
{
case 0:
return 0;
case 1:
return -0.1;
case 2:
return -0.2;
case 3:
return -0.3;
case 4:
return 0.1;
case 5:
return 0.2;
case 6:
return 0.3;
default:
return 0;
}
}
/// <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;
}
private bool XYCanMove()
{
if (!CanGoTurnoverTray())
return false;
//AxisControl.VacZ1.GetOrgStatus(out bool bOrgZ1);
//AxisControl.VacZ2.GetOrgStatus(out bool bOrgZ2);
//if (AxisControl.LoadX.HomeStatus == EHomeStatus.Finished
// && AxisControl.LoadY.HomeStatus == EHomeStatus.Finished
// && bOrgZ1 && bOrgZ2)
//{
// return true;
//}
return true;
}
}
}