[bugfix] 재시작할때 미보고 발생하는 케이스 수정
- pending(보류) data 추가 - Reset을 해야하는 이유는 최초 2번의 WeldingListUpload를 하기 위해 필요함 - Reset을 하니까 pending data 영역이 필요해짐 자동 시퀀스 간소화 - Sub Sequence를 자동 시퀀스 내에 함수 단위로 변경함 .receive / report..
This commit is contained in:
parent
614b5f1a5b
commit
6279c02cd6
@ -28,6 +28,8 @@ namespace AuroraCellTracker
|
|||||||
public int LotIdStartNo { get; set; }
|
public int LotIdStartNo { get; set; }
|
||||||
public int LotIdLength { get; set; }
|
public int LotIdLength { get; set; }
|
||||||
public int CellIdReceiveMethod { get; set; }
|
public int CellIdReceiveMethod { get; set; }
|
||||||
|
[DirectoryPath]
|
||||||
|
public string reportDataLocalPath { get; set; } = "D:\\ILSOSConfig\\_device\\_cellTracker\\";
|
||||||
|
public string EquipmentName { get; set; } = "CCW";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,8 @@ namespace AuroraCellTracker.DaekhonCoporation
|
|||||||
Logger _Logger = new Logger("CellTrackerDaekhon");
|
Logger _Logger = new Logger("CellTrackerDaekhon");
|
||||||
private const string REG_PATH = @"Software\H52A\H52A_ADPT_CELL";
|
private const string REG_PATH = @"Software\H52A\H52A_ADPT_CELL";
|
||||||
|
|
||||||
|
public event Action<string, string> OnCellReceived;
|
||||||
|
|
||||||
public CellInfoStr CellInfoStrings { get; set; } = new CellInfoStr();
|
public CellInfoStr CellInfoStrings { get; set; } = new CellInfoStr();
|
||||||
public ConcurrentQueue<CellInfoStr> CellInfoQueue { get; set; } = new ConcurrentQueue<CellInfoStr>();
|
public ConcurrentQueue<CellInfoStr> CellInfoQueue { get; set; } = new ConcurrentQueue<CellInfoStr>();
|
||||||
|
|
||||||
@ -318,6 +320,7 @@ namespace AuroraCellTracker.DaekhonCoporation
|
|||||||
|
|
||||||
CalcCellInfo(str, out lotId, out cellId);
|
CalcCellInfo(str, out lotId, out cellId);
|
||||||
AddCellInfo(lotId, cellId);
|
AddCellInfo(lotId, cellId);
|
||||||
|
OnCellReceived?.Invoke(lotId, cellId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
_Logger.E(string.Format($"{e.Message}"));
|
_Logger.E(string.Format($"{e.Message}"));
|
||||||
}
|
}
|
||||||
@ -339,6 +342,7 @@ namespace AuroraCellTracker.DaekhonCoporation
|
|||||||
|
|
||||||
//CalcCellInfo(str, out lotId, out cellId);
|
//CalcCellInfo(str, out lotId, out cellId);
|
||||||
AddCellInfo(lotId, cellId);
|
AddCellInfo(lotId, cellId);
|
||||||
|
OnCellReceived?.Invoke(lotId, cellId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
_Logger.E(string.Format($"{e.Message}"));
|
_Logger.E(string.Format($"{e.Message}"));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,12 @@ namespace AuroraCellTracker
|
|||||||
{
|
{
|
||||||
public interface ICellTracker
|
public interface ICellTracker
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// DllSocket_ReceiveDataBuffer에서 lotId/cellId 파싱 완료 시 발화.
|
||||||
|
/// ProcessManager 등 외부에서 구독하여 직접 수신 가능.
|
||||||
|
/// </summary>
|
||||||
|
event Action<string, string> OnCellReceived;
|
||||||
|
|
||||||
void Initialize(eMode mode, string dllDirectory);
|
void Initialize(eMode mode, string dllDirectory);
|
||||||
void Close();
|
void Close();
|
||||||
void CheckDllStatus();
|
void CheckDllStatus();
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
|
using Aurora.Api;
|
||||||
|
using Aurora.Util.HislogPlus;
|
||||||
|
using ILSOS_CCW_H52A.Data;
|
||||||
|
using ILSOS_CCW_H52A.Sequences;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using ILSOS_CCW_H52A.Sequences;
|
|
||||||
using ILSOS_CCW_H52A.Data;
|
|
||||||
|
|
||||||
namespace ILSOS_CCW_H52A.Data
|
namespace ILSOS_CCW_H52A.Data
|
||||||
{
|
{
|
||||||
@ -15,7 +17,7 @@ namespace ILSOS_CCW_H52A.Data
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Dictionary<eJigNo, JigInfo> 상속으로 물리 지그 번호 직접 접근과
|
/// Dictionary<eJigNo, JigInfo> 상속으로 물리 지그 번호 직접 접근과
|
||||||
/// 파이프라인 단계 접근을 동시에 지원하는 셀 스케줄러.
|
/// 파이프라인 단계 접근을 동시에 지원하는 셀 스케줄러.
|
||||||
///
|
///
|
||||||
/// - 물리 지그 접근: scheduler[eJigNo.Jig5]
|
/// - 물리 지그 접근: scheduler[eJigNo.Jig5]
|
||||||
@ -31,6 +33,7 @@ namespace ILSOS_CCW_H52A.Data
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class CellInfoScheduler : Dictionary<eJigNo, JigInfo>
|
public class CellInfoScheduler : Dictionary<eJigNo, JigInfo>
|
||||||
{
|
{
|
||||||
|
private readonly Logger _log = new Logger("CellInfoScheduler");
|
||||||
public JigInfo Prefetch2 { get; private set; } // 전전 셀: 셀 정보 수신, 업로드 전
|
public JigInfo Prefetch2 { get; private set; } // 전전 셀: 셀 정보 수신, 업로드 전
|
||||||
public JigInfo Prefetch1 { get; private set; } // 전 셀: 업로드 완료, 실행 중 / 완료 체크 대상
|
public JigInfo Prefetch1 { get; private set; } // 전 셀: 업로드 완료, 실행 중 / 완료 체크 대상
|
||||||
|
|
||||||
@ -38,23 +41,27 @@ namespace ILSOS_CCW_H52A.Data
|
|||||||
public JigInfo ReportTarget { get; set; }
|
public JigInfo ReportTarget { get; set; }
|
||||||
|
|
||||||
// 재시작 보존용 독립 슬롯 — Reset()에서 건드리지 않음
|
// 재시작 보존용 독립 슬롯 — Reset()에서 건드리지 않음
|
||||||
private readonly JigInfo _pendingSlot = new JigInfo();
|
// 재시작 시, List를 최초 리스트 2번을 생성하는 로직 때문에.. 필요함
|
||||||
|
private readonly JigInfo _pendingSlot = new JigInfo(); // 용접 직후 (용접 완, 보고 미완)
|
||||||
|
private readonly JigInfo _pendingPrefetch1 = new JigInfo(); // 정지 직전 Prefetch1 (업로드 완료, 용접 미완)
|
||||||
|
private readonly JigInfo _pendingPrefetch2 = new JigInfo(); // 정지 직전 Prefetch2 (업로드 완료, 용접 미완)
|
||||||
|
|
||||||
// 재시작 전 미완료 보고 슬롯 (유효 시 non-null)
|
// 재시작 전 미완료 보고 슬롯 (유효 시 non-null)
|
||||||
public JigInfo PendingComplete => HasPendingComplete ? _pendingSlot : null;
|
public JigInfo PendingComplete => HasPendingComplete ? _pendingSlot : null;
|
||||||
|
|
||||||
// 재시작 보존 보고가 있는지
|
// 재시작 보존 보고가 있는지
|
||||||
public bool HasPendingComplete
|
public bool HasPendingComplete => _pendingSlot.IsCanExist && !_pendingSlot.ReportComplete;
|
||||||
=> _pendingSlot.IsCanExist && !_pendingSlot.ReportComplete;
|
|
||||||
|
|
||||||
// 현재 활성 보고 슬롯 — 재시작 pending 우선
|
// 현재 활성 보고 슬롯 — 재시작 pending 우선
|
||||||
public JigInfo ActiveReportSlot
|
public JigInfo ActiveReportSlot => HasPendingComplete ? _pendingSlot : ReportTarget;
|
||||||
=> HasPendingComplete ? _pendingSlot : ReportTarget;
|
|
||||||
|
|
||||||
// 보고가 필요한 상태인지 (정상 + 재시작 모두 포함)
|
// 정지 전 미용접 슬롯이 보존돼 있는지 (재시작 후 복원 가능 여부)
|
||||||
public bool HasReport
|
public bool HasPendingPrefetch =>
|
||||||
=> HasPendingComplete
|
!string.IsNullOrEmpty(_pendingPrefetch1.CellId)
|
||||||
|| (ReportTarget != null && !ReportTarget.ReportComplete);
|
|| !string.IsNullOrEmpty(_pendingPrefetch2.CellId);
|
||||||
|
|
||||||
|
// 보고가 필요한 상태인지 (정상 + 재시작 모두 포함) >> 용접 완, 보고 미완
|
||||||
|
public bool HasReport => HasPendingComplete || (ReportTarget != null && !ReportTarget.ReportComplete);
|
||||||
|
|
||||||
public CellInfoScheduler()
|
public CellInfoScheduler()
|
||||||
{
|
{
|
||||||
@ -62,17 +69,63 @@ namespace ILSOS_CCW_H52A.Data
|
|||||||
Add(no, new JigInfo());
|
Add(no, new JigInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1-based jigNo (_WeldingJigNo 등) → 0-based eJigNo 변환 편의 인덱서
|
// 1-based jigNo (_WeldingJigNo 등) → 0-based eJigNo 변환 의의 인덱서
|
||||||
public JigInfo this[int jigNo] {
|
public JigInfo this[int jigNo] {
|
||||||
get => base[(eJigNo)(jigNo - 1)];
|
get => base[(eJigNo)(jigNo - 1)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset() 전에 호출 — 미완료 보고가 있으면 보류 슬롯(_pendingSlot)에 복사하여 보존.
|
// Reset() 전에 호출 — 미완료 보고 및 미용접 슬롯을 보존.
|
||||||
public void SavePendingComplete()
|
public void SavePendingComplete()
|
||||||
{
|
{
|
||||||
if (ReportTarget != null && ReportTarget.IsCanExist
|
// 용접 완료됐으나 보고 전 정지된 경우 (_pendingSlot)
|
||||||
&& ReportTarget.WeldComplete && !ReportTarget.ReportComplete)
|
if (ReportTarget != null
|
||||||
|
&& ReportTarget.IsCanExist
|
||||||
|
&& ReportTarget.WeldComplete
|
||||||
|
&& !ReportTarget.ReportComplete)
|
||||||
_pendingSlot.CopyFrom(ReportTarget);
|
_pendingSlot.CopyFrom(ReportTarget);
|
||||||
|
|
||||||
|
// 업로드 완료됐으나 로터리 정지로 용접 자체가 안 된 경우 (_pendingPrefetch1/2)
|
||||||
|
// (연속셀이 들어왔을때, 중간에 멈춘 경우)
|
||||||
|
if (Prefetch1 != null
|
||||||
|
&& Prefetch1.IsCanExist
|
||||||
|
&& !string.IsNullOrEmpty(Prefetch1.CellId)
|
||||||
|
&& !Prefetch1.WeldComplete)
|
||||||
|
_pendingPrefetch1.CopyFrom(Prefetch1);
|
||||||
|
else
|
||||||
|
_pendingPrefetch1.Clear();
|
||||||
|
|
||||||
|
if (Prefetch2 != null
|
||||||
|
&& Prefetch2.IsCanExist
|
||||||
|
&& !string.IsNullOrEmpty(Prefetch2.CellId)
|
||||||
|
&& !Prefetch2.WeldComplete)
|
||||||
|
_pendingPrefetch2.CopyFrom(Prefetch2);
|
||||||
|
else
|
||||||
|
_pendingPrefetch2.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 재시작 시 해당 JigNo의 보존된 셀 정보 복원 시도.
|
||||||
|
/// 성공 시 해당 슬롯을 즉시 클리어하여 한 번만 사용되도록 보장.
|
||||||
|
/// canExist=false 지그가 들어오면 슬롯을 소비(폐기)하여 이후 오염 방지.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>복원 성공 시 true (ReceivedCellInfoQueue TryDequeue 불필요)</returns>
|
||||||
|
public bool TryRestoreCell(int jigNo, out string lotId, out string cellId)
|
||||||
|
{
|
||||||
|
if (_pendingPrefetch1.JigNo == jigNo && !string.IsNullOrEmpty(_pendingPrefetch1.CellId)) {
|
||||||
|
lotId = _pendingPrefetch1.LotId;
|
||||||
|
cellId = _pendingPrefetch1.CellId;
|
||||||
|
_pendingPrefetch1.Clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (_pendingPrefetch2.JigNo == jigNo && !string.IsNullOrEmpty(_pendingPrefetch2.CellId)) {
|
||||||
|
lotId = _pendingPrefetch2.LotId;
|
||||||
|
cellId = _pendingPrefetch2.CellId;
|
||||||
|
_pendingPrefetch2.Clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
lotId = null;
|
||||||
|
cellId = null;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 보고 완료 처리 — ReportTarget 마킹 및 _pendingSlot 클리어.
|
// 보고 완료 처리 — ReportTarget 마킹 및 _pendingSlot 클리어.
|
||||||
@ -90,6 +143,13 @@ namespace ILSOS_CCW_H52A.Data
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="nextJig">새 Prefetch2로 지정할 물리 지그 (eJigNo)</param>
|
/// <param name="nextJig">새 Prefetch2로 지정할 물리 지그 (eJigNo)</param>
|
||||||
public void Shift(eJigNo nextJig)
|
public void Shift(eJigNo nextJig)
|
||||||
|
{
|
||||||
|
Prefetch1 = Prefetch2;
|
||||||
|
Prefetch2 = base[nextJig];
|
||||||
|
Prefetch2.Clear();
|
||||||
|
}
|
||||||
|
// AutoRun에서 사용되는 자료형으로 추가 (편의 인덱서 사용)
|
||||||
|
public void Shift(int nextJig)
|
||||||
{
|
{
|
||||||
Prefetch1 = Prefetch2;
|
Prefetch1 = Prefetch2;
|
||||||
Prefetch2 = this[nextJig];
|
Prefetch2 = this[nextJig];
|
||||||
@ -99,7 +159,7 @@ namespace ILSOS_CCW_H52A.Data
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 전체 초기화 (AutoRun 시작 시 호출).
|
/// 전체 초기화 (AutoRun 시작 시 호출).
|
||||||
/// SavePendingComplete() 호출 후 이 메서드를 호출할 것.
|
/// SavePendingComplete() 호출 후 이 메서드를 호출할 것.
|
||||||
/// _pendingSlot은 재시작 보고 보존을 위해 건드리지 않음.
|
/// _pendingSlot / _pendingPrefetch1 / _pendingPrefetch2 는 재시작 복원을 위해 건드리지 않음.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
@ -109,7 +169,7 @@ namespace ILSOS_CCW_H52A.Data
|
|||||||
Prefetch2 = null;
|
Prefetch2 = null;
|
||||||
Prefetch1 = null;
|
Prefetch1 = null;
|
||||||
ReportTarget = null;
|
ReportTarget = null;
|
||||||
// _pendingSlot: SavePendingComplete()가 복사해 둔 데이터를 유지
|
// _pendingSlot, _pendingPrefetch1/2: SavePendingComplete()가 복사해 둔 데이터를 유지
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -23,13 +23,12 @@ namespace ILSOS_CCW_H52A.Data
|
|||||||
public DateTime WeldEndTime;
|
public DateTime WeldEndTime;
|
||||||
public TimeSpan WeldingSpanTime; // 스캐너 리스트 실행 시간 (GetTime() 결과)
|
public TimeSpan WeldingSpanTime; // 스캐너 리스트 실행 시간 (GetTime() 결과)
|
||||||
|
|
||||||
// --- CellTracker 수신 정보 (GetReceiveCellInfo_SeqResult에서 채워짐) ---
|
// CellTracker 수신 정보
|
||||||
public string LotId;
|
public string LotId;
|
||||||
public string CellId;
|
public string CellId;
|
||||||
|
|
||||||
// --- 플래그 ---
|
// --- 플래그 ---
|
||||||
public bool CheckSendCellinfo;
|
public bool CheckSendCellinfo;
|
||||||
public bool CheckSendPLCLaserPower;
|
|
||||||
public bool ReportComplete;
|
public bool ReportComplete;
|
||||||
|
|
||||||
// --- 리포팅/뷰 용 상세 정보 ---
|
// --- 리포팅/뷰 용 상세 정보 ---
|
||||||
@ -48,22 +47,21 @@ namespace ILSOS_CCW_H52A.Data
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void CopyFrom(JigInfo src)
|
public void CopyFrom(JigInfo src)
|
||||||
{
|
{
|
||||||
JigNo = src.JigNo;
|
JigNo = src.JigNo;
|
||||||
ListNo = src.ListNo;
|
ListNo = src.ListNo;
|
||||||
WriteTime = src.WriteTime;
|
WriteTime = src.WriteTime;
|
||||||
StartAngle = src.StartAngle;
|
StartAngle = src.StartAngle;
|
||||||
WeldingCount = src.WeldingCount;
|
WeldingCount = src.WeldingCount;
|
||||||
IsCanExist = src.IsCanExist;
|
IsCanExist = src.IsCanExist;
|
||||||
IsWelding = src.IsWelding;
|
IsWelding = src.IsWelding;
|
||||||
WeldComplete = src.WeldComplete;
|
WeldComplete = src.WeldComplete;
|
||||||
WeldStartTime = src.WeldStartTime;
|
WeldStartTime = src.WeldStartTime;
|
||||||
WeldEndTime = src.WeldEndTime;
|
WeldEndTime = src.WeldEndTime;
|
||||||
WeldingSpanTime = src.WeldingSpanTime;
|
WeldingSpanTime = src.WeldingSpanTime;
|
||||||
LotId = src.LotId;
|
LotId = src.LotId;
|
||||||
CellId = src.CellId;
|
CellId = src.CellId;
|
||||||
CheckSendCellinfo = src.CheckSendCellinfo;
|
CheckSendCellinfo = src.CheckSendCellinfo;
|
||||||
CheckSendPLCLaserPower = src.CheckSendPLCLaserPower;
|
ReportComplete = src.ReportComplete;
|
||||||
ReportComplete = src.ReportComplete;
|
|
||||||
UpdateCellInfo(src.InnerCellInfo);
|
UpdateCellInfo(src.InnerCellInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,40 +79,17 @@ namespace ILSOS_CCW_H52A.Data
|
|||||||
IsCanExist = false;
|
IsCanExist = false;
|
||||||
IsWelding = false;
|
IsWelding = false;
|
||||||
WeldComplete = false;
|
WeldComplete = false;
|
||||||
WeldStartTime = DateTime.MinValue;
|
WeldStartTime = DateTime.MinValue;
|
||||||
WeldEndTime = DateTime.MinValue;
|
WeldEndTime = DateTime.MinValue;
|
||||||
WeldingSpanTime = TimeSpan.Zero;
|
WeldingSpanTime = TimeSpan.Zero;
|
||||||
|
|
||||||
LotId = string.Empty;
|
LotId = string.Empty;
|
||||||
CellId = string.Empty;
|
CellId = string.Empty;
|
||||||
|
|
||||||
CheckSendCellinfo = false;
|
CheckSendCellinfo = false;
|
||||||
CheckSendPLCLaserPower = false;
|
|
||||||
ReportComplete = false;
|
ReportComplete = false;
|
||||||
|
|
||||||
InnerCellInfo.CellId = string.Empty;
|
InnerCellInfo.Clear();
|
||||||
InnerCellInfo.LotId = string.Empty;
|
|
||||||
InnerCellInfo.AutoRunStartTime = DateTime.MinValue;
|
|
||||||
InnerCellInfo.WeldingStartTime = DateTime.MinValue;
|
|
||||||
InnerCellInfo.WeldingEndTime = DateTime.MinValue;
|
|
||||||
InnerCellInfo.WeldingSpanTimeMilliseconds = string.Empty;
|
|
||||||
InnerCellInfo.TodayProduct = 0;
|
|
||||||
InnerCellInfo.TotalProduct = 0;
|
|
||||||
InnerCellInfo.RecipeNo = 0;
|
|
||||||
InnerCellInfo.WeldStartTime = string.Empty;
|
|
||||||
InnerCellInfo.WeldTime = string.Empty;
|
|
||||||
InnerCellInfo.WorkCellId = string.Empty;
|
|
||||||
InnerCellInfo.WorkLotId = string.Empty;
|
|
||||||
InnerCellInfo.LBAD_Judge = string.Empty;
|
|
||||||
InnerCellInfo.LDD_Judge = string.Empty;
|
|
||||||
InnerCellInfo.LaserPowerCore = string.Empty;
|
|
||||||
InnerCellInfo.LaserPowerRing = string.Empty;
|
|
||||||
InnerCellInfo.MarkSpeed = string.Empty;
|
|
||||||
InnerCellInfo.FocalLength = string.Empty;
|
|
||||||
InnerCellInfo.WeldingJigNo = string.Empty;
|
|
||||||
InnerCellInfo.LaserPowerByLBAD = string.Empty;
|
|
||||||
InnerCellInfo.CheckCanExist = false;
|
|
||||||
InnerCellInfo.CheckScannerListEnd = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
using Aurora;
|
using Aurora;
|
||||||
using Aurora.Api;
|
using Aurora.Api;
|
||||||
using Aurora.Util.HislogPlus;
|
using Aurora.Util.HislogPlus;
|
||||||
|
using AuroraCellTracker;
|
||||||
using AuroraLaserScanner;
|
using AuroraLaserScanner;
|
||||||
using AuroraPLC;
|
using AuroraPLC;
|
||||||
using ILSOS_CCW_H52A.Data;
|
using ILSOS_CCW_H52A.Data;
|
||||||
using ILSOS_CCW_H52A.Device;
|
using ILSOS_CCW_H52A.Device;
|
||||||
|
using OpenCvSharp;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -38,9 +40,15 @@ namespace ILSOS_CCW_H52A.Sequences.ProcessObjects
|
|||||||
private IAuroraEnvironment _env;
|
private IAuroraEnvironment _env;
|
||||||
private PLCControllerCCWH52A _plc;
|
private PLCControllerCCWH52A _plc;
|
||||||
private ScannerCCWH52A _scanner;
|
private ScannerCCWH52A _scanner;
|
||||||
|
private CellTracker _cellTracker;
|
||||||
|
|
||||||
public CellInfoScheduler cellScheduler { get; set; }
|
public CellInfoScheduler cellScheduler { get; set; }
|
||||||
|
|
||||||
|
/// CellTracker 콜백에서 직접 수신한 (LotId, CellId) 큐.
|
||||||
|
/// DllSocket_ReceiveDataBuffer 발화 시 즉시 Enqueue — 시퀀스는 TryDequeue로 소비.
|
||||||
|
public ConcurrentQueue<(string LotId, string CellId)> ReceivedCellInfoQueue { get; }
|
||||||
|
= new ConcurrentQueue<(string, string)>();
|
||||||
|
|
||||||
public const double compensateEncoderReset = 0.015; // 엔코더 리셋 보상 각도 설정(70도/sec 기준 약 0.015도)
|
public const double compensateEncoderReset = 0.015; // 엔코더 리셋 보상 각도 설정(70도/sec 기준 약 0.015도)
|
||||||
public const int RotaryJigCount = 16;
|
public const int RotaryJigCount = 16;
|
||||||
public const int RotaryMaxAngle = 360;
|
public const int RotaryMaxAngle = 360;
|
||||||
@ -53,8 +61,21 @@ namespace ILSOS_CCW_H52A.Sequences.ProcessObjects
|
|||||||
_env = env;
|
_env = env;
|
||||||
_plc = _env.DeviceManager[DeviceIds.PLCDevice] as PLCControllerCCWH52A;
|
_plc = _env.DeviceManager[DeviceIds.PLCDevice] as PLCControllerCCWH52A;
|
||||||
_scanner = _env.DeviceManager[DeviceIds.Scanner] as ScannerCCWH52A;
|
_scanner = _env.DeviceManager[DeviceIds.Scanner] as ScannerCCWH52A;
|
||||||
|
_cellTracker = _env.DeviceManager[CommonDeviceIds.CellTracker] as CellTracker;
|
||||||
|
|
||||||
|
//CellTracker의 OnCellReceived 이벤트를 구독하여 콜백 수신 시 CellQueue에 직접 적재
|
||||||
|
if (_cellTracker._CellTracker != null)
|
||||||
|
_cellTracker._CellTracker.OnCellReceived += OnCellReceived;
|
||||||
|
|
||||||
cellScheduler = new CellInfoScheduler();
|
cellScheduler = new CellInfoScheduler();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnCellReceived(string lotId, string cellId)
|
||||||
|
{
|
||||||
|
ReceivedCellInfoQueue.Enqueue((lotId, cellId));
|
||||||
|
_log.I($"Cell Tracker CallBack Received >> LotId({lotId}) / CellId({cellId})");
|
||||||
|
}
|
||||||
|
|
||||||
public IEnumerable<bool> CheckRotaryState()
|
public IEnumerable<bool> CheckRotaryState()
|
||||||
{
|
{
|
||||||
List<bool> rotaryStates = new List<bool>();
|
List<bool> rotaryStates = new List<bool>();
|
||||||
|
|||||||
@ -19,6 +19,8 @@ using ILSOS_CCW_H52A.Device;
|
|||||||
using ILSOS_CCW_H52A.Models;
|
using ILSOS_CCW_H52A.Models;
|
||||||
using ILSOS_CCW_H52A.RMS;
|
using ILSOS_CCW_H52A.RMS;
|
||||||
using ILSOS_CCW_H52A.Sequences.ProcessObjects;
|
using ILSOS_CCW_H52A.Sequences.ProcessObjects;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
using OpenCvSharp;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -26,6 +28,7 @@ using System.Linq;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Media.Animation;
|
||||||
using WeldingCommon;
|
using WeldingCommon;
|
||||||
using WeldingCommon.Alarm;
|
using WeldingCommon.Alarm;
|
||||||
using WeldingCommon.Devices;
|
using WeldingCommon.Devices;
|
||||||
@ -57,9 +60,9 @@ namespace ILSOS_CCW_H52A.Sequences
|
|||||||
public const string SEQ_CHECK_SCANNER_LIST_COMPLETE = "[SeqAutoRunCCWH52A] Check Scanner List Complete";
|
public const string SEQ_CHECK_SCANNER_LIST_COMPLETE = "[SeqAutoRunCCWH52A] Check Scanner List Complete";
|
||||||
const string SEQ_READY_SCANNER_LIST = "[SeqAutoRunCCWH52A] Ready ScannerList";
|
const string SEQ_READY_SCANNER_LIST = "[SeqAutoRunCCWH52A] Ready ScannerList";
|
||||||
|
|
||||||
const string SEQ_SET_PARAMS_RECEIVE_CELL_INFO_SEQ = "[SeqAutoRunCCWH52A] Set Sequence Param (ReceiveCellInfo Seq)";
|
//const string SEQ_SET_PARAMS_RECEIVE_CELL_INFO_SEQ = "[SeqAutoRunCCWH52A] Set Sequence Param (ReceiveCellInfo Seq)";
|
||||||
const string SEQ_DO_ID_RECEIVE_CELL_INFO_SEQ = "[SeqAutoRunCCWH52A] Process (ReceiveCellInfo Seq)";
|
//const string SEQ_DO_ID_RECEIVE_CELL_INFO_SEQ = "[SeqAutoRunCCWH52A] Process (ReceiveCellInfo Seq)";
|
||||||
const string SEQ_GET_PARAMS_RECEIVE_CELL_INFO_SEQ = "[SeqAutoRunCCWH52A] Get Sequence Result (ReceiveCellInfo Seq)";
|
//const string SEQ_GET_PARAMS_RECEIVE_CELL_INFO_SEQ = "[SeqAutoRunCCWH52A] Get Sequence Result (ReceiveCellInfo Seq)";
|
||||||
|
|
||||||
const string SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ = "[SeqAutoRunCCWH52A] Set Sequence Param (UploadWeldingList Seq)";
|
const string SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ = "[SeqAutoRunCCWH52A] Set Sequence Param (UploadWeldingList Seq)";
|
||||||
const string SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ = "[SeqAutoRunCCWH52A] Process (UploadWeldingList Seq)";
|
const string SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ = "[SeqAutoRunCCWH52A] Process (UploadWeldingList Seq)";
|
||||||
@ -68,10 +71,11 @@ namespace ILSOS_CCW_H52A.Sequences
|
|||||||
const string SEQ_EXECUTE_WELDING = "[SeqAutoRunCCWH52A] Execute Welding";
|
const string SEQ_EXECUTE_WELDING = "[SeqAutoRunCCWH52A] Execute Welding";
|
||||||
const string SEQ_REQUEST_UNLOAD_CELL = "[SeqAutoRunCCWH52A] Request Unload Cell";
|
const string SEQ_REQUEST_UNLOAD_CELL = "[SeqAutoRunCCWH52A] Request Unload Cell";
|
||||||
//const string SEQ_WAIT_LBAD_JUDGE = "[SeqAutoRunCCWH52A] Wait LBAD Judge";
|
//const string SEQ_WAIT_LBAD_JUDGE = "[SeqAutoRunCCWH52A] Wait LBAD Judge";
|
||||||
|
const string SEQ_REPORT_CELL_RESULT = "[SeqAutoRunCCWH52A] Report Cell Result";
|
||||||
|
|
||||||
const string SEQ_SET_PARAMS_REPORT_CELL_RESULT_SEQ = "[SeqAutoRunCCWH52A] Set Sequence Param (ReportCellResult Seq)";
|
//const string SEQ_SET_PARAMS_REPORT_CELL_RESULT_SEQ = "[SeqAutoRunCCWH52A] Set Sequence Param (ReportCellResult Seq)";
|
||||||
const string SEQ_DO_ID_REPORT_CELL_RESULT_SEQ = "[SeqAutoRunCCWH52A] Process (ReportCellResult Seq)";
|
//const string SEQ_DO_ID_REPORT_CELL_RESULT_SEQ = "[SeqAutoRunCCWH52A] Process (ReportCellResult Seq)";
|
||||||
const string SEQ_GET_RESULT_REPORT_CELL_RESULT_SEQ = "[SeqAutoRunCCWH52A] Get Sequence Result (ReportCellResult Seq)";
|
//const string SEQ_GET_RESULT_REPORT_CELL_RESULT_SEQ = "[SeqAutoRunCCWH52A] Get Sequence Result (ReportCellResult Seq)";
|
||||||
|
|
||||||
//const string SEQ_REPORT_CELLINFO_TO_PLC = "[SeqAutoRunCCWH52A] ReportCellInfoToPLC";
|
//const string SEQ_REPORT_CELLINFO_TO_PLC = "[SeqAutoRunCCWH52A] ReportCellInfoToPLC";
|
||||||
const string SEQ_CHECK_CYCLE_STOP = "[SeqAutoRunCCWH52A] Check Cycle Stop";
|
const string SEQ_CHECK_CYCLE_STOP = "[SeqAutoRunCCWH52A] Check Cycle Stop";
|
||||||
@ -168,9 +172,10 @@ namespace ILSOS_CCW_H52A.Sequences
|
|||||||
sb.AddAction(SEQ_CHECK_SCANNER_LIST_COMPLETE, CheckScannerListComplete);
|
sb.AddAction(SEQ_CHECK_SCANNER_LIST_COMPLETE, CheckScannerListComplete);
|
||||||
sb.AddDecision(SEQ_READY_SCANNER_LIST, ReadyScannerList);
|
sb.AddDecision(SEQ_READY_SCANNER_LIST, ReadyScannerList);
|
||||||
|
|
||||||
sb.AddAction(SEQ_SET_PARAMS_RECEIVE_CELL_INFO_SEQ, SetReceiveCellInfo_SeqParams); // Cell 정보를 받아와 입력한다.
|
#warning 아래 서브시퀀스가 CellTracker에서 받은 데이터를 WeldingData에 넣기만함, ProcessManager에서 Cell정보를 직접 Callback으로 받도록 수정함
|
||||||
sb.AddSubsequence(SEQ_DO_ID_RECEIVE_CELL_INFO_SEQ, SequenceManager.GetSeqBuilder_SeqReceiveCellInfo()); // cell 정보를 받아오는 Sub Seq 실행
|
//sb.AddAction(SEQ_SET_PARAMS_RECEIVE_CELL_INFO_SEQ, SetReceiveCellInfo_SeqParams); // Cell 정보를 받아와 입력한다.
|
||||||
sb.AddAction(SEQ_GET_PARAMS_RECEIVE_CELL_INFO_SEQ, GetReceiveCellInfo_SeqResult); // Cell 정보를 가져온다
|
//sb.AddSubsequence(SEQ_DO_ID_RECEIVE_CELL_INFO_SEQ, SequenceManager.GetSeqBuilder_SeqReceiveCellInfo()); // cell 정보를 받아오는 Sub Seq 실행
|
||||||
|
//sb.AddAction(SEQ_GET_PARAMS_RECEIVE_CELL_INFO_SEQ, GetReceiveCellInfo_SeqResult); // Cell 정보를 가져온다
|
||||||
|
|
||||||
sb.AddAction(SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ, SetUploadWeldingList_SeqParams);
|
sb.AddAction(SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ, SetUploadWeldingList_SeqParams);
|
||||||
sb.AddSubsequence(SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ, SequenceManager.GetSeqBuilder_SeqUploadWeldingList());
|
sb.AddSubsequence(SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ, SequenceManager.GetSeqBuilder_SeqUploadWeldingList());
|
||||||
@ -178,13 +183,15 @@ namespace ILSOS_CCW_H52A.Sequences
|
|||||||
|
|
||||||
sb.AddAction(SEQ_EXECUTE_WELDING, ExecuteWelding);
|
sb.AddAction(SEQ_EXECUTE_WELDING, ExecuteWelding);
|
||||||
sb.AddAction(SEQ_REQUEST_UNLOAD_CELL, RequestUnloadCell);
|
sb.AddAction(SEQ_REQUEST_UNLOAD_CELL, RequestUnloadCell);
|
||||||
|
sb.AddDecision(SEQ_CHECK_CAN_WELDED, CheckCanWelded);
|
||||||
|
sb.AddAction(SEQ_REPORT_CELL_RESULT, ReportCellResult);
|
||||||
|
|
||||||
sb.AddAction(SEQ_SET_PARAMS_REPORT_CELL_RESULT_SEQ, SetReportCellResult_SeqParams);
|
#warning ReportCellResult함수로 아래 시퀀스 대체
|
||||||
sb.AddSubsequence(SEQ_DO_ID_REPORT_CELL_RESULT_SEQ, SequenceManager.GetSeqBuilder_SeqReportCellResult());
|
//sb.AddAction(SEQ_SET_PARAMS_REPORT_CELL_RESULT_SEQ, SetReportCellResult_SeqParams);
|
||||||
sb.AddAction(SEQ_GET_RESULT_REPORT_CELL_RESULT_SEQ, GetReportCellResult_SeqResult);
|
//sb.AddSubsequence(SEQ_DO_ID_REPORT_CELL_RESULT_SEQ, SequenceManager.GetSeqBuilder_SeqReportCellResult());
|
||||||
|
//sb.AddAction(SEQ_GET_RESULT_REPORT_CELL_RESULT_SEQ, GetReportCellResult_SeqResult);
|
||||||
|
|
||||||
sb.AddDecision(SEQ_CHECK_CYCLE_STOP, CheckCycleStop);
|
sb.AddDecision(SEQ_CHECK_CYCLE_STOP, CheckCycleStop);
|
||||||
sb.AddDecision(SEQ_CHECK_CAN_WELDED, CheckCanWelded);
|
|
||||||
|
|
||||||
sb.AddAction(SEQ_SAVE_RESULT_DATA, SaveResultData); // 해당 공정의 정보를 기록 함.
|
sb.AddAction(SEQ_SAVE_RESULT_DATA, SaveResultData); // 해당 공정의 정보를 기록 함.
|
||||||
sb.AddAction(SEQ_WRITE_COMPLETION_PLC_BIT, WriteCompletionPLCBit); // 정상적으로 종료 되면, complete bit write
|
sb.AddAction(SEQ_WRITE_COMPLETION_PLC_BIT, WriteCompletionPLCBit); // 정상적으로 종료 되면, complete bit write
|
||||||
@ -193,12 +200,11 @@ namespace ILSOS_CCW_H52A.Sequences
|
|||||||
|
|
||||||
sb.Flows(sb.Init > sb[SEQ_ENTER] > sb[SEQ_CHECK_INIT_CONDITION] > sb[SEQ_FORK_ENCODER_MONITOR] > sb[SEQ_CHECK_LOAD_COMPLETE]
|
sb.Flows(sb.Init > sb[SEQ_ENTER] > sb[SEQ_CHECK_INIT_CONDITION] > sb[SEQ_FORK_ENCODER_MONITOR] > sb[SEQ_CHECK_LOAD_COMPLETE]
|
||||||
> sb[SEQ_CHECK_SCANNER_LIST_COMPLETE] > sb[SEQ_READY_SCANNER_LIST]
|
> sb[SEQ_CHECK_SCANNER_LIST_COMPLETE] > sb[SEQ_READY_SCANNER_LIST]
|
||||||
> sb[SEQ_SET_PARAMS_RECEIVE_CELL_INFO_SEQ] > sb[SEQ_DO_ID_RECEIVE_CELL_INFO_SEQ] > sb[SEQ_GET_PARAMS_RECEIVE_CELL_INFO_SEQ]
|
|
||||||
> sb[SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ] > sb[SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ] > sb[SEQ_GET_RESULT_UPLOAD_WELDING_LIST_SEQ]
|
> sb[SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ] > sb[SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ] > sb[SEQ_GET_RESULT_UPLOAD_WELDING_LIST_SEQ]
|
||||||
> sb[SEQ_EXECUTE_WELDING] > sb[SEQ_REQUEST_UNLOAD_CELL] > sb[SEQ_CHECK_CAN_WELDED]
|
> sb[SEQ_EXECUTE_WELDING] > sb[SEQ_REQUEST_UNLOAD_CELL] > sb[SEQ_CHECK_CAN_WELDED] > sb[SEQ_REPORT_CELL_RESULT]
|
||||||
> sb[SEQ_SET_PARAMS_REPORT_CELL_RESULT_SEQ] > sb[SEQ_DO_ID_REPORT_CELL_RESULT_SEQ] > sb[SEQ_GET_RESULT_REPORT_CELL_RESULT_SEQ]
|
//> sb[SEQ_SET_PARAMS_REPORT_CELL_RESULT_SEQ] > sb[SEQ_DO_ID_REPORT_CELL_RESULT_SEQ] > sb[SEQ_GET_RESULT_REPORT_CELL_RESULT_SEQ]
|
||||||
> sb[SEQ_SAVE_RESULT_DATA] > sb[SEQ_CHECK_CYCLE_STOP]
|
> sb[SEQ_SAVE_RESULT_DATA] > sb[SEQ_CHECK_CYCLE_STOP]
|
||||||
> sb[SEQ_WRITE_COMPLETION_PLC_BIT] > sb[SEQ_JOIN_ENCODER_MONITOR] > sb[SEQ_COMPLETE]);
|
> sb[SEQ_WRITE_COMPLETION_PLC_BIT] > sb[SEQ_JOIN_ENCODER_MONITOR] > sb[SEQ_COMPLETE] > sb.Final);
|
||||||
|
|
||||||
sb.Flows(sb[SEQ_READY_SCANNER_LIST] > sb[SEQ_EXECUTE_WELDING]);
|
sb.Flows(sb[SEQ_READY_SCANNER_LIST] > sb[SEQ_EXECUTE_WELDING]);
|
||||||
|
|
||||||
@ -206,7 +212,7 @@ namespace ILSOS_CCW_H52A.Sequences
|
|||||||
sb.Flows(sb[SEQ_CHECK_CYCLE_STOP] > sb[SEQ_CHECK_LOAD_COMPLETE]);
|
sb.Flows(sb[SEQ_CHECK_CYCLE_STOP] > sb[SEQ_CHECK_LOAD_COMPLETE]);
|
||||||
|
|
||||||
sb.Flows(sb[SEQ_CHECK_INIT_CONDITION] > sb[SEQ_INIT_CONDITION_ERROR] > sb.Final);
|
sb.Flows(sb[SEQ_CHECK_INIT_CONDITION] > sb[SEQ_INIT_CONDITION_ERROR] > sb.Final);
|
||||||
sb.Flows(sb[SEQ_FORK_ENCODER_MONITOR] > sb[SEQ_ENCODER_MONITOR] > sb[SEQ_JOIN_ENCODER_MONITOR] > sb[SEQ_COMPLETE]);
|
sb.Flows(sb[SEQ_FORK_ENCODER_MONITOR] > sb[SEQ_ENCODER_MONITOR] > sb[SEQ_JOIN_ENCODER_MONITOR] > sb[SEQ_COMPLETE] > sb.Final);
|
||||||
|
|
||||||
#region
|
#region
|
||||||
//sb.Flows(sb[SEQ_FORK_ENCODER_MONITOR] > sb[SEQ_ENCODER_MONITOR]);
|
//sb.Flows(sb[SEQ_FORK_ENCODER_MONITOR] > sb[SEQ_ENCODER_MONITOR]);
|
||||||
@ -443,6 +449,8 @@ namespace ILSOS_CCW_H52A.Sequences
|
|||||||
// SavePendingComplete()로 _pendingSlot에 복사한 뒤 Reset()을 호출한다.
|
// SavePendingComplete()로 _pendingSlot에 복사한 뒤 Reset()을 호출한다.
|
||||||
|
|
||||||
_CellScheduler.SavePendingComplete();
|
_CellScheduler.SavePendingComplete();
|
||||||
|
if (_CellScheduler.HasPendingPrefetch)
|
||||||
|
Log.I("[PendingRestore] 미용접 셀 보존됨 — 재시작 후 JigNo 매칭 시 복원 예정");
|
||||||
_CellScheduler.Reset();
|
_CellScheduler.Reset();
|
||||||
// ─────────────────────────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@ -690,11 +698,11 @@ namespace ILSOS_CCW_H52A.Sequences
|
|||||||
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);
|
||||||
|
|
||||||
// canExist 여부와 무관하게 매 지그마다 파이프라인 전진
|
// canExist 여부와 무관하게 매 지그마다 파이프라인 전진
|
||||||
// canExist=false 지그도 Shift()해야 Prefetch1 타이밍이 올바르게 유지됨.
|
// canExist=false 지그도 Shift()해야 Prefetch1 타이밍이 올바르게 유지됨.
|
||||||
_CellScheduler.Shift((eJigNo)(_WeldingJigNo - 1));
|
_CellScheduler.Shift(_WeldingJigNo);
|
||||||
|
|
||||||
_CellScheduler.Prefetch2.JigNo = _WeldingJigNo;
|
_CellScheduler.Prefetch2.JigNo = _WeldingJigNo;
|
||||||
_CellScheduler.Prefetch2.ListNo = _WeldingScannerListNo;
|
_CellScheduler.Prefetch2.ListNo = _WeldingScannerListNo;
|
||||||
@ -703,6 +711,36 @@ namespace ILSOS_CCW_H52A.Sequences
|
|||||||
_CellScheduler.Prefetch2.WeldingCount = _WeldingCount;
|
_CellScheduler.Prefetch2.WeldingCount = _WeldingCount;
|
||||||
_CellScheduler.Prefetch2.IsCanExist = canExist;
|
_CellScheduler.Prefetch2.IsCanExist = canExist;
|
||||||
|
|
||||||
|
#warning OC2 ACW 기준 >> Cell Tracker는 어느 시점에 데이터는 주는지 모르겠지만, '전전전 셀' 쯤에서 이미 건네받음! 다른 프로젝트에서 확인 필요함
|
||||||
|
// 복원 우선: 정지 전 업로드됐으나 로터리 감속·정지로 용접 미완된 셀 정보 복원.
|
||||||
|
// canExist=false 지그도 TryRestoreCell을 호출하여 슬롯 소비(폐기) — 이후 오염 방지.
|
||||||
|
if (_CellScheduler.TryRestoreCell(_WeldingJigNo, out var rLot, out var rCell)) {
|
||||||
|
if (canExist) {
|
||||||
|
_CellScheduler.Prefetch2.LotId = rLot;
|
||||||
|
_CellScheduler.Prefetch2.CellId = rCell;
|
||||||
|
Status.GetProcessingWeldingData().WorkLotId = rLot;
|
||||||
|
Status.GetProcessingWeldingData().WorkCellId = rCell;
|
||||||
|
Log.I($"[PendingRestore] Jig{_WeldingJigNo} 셀 복원 >> CellId({rCell})");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Log.W($"[PendingRestore] Jig{_WeldingJigNo} canExist=false, 복원 데이터 폐기 >> CellId({rCell})");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ProcessManager.Instance.ReceivedCellInfoQueue.TryDequeue(out var cell)) {
|
||||||
|
_CellScheduler.Prefetch2.LotId = cell.LotId;
|
||||||
|
_CellScheduler.Prefetch2.CellId = cell.CellId;
|
||||||
|
Status.GetProcessingWeldingData().WorkLotId = cell.LotId;
|
||||||
|
Status.GetProcessingWeldingData().WorkCellId = cell.CellId;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.I($"상태 시프트(Rotate) >> 용접 전전셀({_CellScheduler.Prefetch2.CellId}) [CanExist({_CellScheduler.Prefetch2.IsCanExist})] [JigNo({_CellScheduler.Prefetch2.JigNo})] " +
|
||||||
|
$"[ListNo({_CellScheduler.Prefetch2.ListNo})] [WeldingCount({_CellScheduler.Prefetch2.WeldingCount})]" +
|
||||||
|
$"[StartAngle(Y)({_CellScheduler.Prefetch2.StartAngle})]");
|
||||||
|
|
||||||
|
Log.I($"이번 용접대상 >> 용접 전셀({_CellScheduler.Prefetch1.CellId}) [CanExist({_CellScheduler.Prefetch1.IsCanExist})] [JigNo({_CellScheduler.Prefetch1.JigNo})] " +
|
||||||
|
$"[ListNo({_CellScheduler.Prefetch1.ListNo})] [WeldingCount({_CellScheduler.Prefetch1.WeldingCount})]" +
|
||||||
|
$"[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) {
|
||||||
@ -718,7 +756,7 @@ namespace ILSOS_CCW_H52A.Sequences
|
|||||||
_RecipeNo = _RecipeManager.ActivatedRecipe().Id;
|
_RecipeNo = _RecipeManager.ActivatedRecipe().Id;
|
||||||
|
|
||||||
SetWeldingData();
|
SetWeldingData();
|
||||||
return SEQ_SET_PARAMS_RECEIVE_CELL_INFO_SEQ;
|
return SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return SEQ_EXECUTE_WELDING;
|
return SEQ_EXECUTE_WELDING;
|
||||||
@ -847,22 +885,22 @@ namespace ILSOS_CCW_H52A.Sequences
|
|||||||
return SequenceAction.Ok();
|
return SequenceAction.Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
private SequenceActionResult SetReceiveCellInfo_SeqParams(SequenceContext context, string id, SequenceActionResult param)
|
//private SequenceActionResult SetReceiveCellInfo_SeqParams(SequenceContext context, string id, SequenceActionResult param)
|
||||||
{
|
//{
|
||||||
SeqReceiveCellInfo_InitParam seqParams = new SeqReceiveCellInfo_InitParam() {
|
// SeqReceiveCellInfo_InitParam seqParams = new SeqReceiveCellInfo_InitParam() {
|
||||||
};
|
// };
|
||||||
|
|
||||||
return SequenceAction.Ok(seqParams);
|
// return SequenceAction.Ok(seqParams);
|
||||||
}
|
//}
|
||||||
|
|
||||||
private SequenceActionResult GetReceiveCellInfo_SeqResult(SequenceContext context, string id, SequenceActionResult param)
|
//private SequenceActionResult GetReceiveCellInfo_SeqResult(SequenceContext context, string id, SequenceActionResult param)
|
||||||
{
|
//{
|
||||||
var resultOutParam = param.Param as SeqReceiveCellInfo_OutParam;
|
// var resultOutParam = param.Param as SeqReceiveCellInfo_OutParam;
|
||||||
if (resultOutParam.Success == false) {
|
// if (resultOutParam.Success == false) {
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
return SequenceAction.Ok();
|
// return SequenceAction.Ok();
|
||||||
}
|
//}
|
||||||
|
|
||||||
private SequenceActionResult ExecuteWelding(SequenceContext context, string id, SequenceActionResult param)
|
private SequenceActionResult ExecuteWelding(SequenceContext context, string id, SequenceActionResult param)
|
||||||
{
|
{
|
||||||
@ -905,7 +943,8 @@ namespace ILSOS_CCW_H52A.Sequences
|
|||||||
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();
|
||||||
bool WeldingInPosition = encoderX > _Scanner.Config.MarkingRangeMinRotate + 11.25 - send_time_offset - 0.1 && encoderX < _Scanner.Config.MarkingRangeMinRotate + 11.25 - send_time_offset + 0.1;
|
bool WeldingInPosition = encoderX > _Scanner.Config.MarkingRangeMinRotate + 11.25 - send_time_offset - 0.1
|
||||||
|
&& encoderX < _Scanner.Config.MarkingRangeMinRotate + 11.25 - send_time_offset + 0.1;
|
||||||
|
|
||||||
// ── JigScheduler: 포크 내에서 참조 캡처 (Shift와의 경합 방지) ──────
|
// ── JigScheduler: 포크 내에서 참조 캡처 (Shift와의 경합 방지) ──────
|
||||||
// Prefetch1: 2회 전 업로드된 지그 = 현재 물리적으로 실행 중인 지그.
|
// Prefetch1: 2회 전 업로드된 지그 = 현재 물리적으로 실행 중인 지그.
|
||||||
@ -945,7 +984,7 @@ namespace ILSOS_CCW_H52A.Sequences
|
|||||||
|
|
||||||
var IsLaserToggle = ChangeChecker.IsChangedBool("LaserToggle", LaserIO);
|
var IsLaserToggle = ChangeChecker.IsChangedBool("LaserToggle", LaserIO);
|
||||||
if (IsLaserToggle)
|
if (IsLaserToggle)
|
||||||
Log.I($"Fork Laser On({IsLaserToggle}) Encoder X : ({encoderX}), Encoder Y : ({currentAngle}), PLC Rotary : ({CurrentPosPLC}), List {executeTarget?.ListNo}, JigNo : ({executeTarget?.JigNo})");
|
Log.I($"Fork Laser On({LaserIO}) Encoder X : ({encoderX}), Encoder Y : ({currentAngle}), PLC Rotary : ({CurrentPosPLC}), List {executeTarget?.ListNo}, 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) {
|
||||||
@ -998,6 +1037,58 @@ namespace ILSOS_CCW_H52A.Sequences
|
|||||||
Status.GetProcessingWeldingData().WeldingJigNo = report.JigNo.ToString();
|
Status.GetProcessingWeldingData().WeldingJigNo = report.JigNo.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SequenceActionResult ReportCellResult(SequenceContext context, string id, SequenceActionResult param)
|
||||||
|
{
|
||||||
|
Status.SetWorkingPosition(eWorkingPosition.REPORTING_RESULT);
|
||||||
|
|
||||||
|
string strDate = DateTime.Now.Date.ToString("yyyyMMdd");
|
||||||
|
string strTime = DateTime.Now.ToString("HHmmss");
|
||||||
|
|
||||||
|
var wd = Status.GetProcessingWeldingData();
|
||||||
|
string reportDataLocalPath = _CellTracker._CellTrackerConfig.reportDataLocalPath;
|
||||||
|
string equipName = _CellTracker._CellTrackerConfig.EquipmentName;
|
||||||
|
|
||||||
|
string directory = string.Format(reportDataLocalPath + "{0}", strDate);
|
||||||
|
if (!Directory.Exists(directory))
|
||||||
|
Directory.CreateDirectory(directory);
|
||||||
|
|
||||||
|
string strPath = string.Format(reportDataLocalPath + "{0}\\{1}_{2}_{3}.csv",
|
||||||
|
strDate, strDate, "H52A_" + equipName, strTime.Substring(0, 2));
|
||||||
|
|
||||||
|
// ECS 전송용 strData 빌드
|
||||||
|
string strData = string.Format(
|
||||||
|
"Date={0},Time={1},LotID={2},CellID={3}," +
|
||||||
|
equipName + "DATA001={4}," +
|
||||||
|
equipName + "DATA002={5}," +
|
||||||
|
equipName + "DATA003={6}," +
|
||||||
|
equipName + "DATA004={7}," +
|
||||||
|
equipName + "DATA005={8}," +
|
||||||
|
equipName + "DATA006={9}," +
|
||||||
|
equipName + "DATA007={10}," +
|
||||||
|
equipName + "DATA008={11}," +
|
||||||
|
equipName + "DATA009={12}",
|
||||||
|
strDate, strTime, wd.LotId, wd.CellId,
|
||||||
|
wd.RecipeNo, wd.LaserPowerCore, wd.MarkSpeed, wd.FocalLength,
|
||||||
|
wd.WeldingJigNo, wd.WeldingSpanTimeMilliseconds, wd.LaserPowerByLBAD,
|
||||||
|
wd.TodayProduct, wd.TotalProduct);
|
||||||
|
_CellTracker.SendEcsData(wd.CellId, strPath, strData);
|
||||||
|
|
||||||
|
// 로컬 CSV 저장
|
||||||
|
string strItem = "//Date, Time, LotID, CellID, RecipeNo, LaserPower, MarkSpeed, FocalLength, HeadNo, WeldingTime, LaserPowerByLBAD, TodayCount, TotalCount";
|
||||||
|
string strCsvData = string.Format("{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {12}",
|
||||||
|
strDate, strTime, wd.LotId, wd.CellId,
|
||||||
|
wd.RecipeNo, wd.LaserPowerCore, wd.MarkSpeed, wd.FocalLength,
|
||||||
|
wd.WeldingJigNo, wd.WeldingSpanTimeMilliseconds, wd.LaserPowerByLBAD,
|
||||||
|
wd.TodayProduct, wd.TotalProduct);
|
||||||
|
WeldingCommon.Utils.ExcelManagementUnit.AppendStringInCSV(strPath, strItem, strCsvData);
|
||||||
|
|
||||||
|
// 보고 완료: ReportTarget.ReportComplete=true 설정 + pendingSlot 클리어
|
||||||
|
_CellScheduler.CompleteReport();
|
||||||
|
|
||||||
|
return SequenceAction.Ok();
|
||||||
|
}
|
||||||
|
|
||||||
private SequenceActionResult SetReportCellResult_SeqParams(SequenceContext context, string id, SequenceActionResult param)
|
private SequenceActionResult SetReportCellResult_SeqParams(SequenceContext context, string id, SequenceActionResult param)
|
||||||
{
|
{
|
||||||
Status.SetWorkingPosition(eWorkingPosition.REPORTING_RESULT);
|
Status.SetWorkingPosition(eWorkingPosition.REPORTING_RESULT);
|
||||||
@ -1049,7 +1140,7 @@ namespace ILSOS_CCW_H52A.Sequences
|
|||||||
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_SET_PARAMS_REPORT_CELL_RESULT_SEQ;
|
return SEQ_REPORT_CELL_RESULT;
|
||||||
}
|
}
|
||||||
// ─────────────────────────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@ -1057,7 +1148,7 @@ namespace ILSOS_CCW_H52A.Sequences
|
|||||||
// - ReportTarget이 설정돼 있고 아직 보고 완료되지 않은 경우
|
// - ReportTarget이 설정돼 있고 아직 보고 완료되지 않은 경우
|
||||||
// - 첫번째, 두번째 반복은 SetReportTarget이 호출되지 않으므로 자연스럽게 통과
|
// - 첫번째, 두번째 반복은 SetReportTarget이 호출되지 않으므로 자연스럽게 통과
|
||||||
if (_CellScheduler.HasReport)
|
if (_CellScheduler.HasReport)
|
||||||
return SEQ_SET_PARAMS_REPORT_CELL_RESULT_SEQ;
|
return SEQ_REPORT_CELL_RESULT;
|
||||||
|
|
||||||
return SEQ_CHECK_CYCLE_STOP;
|
return SEQ_CHECK_CYCLE_STOP;
|
||||||
}
|
}
|
||||||
@ -1073,7 +1164,6 @@ namespace ILSOS_CCW_H52A.Sequences
|
|||||||
}
|
}
|
||||||
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();
|
||||||
}
|
}
|
||||||
@ -1201,6 +1291,12 @@ namespace ILSOS_CCW_H52A.Sequences
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 정지 시점 파이프라인 상태 로그 (재시작 후 복원 여부 사전 확인용)
|
||||||
|
if (_CellScheduler.Prefetch1 != null && !string.IsNullOrEmpty(_CellScheduler.Prefetch1.CellId))
|
||||||
|
Log.I($"Stoped Seq >> Prefetch1[Jig{_CellScheduler.Prefetch1.JigNo}] CellId={_CellScheduler.Prefetch1.CellId}, WeldComplete={_CellScheduler.Prefetch1.WeldComplete}");
|
||||||
|
if (_CellScheduler.Prefetch2 != null && !string.IsNullOrEmpty(_CellScheduler.Prefetch2.CellId))
|
||||||
|
Log.I($"Stoped Seq >> Prefetch2[Jig{_CellScheduler.Prefetch2.JigNo}] CellId={_CellScheduler.Prefetch2.CellId}, WeldComplete={_CellScheduler.Prefetch2.WeldComplete}");
|
||||||
|
|
||||||
//PLC All BIT OFF
|
//PLC All BIT OFF
|
||||||
for (int i = 0; i < _RotaryJigCount; i++)
|
for (int i = 0; i < _RotaryJigCount; i++)
|
||||||
_PLC.WriteBit(eBitOutput.PC_WELD_COMPLETE_1 + i, false);
|
_PLC.WriteBit(eBitOutput.PC_WELD_COMPLETE_1 + i, false);
|
||||||
|
|||||||
@ -103,11 +103,34 @@ namespace WeldingCommon.Data
|
|||||||
|
|
||||||
public WeldingData()
|
public WeldingData()
|
||||||
{
|
{
|
||||||
|
Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
|
this.CellId = string.Empty;
|
||||||
|
this.LotId = string.Empty;
|
||||||
|
this.AutoRunStartTime = DateTime.MinValue;
|
||||||
|
this.WeldingStartTime = DateTime.MinValue;
|
||||||
|
this.WeldingEndTime = DateTime.MinValue;
|
||||||
|
this.WeldingSpanTimeMilliseconds = string.Empty;
|
||||||
|
this.TodayProduct = 0;
|
||||||
|
this.TotalProduct = 0;
|
||||||
|
this.RecipeNo = 0;
|
||||||
|
this.WeldStartTime = string.Empty;
|
||||||
|
this.WeldTime = string.Empty;
|
||||||
|
this.WorkCellId = string.Empty;
|
||||||
|
this.WorkLotId = string.Empty;
|
||||||
|
this.LBAD_Judge = string.Empty;
|
||||||
|
this.LDD_Judge = string.Empty;
|
||||||
|
this.LaserPowerCore = string.Empty;
|
||||||
|
this.LaserPowerRing = string.Empty;
|
||||||
|
this.MarkSpeed = string.Empty;
|
||||||
|
this.FocalLength = string.Empty;
|
||||||
|
this.WeldingJigNo = string.Empty;
|
||||||
|
this.LaserPowerByLBAD = string.Empty;
|
||||||
|
this.CheckCanExist = false;
|
||||||
|
this.CheckScannerListEnd = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Clone()
|
public object Clone()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user