1027 lines
46 KiB
C#
1027 lines
46 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices.WindowsRuntime;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using AR;
|
|
using Chilkat;
|
|
|
|
namespace Project
|
|
{
|
|
public partial class FMain
|
|
{
|
|
public Boolean _RUN_ROOT_SEQUENCE(eWorkPort target, eSMStep cmdIndex)
|
|
{
|
|
UInt16 idx = 1;
|
|
var mv = PUB.Result.vModel;
|
|
var mc = PUB.Result.mModel;
|
|
var funcName = System.Reflection.MethodBase.GetCurrentMethod().Name;
|
|
var seqTime = PUB.sm.seq.GetTime(cmdIndex);
|
|
var msgType = (Class.eStatusMesage)target;
|
|
var item = target == eWorkPort.Left ? PUB.Result.ItemDataL : PUB.Result.ItemDataR;
|
|
//var Jobtype = VAR.STR[eVarString.JOB_TYPE];
|
|
var CVMode = VAR.BOOL[eVarBool.Use_Conveyor];
|
|
|
|
//option check
|
|
var OPT_PrinterOff = PUB.OPT_PRINTEROFF(target);
|
|
var OPT_CameraOff = PUB.OPT_CAMERA();
|
|
var OPT_BYPASS = PUB.OPT_BYPASS();
|
|
|
|
//####################################################
|
|
//### 작업시작
|
|
//####################################################
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
PUB.StatusMessage.set(msgType, $"[{target}] 작업을 시작 합니다");
|
|
|
|
//프린터용 백큠이 켜져있다면 오류로 한다.
|
|
if (target == eWorkPort.Left)
|
|
{
|
|
if (DIO.GetIOOutput(eDOName.PRINTL_AIRON))
|
|
{
|
|
PUB.Result.SetResultMessage(eResult.OPERATION, eECode.NEED_AIROFF_L, eNextStep.PAUSE);
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (DIO.GetIOOutput(eDOName.PRINTR_AIRON))
|
|
{
|
|
PUB.Result.SetResultMessage(eResult.OPERATION, eECode.NEED_AIROFF_R, eNextStep.PAUSE);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//Keyence_Trigger(true);
|
|
PUB.sm.seq.Update(cmdIndex);
|
|
return false;
|
|
}
|
|
|
|
//####################################################
|
|
//### 프린터(Y,Z) 안전위치로
|
|
//####################################################
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
sPositionData PosY, PosZ;
|
|
if (target == eWorkPort.Left)
|
|
{
|
|
PosY = MOT.GetLMPos(eLMLoc.READY);
|
|
PosZ = MOT.GetLZPos(eLZLoc.READY);
|
|
}
|
|
else
|
|
{
|
|
PosY = MOT.GetRMPos(eRMLoc.READY);
|
|
PosZ = MOT.GetRZPos(eRZLoc.READY);
|
|
}
|
|
|
|
//Y축이 준비위가 아닌경우에만 이 처리를 한다.
|
|
if (MOT.getPositionMatch(PosY) == false)
|
|
{
|
|
if (MOT.CheckMotionPos(seqTime, PosZ, funcName) == false) return false;
|
|
if (MOT.CheckMotionPos(seqTime, PosY, funcName) == false) return false;
|
|
}
|
|
|
|
PUB.sm.seq.Update(cmdIndex);
|
|
return false;
|
|
}
|
|
|
|
//####################################################
|
|
//### 로더에 릴이 감지되어있어야 다음 작업을 진행할 수 있음
|
|
//####################################################
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
//Check Port Ready
|
|
if (PUB.flag.get(eVarBool.FG_RDY_PORT_PC) == false && DIO.GetIOInput(eDIName.PORTC_DET_UP) == false) return false;
|
|
|
|
//Check Reel Detect Sensor
|
|
if (DIO.GetIOInput(eDIName.PORTC_DET_UP) == false) return false;
|
|
|
|
//check Reel Limit Sensor
|
|
if (DIO.GetIOInput(eDIName.PORTC_LIM_UP) == true) return false;
|
|
|
|
if (CVMode)
|
|
{
|
|
if (target == eWorkPort.Left)
|
|
{
|
|
if (DIO.GetIOInput(eDIName.L_CONV1)) return false;
|
|
//혹은 컨베이어 가동시간이 5초전이라면 넘어간다 230926
|
|
if (VAR.I32[eVarInt32.LEFT_ITEM_COUNT] > 0)
|
|
{
|
|
if (seqTime.TotalSeconds > 5)
|
|
{
|
|
//if (PUB.flag.get(eVarBool.FG_RDY_CAMERA_L) && PUB.flag.get(eVarBool.VS_DETECT_REEL_L) == false)
|
|
//{
|
|
// //비젼에서 없다고 보고 되어있다면 그대로 진행한다..
|
|
// PUB.log.AddAT($"(L)비전에서 자재가 감지되지 않아 강제 진행 합니다");
|
|
// VAR.I32[eVarInt32.LEFT_ITEM_COUNT] = 0;
|
|
//}
|
|
if (VAR.DBL[eVarDBL.CONVL_RUNTIME] > 15)
|
|
{
|
|
PUB.log.AddE($"(L) Buffer cleared due to conveyor exceeding 15 seconds");
|
|
VAR.I32[eVarInt32.LEFT_ITEM_COUNT] = 0;
|
|
}
|
|
else return false;
|
|
}
|
|
else return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (DIO.GetIOInput(eDIName.R_CONV1)) return false;
|
|
//혹은 컨베이어 가동시간이 5초전이라면 넘어간다 230926
|
|
if (VAR.I32[eVarInt32.RIGT_ITEM_COUNT] > 0)
|
|
{
|
|
if (seqTime.TotalSeconds > 5)
|
|
{
|
|
//if (PUB.flag.get(eVarBool.FG_RDY_CAMERA_R) && PUB.flag.get(eVarBool.VS_DETECT_REEL_R) == false)
|
|
//{
|
|
// //비젼에서 없다고 보고 되어있다면 그대로 진행한다..
|
|
// PUB.log.AddAT($"(r)비전에서 자재가 감지되지 않아 강제 진행 합니다");
|
|
// VAR.I32[eVarInt32.RIGT_ITEM_COUNT] = 0;
|
|
//}
|
|
if (VAR.DBL[eVarDBL.CONVR_RUNTIME] > 15)
|
|
{
|
|
PUB.log.AddE($"(R) Buffer cleared due to conveyor exceeding 15 seconds");
|
|
VAR.I32[eVarInt32.RIGT_ITEM_COUNT] = 0;
|
|
}
|
|
else return false;
|
|
}
|
|
else return false;
|
|
}
|
|
}
|
|
//PUB.log.Add($"CVMODE에서 컨베이어 비어있음(SEQ)");
|
|
}
|
|
|
|
VAR.TIME[(int)eVarTime.JOBEVENT] = DateTime.Now;
|
|
PUB.sm.seq.Update(cmdIndex);
|
|
return false;
|
|
}
|
|
|
|
//####################################################
|
|
//### 피커 사용확인
|
|
//####################################################
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
PUB.StatusMessage.set(msgType, $"[{target}] 피커(X) 사용 권한 확인");
|
|
|
|
if (LockPK.WaitOne(1) == false) return false;
|
|
LockPK.Reset();
|
|
hmi1.AddLockItem((int)target, "PICKER");
|
|
|
|
PUB.mot.ClearPosition((int)eAxis.Z_THETA);
|
|
if (target == eWorkPort.Left)
|
|
{
|
|
//카트가 없으면 동작하지 않게한다.
|
|
PUB.flag.set(eVarBool.FG_RUN_RIGHT, false, funcName);
|
|
PUB.flag.set(eVarBool.FG_RUN_LEFT, true, funcName);
|
|
}
|
|
else
|
|
{
|
|
PUB.flag.set(eVarBool.FG_RUN_LEFT, false, funcName);
|
|
PUB.flag.set(eVarBool.FG_RUN_RIGHT, true, funcName);
|
|
}
|
|
|
|
PUB.sm.seq.Clear(eSMStep.RUN_PICK_RETRY);
|
|
PUB.Result.ItemDataC.VisionData.STime = DateTime.Now;
|
|
PUB.sm.seq.Update(cmdIndex);
|
|
return false;
|
|
}
|
|
|
|
//####################################################
|
|
//### 피커 리딩위치 이동
|
|
//####################################################
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
var PickerRetryCount = AR.VAR.I32[AR.eVarInt32.PickOnRetry];
|
|
//PUB.StatusMessage.set(msgType, $"[{target}] 피커(X) 읽기위치 이동");
|
|
|
|
//비젼이 읽혀지지 않다면 안전위치로 이동시킨다.
|
|
//PUB.log.AddAT("비젼이 읽히지 않은 경우에만 리딩위치로 이동시켜준다");
|
|
|
|
//완료되지않았다면 비켜준다 220920
|
|
if (PUB.Result.ItemDataC.VisionData.Confirm == false)
|
|
{
|
|
|
|
if (PickerRetryCount == 0) //처음작업이다
|
|
{
|
|
sPositionData Pos;
|
|
if (target == eWorkPort.Left)
|
|
{
|
|
//우측을 사용하지 않으면 좌측으로 이동한다
|
|
if (PUB.flag.get(eVarBool.FG_ENABLE_RIGHT) == false) Pos = MOT.GetPXPos(ePXLoc.READYR);
|
|
else Pos = MOT.GetPXPos(ePXLoc.READYL);
|
|
}
|
|
else
|
|
{
|
|
//우측이나 좌측을 사용하지 않으면 좌측으로 이동한다
|
|
if (PUB.flag.get(eVarBool.FG_ENABLE_LEFT) == false) Pos = MOT.GetPXPos(ePXLoc.READYL);
|
|
else Pos = MOT.GetPXPos(ePXLoc.READYR);
|
|
}
|
|
|
|
if (MOT.CheckMotionPos(seqTime, Pos, funcName) == false) return false;
|
|
PUB.log.AddAT($"###### Initial work avoidance movement completed ({target})");
|
|
}
|
|
else
|
|
{
|
|
//재시도 작업이므로 잡아서 79도 돌리는 작업 한다
|
|
if (PICKER_RETRY(target, eSMStep.RUN_PICK_RETRY) == false) return false;
|
|
PUB.sm.seq.Clear(eSMStep.RUN_PICK_RETRY);
|
|
}
|
|
}
|
|
|
|
PUB.sm.seq.Update(cmdIndex);
|
|
return false;
|
|
}
|
|
|
|
//####################################################
|
|
//### 픽온작업용 시퀀스값 초기화
|
|
//####################################################
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
VAR.BOOL[eVarBool.wait_for_keyence] = true;
|
|
if (target == eWorkPort.Left)
|
|
{
|
|
PUB.sm.seq.Clear(eSMStep.RUN_KEYENCE_READ_L);
|
|
PUB.Result.ItemDataL.Clear(funcName);
|
|
VAR.BOOL[eVarBool.wait_for_keyenceR] = false;
|
|
VAR.BOOL[eVarBool.wait_for_keyenceL] = true;
|
|
}
|
|
else
|
|
{
|
|
PUB.sm.seq.Clear(eSMStep.RUN_KEYENCE_READ_R);
|
|
PUB.Result.ItemDataR.Clear(funcName);
|
|
VAR.BOOL[eVarBool.wait_for_keyenceL] = false;
|
|
VAR.BOOL[eVarBool.wait_for_keyenceR] = true;
|
|
}
|
|
|
|
//키엔스데이터 기다리는중
|
|
VAR.BOOL[eVarBool.FG_WAIT_INFOSELECTCLOSE] = false;
|
|
PUB.sm.seq.Update(cmdIndex);
|
|
return false;
|
|
}
|
|
|
|
//####################################################
|
|
//### 키엔스바코드 확인 작업
|
|
//####################################################
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
EResultKeyence Complete = EResultKeyence.Wait;
|
|
if (target == eWorkPort.Left)
|
|
Complete = KEYENCE_READ(target, eSMStep.RUN_KEYENCE_READ_L);
|
|
else
|
|
Complete = KEYENCE_READ(target, eSMStep.RUN_KEYENCE_READ_R);
|
|
|
|
if (Complete == EResultKeyence.Wait)
|
|
{
|
|
//읽을수있도록 좌표를 이동시켜준다
|
|
sPositionData Pos;
|
|
if (target == eWorkPort.Left)
|
|
{
|
|
//우측을 사용하지 않으면 좌측으로 이동한다
|
|
if (PUB.flag.get(eVarBool.FG_ENABLE_RIGHT) == false) Pos = MOT.GetPXPos(ePXLoc.READYR);
|
|
else Pos = MOT.GetPXPos(ePXLoc.READYL);
|
|
}
|
|
else
|
|
{
|
|
//우측이나 좌측을 사용하지 않으면 좌측으로 이동한다
|
|
if (PUB.flag.get(eVarBool.FG_ENABLE_LEFT) == false) Pos = MOT.GetPXPos(ePXLoc.READYL);
|
|
else Pos = MOT.GetPXPos(ePXLoc.READYR);
|
|
}
|
|
|
|
//sPositionData Pos = target == eWorkPort.Left ? MOT.GetPXPos(ePXLoc.READYL) : MOT.GetPXPos(ePXLoc.READYR);
|
|
if (MOT.getPositionMatch(Pos) == false)
|
|
{
|
|
PUB.log.AddAT($"######Avoidance movement II due to no vision data({target})");
|
|
MOT.Move(Pos);
|
|
}
|
|
return false;
|
|
}
|
|
else if (Complete == EResultKeyence.MultiSID)
|
|
{
|
|
//이미 사용자 확인창
|
|
if (PUB.flag.get(eVarBool.FG_WAIT_INFOSELECT))
|
|
{
|
|
//아무것도 하지 않는다
|
|
//사용자가 정보를 설정하는 중
|
|
}
|
|
else {
|
|
|
|
//사용자사 해당 창을 닫았다.
|
|
if (VAR.BOOL[eVarBool.FG_WAIT_INFOSELECTCLOSE] == true & PUB.Result.ItemDataC.VisionData.SID.isEmpty())
|
|
{
|
|
//사용자가 창을 닫았고 SID값이 없다면 오류 처리한다.
|
|
PUB.Result.SetResultMessage(eResult.OPERATION, eECode.NOTSELECTMULTISID, eNextStep.PAUSE);
|
|
VAR.BOOL[eVarBool.FG_WAIT_INFOSELECTCLOSE] = false;
|
|
}
|
|
else
|
|
{
|
|
bool SHowUserFormINF = true;
|
|
|
|
//사용자 확인창을 표시한다
|
|
if (SHowUserFormINF) //다중SID정보 선택건
|
|
{
|
|
this.Invoke(new Action(() =>
|
|
{
|
|
PUB.log.Add("Calling user selection window (INF)");
|
|
var f = new Dialog.fSelectSIDInformation();
|
|
f.Show();
|
|
}));
|
|
}
|
|
}
|
|
|
|
}
|
|
return false;
|
|
}
|
|
else if (Complete == EResultKeyence.TimeOut)
|
|
{
|
|
//이미 사용자 확인창
|
|
if (PUB.flag.get(eVarBool.FG_WAIT_LOADERINFO))
|
|
{
|
|
//아무것도 하지 않는다
|
|
//사용자가 정보를 설정하는 중
|
|
}
|
|
else
|
|
{
|
|
//반복시도횟수가 설정되지 않았거나 최대를 초과하면 사용자 확인창을 띄운다
|
|
bool ShowUserFormBCD = false;
|
|
if (AR.SETTING.Data.RetryPickOnMaxCount == 0)
|
|
{
|
|
PUB.log.Add($"Showing user confirmation window due to no pick-on retry count");
|
|
ShowUserFormBCD = true;
|
|
}
|
|
else if (AR.VAR.I32[AR.eVarInt32.PickOnRetry] >= AR.SETTING.Data.RetryPickOnMaxCount)
|
|
{
|
|
PUB.log.Add($"Pick-on retry count exceeded (Max: {AR.SETTING.Data.RetryPickOnMaxCount})");
|
|
ShowUserFormBCD = true;
|
|
}
|
|
else
|
|
{
|
|
if (VAR.BOOL[eVarBool.Need_UserConfirm_Data])
|
|
{
|
|
PUB.log.Add($"Need to show user confirmation window");
|
|
ShowUserFormBCD = true;
|
|
}
|
|
else
|
|
{
|
|
//읽은데이터가 atkstandard라면 바로 팝업을 띄운다
|
|
if (PUB.Result.ItemDataC.VisionData.SID.isEmpty() || PUB.Result.ItemDataC.VisionData.SID_Trust == false)
|
|
{
|
|
PUB.log.Add($"Retrying pick-on ({AR.VAR.I32[AR.eVarInt32.PickOnRetry]}/{AR.SETTING.Data.RetryPickOnMaxCount})");
|
|
ShowUserFormBCD = false;
|
|
}
|
|
else
|
|
{
|
|
PUB.log.Add($"SID value exists, showing user confirmation window instead of retrying");
|
|
ShowUserFormBCD = true;
|
|
}
|
|
}
|
|
}
|
|
if (ShowUserFormBCD)
|
|
{
|
|
this.Invoke(new Action(() =>
|
|
{
|
|
var itemC = PUB.Result.ItemDataC;
|
|
PUB.log.Add("Calling user confirmation window");
|
|
var f = new Dialog.fLoaderInfo(itemC.VisionData.bcdMessage);
|
|
f.Show();
|
|
}));
|
|
}
|
|
else
|
|
{
|
|
//픽온재시도
|
|
PUB.sm.seq.Clear(eSMStep.RUN_PICK_RETRY);
|
|
VAR.I32[eVarInt32.PickOnRetry] += 1;//, 1);
|
|
VAR.BOOL[eVarBool.JOB_PickON_Retry] = true;
|
|
|
|
PUB.log.Add($"Pick-on retry ({VAR.I32[eVarInt32.PickOnRetry]})");
|
|
PUB.sm.seq.Update(cmdIndex, -2);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//키엔스대기상태를 설정해준다
|
|
VAR.BOOL[eVarBool.wait_for_keyence] = false;
|
|
if (target == eWorkPort.Left) VAR.BOOL[eVarBool.wait_for_keyenceL] = false;
|
|
else VAR.BOOL[eVarBool.wait_for_keyenceR] = false;
|
|
|
|
PUB.Result.ItemDataC.VisionData.ReelSize = DIO.getCartSize(1);
|
|
PUB.log.AddI($"[{target}] Keyence verification completed (Size: {PUB.Result.ItemDataC.VisionData.ReelSize})");
|
|
PUB.log.AddI($"[{target}] Print Position:{PUB.Result.ItemDataC.VisionData.PrintPositionData}");
|
|
|
|
|
|
//픽온작업용 시퀀스값 초기화
|
|
if (target == eWorkPort.Left)
|
|
{
|
|
//프린트Z축을 픽온위치에둔다.
|
|
var PosLM = MOT.GetLZPos(eLZLoc.PICKON);
|
|
MOT.Move(PosLM);
|
|
PUB.sm.seq.Clear(eSMStep.RUN_PICKER_ON_L);
|
|
PUB.sm.seq.Clear(eSMStep.RUN_PRINTER_F);
|
|
PUB.sm.seq.Clear(eSMStep.RUN_PRINTER_ON_F);
|
|
//PUB.sm.seq.Clear(eSMStep.RUN_PRINTER_OFF_F);
|
|
PUB.Result.ItemDataC.CopyTo(ref PUB.Result.ItemDataL);
|
|
PUB.log.Add($"[{target}] Vision data copy (C->L) ID:{PUB.Result.ItemDataL.VisionData.RID}");
|
|
}
|
|
else
|
|
{
|
|
var PosRM = MOT.GetRZPos(eRZLoc.PICKON);
|
|
MOT.Move(PosRM);
|
|
PUB.sm.seq.Clear(eSMStep.RUN_PICKER_ON_R);
|
|
PUB.sm.seq.Clear(eSMStep.RUN_PRINTER_R);
|
|
PUB.sm.seq.Clear(eSMStep.RUN_PRINTER_ON_R);
|
|
//PUB.sm.seq.Clear(eSMStep.RUN_PRINTER_OFF_R);
|
|
PUB.Result.ItemDataC.CopyTo(ref PUB.Result.ItemDataR);
|
|
PUB.log.Add($"[{target}] Vision data copy (C->R) ID:{PUB.Result.ItemDataR.VisionData.RID}");
|
|
}
|
|
|
|
//트리거 OFF
|
|
System.Threading.Tasks.Task.Run(() =>
|
|
{
|
|
if (PUB.keyenceF != null) PUB.keyenceF.Trigger(false);
|
|
if (PUB.keyenceR != null) PUB.keyenceR.Trigger(false);
|
|
});
|
|
|
|
|
|
PUB.log.Add($"[{target}] Print Pos={item.VisionData.PrintPositionData}");
|
|
PUB.sm.seq.Update(cmdIndex);
|
|
return false;
|
|
}
|
|
|
|
//####################################################
|
|
//### 릴아이디 사용 체크 221107
|
|
//####################################################
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
//만약 현재의 바코드가 이전바코드와 동일하다면 오류로 처리한다.
|
|
var pre_ridN = VAR.STR[eVarString.PrePick_ReelIDNew].Trim();
|
|
var pre_ridO = VAR.STR[eVarString.PrePick_ReelIDOld].Trim();
|
|
var pre_targ = VAR.STR[eVarString.PrePick_ReelIDTarget].ToUpper().Trim();
|
|
|
|
var cur_ridN = target == eWorkPort.Left ? PUB.Result.ItemDataL.VisionData.RID : PUB.Result.ItemDataR.VisionData.RID.Trim();
|
|
var cur_ridO = target == eWorkPort.Left ? PUB.Result.ItemDataL.VisionData.RID0 : PUB.Result.ItemDataR.VisionData.RID0.Trim();
|
|
|
|
if (OPT_BYPASS)
|
|
{
|
|
PUB.log.Add($"Bypass mode - skipping previous reel ID check");
|
|
}
|
|
else
|
|
{
|
|
if (pre_ridN.isEmpty() == false) //일단 무조건 신규아이디가 있어야한다
|
|
{
|
|
|
|
//이전과 동일한 ID를 처리했다 오류, 스카이웍스는 본래의 ID를 사용하므로 이곳에서 걸린다
|
|
if (pre_ridN.Equals(cur_ridN))
|
|
{
|
|
if (pre_targ == "LEFT")
|
|
PUB.Result.SetResultMessage(eResult.OPERATION, eECode.PRE_USE_REELID_L, eNextStep.ERROR, target, pre_ridN, cur_ridN);
|
|
else
|
|
PUB.Result.SetResultMessage(eResult.OPERATION, eECode.PRE_USE_REELID_R, eNextStep.ERROR, target, pre_ridN, cur_ridN);
|
|
}
|
|
else
|
|
{
|
|
PUB.log.Add($"New ID usage check OK PRE={pre_ridN},NEW={cur_ridN}");
|
|
|
|
if (pre_ridO.isEmpty() == false && cur_ridO.isEmpty() == false) //구형아이디는 둘다 값이 있을때 처리한다.
|
|
{
|
|
if (pre_ridO.Equals(cur_ridO))
|
|
{
|
|
if (pre_targ == "LEFT")
|
|
PUB.Result.SetResultMessage(eResult.OPERATION, eECode.PRE_USE_REELID_L, eNextStep.ERROR, target, pre_ridO, cur_ridO);
|
|
else
|
|
PUB.Result.SetResultMessage(eResult.OPERATION, eECode.PRE_USE_REELID_R, eNextStep.ERROR, target, pre_ridO, cur_ridO);
|
|
}
|
|
else PUB.log.Add($"New ID usage check (ORG) OK PRE={pre_ridO},NEW={cur_ridO}");
|
|
}
|
|
else
|
|
{
|
|
PUB.log.Add($"New ID usage check (ORG) SKIP (NO DATA) PRE={pre_ridO},NEW={cur_ridO}");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PUB.log.Add($"First work - skipping previous reel ID check");
|
|
}
|
|
|
|
VAR.STR[eVarString.PrePick_ReelIDNew] = cur_ridN;
|
|
VAR.STR[eVarString.PrePick_ReelIDOld] = cur_ridO;
|
|
VAR.STR[eVarString.PrePick_ReelIDTarget] = target.ToString();
|
|
|
|
PUB.log.Add($"Previous work reel ID set values N={cur_ridN},O={cur_ridO}");
|
|
}
|
|
|
|
PUB.sm.seq.Update(cmdIndex);
|
|
return false;
|
|
}
|
|
|
|
//####################################################
|
|
//### bypass check 230510
|
|
//####################################################
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
|
|
|
|
//컨베이어모드에서는 좌측 센서에 릴이 있다면 대기해야한다. 230829
|
|
if (CVMode)
|
|
{
|
|
if (target == eWorkPort.Left)
|
|
{
|
|
if (DIO.GetIOInput(eDIName.L_CONV1)) return false;
|
|
//혹은 컨베이어 가동시간이 5초전이라면 넘어간다 230926
|
|
if (VAR.I32[eVarInt32.LEFT_ITEM_COUNT] > 0) return false;
|
|
//{
|
|
// var cvrun = VAR.DBL[eVarDBL.LEFT_ITEM_PICKOFF];
|
|
// if (cvrun < 6) return false;
|
|
//}
|
|
}
|
|
else
|
|
{
|
|
if (DIO.GetIOInput(eDIName.R_CONV1)) return false;
|
|
//혹은 컨베이어 가동시간이 5초전이라면 넘어간다 230926
|
|
if (VAR.I32[eVarInt32.RIGT_ITEM_COUNT] > 0) return false;
|
|
//{
|
|
// var cvrun = VAR.DBL[eVarDBL.RIGT_ITEM_PICKOFF];
|
|
// if (cvrun < 6) return false;
|
|
//}
|
|
}
|
|
PUB.log.Add($"Conveyor empty in CV MODE (SEQ)");
|
|
}
|
|
|
|
PUB.sm.seq.Update(cmdIndex);
|
|
return false;
|
|
}
|
|
|
|
//####################################################
|
|
//### PICKER ON
|
|
//####################################################
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
bool Complete = false;
|
|
if (target == eWorkPort.Left)
|
|
{
|
|
if (PRINTER(target, eSMStep.RUN_PRINTER_F))
|
|
PRINTER_ON(target, eSMStep.RUN_PRINTER_ON_F);
|
|
Complete = PICKER_ON(target, eSMStep.RUN_PICKER_ON_L);
|
|
}
|
|
else
|
|
{
|
|
if (PRINTER(target, eSMStep.RUN_PRINTER_R))
|
|
PRINTER_ON(target, eSMStep.RUN_PRINTER_ON_R);
|
|
Complete = PICKER_ON(target, eSMStep.RUN_PICKER_ON_R);
|
|
}
|
|
|
|
if (Complete == false) return false;
|
|
//PUB.log.Add($"[{target}] 피커 ON 작업 완료");
|
|
VAR.I32.Clear((int)eVarInt32.PickOnRetry);
|
|
|
|
//픽온작업용 시퀀스값 초기화
|
|
if (target == eWorkPort.Left)
|
|
{
|
|
PUB.sm.seq.Clear(eSMStep.RUN_PICKER_OFF_L);
|
|
//PUB.Result.ItemData[1].CopyTo(ref PUB.Result.ItemData[0]);
|
|
PUB.log.Add($"Barcode data copy (LEFT)");
|
|
|
|
PUB.flag.set(eVarBool.FG_BUSY_LEFT, true, funcName);
|
|
//프린터용 AIR처리해준다.
|
|
DIO.SetPrintLVac(ePrintVac.inhalation);
|
|
DIO.SetPrintLAir(true);
|
|
//PUB.Result.ItemData[1].UpdateTo(ref PUB.Result.ItemData[0]);
|
|
}
|
|
else
|
|
{
|
|
PUB.sm.seq.Clear(eSMStep.RUN_PICKER_OFF_R);
|
|
//PUB.Result.ItemData[1].CopyTo(ref PUB.Result.ItemData[0]);
|
|
PUB.log.Add($"Barcode data copy (RIGHT)");
|
|
|
|
PUB.flag.set(eVarBool.FG_BUSY_RIGHT, true, funcName);
|
|
//프린터용 AIR처리해준다.
|
|
DIO.SetPrintRVac(ePrintVac.inhalation);
|
|
DIO.SetPrintRAir(true);
|
|
//PUB.Result.ItemData[1].UpdateTo(ref PUB.Result.ItemData[2]);
|
|
}
|
|
|
|
PUB.Result.ItemDataC.Clear($"[{target}] Pick-on completed"); //Clear after transmission
|
|
|
|
KeyenceBarcodeDataF = string.Empty;
|
|
KeyenceBarcodeDataR = string.Empty;
|
|
//PUB.log.AddAT($"바코드데이터 삭제(CENTER)");
|
|
|
|
//다음데이터를 읽을 수 있도록 트리거를 전송한다
|
|
System.Threading.Tasks.Task.Run(() =>
|
|
{
|
|
if (PUB.keyenceF != null) PUB.keyenceF.Trigger(true);
|
|
if (PUB.keyenceR != null) PUB.keyenceR.Trigger(true);
|
|
});
|
|
|
|
//Keyence_Trigger(true);
|
|
|
|
//SID목록을 저장한다 231005
|
|
|
|
string sid, prn; sid = prn = "";
|
|
if (target == eWorkPort.Left)
|
|
{
|
|
sid = PUB.Result.ItemDataL.VisionData.SID;
|
|
prn = PUB.Result.ItemDataL.VisionData.PrintPositionData;
|
|
}
|
|
else
|
|
{
|
|
sid = PUB.Result.ItemDataR.VisionData.SID;
|
|
prn = PUB.Result.ItemDataR.VisionData.PrintPositionData;
|
|
}
|
|
|
|
if (sid.isEmpty() == false)
|
|
{
|
|
if (PUB.Result.PrintPostionList.ContainsKey(sid) == false)
|
|
{
|
|
PUB.Result.PrintPostionList.Add(sid, prn);
|
|
PUB.log.AddAT($"Print position saved SID:{sid} = {prn}");
|
|
}
|
|
else
|
|
{
|
|
var predata = PUB.Result.PrintPostionList[sid];
|
|
if (predata != prn)
|
|
{
|
|
PUB.log.AddAT($"Print position save value changed SID:{sid} = {predata} -> {prn}");
|
|
PUB.Result.PrintPostionList[sid] = prn;
|
|
}
|
|
}
|
|
}
|
|
|
|
PUB.sm.seq.Update(cmdIndex);
|
|
return false;
|
|
}
|
|
|
|
//####################################################
|
|
//### PICKER OFF
|
|
//####################################################
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
bool Complete = false;
|
|
if (target == eWorkPort.Left)
|
|
{
|
|
if (PRINTER(target, eSMStep.RUN_PRINTER_F))
|
|
PRINTER_ON(target, eSMStep.RUN_PRINTER_ON_F);
|
|
Complete = PICKER_OFF(target, eSMStep.RUN_PICKER_OFF_L);
|
|
}
|
|
else
|
|
{
|
|
if (PRINTER(target, eSMStep.RUN_PRINTER_R))
|
|
PRINTER_ON(target, eSMStep.RUN_PRINTER_ON_R);
|
|
Complete = PICKER_OFF(target, eSMStep.RUN_PICKER_OFF_R);
|
|
}
|
|
|
|
if (Complete == false) return false;
|
|
|
|
//PUB.log.Add($"[{target}] 피커 OFF 작업 완료");
|
|
PUB.sm.seq.Update(cmdIndex);
|
|
return false;
|
|
}
|
|
|
|
//####################################################
|
|
//### 피커위치로 이동시키고 권한을 넘겨준다
|
|
//####################################################
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
|
|
//프린터와 pickoin 작업을 진행한다
|
|
if (target == eWorkPort.Left)
|
|
{
|
|
if (PRINTER(target, eSMStep.RUN_PRINTER_F))
|
|
PRINTER_ON(target, eSMStep.RUN_PRINTER_ON_F);
|
|
}
|
|
else
|
|
{
|
|
if (PRINTER(target, eSMStep.RUN_PRINTER_R))
|
|
PRINTER_ON(target, eSMStep.RUN_PRINTER_ON_R);
|
|
}
|
|
|
|
//X축 중앙으로 이동
|
|
var Pos = MOT.GetPXPos(ePXLoc.PICKON);
|
|
if (target == eWorkPort.Left && PUB.flag.get(eVarBool.FG_ENABLE_RIGHT) == false)
|
|
Pos = MOT.GetPXPos(ePXLoc.READYR); //우측이 꺼져잇다면 바코드 읽도록 우측으로 비켜준다
|
|
if (target == eWorkPort.Right && PUB.flag.get(eVarBool.FG_ENABLE_LEFT) == false)
|
|
Pos = MOT.GetPXPos(ePXLoc.READYL); //좌측이 꺼져있다면 바코드 읽도록 좌측으로 비켜준다
|
|
|
|
|
|
if (MOT.CheckMotionPos(seqTime, Pos, funcName) == false) return false;
|
|
|
|
//X축을 놓아준다
|
|
LockPK.Set();
|
|
hmi1.RemoveLockItem((int)target, "LD-FRONT");
|
|
PUB.logDbg.Add($"[{target}] X축 권한 해제");
|
|
PUB.mot.ClearPosition((int)eAxis.Z_THETA);
|
|
|
|
//if (target == eWorkShuttle.Left)
|
|
// PUB.sm.seq.Clear(eSMStep.RUN_PRINTER_F);
|
|
//else
|
|
// PUB.sm.seq.Clear(eSMStep.RUN_PRINTER_R);
|
|
|
|
PUB.sm.seq.Update(cmdIndex);
|
|
return false;
|
|
}
|
|
|
|
//####################################################
|
|
//### 프린터
|
|
//####################################################
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
bool Complete = false;
|
|
if (target == eWorkPort.Left)
|
|
Complete = PRINTER(target, eSMStep.RUN_PRINTER_F);
|
|
else
|
|
Complete = PRINTER(target, eSMStep.RUN_PRINTER_R);
|
|
if (Complete == false) return false;
|
|
|
|
//PUB.log.Add($"[{target}] 프린터 작업 완료");
|
|
|
|
//if (target == eWorkShuttle.Left)
|
|
// PUB.sm.seq.Clear(eSMStep.RUN_PRINTER_ON_F);
|
|
//else
|
|
// PUB.sm.seq.Clear(eSMStep.RUN_PRINTER_ON_R);
|
|
|
|
PUB.sm.seq.Update(cmdIndex);
|
|
return false;
|
|
}
|
|
|
|
|
|
//####################################################
|
|
//### 프린터 PICK ON
|
|
//####################################################
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
bool Complete = false;
|
|
if (target == eWorkPort.Left)
|
|
Complete = PRINTER_ON(target, eSMStep.RUN_PRINTER_ON_F);
|
|
else
|
|
Complete = PRINTER_ON(target, eSMStep.RUN_PRINTER_ON_R);
|
|
if (Complete == false) return false;
|
|
|
|
//PUB.log.Add($"[{target}] 프린터 ON 작업 완료");
|
|
|
|
if (target == eWorkPort.Left)
|
|
{
|
|
PUB.sm.seq.Clear(eSMStep.RUN_PRINTER_OFF_F);
|
|
DIO.SetPrintLAir(false);
|
|
}
|
|
else
|
|
{
|
|
PUB.sm.seq.Clear(eSMStep.RUN_PRINTER_OFF_R);
|
|
DIO.SetPrintRAir(false);
|
|
}
|
|
|
|
PUB.sm.seq.Update(cmdIndex);
|
|
return false;
|
|
}
|
|
|
|
|
|
//####################################################
|
|
//### 프린터 PICK OFF
|
|
//####################################################
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
bool Complete = false;
|
|
if (target == eWorkPort.Left)
|
|
Complete = PRINTER_OFF(target, eSMStep.RUN_PRINTER_OFF_F);
|
|
else
|
|
Complete = PRINTER_OFF(target, eSMStep.RUN_PRINTER_OFF_R);
|
|
if (Complete == false) return false;
|
|
|
|
//PUB.log.Add($"[{target}] 프린터 OFF 작업 완료");
|
|
PUB.sm.seq.Update(cmdIndex);
|
|
return false;
|
|
}
|
|
|
|
//####################################################
|
|
//### 프린터(Y,Z) 안전위치로
|
|
//####################################################
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
sPositionData PosZ;
|
|
if (target == eWorkPort.Left)
|
|
{
|
|
PosZ = MOT.GetLZPos(eLZLoc.READY);
|
|
}
|
|
else
|
|
{
|
|
PosZ = MOT.GetRZPos(eRZLoc.READY);
|
|
}
|
|
if (MOT.CheckMotionPos(seqTime, PosZ, funcName) == false) return false;
|
|
|
|
//카메라를 사용한다면 검증해야하니 컨베이어를 멈춘다
|
|
if (OPT_CameraOff == false)
|
|
{
|
|
if (target == eWorkPort.Left)
|
|
PUB.iLockCVL.set((int)eILockCV.VISION, true, funcName);
|
|
else
|
|
PUB.iLockCVR.set((int)eILockCV.VISION, true, funcName);
|
|
}
|
|
|
|
|
|
//Z가 올라갔으니 컨베이어를 돌려도된다
|
|
if (CVMode)
|
|
{
|
|
//카메라를 사용하지 않는다면 바로 OFF 한다
|
|
if (VAR.BOOL[eVarBool.Opt_DisableCamera] == false)
|
|
{
|
|
if (target == eWorkPort.Left)
|
|
PUB.iLockCVL.set((int)eILockCV.BUSY, false, funcName);
|
|
else
|
|
PUB.iLockCVR.set((int)eILockCV.BUSY, false, funcName);
|
|
}
|
|
}
|
|
|
|
PUB.sm.seq.Update(cmdIndex);
|
|
return false;
|
|
}
|
|
|
|
//####################################################
|
|
//### 실리더 원위치 이동시킨다
|
|
//####################################################
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
if (target == eWorkPort.Left)
|
|
{
|
|
DIO.SetOutput(eDOName.PRINTL_FWD, false);
|
|
}
|
|
else
|
|
{
|
|
DIO.SetOutput(eDOName.PRINTR_FWD, false);
|
|
}
|
|
PUB.sm.seq.Update(cmdIndex);
|
|
return false;
|
|
}
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
if (target == eWorkPort.Left)
|
|
{
|
|
if (DIO.checkDigitalO(eDIName.L_PICK_BW, seqTime, true) != eNormalResult.True) return false;
|
|
}
|
|
else
|
|
{
|
|
if (DIO.checkDigitalO(eDIName.R_PICK_BW, seqTime, true) != eNormalResult.True) return false;
|
|
}
|
|
PUB.sm.seq.Update(cmdIndex);
|
|
return false;
|
|
}
|
|
|
|
|
|
//####################################################
|
|
//### 프린터(Y,Z) 안전위치로
|
|
//####################################################
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
sPositionData PosY, PosZ;
|
|
if (target == eWorkPort.Left)
|
|
{
|
|
PosY = MOT.GetLMPos(eLMLoc.READY);
|
|
PosZ = MOT.GetLZPos(eLZLoc.READY);
|
|
PUB.sm.seq.Clear(eSMStep.RUN_QRVALID_F);
|
|
}
|
|
else
|
|
{
|
|
PosY = MOT.GetRMPos(eRMLoc.READY);
|
|
PosZ = MOT.GetRZPos(eRZLoc.READY);
|
|
PUB.sm.seq.Clear(eSMStep.RUN_QRVALID_R);
|
|
}
|
|
if (MOT.CheckMotionPos(seqTime, PosZ, funcName) == false) return false;
|
|
if (MOT.CheckMotionPos(seqTime, PosY, funcName) == false) return false;
|
|
PUB.sm.seq.Update(cmdIndex);
|
|
return false;
|
|
}
|
|
|
|
|
|
//####################################################
|
|
//### QR코드 검증
|
|
//####################################################
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
bool Complete = false;
|
|
|
|
if (OPT_CameraOff) //카메라사용하지 않음
|
|
{
|
|
PUB.log.Add($"QR Validation SKIP:{target} - Camera Off");
|
|
Complete = true;
|
|
item.PrintQRValidResult = "SKIP";
|
|
|
|
|
|
//var sendok = WS_Send(target, WS, item.guid, "TRIG", item.VisionData.PrintQRData);
|
|
}
|
|
else
|
|
{
|
|
if (target == eWorkPort.Left)
|
|
Complete = QR_VALIDATION(target, eSMStep.RUN_QRVALID_F);
|
|
else
|
|
Complete = QR_VALIDATION(target, eSMStep.RUN_QRVALID_R);
|
|
}
|
|
if (Complete == false) return false;
|
|
PUB.log.Add($"QR Validation Complete:{target}");
|
|
|
|
//작업이완료되었다
|
|
if (target == eWorkPort.Left)
|
|
{
|
|
PUB.iLockCVL.set((int)eILockCV.BUSY, false, funcName);
|
|
PUB.iLockCVL.set((int)eILockCV.VISION, false, funcName);
|
|
WS_Send(eWorkPort.Left, PUB.wsL, "", "OFF", "");
|
|
}
|
|
else
|
|
{
|
|
PUB.iLockCVR.set((int)eILockCV.BUSY, false, funcName);
|
|
PUB.iLockCVR.set((int)eILockCV.VISION, false, funcName);
|
|
WS_Send(eWorkPort.Right, PUB.wsR, "", "OFF", "");
|
|
}
|
|
|
|
PUB.sm.seq.Update(cmdIndex);
|
|
return false;
|
|
}
|
|
|
|
|
|
//####################################################
|
|
//### 결과업데이트(22/07/07)
|
|
//####################################################
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
item.JobEnd = DateTime.Now;
|
|
|
|
//전송한다
|
|
var reelsize = "0";
|
|
if (item.VisionData.ReelSize == eCartSize.Inch7) reelsize = "7";
|
|
else if (item.VisionData.ReelSize == eCartSize.Inch13) reelsize = "13";
|
|
var reelinfo = new
|
|
{
|
|
AMKOR_SID = item.VisionData.SID,// tbsid.Text,
|
|
AMKOR_BATCH = item.VisionData.BATCH,// tbbatch.Text,
|
|
LABEL_ID = item.VisionData.RID,// tbrid.Text,
|
|
LABEL_VENDOR_LOT = item.VisionData.VLOT,// tblot.Text,
|
|
LABEL_AMKOR_SID = item.VisionData.SID,// tbsid.Text,
|
|
LABEL_QTY = item.VisionData.QTY,// tbqty.Text,
|
|
LABEL_MANUFACTURER = item.VisionData.VNAME,// tbvname.Text,
|
|
LABEL_PRODUCTION_DATE = item.VisionData.MFGDATE,// tbmfg.Text,
|
|
LABEL_INCH_INFO = reelsize,// tbinch.Text,
|
|
LABEL_PART_NUM = item.VisionData.PARTNO,// tbpart.Text,
|
|
EQP_ID = AR.SETTING.Data.McName,// tbeqid.Text,
|
|
EQP_NAME = $"Auto Label Attach {SETTING.Data.McName}",
|
|
BADGE = string.Empty,
|
|
OPER_NAME = string.Empty,
|
|
CPN = item.VisionData.MCN,
|
|
TARGET = item.VisionData.Target,
|
|
};
|
|
|
|
bool rlt = false;
|
|
string errmsg = string.Empty;
|
|
//var systembypassmode = SETTING PUB.Result.vModel.Title.Equals("BYPASS"); CVMode == true &&
|
|
if (SETTING.Data.SystemBypass == false)
|
|
{
|
|
rlt = PUB.UpdateWMS(item.VisionData); //rlt = Amkor.RestfulService.Inbound_label_attach_reel_info(reelinfo, out errmsg);
|
|
PUB.log.AddE("WMS transmission " + (rlt ? "success" : "failed") + $": {errmsg}");
|
|
if (rlt == false) //230927 - 오류발생시
|
|
{
|
|
PUB.Result.SetResultMessage(eResult.OPERATION, eECode.INBOUNDWEBAPIERROR, eNextStep.PAUSE, target, errmsg);
|
|
return false; ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errmsg = "bypass";
|
|
rlt = false;
|
|
PUB.log.AddAT($"WMS save disabled due to System bypass");
|
|
}
|
|
if (errmsg.Length > 190) errmsg = errmsg.Substring(0, 190); //230810 maxlength error
|
|
SaveData_EE(item, (target == eWorkPort.Left ? "L" : "R"), (rlt ? "OK" : errmsg), "root_sequence");
|
|
//RefreshList(); //목록업데이트
|
|
//EEMStatus.AddStatusCount(1, $"{item.VisionData.SID}|{item.VisionData.RID}"); //eem 추가 230620
|
|
PUB.sm.seq.Update(cmdIndex);
|
|
return false;
|
|
}
|
|
|
|
//####################################################
|
|
//### 다시`` 처음으로 이동
|
|
//####################################################
|
|
if (PUB.sm.seq.Get(cmdIndex) == idx++)
|
|
{
|
|
PUB.StatusMessage.set(msgType, $"[{target}] 전체작업완료 초기화");
|
|
UserStepWait(target);
|
|
|
|
item.Clear($"{target}:{funcName}");
|
|
if (target == eWorkPort.Left)
|
|
{
|
|
PUB.flag.set(eVarBool.FG_BUSY_LEFT, false, funcName);
|
|
}
|
|
else
|
|
{
|
|
PUB.flag.set(eVarBool.FG_BUSY_RIGHT, false, funcName);
|
|
}
|
|
|
|
VAR.TIME[(int)eVarTime.JOBEVENT] = DateTime.Now;
|
|
PUB.log.AddI($"[{target}] Work completed");
|
|
PUB.sm.seq.Clear(cmdIndex);
|
|
return true;
|
|
}
|
|
|
|
PUB.sm.seq.Clear(cmdIndex);
|
|
return true;
|
|
}
|
|
}
|
|
} |