CheckScannerList report -> jigComplete로 변경

This commit is contained in:
최민영 2026-04-08 19:15:20 +09:00
commit f1908696b5

View File

@ -43,10 +43,8 @@ using static ILSOS_CCW_H52A.Device.IOController_CCW_H52A;
using static ILSOS_CCW_H52A.Device.PLCControllerCCWH52A; using static ILSOS_CCW_H52A.Device.PLCControllerCCWH52A;
using static ILSOS_CCW_H52A.Device.ScannerListCCWH52A; using static ILSOS_CCW_H52A.Device.ScannerListCCWH52A;
namespace ILSOS_CCW_H52A.Sequences namespace ILSOS_CCW_H52A.Sequences {
{ class SeqAutoRunCCWH52A {
class SeqAutoRunCCWH52A
{
static readonly Logger Log = new Logger("SeqAutoRunCCWH52A"); static readonly Logger Log = new Logger("SeqAutoRunCCWH52A");
const string SEQ_ENTER = "[SeqAutoRunCCWH52A] SEQ_ENTER"; // inputParam 으로 받자. const string SEQ_ENTER = "[SeqAutoRunCCWH52A] SEQ_ENTER"; // inputParam 으로 받자.
@ -89,8 +87,7 @@ namespace ILSOS_CCW_H52A.Sequences
const string SEQ_INIT_CONDITION_ERROR = "[SeqAutoRunCCWH52A] Init Condition Error"; const string SEQ_INIT_CONDITION_ERROR = "[SeqAutoRunCCWH52A] Init Condition Error";
const string SEQ_COMPLETE = "[SeqAutoRunCCWH52A] SEQ_COMPLETE"; // 완료 const string SEQ_COMPLETE = "[SeqAutoRunCCWH52A] SEQ_COMPLETE"; // 완료
static class ContextKey static class ContextKey {
{
public const string KEY_SEQUENCE_RESULT = "KEY_SEQUENCE_RESULT_SeqAutoRunCCWH52A"; public const string KEY_SEQUENCE_RESULT = "KEY_SEQUENCE_RESULT_SeqAutoRunCCWH52A";
public const string KEY_SEQUENCE_START_TIME = "KEY_SEQUENCE_START_TIME_SeqAutoRunCCWH52A"; public const string KEY_SEQUENCE_START_TIME = "KEY_SEQUENCE_START_TIME_SeqAutoRunCCWH52A";
public const string KEY_SEQUENCE_ERROR_CODE = "KEY_SEQUENCE_ERROR_CODE_SeqAutoRunCCWH52A"; public const string KEY_SEQUENCE_ERROR_CODE = "KEY_SEQUENCE_ERROR_CODE_SeqAutoRunCCWH52A";
@ -145,8 +142,7 @@ namespace ILSOS_CCW_H52A.Sequences
private bool UsePlcShotThemAll { get; set; } = false; private bool UsePlcShotThemAll { get; set; } = false;
private bool UsePlcPositionCompensation { get; set; } = false; private bool UsePlcPositionCompensation { get; set; } = false;
private string RecipeFileName { get; set; } = ""; private string RecipeFileName { get; set; } = "";
private enum InitErrorList private enum InitErrorList {
{
SUCCESS = 0, SUCCESS = 0,
LBAD_CLIENT_ACTIVATE_FAILED, LBAD_CLIENT_ACTIVATE_FAILED,
LBAD_SUB_ACTIVATE_FAILED, LBAD_SUB_ACTIVATE_FAILED,
@ -155,8 +151,7 @@ namespace ILSOS_CCW_H52A.Sequences
MOTF_OFF, MOTF_OFF,
PLC_ALARM, PLC_ALARM,
} }
public SequenceBuilder Builder() public SequenceBuilder Builder() {
{
var sb = new SequenceBuilder(1000, true); var sb = new SequenceBuilder(1000, true);
sb.AddAction(SEQ_ENTER, Sequence_Enter); sb.AddAction(SEQ_ENTER, Sequence_Enter);
@ -257,8 +252,7 @@ namespace ILSOS_CCW_H52A.Sequences
return sb; return sb;
} }
private SequenceActionResult Sequence_Enter(SequenceContext context, string id, SequenceActionResult param) private SequenceActionResult Sequence_Enter(SequenceContext context, string id, SequenceActionResult param) {
{
Log.I("SeqAutoRunCCWH52A Start"); Log.I("SeqAutoRunCCWH52A Start");
Status.SetWorkingPosition(eWorkingPosition.CHECKING_CONDITION); Status.SetWorkingPosition(eWorkingPosition.CHECKING_CONDITION);
@ -267,22 +261,19 @@ namespace ILSOS_CCW_H52A.Sequences
_SystemParameter = context.GetSetting<SystemParameter>(CommonSettingIds.SystemParameter); _SystemParameter = context.GetSetting<SystemParameter>(CommonSettingIds.SystemParameter);
InitDev(context); InitDev(context);
if (!CheckDeviceReady(context)) if (!CheckDeviceReady(context)) {
{
//Check Device //Check Device
Log.E("The devices are not active."); Log.E("The devices are not active.");
return SequenceAction.ForceStopByAlarm(AlarmCode.ALARM_SEQUENCE_AutoRun_DeviceNotReady); return SequenceAction.ForceStopByAlarm(AlarmCode.ALARM_SEQUENCE_AutoRun_DeviceNotReady);
} }
if (InitSequenceVariable(context) == false) if (InitSequenceVariable(context) == false) {
{
return SequenceAction.ForceStopByAlarm(AlarmCode.ALARM_SEQUENCE_AutoRun_InitVariableError); return SequenceAction.ForceStopByAlarm(AlarmCode.ALARM_SEQUENCE_AutoRun_InitVariableError);
} }
Thread.Sleep(1); // 부하 방지 Thread.Sleep(1); // 부하 방지
return SequenceAction.Ok(); return SequenceAction.Ok();
} }
private bool InitSequenceVariable(SequenceContext context) private bool InitSequenceVariable(SequenceContext context) {
{
_AutoRunStartTime = DateTime.Now; _AutoRunStartTime = DateTime.Now;
var ActivateRecipeName = _RecipeManager.ActivatedRecipe(); var ActivateRecipeName = _RecipeManager.ActivatedRecipe();
@ -301,13 +292,11 @@ namespace ILSOS_CCW_H52A.Sequences
return true; return true;
} }
private void InitDev(SequenceContext context) private void InitDev(SequenceContext context) {
{
//Device Init //Device Init
_Scanner = context.GetLaserScanner(); _Scanner = context.GetLaserScanner();
_Laser = context.GetLaser(); _Laser = context.GetLaser();
if (_InitParam.UseStream) if (_InitParam.UseStream) {
{
_StreamLightLBAD = new StreamLightLBAD(); _StreamLightLBAD = new StreamLightLBAD();
_StreamLightLBAD._Client = context.GetStreamLightClient(); _StreamLightLBAD._Client = context.GetStreamLightClient();
_StreamLightLBAD._Sub = context.GetStreamLightSub(); _StreamLightLBAD._Sub = context.GetStreamLightSub();
@ -320,21 +309,17 @@ namespace ILSOS_CCW_H52A.Sequences
} }
private bool CheckDeviceReady(SequenceContext context) private bool CheckDeviceReady(SequenceContext context) {
{
List<string> deviceListToCheck = new List<string>() { CommonDeviceIds.Scanner, CommonDeviceIds.Laser, CommonDeviceIds.PLCDevice, CommonDeviceIds.IODevice }; List<string> deviceListToCheck = new List<string>() { CommonDeviceIds.Scanner, CommonDeviceIds.Laser, CommonDeviceIds.PLCDevice, CommonDeviceIds.IODevice };
if (_InitParam.UseStream) if (_InitParam.UseStream) {
{
deviceListToCheck.Add(CommonServiceIds.StreamLightLBADClient); deviceListToCheck.Add(CommonServiceIds.StreamLightLBADClient);
deviceListToCheck.Add(CommonServiceIds.StreamLightLBADSub); deviceListToCheck.Add(CommonServiceIds.StreamLightLBADSub);
} }
bool isAllDeviceActivated = true; bool isAllDeviceActivated = true;
foreach (string item in deviceListToCheck) foreach (string item in deviceListToCheck) {
{ if (!context.Devices[item].IsActivated) {
if (!context.Devices[item].IsActivated)
{
isAllDeviceActivated = isAllDeviceActivated && false; isAllDeviceActivated = isAllDeviceActivated && false;
} }
} }
@ -342,8 +327,7 @@ namespace ILSOS_CCW_H52A.Sequences
return isAllDeviceActivated; return isAllDeviceActivated;
} }
private bool CheckCondition(SequenceContext context) private bool CheckCondition(SequenceContext context) {
{
int InitializeCode = InitializeDeviceStatus(context); int InitializeCode = InitializeDeviceStatus(context);
if (InitializeCode == (int)InitErrorList.SUCCESS) if (InitializeCode == (int)InitErrorList.SUCCESS)
return true; return true;
@ -352,8 +336,7 @@ namespace ILSOS_CCW_H52A.Sequences
return false; return false;
} }
private int InitializeDeviceStatus(SequenceContext context) private int InitializeDeviceStatus(SequenceContext context) {
{
// PLC Interface AutoStatus Start // PLC Interface AutoStatus Start
// Won : PC의 AutoStatus 가 True 되는 순간 Rotary가 돌기 시작한다. // Won : PC의 AutoStatus 가 True 되는 순간 Rotary가 돌기 시작한다.
// Rotary 돌기 시작 한 후 Encoder 값을 읽으면 안 되므로 정지상태에서 읽은 후 AutoStatus true 하도록 // Rotary 돌기 시작 한 후 Encoder 값을 읽으면 안 되므로 정지상태에서 읽은 후 AutoStatus true 하도록
@ -361,32 +344,26 @@ namespace ILSOS_CCW_H52A.Sequences
//InitAutoRunBit(); //InitAutoRunBit();
// LBAD Initialize // LBAD Initialize
// LBAD 는 server 이기 때문에, 만약 끊어졌으면 다시 접속이 필요함 // LBAD 는 server 이기 때문에, 만약 끊어졌으면 다시 접속이 필요함
if (_SystemParameter.BypassModeLBAD == false) if (_SystemParameter.BypassModeLBAD == false) {
{ if (!_StreamLightLBAD._Client.IsActivated) {
if (!_StreamLightLBAD._Client.IsActivated)
{
int ret = _StreamLightLBAD._Client.Activate(); int ret = _StreamLightLBAD._Client.Activate();
Thread.Sleep(500); Thread.Sleep(500);
if (ret != E1.OK) if (ret != E1.OK) {
{
Log.E($"StreamLightClient activate failed"); Log.E($"StreamLightClient activate failed");
return (int)InitErrorList.LBAD_CLIENT_ACTIVATE_FAILED; return (int)InitErrorList.LBAD_CLIENT_ACTIVATE_FAILED;
} }
} }
if (_StreamLightLBAD._Sub.IsActivated == false) if (_StreamLightLBAD._Sub.IsActivated == false) {
{
int ret = _StreamLightLBAD._Sub.Activate(); int ret = _StreamLightLBAD._Sub.Activate();
Thread.Sleep(500); Thread.Sleep(500);
if (ret != E1.OK) if (ret != E1.OK) {
{
Log.E($"StreamLightSub activate failed"); Log.E($"StreamLightSub activate failed");
return (int)InitErrorList.LBAD_SUB_ACTIVATE_FAILED; return (int)InitErrorList.LBAD_SUB_ACTIVATE_FAILED;
} }
} }
_StreamLightLBAD.Initialize(); _StreamLightLBAD.Initialize();
if (_StreamLightLBAD.SendReadyStatus(eRequestData.Ready_On) == false) if (_StreamLightLBAD.SendReadyStatus(eRequestData.Ready_On) == false) {
{
Log.I(string.Format($"[LBAD Interface]CheckReadyStatus null")); Log.I(string.Format($"[LBAD Interface]CheckReadyStatus null"));
//return false; //return false;
} }
@ -396,40 +373,31 @@ namespace ILSOS_CCW_H52A.Sequences
_Laser.PilotLaserOff(); _Laser.PilotLaserOff();
_Laser.LaserOn(); _Laser.LaserOn();
Thread.Sleep(500); Thread.Sleep(500);
if (!_Laser.GetLaserReady()) if (!_Laser.GetLaserReady()) {
{
Log.E("ERROR Initialize Laser"); Log.E("ERROR Initialize Laser");
return (int)InitErrorList.LASER_INIT_ERROR; return (int)InitErrorList.LASER_INIT_ERROR;
} }
// Scanner Initialize // Scanner Initialize
if (_Scanner.GetModulationMode()) if (_Scanner.GetModulationMode()) {
{
_ModulationMode = true; _ModulationMode = true;
} } else {
else
{
_ModulationMode = false; _ModulationMode = false;
} }
///// AutoRun Bit가 OFF인 경우 ///// AutoRun Bit가 OFF인 경우
if (_PLC.ReadBit((int)eBitInput.PLC_AUTO_STATUS).data == false) if (_PLC.ReadBit((int)eBitInput.PLC_AUTO_STATUS).data == false) {
{
// AutoRun Request 상태 체크 // AutoRun Request 상태 체크
if (_PLC.ReadBit((int)eBitInput.PLC_AUTO_REQ).data == false) if (_PLC.ReadBit((int)eBitInput.PLC_AUTO_REQ).data == false) {
{
Log.E(string.Format("ERROR Initialize PLC, PLC Alarm ON")); // AutoRun Request와 AutoRun Bit 모두 OFF인 경우, PLC 측에서 Alarm 발생함. Log.E(string.Format("ERROR Initialize PLC, PLC Alarm ON")); // AutoRun Request와 AutoRun Bit 모두 OFF인 경우, PLC 측에서 Alarm 발생함.
return (int)InitErrorList.PLC_ALARM; return (int)InitErrorList.PLC_ALARM;
} } else {
else
{
Log.E(string.Format("ERROR Initialize PLC, Bit Off PLC_AUTO_STATUS")); // AutoRun Request가 ON인데 AutoRun Bit 모두 OFF인 경우, PLC에서 AutoRun Bit를 켜지 않음. Log.E(string.Format("ERROR Initialize PLC, Bit Off PLC_AUTO_STATUS")); // AutoRun Request가 ON인데 AutoRun Bit 모두 OFF인 경우, PLC에서 AutoRun Bit를 켜지 않음.
return (int)InitErrorList.PLC_AUTORUN_BIT_OFF; return (int)InitErrorList.PLC_AUTORUN_BIT_OFF;
} }
} }
// Marking On The Flying Off // Marking On The Flying Off
if (_Scanner.Config.UseMarkingOnTheFly == false) if (_Scanner.Config.UseMarkingOnTheFly == false) {
{
Log.E("ERROR Config Setting : Scanner Marking on the fly (OFF)"); Log.E("ERROR Config Setting : Scanner Marking on the fly (OFF)");
return (int)InitErrorList.MOTF_OFF; return (int)InitErrorList.MOTF_OFF;
} }
@ -471,11 +439,9 @@ namespace ILSOS_CCW_H52A.Sequences
// 큐 잔류 셀 보존 — DrainCellInfoQueue 전에 선행 (Prefetch2 다음 지그 기준) // 큐 잔류 셀 보존 — DrainCellInfoQueue 전에 선행 (Prefetch2 다음 지그 기준)
// Prefetch2.JigNo가 확정값이므로 다음 지그 = (JigNo % 16) + 1 로 신뢰성 있게 계산 // Prefetch2.JigNo가 확정값이므로 다음 지그 = (JigNo % 16) + 1 로 신뢰성 있게 계산
if (_CellScheduler.Prefetch2 != null && _CellScheduler.Prefetch2.JigNo > 0) if (_CellScheduler.Prefetch2 != null && _CellScheduler.Prefetch2.JigNo > 0) {
{
int nextJigNo = (_CellScheduler.Prefetch2.JigNo % ProcessManager.RotaryJigCount) + 1; int nextJigNo = (_CellScheduler.Prefetch2.JigNo % ProcessManager.RotaryJigCount) + 1;
if (ProcessManager.Instance.ReceivedCellInfoQueue.TryDequeue(out var qCell)) if (ProcessManager.Instance.ReceivedCellInfoQueue.TryDequeue(out var qCell)) {
{
_CellScheduler.SaveQueueEntry(qCell.LotId, qCell.CellId, nextJigNo); _CellScheduler.SaveQueueEntry(qCell.LotId, qCell.CellId, nextJigNo);
Log.I($"[QueueSave] Jig{nextJigNo} 큐 잔류 셀 보존 >> CellId({qCell.CellId})"); Log.I($"[QueueSave] Jig{nextJigNo} 큐 잔류 셀 보존 >> CellId({qCell.CellId})");
} }
@ -500,34 +466,25 @@ namespace ILSOS_CCW_H52A.Sequences
} }
private double GetRotaryCurrentPosition() private double GetRotaryCurrentPosition() {
{ try {
try
{
//double finalValue = Convert.ToDouble(_plc.GetLongAIValue("PLC_CURRENT_POS_1") / 100000f); //double finalValue = Convert.ToDouble(_plc.GetLongAIValue("PLC_CURRENT_POS_1") / 100000f);
double finalValue = Convert.ToDouble(_PLC.ReadDWord((int)eWordInput.PLC_CURRENT_POS_1).data / 100000f); double finalValue = Convert.ToDouble(_PLC.ReadDWord((int)eWordInput.PLC_CURRENT_POS_1).data / 100000f);
finalValue += _Scanner.Config.RotaryEncoderOffset; finalValue += _Scanner.Config.RotaryEncoderOffset;
if (360.0 <= finalValue) if (360.0 <= finalValue) {
{ while (360.0 <= finalValue) {
while (360.0 <= finalValue)
{
finalValue -= 360.0; finalValue -= 360.0;
} }
} } else if (finalValue < 0) {
else if (finalValue < 0) while (finalValue < 0) {
{
while (finalValue < 0)
{
finalValue += 360.0; finalValue += 360.0;
} }
} }
return finalValue; return finalValue;
} } catch {
catch
{
return -9999.9999; return -9999.9999;
} }
} }
@ -539,8 +496,7 @@ namespace ILSOS_CCW_H52A.Sequences
/// <param name="rotaryJigCount">Rotary 내 지그 갯수임. 장비 및 T/T에 따라서, 360도 당 지그의 개수는 다를 수 있으므로.</param> /// <param name="rotaryJigCount">Rotary 내 지그 갯수임. 장비 및 T/T에 따라서, 360도 당 지그의 개수는 다를 수 있으므로.</param>
/// <param name="weldingCount">Rotary Welding Count. 30도 구간 하나가 지나갈 때마다 +1</param> /// <param name="weldingCount">Rotary Welding Count. 30도 구간 하나가 지나갈 때마다 +1</param>
/// <param name="weldingJigNo">현재 '용접 중' 구간에 들어가 있는 지그 번호</param> /// <param name="weldingJigNo">현재 '용접 중' 구간에 들어가 있는 지그 번호</param>
public void InitRotaryOnTheFlyWeldingCount(double rotaryAngleOffset, int rotaryJigCount, out int weldingCount, out int weldingJigNo) public void InitRotaryOnTheFlyWeldingCount(double rotaryAngleOffset, int rotaryJigCount, out int weldingCount, out int weldingJigNo) {
{
// 현재 로터리 엔코더 값을 기준으로 현재 카운트, 지그 번호를 확인 // 현재 로터리 엔코더 값을 기준으로 현재 카운트, 지그 번호를 확인
double anglePerOneJig = 360 / (double)rotaryJigCount; //double로 바꿔서 계산해야 22가 아닌 22.5로 anglePerOneJig가 계산됨 25.08.02 double anglePerOneJig = 360 / (double)rotaryJigCount; //double로 바꿔서 계산해야 22가 아닌 22.5로 anglePerOneJig가 계산됨 25.08.02
weldingCount = (int)((rotaryAngleOffset + anglePerOneJig / 2) / anglePerOneJig); // _WeldingCount = 0, 1, 2, ... weldingCount = (int)((rotaryAngleOffset + anglePerOneJig / 2) / anglePerOneJig); // _WeldingCount = 0, 1, 2, ...
@ -549,10 +505,8 @@ namespace ILSOS_CCW_H52A.Sequences
Log.I($"Angle Per One Jig : {anglePerOneJig}"); Log.I($"Angle Per One Jig : {anglePerOneJig}");
} }
private string CheckInitCondition(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param) private string CheckInitCondition(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param) {
{ if (!CheckCondition(context)) {
if (!CheckCondition(context))
{
//AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_AutoRun_CheckInitCondition); //AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_AutoRun_CheckInitCondition);
Log.E("Condition is not in state to start sequence."); Log.E("Condition is not in state to start sequence.");
context.PutValue(ContextKey.KEY_SEQUENCE_RESULT, false); context.PutValue(ContextKey.KEY_SEQUENCE_RESULT, false);
@ -570,8 +524,7 @@ namespace ILSOS_CCW_H52A.Sequences
} }
// 지그 상태 확인 // 지그 상태 확인
private SequenceActionResult CheckLoadComplete(SequenceContext context, string id, SequenceActionResult param) private SequenceActionResult CheckLoadComplete(SequenceContext context, string id, SequenceActionResult param) {
{
Status.SetWorkingPosition(eWorkingPosition.LOADING_CELL); Status.SetWorkingPosition(eWorkingPosition.LOADING_CELL);
// MOTF WaitScannerLoadListEnable // MOTF WaitScannerLoadListEnable
@ -579,8 +532,7 @@ namespace ILSOS_CCW_H52A.Sequences
// LoadList가 0보다 크면 다음 시퀀스 진행해야 함 // LoadList가 0보다 크면 다음 시퀀스 진행해야 함
WaitContinue: WaitContinue:
var ret = context.RetryUntilSuccess(() => _Scanner.LoadList(_WeldingScannerListNo) > 0, int.MaxValue, 10, true); var ret = context.RetryUntilSuccess(() => _Scanner.LoadList(_WeldingScannerListNo) > 0, int.MaxValue, 10, true);
if (ret == E2.TIMEOUT) if (ret == E2.TIMEOUT) {
{
Log.E("TIMEOUT_Scanner_LoadList : 600시간 Run"); Log.E("TIMEOUT_Scanner_LoadList : 600시간 Run");
goto WaitContinue; goto WaitContinue;
} }
@ -590,38 +542,30 @@ namespace ILSOS_CCW_H52A.Sequences
return SequenceAction.Ok(); return SequenceAction.Ok();
} }
private SequenceActionResult CheckScannerListComplete(SequenceContext context, string id, SequenceActionResult param) private SequenceActionResult CheckScannerListComplete(SequenceContext context, string id, SequenceActionResult param) {
{
// Prefetch1 = 2회 전 업로드된 지그 = 현재 물리적으로 레이저 통과 중 = 완료 체크 대상. // Prefetch1 = 2회 전 업로드된 지그 = 현재 물리적으로 레이저 통과 중 = 완료 체크 대상.
// Shift()는 이 메서드 이후 ReadyScannerList에서 실행되므로, 이 시점의 Prefetch1이 // Shift()는 이 메서드 이후 ReadyScannerList에서 실행되므로, 이 시점의 Prefetch1이
// 원본 코드의 InputScannerList[(listNo-1)]과 동일 대상이다. // 원본 코드의 InputScannerList[(listNo-1)]과 동일 대상이다.
// 예열 구간: iter 1~2(Pf1=null) → 통과. iter 3~: Pf1=Jig1 → 실제 처리. // 예열 구간: iter 1~2(Pf1=null) → 통과. iter 3~: Pf1=Jig1 → 실제 처리.
var jigComplete = _CellScheduler.Prefetch1; var jigComplete = _CellScheduler.Prefetch1;
if (jigComplete == null) if (jigComplete == null) {
{
Log.I($"[Warmup] ScannerList {_WeldingCount}: pipeline not ready, skip complete check"); Log.I($"[Warmup] ScannerList {_WeldingCount}: pipeline not ready, skip complete check");
return SequenceAction.Ok(); return SequenceAction.Ok();
} }
if (!CheckInsideWeldPosition(jigComplete.StartAngle)) if (!CheckInsideWeldPosition(jigComplete.StartAngle)) {
{
// IsCanExist=false(공 지그)는 리스트 실행은 하지만 용접이 없으므로 // IsCanExist=false(공 지그)는 리스트 실행은 하지만 용접이 없으므로
// 엔코더 범위를 벗어나도 에러가 아님 // 엔코더 범위를 벗어나도 에러가 아님
if (jigComplete.IsCanExist) if (jigComplete.IsCanExist) {
{
Log.I("ERR_SCANNER_LIST_PROCESSING_TIMEOVER"); Log.I("ERR_SCANNER_LIST_PROCESSING_TIMEOVER");
return SequenceAction.Error(); return SequenceAction.Error();
} }
return SequenceAction.Ok(); return SequenceAction.Ok();
} } else {
else if (jigComplete.IsCanExist) {
{
if (jigComplete.IsCanExist)
{
#region 용접 시간, 엔코더 측정/기록 #region 용접 시간, 엔코더 측정/기록
double elaspedTime = _Scanner.GetTime(); double elaspedTime = _Scanner.GetTime();
if (jigComplete.WeldComplete) if (jigComplete.WeldComplete) {
{
jigComplete.WeldEndTime = DateTime.Now; jigComplete.WeldEndTime = DateTime.Now;
jigComplete.WeldingSpanTime = TimeSpan.FromSeconds(elaspedTime); jigComplete.WeldingSpanTime = TimeSpan.FromSeconds(elaspedTime);
TimeSpan weldInterval = jigComplete.WeldEndTime - _prevWeldEndTime; TimeSpan weldInterval = jigComplete.WeldEndTime - _prevWeldEndTime;
@ -635,25 +579,21 @@ namespace ILSOS_CCW_H52A.Sequences
jigComplete.WeldingSpanTime.TotalMilliseconds, jigComplete.WeldingSpanTime.TotalMilliseconds,
weldInterval.TotalSeconds)); weldInterval.TotalSeconds));
if (_PLC.ReadBit((int)eBitInput.PLC_USE_WELD_JIG_1 + jigComplete.JigNo - 1).data) if (_PLC.ReadBit((int)eBitInput.PLC_USE_WELD_JIG_1 + jigComplete.JigNo - 1).data) {
{
_PLC.WriteBit((int)eBitOutput.PC_WELD_COMPLETE_1 + jigComplete.JigNo - 1, true); _PLC.WriteBit((int)eBitOutput.PC_WELD_COMPLETE_1 + jigComplete.JigNo - 1, true);
Log.I(string.Format($"PC_WELD_COMPLETE_{jigComplete.JigNo} -> true)")); Log.I(string.Format($"PC_WELD_COMPLETE_{jigComplete.JigNo} -> true)"));
} }
if (_SystemParameter.LastResetTime < DateTime.Now.Date) if (_SystemParameter.LastResetTime < DateTime.Now.Date) {
{
_SystemParameter.LastResetTime = DateTime.Now.Date; _SystemParameter.LastResetTime = DateTime.Now.Date;
Log.I($"Today Count Reset. {_SystemParameter.TodayProductCount} -> 0"); Log.I($"Today Count Reset. {_SystemParameter.TodayProductCount} -> 0");
_SystemParameter.TodayProductCount = 0; _SystemParameter.TodayProductCount = 0;
} }
if (_SystemParameter.TodayProductCount < uint.MaxValue) if (_SystemParameter.TodayProductCount < uint.MaxValue) {
{
_SystemParameter.TodayProductCount++; _SystemParameter.TodayProductCount++;
} }
if (_SystemParameter.TotalProductCount < uint.MaxValue) if (_SystemParameter.TotalProductCount < uint.MaxValue) {
{
_SystemParameter.TotalProductCount++; _SystemParameter.TotalProductCount++;
} }
@ -663,19 +603,14 @@ namespace ILSOS_CCW_H52A.Sequences
Status.GetProcessingWeldingData().RecipeNo = _RecipeNo; Status.GetProcessingWeldingData().RecipeNo = _RecipeNo;
Status.GetProcessingWeldingData().LaserPowerByLBAD = _LaserPowerByLBAD.ToString(); Status.GetProcessingWeldingData().LaserPowerByLBAD = _LaserPowerByLBAD.ToString();
// 보고 데이터는 스케줄러의 ActiveReportSlot(Complete 또는 PendingComplete)에서 읽음 Status.GetProcessingWeldingData().LotId = jigComplete.LotId;
var report = _CellScheduler.ActiveReportSlot; Status.GetProcessingWeldingData().CellId = jigComplete.CellId;
if (report != null) Status.GetProcessingWeldingData().WeldingStartTime = jigComplete.WeldStartTime;
{ Status.GetProcessingWeldingData().WeldingEndTime = jigComplete.WeldEndTime;
Status.GetProcessingWeldingData().LotId = report.LotId; Status.GetProcessingWeldingData().WeldingSpanTimeMilliseconds = jigComplete.WeldingSpanTime.TotalMilliseconds.ToString();
Status.GetProcessingWeldingData().CellId = report.CellId; Status.GetProcessingWeldingData().JigNo = jigComplete.JigNo.ToString();
Status.GetProcessingWeldingData().WeldingStartTime = report.WeldStartTime;
Status.GetProcessingWeldingData().WeldingEndTime = report.WeldEndTime;
Status.GetProcessingWeldingData().WeldingSpanTimeMilliseconds = report.WeldingSpanTime.TotalMilliseconds.ToString();
Status.GetProcessingWeldingData().JigNo = report.JigNo.ToString();
SaveCellAPD(); SaveCellAPD();
} }
}
UtilUnit.logUnit.SetLog(LogUnit.eLogType.PRODUCT, MethodBase.GetCurrentMethod().Name, "UPDATE_WELDING_TIME;" + jigComplete.WeldingSpanTime.TotalMilliseconds); UtilUnit.logUnit.SetLog(LogUnit.eLogType.PRODUCT, MethodBase.GetCurrentMethod().Name, "UPDATE_WELDING_TIME;" + jigComplete.WeldingSpanTime.TotalMilliseconds);
UtilUnit.logUnit.SetLog(LogUnit.eLogType.PRODUCT, MethodBase.GetCurrentMethod().Name, "UPDATE_PRODUCT_COUNT;" + jigComplete.WeldEndTime.ToString("yyyy-MM-dd HH:mm:ss")); UtilUnit.logUnit.SetLog(LogUnit.eLogType.PRODUCT, MethodBase.GetCurrentMethod().Name, "UPDATE_PRODUCT_COUNT;" + jigComplete.WeldEndTime.ToString("yyyy-MM-dd HH:mm:ss"));
@ -690,8 +625,7 @@ namespace ILSOS_CCW_H52A.Sequences
Log.I(string.Format("Encoder start : {0:F4}, end : {1:F4}, vel : {2:F2}", startEncoderCount, endEncoderCount, angularVelocity)); Log.I(string.Format("Encoder start : {0:F4}, end : {1:F4}, vel : {2:F2}", startEncoderCount, endEncoderCount, angularVelocity));
#endregion #endregion
#region 스캐너 리스트 Record 파일 기록 #region 스캐너 리스트 Record 파일 기록
if (_Scanner.Config.UseRecordSignal) if (_Scanner.Config.UseRecordSignal) {
{
String RecordFileName = _RecipeManager.ActivatedRecipe().Name + "_Jig#" + jigComplete.JigNo.ToString(); String RecordFileName = _RecipeManager.ActivatedRecipe().Name + "_Jig#" + jigComplete.JigNo.ToString();
string DataFilePath = ProjectUtil.GetDataLogSetting().GetFilePath_ScannerRecordLog(RecordFileName, true); string DataFilePath = ProjectUtil.GetDataLogSetting().GetFilePath_ScannerRecordLog(RecordFileName, true);
_Scanner.SaveRecord(DataFilePath); _Scanner.SaveRecord(DataFilePath);
@ -715,8 +649,7 @@ namespace ILSOS_CCW_H52A.Sequences
/// </summary> /// </summary>
/// <param name="startAngle"> 현재 지그의 시작 각도 </param> /// <param name="startAngle"> 현재 지그의 시작 각도 </param>
/// <returns> 지나갔으면 True </returns> /// <returns> 지나갔으면 True </returns>
public bool CheckInsideWeldPosition(double startAngle) public bool CheckInsideWeldPosition(double startAngle) {
{
double encoderX, currentAngle; double encoderX, currentAngle;
_Scanner.GetEncoder(out encoderX, out currentAngle, true); _Scanner.GetEncoder(out encoderX, out currentAngle, true);
@ -724,8 +657,7 @@ namespace ILSOS_CCW_H52A.Sequences
if (0 < startAngle && currentAngle < 0) if (0 < startAngle && currentAngle < 0)
return false; return false;
if (startAngle <= currentAngle && currentAngle < startAngle + 45) if (startAngle <= currentAngle && currentAngle < startAngle + 45) {
{
Log.I(string.Format("Current encoder check OK, startAngle : {0}, currentAngle : {1})", startAngle, currentAngle)); Log.I(string.Format("Current encoder check OK, startAngle : {0}, currentAngle : {1})", startAngle, currentAngle));
return true; return true;
} }
@ -738,8 +670,7 @@ namespace ILSOS_CCW_H52A.Sequences
return false; return false;
} }
private string ReadyScannerList(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param) private string ReadyScannerList(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param) {
{
Status.SetWorkingPosition(eWorkingPosition.UPLOADING_WELD_LIST); Status.SetWorkingPosition(eWorkingPosition.UPLOADING_WELD_LIST);
//_SelectedDrawObjectList = _ScannerCanvasUserCtrl.Model.Layers[0].Objects; //_SelectedDrawObjectList = _ScannerCanvasUserCtrl.Model.Layers[0].Objects;
@ -776,12 +707,10 @@ namespace ILSOS_CCW_H52A.Sequences
bool canExist; // 지그 용접 수행 여부 확인 bool canExist; // 지그 용접 수행 여부 확인
if (UsePlcShotThemAll) if (UsePlcShotThemAll) {
{
canExist = true; canExist = true;
Log.I("Settings - PLC : Shot Them All Mode"); Log.I("Settings - PLC : Shot Them All Mode");
} } else
else
canExist = GetRotaryCanExist(_WeldingJigNo); canExist = GetRotaryCanExist(_WeldingJigNo);
//Log.I("Can Exist : " + canExist.ToString() + ", JigNo " + _WeldingJigNo + " ,CountNo " + _WeldingCount + ", StartAngle(Y) : " + _WeldingStartAngle); //Log.I("Can Exist : " + canExist.ToString() + ", JigNo " + _WeldingJigNo + " ,CountNo " + _WeldingCount + ", StartAngle(Y) : " + _WeldingStartAngle);
@ -801,35 +730,24 @@ namespace ILSOS_CCW_H52A.Sequences
// 복원 우선: 정지 전 업로드됐으나 로터리 감속·정지로 용접 미완된 셀 정보 복원. // 복원 우선: 정지 전 업로드됐으나 로터리 감속·정지로 용접 미완된 셀 정보 복원.
// canExist=false 지그도 TryRestoreCell을 호출하여 슬롯 소비(폐기) — 이후 오염 방지. // canExist=false 지그도 TryRestoreCell을 호출하여 슬롯 소비(폐기) — 이후 오염 방지.
(string LotId, string CellId) recvInfo = (string.Empty, string.Empty); (string LotId, string CellId) recvInfo = (string.Empty, string.Empty);
if (_CellScheduler.TryRestoreCell(_WeldingJigNo, out var rLot, out var rCell)) if (_CellScheduler.TryRestoreCell(_WeldingJigNo, out var rLot, out var rCell)) {
{ if (canExist) {
if (canExist)
{
recvInfo.LotId = rLot; recvInfo.LotId = rLot;
recvInfo.CellId = rCell; recvInfo.CellId = rCell;
Log.I($"[PendingRestore] Jig{_WeldingJigNo} 셀 복원 >> CellId({rCell})"); Log.I($"[PendingRestore] Jig{_WeldingJigNo} 셀 복원 >> CellId({rCell})");
} } else {
else
{
Log.W($"[PendingRestore] Jig{_WeldingJigNo} canExist=false, 복원 데이터 폐기 >> CellId({rCell})"); Log.W($"[PendingRestore] Jig{_WeldingJigNo} canExist=false, 복원 데이터 폐기 >> CellId({rCell})");
} }
} } else if (ProcessManager.Instance.ReceivedCellInfoQueue.TryDequeue(out var cell)) {
else if (ProcessManager.Instance.ReceivedCellInfoQueue.TryDequeue(out var cell)) if (canExist) {
{
if (canExist)
{
recvInfo.LotId = cell.LotId; recvInfo.LotId = cell.LotId;
recvInfo.CellId = cell.CellId; recvInfo.CellId = cell.CellId;
} } else {
else
{
// 앞공정 NG 셀: CellTracker는 투입 시 이미 스캔했으므로 큐에서 소비 후 폐기. // 앞공정 NG 셀: CellTracker는 투입 시 이미 스캔했으므로 큐에서 소비 후 폐기.
// 소비하지 않으면 다음 정상 셀이 이 NG 데이터를 가져가 정합성 붕괴. // 소비하지 않으면 다음 정상 셀이 이 NG 데이터를 가져가 정합성 붕괴.
Log.W($"[NG Skip] Jig{_WeldingJigNo} canExist=false, 큐 데이터 폐기 >> CellId({cell.CellId})"); Log.W($"[NG Skip] Jig{_WeldingJigNo} canExist=false, 큐 데이터 폐기 >> CellId({cell.CellId})");
} }
} } else {
else
{
if (canExist) if (canExist)
Log.E($"[QueueEmpty] Jig{_WeldingJigNo} canExist=true 이지만 큐가 비어있음"); Log.E($"[QueueEmpty] Jig{_WeldingJigNo} canExist=true 이지만 큐가 비어있음");
@ -854,32 +772,25 @@ namespace ILSOS_CCW_H52A.Sequences
$"[ListNo({_CellScheduler.Prefetch1.ListNo})] [WeldingCount({_CellScheduler.Prefetch1.WeldingCount})]" + $"[ListNo({_CellScheduler.Prefetch1.ListNo})] [WeldingCount({_CellScheduler.Prefetch1.WeldingCount})]" +
$"[StartAngle(Y)({_CellScheduler.Prefetch1.StartAngle})]"); $"[StartAngle(Y)({_CellScheduler.Prefetch1.StartAngle})]");
if (canExist) if (canExist) {
{
#region 용접할 Objects 선택 #region 용접할 Objects 선택
if (_WeldingJigNo - 1 < _ScannerCanvasUserCtrl.Model.Layers.Length) if (_WeldingJigNo - 1 < _ScannerCanvasUserCtrl.Model.Layers.Length) {
{
_SelectedDrawObjectList = _ScannerCanvasUserCtrl.Model.Layers[_WeldingJigNo - 1].Objects; _SelectedDrawObjectList = _ScannerCanvasUserCtrl.Model.Layers[_WeldingJigNo - 1].Objects;
Log.I(string.Format("Page 불러오기 : [{0}])", _WeldingJigNo - 1)); Log.I(string.Format("Page 불러오기 : [{0}])", _WeldingJigNo - 1));
} } else {
else
{
_SelectedDrawObjectList = _ScannerCanvasUserCtrl.Model.Layers[0].Objects; _SelectedDrawObjectList = _ScannerCanvasUserCtrl.Model.Layers[0].Objects;
Log.I(string.Format("Page 불러오기 : [0])")); Log.I(string.Format("Page 불러오기 : [0])"));
} }
#endregion #endregion
return SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ; return SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ;
} } else {
else
{
return SEQ_EXECUTE_WELDING; return SEQ_EXECUTE_WELDING;
} }
#endregion #endregion
} }
private ScannerParam GetSelectedDrawObjectData(IDrawObject DrawObj) private ScannerParam GetSelectedDrawObjectData(IDrawObject DrawObj) {
{
if (DrawObj is Line lineItem) if (DrawObj is Line lineItem)
return WeldingRecipeManager.GetScannerParam(lineItem.ScannerParamNo); return WeldingRecipeManager.GetScannerParam(lineItem.ScannerParamNo);
else if (DrawObj is Arc arcItem) else if (DrawObj is Arc arcItem)
@ -890,8 +801,7 @@ namespace ILSOS_CCW_H52A.Sequences
return null; return null;
} }
public void WaitForEncoderNextRotarySection(int weldingCount, int rotaryJigCount, double rotaryAngleOffset, double encoderResetOffset, out double sectionStartAngle) public void WaitForEncoderNextRotarySection(int weldingCount, int rotaryJigCount, double rotaryAngleOffset, double encoderResetOffset, out double sectionStartAngle) {
{
// 한 바퀴당 지그 숫자에 따른 변경 // 한 바퀴당 지그 숫자에 따른 변경
double encoderAllowedMinDegree = Int32.MinValue / _Scanner.Config.MarkingOnTheFlyEncoderResolutionRotate * 360.0; double encoderAllowedMinDegree = Int32.MinValue / _Scanner.Config.MarkingOnTheFlyEncoderResolutionRotate * 360.0;
double encoderAllowedMaxDegree = Int32.MaxValue / _Scanner.Config.MarkingOnTheFlyEncoderResolutionRotate * 360.0; double encoderAllowedMaxDegree = Int32.MaxValue / _Scanner.Config.MarkingOnTheFlyEncoderResolutionRotate * 360.0;
@ -910,8 +820,7 @@ namespace ILSOS_CCW_H52A.Sequences
// 1.2. 계산된 시작각도가 이미 지나버렸으면 알람 발생 필요 // 1.2. 계산된 시작각도가 이미 지나버렸으면 알람 발생 필요
// 1.3. Overflow가 나는 숫자라면, 보상할 것. // 1.3. Overflow가 나는 숫자라면, 보상할 것.
if (sectionStartAngle > encoderAllowedMaxDegree) if (sectionStartAngle > encoderAllowedMaxDegree) {
{
sectionStartAngle -= encoderAllowedMaxDegree - encoderAllowedMinDegree; sectionStartAngle -= encoderAllowedMaxDegree - encoderAllowedMinDegree;
_EncoderOverflowCount++; _EncoderOverflowCount++;
} }
@ -921,19 +830,16 @@ namespace ILSOS_CCW_H52A.Sequences
_Scanner.WaitForEncoderRotateRange(encoderAllowedMinDegree, encoderAllowedMaxDegree, sectionStartAngle, sectionEndAngle); _Scanner.WaitForEncoderRotateRange(encoderAllowedMinDegree, encoderAllowedMaxDegree, sectionStartAngle, sectionEndAngle);
} }
public bool GetRotaryCanExist(int jigNo) public bool GetRotaryCanExist(int jigNo) {
{
if (jigNo <= _RotaryJigCount) if (jigNo <= _RotaryJigCount)
return _PLC.ReadBit((int)eBitInput.PLC_USE_WELD_JIG_1 + (jigNo - 1)).data; return _PLC.ReadBit((int)eBitInput.PLC_USE_WELD_JIG_1 + (jigNo - 1)).data;
else else
return false; return false;
} }
private SequenceActionResult SetUploadWeldingList_SeqParams(SequenceContext context, string id, SequenceActionResult param) private SequenceActionResult SetUploadWeldingList_SeqParams(SequenceContext context, string id, SequenceActionResult param) {
{
//현재 시퀀스에서 LoadList를 해주기 때문에 Sub 시퀀스에 IncludeListStartEnd를 false로 넘겨줘야 함 //현재 시퀀스에서 LoadList를 해주기 때문에 Sub 시퀀스에 IncludeListStartEnd를 false로 넘겨줘야 함
SeqUploadWeldingList_InitParam seqParams = new SeqUploadWeldingList_InitParam() SeqUploadWeldingList_InitParam seqParams = new SeqUploadWeldingList_InitParam() {
{
NeedSetLaserTiming = _ModulationMode, NeedSetLaserTiming = _ModulationMode,
IncludeListStartEnd = false, IncludeListStartEnd = false,
CellMeasureCenterOffsetX = 0, CellMeasureCenterOffsetX = 0,
@ -946,11 +852,9 @@ namespace ILSOS_CCW_H52A.Sequences
return SequenceAction.Ok(seqParams); return SequenceAction.Ok(seqParams);
} }
private SequenceActionResult GetUploadWeldingList_SeqResult(SequenceContext context, string id, SequenceActionResult param) private SequenceActionResult GetUploadWeldingList_SeqResult(SequenceContext context, string id, SequenceActionResult param) {
{
var resultOutParam = param.Param as SeqUploadWeldingList_OutParam; var resultOutParam = param.Param as SeqUploadWeldingList_OutParam;
if (resultOutParam.Success == false) if (resultOutParam.Success == false) {
{
//AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_UploadWeldingList_ResultFailed); //AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_UploadWeldingList_ResultFailed);
return SequenceAction.ForceStopByAlarm(AlarmCode.ALARM_SEQUENCE_UploadWeldingList_ResultFailed); return SequenceAction.ForceStopByAlarm(AlarmCode.ALARM_SEQUENCE_UploadWeldingList_ResultFailed);
//return null; //return null;
@ -990,8 +894,7 @@ namespace ILSOS_CCW_H52A.Sequences
// return SequenceAction.Ok(); // return SequenceAction.Ok();
//} //}
private SequenceActionResult ExecuteWelding(SequenceContext context, string id, SequenceActionResult param) private SequenceActionResult ExecuteWelding(SequenceContext context, string id, SequenceActionResult param) {
{
Status.SetWorkingPosition(eWorkingPosition.EXECUTING_WELD); Status.SetWorkingPosition(eWorkingPosition.EXECUTING_WELD);
// MOTF Welding // MOTF Welding
@ -999,15 +902,12 @@ namespace ILSOS_CCW_H52A.Sequences
_Scanner.SetEndList(); _Scanner.SetEndList();
#region List 실행(처음엔 ExecuteList, 다음부터 AutoChangeList, 이후 대상 리스트 교체 (1 <-> 2)) #region List 실행(처음엔 ExecuteList, 다음부터 AutoChangeList, 이후 대상 리스트 교체 (1 <-> 2))
if (isTheFirstListExecute) if (isTheFirstListExecute) {
{
isTheFirstListExecute = false; isTheFirstListExecute = false;
_Scanner.ExecuteList(_WeldingScannerListNo); _Scanner.ExecuteList(_WeldingScannerListNo);
Log.I(string.Format($"START Welding : ExecuteList_{_WeldingScannerListNo}")); Log.I(string.Format($"START Welding : ExecuteList_{_WeldingScannerListNo}"));
} } else {
else
{
_Scanner.AutoChange(); _Scanner.AutoChange();
Log.I(string.Format($"Next upload list : uploadList_{_WeldingScannerListNo}")); Log.I(string.Format($"Next upload list : uploadList_{_WeldingScannerListNo}"));
} }
@ -1018,18 +918,15 @@ namespace ILSOS_CCW_H52A.Sequences
return SequenceAction.Ok(); return SequenceAction.Ok();
} }
private SequenceActionResult RequestUnloadCell(SequenceContext context, string id, SequenceActionResult param) private SequenceActionResult RequestUnloadCell(SequenceContext context, string id, SequenceActionResult param) {
{
Status.SetWorkingPosition(eWorkingPosition.UNLOADING_CELL); Status.SetWorkingPosition(eWorkingPosition.UNLOADING_CELL);
return SequenceAction.Ok(); return SequenceAction.Ok();
} }
private SequenceActionResult EncoderMonitor(SequenceContext context, string id, SequenceActionResult param) private SequenceActionResult EncoderMonitor(SequenceContext context, string id, SequenceActionResult param) {
{
double send_time_offset = 0.1; double send_time_offset = 0.1;
while (!context.Stopped) while (!context.Stopped) {
{
double encoderX, currentAngle; double encoderX, currentAngle;
_Scanner.GetEncoder(out encoderX, out currentAngle, true); _Scanner.GetEncoder(out encoderX, out currentAngle, true);
double CurrentPosPLC = GetRotaryCurrentPosition(); double CurrentPosPLC = GetRotaryCurrentPosition();
@ -1042,17 +939,12 @@ namespace ILSOS_CCW_H52A.Sequences
// Shift()는 메인 시퀀스에서만 호출되므로 루프 시작 시 캡처해도 안전. // Shift()는 메인 시퀀스에서만 호출되므로 루프 시작 시 캡처해도 안전.
var executeTarget = _CellScheduler.Prefetch1; var executeTarget = _CellScheduler.Prefetch1;
if (WeldingInPosition) if (WeldingInPosition) {
{ if (executeTarget != null && executeTarget.IsCanExist && executeTarget.JigNo > 0) {
if (executeTarget != null && executeTarget.IsCanExist && executeTarget.JigNo > 0)
{
Log.I($"Fork Before Min Rotate Encoder X : ({encoderX}), Encoder Y : ({currentAngle}), PLC Rotary : ({CurrentPosPLC}), List {executeTarget.ListNo}, JigNo : ({executeTarget.JigNo})"); Log.I($"Fork Before Min Rotate Encoder X : ({encoderX}), Encoder Y : ({currentAngle}), PLC Rotary : ({CurrentPosPLC}), List {executeTarget.ListNo}, JigNo : ({executeTarget.JigNo})");
if (!_SystemParameter.BypassModeLBAD) if (!_SystemParameter.BypassModeLBAD) {
{ if (!executeTarget.CheckSendCellinfo) {
if (!executeTarget.CheckSendCellinfo) if (currentAngle > executeTarget.StartAngle) {
{
if (currentAngle > executeTarget.StartAngle)
{
executeTarget.CheckSendCellinfo = _StreamLightLBAD.SendCellInfo(executeTarget.LotId, executeTarget.CellId, _RecipeNo, _ModelNo, executeTarget.JigNo); executeTarget.CheckSendCellinfo = _StreamLightLBAD.SendCellInfo(executeTarget.LotId, executeTarget.CellId, _RecipeNo, _ModelNo, executeTarget.JigNo);
if (!executeTarget.CheckSendCellinfo) if (!executeTarget.CheckSendCellinfo)
@ -1067,10 +959,8 @@ namespace ILSOS_CCW_H52A.Sequences
var LaserIO = _IO._iOUnit.ReadDiBit(Convert.ToInt32(eADIAddress.LaserOn)); var LaserIO = _IO._iOUnit.ReadDiBit(Convert.ToInt32(eADIAddress.LaserOn));
//var IsLaserOn = ChangeChecker.IsChangedBoolMonitoring("LaserOn", LaserIO, true); //var IsLaserOn = ChangeChecker.IsChangedBoolMonitoring("LaserOn", LaserIO, true);
if (true) if (true) {
{ if (executeTarget != null && executeTarget.IsCanExist && executeTarget.WeldStartTime == DateTime.MinValue) {
if (executeTarget != null && executeTarget.IsCanExist && executeTarget.WeldStartTime == DateTime.MinValue)
{
executeTarget.WeldStartTime = DateTime.Now; executeTarget.WeldStartTime = DateTime.Now;
executeTarget.WeldComplete = true; executeTarget.WeldComplete = true;
Log.I($"Laser On, Welding Complete. JigNo : ({executeTarget.JigNo})"); Log.I($"Laser On, Welding Complete. JigNo : ({executeTarget.JigNo})");
@ -1083,8 +973,7 @@ namespace ILSOS_CCW_H52A.Sequences
eListNo effectiveList = (!isBusy && (curList == eListNo.LIST1 || curList == eListNo.LIST2)) eListNo effectiveList = (!isBusy && (curList == eListNo.LIST1 || curList == eListNo.LIST2))
? eListNo.NONE : curList; ? eListNo.NONE : curList;
if (ChangeChecker.IsChangedInt("ListState", (int)effectiveList, out int prevListRaw)) if (ChangeChecker.IsChangedInt("ListState", (int)effectiveList, out int prevListRaw)) {
{
var prevList = (eListNo)prevListRaw; var prevList = (eListNo)prevListRaw;
if (prevList != eListNo.NONE) if (prevList != eListNo.NONE)
Log.I($"[ListEnd] List {prevList} 종료 >> LaserOn({LaserIO}) EncoderY({currentAngle:F3}) JigNo({executeTarget?.JigNo})"); Log.I($"[ListEnd] List {prevList} 종료 >> LaserOn({LaserIO}) EncoderY({currentAngle:F3}) JigNo({executeTarget?.JigNo})");
@ -1092,10 +981,8 @@ namespace ILSOS_CCW_H52A.Sequences
Log.I($"[ListStart] List {effectiveList} 시작 >> LaserOn({LaserIO}) EncoderY({currentAngle:F3}) JigNo({executeTarget?.JigNo})"); Log.I($"[ListStart] List {effectiveList} 시작 >> LaserOn({LaserIO}) EncoderY({currentAngle:F3}) JigNo({executeTarget?.JigNo})");
} }
for (int i = 0; i < _RotaryJigCount; i++) for (int i = 0; i < _RotaryJigCount; i++) {
{ if (_PLC.ReadBit((int)eBitInput.PLC_USE_WELD_JIG_1 + i).data == false) {
if (_PLC.ReadBit((int)eBitInput.PLC_USE_WELD_JIG_1 + i).data == false)
{
_PLC.WriteBit((int)eBitOutput.PC_WELD_COMPLETE_1 + i, false); _PLC.WriteBit((int)eBitOutput.PC_WELD_COMPLETE_1 + i, false);
} }
} }
@ -1106,8 +993,7 @@ namespace ILSOS_CCW_H52A.Sequences
return SequenceAction.Ok(); return SequenceAction.Ok();
} }
private SequenceActionResult ReportCellResult(SequenceContext context, string id, SequenceActionResult param) private SequenceActionResult ReportCellResult(SequenceContext context, string id, SequenceActionResult param) {
{
Status.SetWorkingPosition(eWorkingPosition.REPORTING_RESULT); Status.SetWorkingPosition(eWorkingPosition.REPORTING_RESULT);
string strDate = DateTime.Now.Date.ToString("yyyyMMdd"); string strDate = DateTime.Now.Date.ToString("yyyyMMdd");
@ -1190,8 +1076,7 @@ namespace ILSOS_CCW_H52A.Sequences
// return SequenceAction.Ok(); // return SequenceAction.Ok();
//} //}
private static string CheckCycleStop(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param) private static string CheckCycleStop(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param) {
{
Status.SetWorkingPosition(eWorkingPosition.CHECKING_CYCLE); Status.SetWorkingPosition(eWorkingPosition.CHECKING_CYCLE);
// TODO: 확인 필요, CybleStop 에 대한 내용, cycle stop 여부 가져오기 // TODO: 확인 필요, CybleStop 에 대한 내용, cycle stop 여부 가져오기
@ -1201,22 +1086,17 @@ namespace ILSOS_CCW_H52A.Sequences
//Jin : cycleStop 명령을 용접 프로그램에서 할 경우가 현재는 없음.. //Jin : cycleStop 명령을 용접 프로그램에서 할 경우가 현재는 없음..
// CheckCycleStop 노드와 Complete 노드 사이 다른 노드가 필요하다면 해당 노드를 CheckCycleStop 노드 위로 올리자 // CheckCycleStop 노드와 Complete 노드 사이 다른 노드가 필요하다면 해당 노드를 CheckCycleStop 노드 위로 올리자
bool cycleStop = false; bool cycleStop = false;
if (cycleStop) if (cycleStop) {
{
return SEQ_SAVE_RESULT_DATA; return SEQ_SAVE_RESULT_DATA;
} } else {
else
{
return SEQ_CHECK_LOAD_COMPLETE; return SEQ_CHECK_LOAD_COMPLETE;
} }
} }
private string CheckCanWelded(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param) private string CheckCanWelded(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param) {
{
// ── 재시작 전 미완료 보고 우선 처리 ───────────────────────────────────────── // ── 재시작 전 미완료 보고 우선 처리 ─────────────────────────────────────────
// SavePendingComplete()로 보존된 슬롯이 있으면 정상 파이프라인(Complete)보다 우선. // SavePendingComplete()로 보존된 슬롯이 있으면 정상 파이프라인(Complete)보다 우선.
if (_CellScheduler.HasPendingComplete) if (_CellScheduler.HasPendingComplete) {
{
var p = _CellScheduler.PendingComplete; var p = _CellScheduler.PendingComplete;
Log.I($"[PendingReport] 재시작 전 미완료 보고: LotId={p.LotId}, CellId={p.CellId}, JigNo={p.JigNo}"); Log.I($"[PendingReport] 재시작 전 미완료 보고: LotId={p.LotId}, CellId={p.CellId}, JigNo={p.JigNo}");
return SEQ_REPORT_CELL_RESULT; return SEQ_REPORT_CELL_RESULT;
@ -1232,35 +1112,29 @@ namespace ILSOS_CCW_H52A.Sequences
return SEQ_CHECK_CYCLE_STOP; return SEQ_CHECK_CYCLE_STOP;
} }
private void SaveCellAPD() private void SaveCellAPD() {
{ if (Status.GetProcessingWeldingData().APD.Count > 0) {
if (Status.GetProcessingWeldingData().APD.Count > 0)
{
string directoryPath = "D:\\ILSOSConfig\\APD_History"; string directoryPath = "D:\\ILSOSConfig\\APD_History";
string fileName = DateTime.Now.ToString("HH") + "_CellAPD"; string fileName = DateTime.Now.ToString("HH") + "_CellAPD";
string fullPath = Path.Combine(directoryPath, Status.GetProcessingWeldingData().APD.First().Date.ToString("yyyy-MM-dd"), fileName); string fullPath = Path.Combine(directoryPath, Status.GetProcessingWeldingData().APD.First().Date.ToString("yyyy-MM-dd"), fileName);
Status.GetProcessingWeldingData().APD.CreateFiles(fullPath); Status.GetProcessingWeldingData().APD.CreateFiles(fullPath);
} }
} }
private SequenceActionResult SaveResultData(SequenceContext context, string id, SequenceActionResult param) private SequenceActionResult SaveResultData(SequenceContext context, string id, SequenceActionResult param) {
{
context.PutValue(ContextKey.KEY_SEQUENCE_RESULT, true); context.PutValue(ContextKey.KEY_SEQUENCE_RESULT, true);
return SequenceAction.Ok(); return SequenceAction.Ok();
} }
private SequenceActionResult WriteCompletionPLCBit(SequenceContext context, string id, SequenceActionResult param) private SequenceActionResult WriteCompletionPLCBit(SequenceContext context, string id, SequenceActionResult param) {
{
// 완료 비트 write 하는 Node 추가 필요. format 유지, ReceiveCellInfo 없음 // 완료 비트 write 하는 Node 추가 필요. format 유지, ReceiveCellInfo 없음
Log.D("AutoRun Sequence WriteCompletionPLCBit"); Log.D("AutoRun Sequence WriteCompletionPLCBit");
return SequenceAction.Ok(); return SequenceAction.Ok();
} }
private SequenceActionResult InitConditionError(SequenceContext context, string id, SequenceActionResult param) private SequenceActionResult InitConditionError(SequenceContext context, string id, SequenceActionResult param) {
{
context.TryGetValue(ContextKey.KEY_SEQUENCE_ERROR_CODE, out int InitializeCode); context.TryGetValue(ContextKey.KEY_SEQUENCE_ERROR_CODE, out int InitializeCode);
switch (InitializeCode) switch (InitializeCode) {
{
case (int)InitErrorList.PLC_AUTORUN_BIT_OFF: case (int)InitErrorList.PLC_AUTORUN_BIT_OFF:
Log.D("AutoRun Sequence InitConditionError : PLC_AUTORUN_OFF"); Log.D("AutoRun Sequence InitConditionError : PLC_AUTORUN_OFF");
return SequenceAction.ForceStopByAlarm(AlarmCode.ALARM_SEQUENCE_AutoRun_CheckInitCondition_PLC_AUTORUN_OFF); return SequenceAction.ForceStopByAlarm(AlarmCode.ALARM_SEQUENCE_AutoRun_CheckInitCondition_PLC_AUTORUN_OFF);
@ -1285,8 +1159,7 @@ namespace ILSOS_CCW_H52A.Sequences
} }
} }
private SequenceActionResult Complete(SequenceContext context, string id, SequenceActionResult param) private SequenceActionResult Complete(SequenceContext context, string id, SequenceActionResult param) {
{
RestoreDeviceStatus(); RestoreDeviceStatus();
context.Settings.Save(CommonSettingIds.SystemParameter, _SystemParameter, "SeqAutoRunCCWH52A"); context.Settings.Save(CommonSettingIds.SystemParameter, _SystemParameter, "SeqAutoRunCCWH52A");
@ -1294,8 +1167,7 @@ namespace ILSOS_CCW_H52A.Sequences
context.TryGetValue(ContextKey.KEY_SEQUENCE_RESULT, out bool seqResult); context.TryGetValue(ContextKey.KEY_SEQUENCE_RESULT, out bool seqResult);
SeqAutoRunCCWH52A_OutParam result = new SeqAutoRunCCWH52A_OutParam() { Success = seqResult }; SeqAutoRunCCWH52A_OutParam result = new SeqAutoRunCCWH52A_OutParam() { Success = seqResult };
if (seqResult == false) if (seqResult == false) {
{
//AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_AutoRun_ResultFailed); //AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_AutoRun_ResultFailed);
} }
Log.D("AutoRun Sequence Complete"); Log.D("AutoRun Sequence Complete");
@ -1304,11 +1176,9 @@ namespace ILSOS_CCW_H52A.Sequences
return SequenceAction.Ok(result); return SequenceAction.Ok(result);
} }
private bool RestoreDeviceStatus() private bool RestoreDeviceStatus() {
{
//PLC All BIT OFF //PLC All BIT OFF
for (int i = 0; i < _RotaryJigCount; i++) for (int i = 0; i < _RotaryJigCount; i++) {
{
_PLC.WriteBit((int)eBitOutput.PC_WELD_COMPLETE_1 + i, false); _PLC.WriteBit((int)eBitOutput.PC_WELD_COMPLETE_1 + i, false);
} }
_PLC.WriteBit((int)eBitOutput.PC_AUTO_STATUS, false); _PLC.WriteBit((int)eBitOutput.PC_AUTO_STATUS, false);
@ -1317,10 +1187,8 @@ namespace ILSOS_CCW_H52A.Sequences
//LBAD Ready Off //LBAD Ready Off
//_LBAD.SetReadybyAuto(false); //_LBAD.SetReadybyAuto(false);
if (_SystemParameter.BypassModeLBAD == false) if (_SystemParameter.BypassModeLBAD == false) {
{ if (_StreamLightLBAD.SendReadyStatus(eRequestData.Ready_Off) == false) {
if (_StreamLightLBAD.SendReadyStatus(eRequestData.Ready_Off) == false)
{
Log.I(string.Format($"[LBAD Interface]CheckReadyStatus null")); Log.I(string.Format($"[LBAD Interface]CheckReadyStatus null"));
} }
} }
@ -1347,8 +1215,7 @@ namespace ILSOS_CCW_H52A.Sequences
return true; return true;
} }
private void OnForceError(SequenceContext context, string arg2) private void OnForceError(SequenceContext context, string arg2) {
{
context.Settings.Save(CommonSettingIds.SystemParameter, _SystemParameter, "SeqAutoRunCCWH52A"); context.Settings.Save(CommonSettingIds.SystemParameter, _SystemParameter, "SeqAutoRunCCWH52A");
OnSeqActionStop(); OnSeqActionStop();
@ -1356,8 +1223,7 @@ namespace ILSOS_CCW_H52A.Sequences
Log.I("SequenceAction Ok : OnForceError"); Log.I("SequenceAction Ok : OnForceError");
} }
private void OnStopped(SequenceContext context) private void OnStopped(SequenceContext context) {
{
context.Settings.Save(CommonSettingIds.SystemParameter, _SystemParameter, "SeqAutoRunCCWH52A"); context.Settings.Save(CommonSettingIds.SystemParameter, _SystemParameter, "SeqAutoRunCCWH52A");
OnSeqActionStop(); OnSeqActionStop();
@ -1365,12 +1231,10 @@ namespace ILSOS_CCW_H52A.Sequences
Log.I("SequenceAction Ok : OnStopped"); Log.I("SequenceAction Ok : OnStopped");
} }
private void OnSeqActionStop() private void OnSeqActionStop() {
{
Status.EquipmentMode = eEquipmentMode.MANUAL; Status.EquipmentMode = eEquipmentMode.MANUAL;
foreach (var info in ProcessManager.Instance.ReceivedCellInfoQueue.Select((value, index) => (value, index))) foreach (var info in ProcessManager.Instance.ReceivedCellInfoQueue.Select((value, index) => (value, index))) {
{
Log.I($"[{info.index}]Queue >> CellId({info.value.CellId}) LotId({info.value.LotId})"); Log.I($"[{info.index}]Queue >> CellId({info.value.CellId}) LotId({info.value.LotId})");
} }
@ -1388,10 +1252,8 @@ namespace ILSOS_CCW_H52A.Sequences
//LBAD Ready Off //LBAD Ready Off
//_LBAD.SetReadybyAuto(false); //_LBAD.SetReadybyAuto(false);
if (_SystemParameter.BypassModeLBAD == false) if (_SystemParameter.BypassModeLBAD == false) {
{ if (_StreamLightLBAD.SendReadyStatus(eRequestData.Ready_Off) == false) {
if (_StreamLightLBAD.SendReadyStatus(eRequestData.Ready_Off) == false)
{
Log.I(string.Format($"[LBAD Interface]CheckReadyStatus null")); Log.I(string.Format($"[LBAD Interface]CheckReadyStatus null"));
} }
} }
@ -1418,23 +1280,20 @@ namespace ILSOS_CCW_H52A.Sequences
} }
// For CSV 저장용 // For CSV 저장용
public class CenterPositionData : NotifyPropertyChangedBase public class CenterPositionData : NotifyPropertyChangedBase {
{
private double _CenterX; private double _CenterX;
public double CenterX { get => _CenterX; set => SetProperty(ref _CenterX, value); } public double CenterX { get => _CenterX; set => SetProperty(ref _CenterX, value); }
private double _CenterY; private double _CenterY;
public double CenterY { get => _CenterY; set => SetProperty(ref _CenterY, value); } public double CenterY { get => _CenterY; set => SetProperty(ref _CenterY, value); }
} }
public class SeqAutoRunCCWH52A_InitParam : InitParam public class SeqAutoRunCCWH52A_InitParam : InitParam {
{
public ScoutSeqParams ScoutSeqParams { get; set; } public ScoutSeqParams ScoutSeqParams { get; set; }
public bool UseStream { get; set; } public bool UseStream { get; set; }
} }
public class SeqAutoRunCCWH52A_OutParam : OutParam public class SeqAutoRunCCWH52A_OutParam : OutParam {
{
} }
} }