Compare commits
11 Commits
1ec5b0750f
...
bdd76349dc
| Author | SHA1 | Date | |
|---|---|---|---|
| bdd76349dc | |||
| b6c0b59a92 | |||
| f735c6ba4c | |||
|
|
2bda9c5f9c | ||
| 20b846c9a6 | |||
| 99032bce9a | |||
|
|
0300cb6ee0 | ||
| 6279c02cd6 | |||
| 614b5f1a5b | |||
| 54b6b6ccdc | |||
|
|
ad37cb326a |
1
.gitignore
vendored
1
.gitignore
vendored
@ -32,3 +32,4 @@ AuroraVision/VisionInspector/bin
|
||||
/hislog.config
|
||||
|
||||
*.bak
|
||||
/ignoreFolder
|
||||
@ -146,5 +146,17 @@ namespace AuroraCellTracker
|
||||
|
||||
_CellTracker.SetIPConfig();
|
||||
}
|
||||
public void getDummyData(out string lotId, out string cellId)
|
||||
{
|
||||
lotId = string.Empty;
|
||||
cellId = string.Empty;
|
||||
|
||||
if (!IsActivated) {
|
||||
return;
|
||||
}
|
||||
if (_CellTracker != null && _CellTracker is CellTrackerDaekhon core) {
|
||||
core.CalcCellInfo("", out lotId, out cellId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,6 +28,8 @@ namespace AuroraCellTracker
|
||||
public int LotIdStartNo { get; set; }
|
||||
public int LotIdLength { 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");
|
||||
private const string REG_PATH = @"Software\H52A\H52A_ADPT_CELL";
|
||||
|
||||
public event Action<string, string> OnCellReceived;
|
||||
|
||||
public CellInfoStr CellInfoStrings { get; set; } = new CellInfoStr();
|
||||
public ConcurrentQueue<CellInfoStr> CellInfoQueue { get; set; } = new ConcurrentQueue<CellInfoStr>();
|
||||
|
||||
@ -318,6 +320,7 @@ namespace AuroraCellTracker.DaekhonCoporation
|
||||
|
||||
CalcCellInfo(str, out lotId, out cellId);
|
||||
AddCellInfo(lotId, cellId);
|
||||
OnCellReceived?.Invoke(lotId, cellId);
|
||||
} catch (Exception e) {
|
||||
_Logger.E(string.Format($"{e.Message}"));
|
||||
}
|
||||
@ -339,6 +342,7 @@ namespace AuroraCellTracker.DaekhonCoporation
|
||||
|
||||
//CalcCellInfo(str, out lotId, out cellId);
|
||||
AddCellInfo(lotId, cellId);
|
||||
OnCellReceived?.Invoke(lotId, cellId);
|
||||
} catch (Exception e) {
|
||||
_Logger.E(string.Format($"{e.Message}"));
|
||||
}
|
||||
@ -388,7 +392,7 @@ namespace AuroraCellTracker.DaekhonCoporation
|
||||
/// Cell 추적 API에서 받은 문자열에서, Cell ID와 Lot ID를 Parsing 하는 함수
|
||||
/// </summary>
|
||||
/// <param name="str">Cell 추적 API에서 받은 문자열. Callback 방식일 때와 Queue 방식일 때 각각 다르다</param>
|
||||
private void CalcCellInfo(string str, out string lotId, out string cellId)
|
||||
public void CalcCellInfo(string str, out string lotId, out string cellId)
|
||||
{
|
||||
lotId = cellId = "";
|
||||
|
||||
|
||||
@ -10,6 +10,12 @@ namespace AuroraCellTracker
|
||||
{
|
||||
public interface ICellTracker
|
||||
{
|
||||
/// <summary>
|
||||
/// DllSocket_ReceiveDataBuffer에서 lotId/cellId 파싱 완료 시 발화.
|
||||
/// ProcessManager 등 외부에서 구독하여 직접 수신 가능.
|
||||
/// </summary>
|
||||
event Action<string, string> OnCellReceived;
|
||||
|
||||
void Initialize(eMode mode, string dllDirectory);
|
||||
void Close();
|
||||
void CheckDllStatus();
|
||||
|
||||
@ -348,7 +348,7 @@ namespace AuroraLBAD.Service
|
||||
}
|
||||
string LotID_string = new string(LotID);
|
||||
string CellID_string = new string(CellID);
|
||||
Log.I($"StreamLight LBAD Report Data : LotID {LotID_string}");
|
||||
Log.I($"StreamLight LBAD Report Data : LotID({LotID_string}) / CellID({CellID_string})");
|
||||
Log.I($"StreamLight LBAD Report Data : HeadNum {replyParsed_LBAD.HeadNum}");
|
||||
Log.I($"StreamLight LBAD Report Data : LaserPower_AVG {replyParsed_LBAD.AVG}");
|
||||
if (replyParsed_LBAD.HeadNum > 0)
|
||||
|
||||
@ -577,6 +577,15 @@ namespace AuroraLaserScanner
|
||||
}
|
||||
_scannerObj.SetConfigList(mem1, mem2);
|
||||
}
|
||||
public void GetListPointer(out eListNo list_no, out uint list_pos)
|
||||
{
|
||||
if (!IsActivated) {
|
||||
list_no = eListNo.NONE;
|
||||
list_pos = 0;
|
||||
return;
|
||||
}
|
||||
_scannerObj.GetListPointer(out list_no, out list_pos);
|
||||
}
|
||||
public double GetCommandPosX()
|
||||
{
|
||||
return _scannerObj.CommandPosX;
|
||||
|
||||
@ -313,6 +313,7 @@ namespace AuroraLaserScanner
|
||||
#endregion
|
||||
public abstract uint GetListSpace();
|
||||
public abstract void SetConfigList(uint mem1, uint mem2);
|
||||
public abstract void GetListPointer(out eListNo list_no, out uint list_pos);
|
||||
|
||||
public void WaitForListTaskCompleted(int timeOut, SequenceContext context = null) //단위는 초
|
||||
{
|
||||
|
||||
@ -1111,5 +1111,14 @@ namespace AuroraLaserScanner
|
||||
{
|
||||
RTC5Wrap.config_list(mem1, mem2);
|
||||
}
|
||||
public override void GetListPointer(out eListNo list_no, out uint list_pos)
|
||||
{
|
||||
list_no = eListNo.NONE;
|
||||
|
||||
uint listNo = 0, listPos = 0;
|
||||
RTC5Wrap.get_list_pointer(out listNo, out listPos);
|
||||
list_no = (eListNo)listNo;
|
||||
list_pos = listPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1113,5 +1113,14 @@ namespace AuroraLaserScanner
|
||||
{
|
||||
RTC6Wrap.config_list(mem1, mem2);
|
||||
}
|
||||
public override void GetListPointer(out eListNo list_no, out uint list_pos)
|
||||
{
|
||||
list_no = eListNo.NONE;
|
||||
|
||||
uint listNo = 0, listPos = 0;
|
||||
RTC6Wrap.get_list_pointer(out listNo, out listPos);
|
||||
list_no = (eListNo)listNo;
|
||||
list_pos = listPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -852,5 +852,15 @@ namespace AuroraLaserScanner
|
||||
{
|
||||
|
||||
}
|
||||
public override void GetListPointer(out eListNo list_no, out uint list_pos)
|
||||
{
|
||||
list_no = eListNo.NONE;
|
||||
if (_list1Busy)
|
||||
list_no = eListNo.LIST1;
|
||||
else if (_list2Busy)
|
||||
list_no = eListNo.LIST2;
|
||||
|
||||
list_pos = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BIN
Doc/ProgramHelper/MOTF 구현 시나리오.pptx
Normal file
BIN
Doc/ProgramHelper/MOTF 구현 시나리오.pptx
Normal file
Binary file not shown.
184
Machines/ILSOS_CCW_H52A/Datas/CellInfoScheduler.cs
Normal file
184
Machines/ILSOS_CCW_H52A/Datas/CellInfoScheduler.cs
Normal file
@ -0,0 +1,184 @@
|
||||
using Aurora.Api;
|
||||
using Aurora.Util.HislogPlus;
|
||||
using ILSOS_CCW_H52A.Data;
|
||||
using ILSOS_CCW_H52A.Sequences;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ILSOS_CCW_H52A.Data
|
||||
{
|
||||
// 물리 지그 번호 (0-based enum, 1-based 변환: (eJigNo)(jigNo - 1))
|
||||
public enum eJigNo
|
||||
{
|
||||
Jig1, Jig2, Jig3, Jig4,
|
||||
Jig5, Jig6, Jig7, Jig8,
|
||||
Jig9, Jig10, Jig11, Jig12,
|
||||
Jig13, Jig14, Jig15, Jig16,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dictionary<eJigNo, JigInfo> 상속으로 물리 지그 번호 직접 접근과
|
||||
/// 파이프라인 단계 접근을 동시에 지원하는 셀 스케줄러.
|
||||
///
|
||||
/// - 물리 지그 접근: scheduler[eJigNo.Jig5]
|
||||
/// - 파이프라인 접근: scheduler.Prefetch1, scheduler.Prefetch2
|
||||
///
|
||||
/// 3단계 파이프라인: Prefetch2 → Prefetch1 → ReportTarget
|
||||
/// Prefetch2 : 셀 정보 수신 완료, 스캐너 리스트 업로드 전
|
||||
/// Prefetch1 : 업로드 완료, 실행 중 — EncoderMonitor 감시 + 완료 체크 대상
|
||||
/// ReportTarget: 완료, 보고 대기
|
||||
///
|
||||
/// Shift()는 Prefetch2→Prefetch1만 전진. GC 할당 없음.
|
||||
/// Prefetch1 ← Prefetch2 ← this[nextJig]
|
||||
/// </summary>
|
||||
public class CellInfoScheduler : Dictionary<eJigNo, JigInfo>
|
||||
{
|
||||
private readonly Logger _log = new Logger("CellInfoScheduler");
|
||||
public JigInfo Prefetch2 { get; private set; } // 전전 셀: 셀 정보 수신, 업로드 전
|
||||
public JigInfo Prefetch1 { get; private set; } // 전 셀: 업로드 완료, 실행 중 / 완료 체크 대상
|
||||
|
||||
/// 현재 보고 대상 JigInfo (CheckScannerListComplete에서 지정, 보고 완료 후 null)
|
||||
public JigInfo ReportTarget { get; set; }
|
||||
|
||||
// 재시작 보존용 독립 슬롯 — Reset()에서 건드리지 않음
|
||||
// 재시작 시, List를 최초 리스트 2번을 생성하는 로직 때문에.. 필요함
|
||||
private readonly JigInfo _pendingSlot = new JigInfo(); // 용접 직후 (용접 완, 보고 미완)
|
||||
private readonly JigInfo _pendingPrefetch1 = new JigInfo(); // 정지 직전 Prefetch1 (업로드 완료, 용접 미완)
|
||||
private readonly JigInfo _pendingPrefetch2 = new JigInfo(); // 정지 직전 Prefetch2 (업로드 완료, 용접 미완)
|
||||
|
||||
// 재시작 전 미완료 보고 슬롯 (유효 시 non-null)
|
||||
public JigInfo PendingComplete => HasPendingComplete ? _pendingSlot : null;
|
||||
|
||||
// 재시작 보존 보고가 있는지
|
||||
public bool HasPendingComplete => _pendingSlot.IsCanExist && !_pendingSlot.ReportComplete;
|
||||
|
||||
// 현재 활성 보고 슬롯 — 재시작 pending 우선
|
||||
public JigInfo ActiveReportSlot => HasPendingComplete ? _pendingSlot : ReportTarget;
|
||||
|
||||
// 정지 전 미용접 슬롯이 보존돼 있는지 (재시작 후 복원 가능 여부)
|
||||
public bool HasPendingPrefetch =>
|
||||
!string.IsNullOrEmpty(_pendingPrefetch1.CellId)
|
||||
|| !string.IsNullOrEmpty(_pendingPrefetch2.CellId);
|
||||
|
||||
// 보고가 필요한 상태인지 (정상 + 재시작 모두 포함) >> 용접 완, 보고 미완
|
||||
public bool HasReport => HasPendingComplete || (ReportTarget != null && !ReportTarget.ReportComplete);
|
||||
|
||||
public CellInfoScheduler()
|
||||
{
|
||||
foreach (eJigNo no in Enum.GetValues(typeof(eJigNo)))
|
||||
Add(no, new JigInfo());
|
||||
}
|
||||
|
||||
// 1-based jigNo (_WeldingJigNo 등) → 0-based eJigNo 변환 의의 인덱서
|
||||
public JigInfo this[int jigNo] {
|
||||
get => base[(eJigNo)(jigNo - 1)];
|
||||
}
|
||||
|
||||
// Reset() 전에 호출 — 미완료 보고 및 미용접 슬롯을 보존.
|
||||
public void SavePendingComplete()
|
||||
{
|
||||
// 용접 완료됐으나 보고 전 정지된 경우 (_pendingSlot)
|
||||
if (ReportTarget != null
|
||||
&& ReportTarget.IsCanExist
|
||||
&& ReportTarget.WeldComplete
|
||||
&& !ReportTarget.ReportComplete)
|
||||
_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 클리어.
|
||||
// GetReportCellResult_SeqResult 성공 시 호출.
|
||||
public void CompleteReport()
|
||||
{
|
||||
_log.I($"Report >> CellId({ReportTarget.CellId}), JigNo({ReportTarget.JigNo})");
|
||||
ReportTarget?.SetReportComplete(true);
|
||||
ReportTarget = null;
|
||||
_pendingSlot.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prefetch2→Prefetch1 한 칸 전진. GC 할당 없음.
|
||||
/// 새 Prefetch2 슬롯은 Clear 후 반환 — 호출자가 셀 정보를 채워야 한다.
|
||||
/// </summary>
|
||||
/// <param name="nextJig">새 Prefetch2로 지정할 물리 지그 (eJigNo)</param>
|
||||
public void Shift(eJigNo nextJig)
|
||||
{
|
||||
Prefetch1 = Prefetch2;
|
||||
Prefetch2 = base[nextJig];
|
||||
Prefetch2.Clear();
|
||||
}
|
||||
// AutoRun에서 사용되는 자료형으로 추가 (편의 인덱서 사용)
|
||||
public void Shift(int nextJig)
|
||||
{
|
||||
Prefetch1 = Prefetch2;
|
||||
Prefetch2 = this[nextJig];
|
||||
Prefetch2.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 전체 초기화 (AutoRun 시작 시 호출).
|
||||
/// SavePendingComplete() 호출 후 이 메서드를 호출할 것.
|
||||
/// _pendingSlot / _pendingPrefetch1 / _pendingPrefetch2 는 재시작 복원을 위해 건드리지 않음.
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
foreach (var info in Values)
|
||||
info.Clear();
|
||||
|
||||
Prefetch2 = null;
|
||||
Prefetch1 = null;
|
||||
ReportTarget = null;
|
||||
// _pendingSlot, _pendingPrefetch1/2: SavePendingComplete()가 복사해 둔 데이터를 유지
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 스케줄러 자체는 Clear 할 수 없도록 함
|
||||
/// </summary>
|
||||
public new void Clear()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
125
Machines/ILSOS_CCW_H52A/Datas/JigInfo.cs
Normal file
125
Machines/ILSOS_CCW_H52A/Datas/JigInfo.cs
Normal file
@ -0,0 +1,125 @@
|
||||
using AuroraLaserScanner;
|
||||
using System;
|
||||
using WeldingCommon.Data;
|
||||
|
||||
namespace ILSOS_CCW_H52A.Data
|
||||
{
|
||||
public class JigInfo
|
||||
{
|
||||
// --- 지그 식별 ---
|
||||
public int JigNo; // 물리 지그 번호 (1-based, -1: 미설정)
|
||||
|
||||
// --- 스캐너 리스트 파라미터 (ReadyScannerList에서 채워짐) ---
|
||||
public eListNo ListNo;
|
||||
public DateTime WriteTime;
|
||||
public double StartAngle;
|
||||
public int WeldingCount;
|
||||
|
||||
// --- 캔 유무 / 용접 상태 ---
|
||||
public bool IsCanExist;
|
||||
public bool IsWelding;
|
||||
public bool WeldComplete;
|
||||
public DateTime WeldStartTime;
|
||||
public DateTime WeldEndTime;
|
||||
public TimeSpan WeldingSpanTime; // 스캐너 리스트 실행 시간 (GetTime() 결과)
|
||||
|
||||
// CellTracker 수신 정보
|
||||
public string LotId;
|
||||
public string CellId;
|
||||
|
||||
// --- 플래그 ---
|
||||
public bool CheckSendCellinfo;
|
||||
public bool ReportComplete;
|
||||
|
||||
// --- 리포팅/뷰 용 상세 정보 ---
|
||||
public WeldingData InnerCellInfo;
|
||||
|
||||
public JigInfo()
|
||||
{
|
||||
InnerCellInfo = new WeldingData();
|
||||
Clear();
|
||||
}
|
||||
|
||||
public void SetReportComplete(bool comp) => ReportComplete = comp;
|
||||
|
||||
/// <summary>
|
||||
/// 다른 JigInfo의 모든 필드를 이 슬롯에 복사 (재시작 보존용 pendingSlot에 사용)
|
||||
/// </summary>
|
||||
public void CopyFrom(JigInfo src)
|
||||
{
|
||||
JigNo = src.JigNo;
|
||||
ListNo = src.ListNo;
|
||||
WriteTime = src.WriteTime;
|
||||
StartAngle = src.StartAngle;
|
||||
WeldingCount = src.WeldingCount;
|
||||
IsCanExist = src.IsCanExist;
|
||||
IsWelding = src.IsWelding;
|
||||
WeldComplete = src.WeldComplete;
|
||||
WeldStartTime = src.WeldStartTime;
|
||||
WeldEndTime = src.WeldEndTime;
|
||||
WeldingSpanTime = src.WeldingSpanTime;
|
||||
LotId = src.LotId;
|
||||
CellId = src.CellId;
|
||||
CheckSendCellinfo = src.CheckSendCellinfo;
|
||||
ReportComplete = src.ReportComplete;
|
||||
UpdateCellInfo(src.InnerCellInfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 슬롯 전체 초기화 (Shift 시 새 Prefetch2 슬롯에 자동 호출됨)
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
JigNo = -1;
|
||||
ListNo = 0;
|
||||
WriteTime = DateTime.MinValue;
|
||||
StartAngle = 0.0;
|
||||
WeldingCount = -1;
|
||||
|
||||
IsCanExist = false;
|
||||
IsWelding = false;
|
||||
WeldComplete = false;
|
||||
WeldStartTime = DateTime.MinValue;
|
||||
WeldEndTime = DateTime.MinValue;
|
||||
WeldingSpanTime = TimeSpan.Zero;
|
||||
|
||||
LotId = string.Empty;
|
||||
CellId = string.Empty;
|
||||
|
||||
CheckSendCellinfo = false;
|
||||
ReportComplete = false;
|
||||
|
||||
InnerCellInfo.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// InnerCellInfo를 WeldingData 로부터 필드 단위로 복사 (GC 할당 없음)
|
||||
/// </summary>
|
||||
public void UpdateCellInfo(WeldingData data)
|
||||
{
|
||||
InnerCellInfo.CellId = data.CellId;
|
||||
InnerCellInfo.LotId = data.LotId;
|
||||
InnerCellInfo.AutoRunStartTime = data.AutoRunStartTime;
|
||||
InnerCellInfo.WeldingStartTime = data.WeldingStartTime;
|
||||
InnerCellInfo.WeldingEndTime = data.WeldingEndTime;
|
||||
InnerCellInfo.WeldingSpanTimeMilliseconds = data.WeldingSpanTimeMilliseconds;
|
||||
InnerCellInfo.TodayProduct = data.TodayProduct;
|
||||
InnerCellInfo.TotalProduct = data.TotalProduct;
|
||||
InnerCellInfo.RecipeNo = data.RecipeNo;
|
||||
InnerCellInfo.WeldStartTime = data.WeldStartTime;
|
||||
InnerCellInfo.WeldTime = data.WeldTime;
|
||||
InnerCellInfo.WorkCellId = data.WorkCellId;
|
||||
InnerCellInfo.WorkLotId = data.WorkLotId;
|
||||
InnerCellInfo.LBAD_Judge = data.LBAD_Judge;
|
||||
InnerCellInfo.LDD_Judge = data.LDD_Judge;
|
||||
InnerCellInfo.LaserPowerCore = data.LaserPowerCore;
|
||||
InnerCellInfo.LaserPowerRing = data.LaserPowerRing;
|
||||
InnerCellInfo.MarkSpeed = data.MarkSpeed;
|
||||
InnerCellInfo.FocalLength = data.FocalLength;
|
||||
InnerCellInfo.WeldingJigNo = data.WeldingJigNo;
|
||||
InnerCellInfo.LaserPowerByLBAD = data.LaserPowerByLBAD;
|
||||
InnerCellInfo.CheckCanExist = data.CheckCanExist;
|
||||
InnerCellInfo.CheckScannerListEnd = data.CheckScannerListEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,15 @@
|
||||
using WeldingCommon;
|
||||
using Aurora;
|
||||
using Aurora.Api;
|
||||
using ILSOS_CCW_H52A.Sequences.ProcessObjects;
|
||||
using WeldingCommon;
|
||||
|
||||
namespace ILSOS_CCW_H52A
|
||||
{
|
||||
public static class AuroraEnvironmentExt
|
||||
{
|
||||
public static ProcessManager GetProcessManager(this IAuroraEnvironment _) => ProcessManager.Instance;
|
||||
public static ProcessManager GetProcessManager(this SequenceContext _) => ProcessManager.Instance;
|
||||
}
|
||||
internal class EquipDef
|
||||
{
|
||||
}
|
||||
|
||||
@ -76,6 +76,8 @@ namespace ILSOS_CCW_H52A
|
||||
base.OnStartUp();
|
||||
|
||||
AuroraEnv.SequenceEntry[SequenceIds.AlarmMonitoring].Start();
|
||||
|
||||
AuroraEnv.GetProcessManager().Init(AuroraEnv);
|
||||
}
|
||||
|
||||
// For Selection LaserDevice
|
||||
|
||||
@ -92,6 +92,8 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="Alarm\AlarmHelper.cs" />
|
||||
<Compile Include="Alarm\AlarmManager.cs" />
|
||||
<Compile Include="Datas\CellInfoScheduler.cs" />
|
||||
<Compile Include="Datas\JigInfo.cs" />
|
||||
<Compile Include="Device\IO\IOController.Address.cs" />
|
||||
<Compile Include="Device\IO\IOController.Logic.cs" />
|
||||
<Compile Include="Device\Laser\LaserCoherentArm_IO.cs" />
|
||||
|
||||
@ -1,14 +1,18 @@
|
||||
using Aurora;
|
||||
using Aurora.Api;
|
||||
using Aurora.Util.HislogPlus;
|
||||
using AuroraCellTracker;
|
||||
using AuroraLaserScanner;
|
||||
using AuroraPLC;
|
||||
using ILSOS_CCW_H52A.Data;
|
||||
using ILSOS_CCW_H52A.Device;
|
||||
using OpenCvSharp;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
@ -29,12 +33,21 @@ namespace ILSOS_CCW_H52A.Sequences.ProcessObjects
|
||||
return _Instance;
|
||||
}
|
||||
}
|
||||
private bool usedAnalyzerLog = false;
|
||||
private readonly Logger _log = new Logger("ProcessManager");
|
||||
|
||||
|
||||
private IAuroraEnvironment _env;
|
||||
private PLCControllerCCWH52A _plc;
|
||||
private ScannerCCWH52A _scanner;
|
||||
private CellTracker _cellTracker;
|
||||
|
||||
private bool usedAnalyzerLog = false;
|
||||
private readonly Logger _log = new Logger("ProcessManager");
|
||||
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 int RotaryJigCount = 16;
|
||||
@ -48,7 +61,23 @@ namespace ILSOS_CCW_H52A.Sequences.ProcessObjects
|
||||
_env = env;
|
||||
_plc = _env.DeviceManager[DeviceIds.PLCDevice] as PLCControllerCCWH52A;
|
||||
_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();
|
||||
}
|
||||
|
||||
private void OnCellReceived(string lotId, string cellId)
|
||||
{
|
||||
lotId = lotId.Replace("\0", "").Trim();
|
||||
cellId = cellId.Replace("\0", "").Trim();
|
||||
ReceivedCellInfoQueue.Enqueue((lotId, cellId));
|
||||
_log.I($"Cell Tracker CallBack Received >> [LotId({lotId})] [CellId({cellId})]");
|
||||
}
|
||||
|
||||
public IEnumerable<bool> CheckRotaryState()
|
||||
{
|
||||
List<bool> rotaryStates = new List<bool>();
|
||||
|
||||
@ -14,9 +14,13 @@ using CoreUnit.Control.UserControl.Canvas;
|
||||
using CoreUnit.Scanner.UserControl.ScannerCanvas;
|
||||
using DB;
|
||||
using Hermes;
|
||||
using ILSOS_CCW_H52A.Data;
|
||||
using ILSOS_CCW_H52A.Device;
|
||||
using ILSOS_CCW_H52A.Models;
|
||||
using ILSOS_CCW_H52A.RMS;
|
||||
using ILSOS_CCW_H52A.Sequences.ProcessObjects;
|
||||
using Microsoft.Win32;
|
||||
using OpenCvSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@ -24,6 +28,7 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using System.Windows.Media.Animation;
|
||||
using WeldingCommon;
|
||||
using WeldingCommon.Alarm;
|
||||
using WeldingCommon.Devices;
|
||||
@ -52,24 +57,25 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
// TODO: [장비구현필요] 실제 공정 추가
|
||||
const string SEQ_CHECK_LOAD_COMPLETE = "[SeqAutoRunCCWH52A] Check Load 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_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_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_DO_ID_UPLOAD_WELDING_LIST_SEQ = "[SeqAutoRunCCWH52A] Process (UploadWeldingList Seq)";
|
||||
const string SEQ_GET_RESULT_UPLOAD_WELDING_LIST_SEQ = "[SeqAutoRunCCWH52A] Get Sequence Result (UploadWeldingList Seq)";
|
||||
|
||||
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_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_GET_PARAMS_RECEIVE_CELL_INFO_SEQ = "[SeqAutoRunCCWH52A] Get Sequence Result (ReceiveCellInfo Seq)";
|
||||
|
||||
const string SEQ_EXECUTE_WELDING = "[SeqAutoRunCCWH52A] Execute Welding";
|
||||
const string SEQ_REQUEST_UNLOAD_CELL = "[SeqAutoRunCCWH52A] Request Unload Cell";
|
||||
//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_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_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_GET_RESULT_REPORT_CELL_RESULT_SEQ = "[SeqAutoRunCCWH52A] Get Sequence Result (ReportCellResult Seq)";
|
||||
|
||||
//const string SEQ_REPORT_CELLINFO_TO_PLC = "[SeqAutoRunCCWH52A] ReportCellInfoToPLC";
|
||||
const string SEQ_CHECK_CYCLE_STOP = "[SeqAutoRunCCWH52A] Check Cycle Stop";
|
||||
@ -101,8 +107,6 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
private SystemParameter _SystemParameter;
|
||||
private ScannerCanvasUserCtrl _ScannerCanvasUserCtrl; //스캐너 동작관련 객체 선언
|
||||
|
||||
private string _LotId = "N/A";
|
||||
private string _CellId = "N/A";
|
||||
private int _ModelNo;
|
||||
|
||||
private IRecipeManager _RecipeManager;
|
||||
@ -117,25 +121,13 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
private uint _TotalProduct;
|
||||
|
||||
private double _LaserPowerByLBAD;
|
||||
private int _CompletedJigNo;
|
||||
private static bool isWeled;
|
||||
|
||||
private bool _ModulationMode;
|
||||
|
||||
private DateTime _AutoRunStartTime;
|
||||
private DateTime _WeldingStartTime;
|
||||
private TimeSpan _WeldingSpanTime;
|
||||
private DateTime _WeldEndTime;
|
||||
private TimeSpan _InterfaceSpanTime;
|
||||
private DateTime _InterfaceStartTime;
|
||||
// 연속 지그 간 용접 간격 계산 전용 (보고 데이터 아님 — 인터벌 로그용)
|
||||
private DateTime _prevWeldEndTime;
|
||||
|
||||
private double _CellMeasureCenterOffsetX;
|
||||
private double _CellMeasureCenterOffsetY;
|
||||
|
||||
// MOTF
|
||||
private TimeSpan _WeldInterval;
|
||||
|
||||
private int _LastScannerParamNo = -1; //마지막 작업한 스캔 변수값들이 현재 작업하려는 스캔 변수값과 같은지 판단함(같으면 설정작업을 skip함)
|
||||
private int _EncoderOverflowCount = 0;
|
||||
|
||||
private double _RotaryEncoderOffset = 0;
|
||||
@ -143,10 +135,11 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
private int _WeldingCount = 0;
|
||||
private int _RotaryJigCount = 16;
|
||||
|
||||
// 전전 셀/전 셀/대기 셀/완료 셀 파이프라인 스케줄러 (16개 JigInfo 풀, GC-free)
|
||||
private CellInfoScheduler _CellScheduler;
|
||||
|
||||
private double _WeldingStartAngle;
|
||||
|
||||
private bool isTheFirstListWrite;
|
||||
private bool isTheSecondListWrite;
|
||||
private bool isTheFirstListExecute;
|
||||
private int _RecipeNo;
|
||||
|
||||
@ -176,26 +169,29 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
|
||||
sb.AddAction(SEQ_CHECK_LOAD_COMPLETE, CheckLoadComplete);
|
||||
|
||||
sb.AddAction(SEQ_SET_PARAMS_RECEIVE_CELL_INFO_SEQ, SetReceiveCellInfo_SeqParams); // 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_CHECK_SCANNER_LIST_COMPLETE, CheckScannerListComplete);
|
||||
sb.AddDecision(SEQ_READY_SCANNER_LIST, ReadyScannerList);
|
||||
|
||||
#warning 아래 서브시퀀스가 CellTracker에서 받은 데이터를 WeldingData에 넣기만함, ProcessManager에서 Cell정보를 직접 Callback으로 받도록 수정함
|
||||
//sb.AddAction(SEQ_SET_PARAMS_RECEIVE_CELL_INFO_SEQ, SetReceiveCellInfo_SeqParams); // 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.AddSubsequence(SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ, SequenceManager.GetSeqBuilder_SeqUploadWeldingList());
|
||||
sb.AddAction(SEQ_GET_RESULT_UPLOAD_WELDING_LIST_SEQ, GetUploadWeldingList_SeqResult);
|
||||
|
||||
sb.AddAction(SEQ_EXECUTE_WELDING, ExecuteWelding);
|
||||
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);
|
||||
sb.AddSubsequence(SEQ_DO_ID_REPORT_CELL_RESULT_SEQ, SequenceManager.GetSeqBuilder_SeqReportCellResult());
|
||||
sb.AddAction(SEQ_GET_RESULT_REPORT_CELL_RESULT_SEQ, GetReportCellResult_SeqResult);
|
||||
#warning ReportCellResult함수로 아래 시퀀스 대체
|
||||
//sb.AddAction(SEQ_SET_PARAMS_REPORT_CELL_RESULT_SEQ, SetReportCellResult_SeqParams);
|
||||
//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_CAN_WELDED, CheckCanWelded);
|
||||
|
||||
sb.AddAction(SEQ_SAVE_RESULT_DATA, SaveResultData); // 해당 공정의 정보를 기록 함.
|
||||
sb.AddAction(SEQ_WRITE_COMPLETION_PLC_BIT, WriteCompletionPLCBit); // 정상적으로 종료 되면, complete bit write
|
||||
@ -203,13 +199,12 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
sb.AddAction(SEQ_COMPLETE, 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_SET_PARAMS_RECEIVE_CELL_INFO_SEQ] > sb[SEQ_DO_ID_RECEIVE_CELL_INFO_SEQ] > sb[SEQ_GET_PARAMS_RECEIVE_CELL_INFO_SEQ]
|
||||
> sb[SEQ_CHECK_SCANNER_LIST_COMPLETE] > sb[SEQ_READY_SCANNER_LIST]
|
||||
> 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_SET_PARAMS_REPORT_CELL_RESULT_SEQ] > sb[SEQ_DO_ID_REPORT_CELL_RESULT_SEQ] > sb[SEQ_GET_RESULT_REPORT_CELL_RESULT_SEQ]
|
||||
> 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_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]);
|
||||
|
||||
@ -217,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_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
|
||||
//sb.Flows(sb[SEQ_FORK_ENCODER_MONITOR] > sb[SEQ_ENCODER_MONITOR]);
|
||||
@ -299,9 +294,6 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
|
||||
_WeldingScannerListNo = eListNo.LIST1;
|
||||
|
||||
_CellMeasureCenterOffsetX = 0.0;
|
||||
_CellMeasureCenterOffsetY = 0.0;
|
||||
|
||||
var currentModelName = context.Recipes.ActivatedModelName();
|
||||
var modelItem = context.GetModel<EquipmentSpecificModel_CCW_H52A>(currentModelName, CommonModelIds.EquipmentSpecificModel);
|
||||
_ModelNo = modelItem.Model_No;
|
||||
@ -322,6 +314,8 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
_CellTracker = context.GetCellTracker();
|
||||
_PLC = context.Devices[DeviceIds.PLCDevice] as PLCControllerCCWH52A;
|
||||
_IO = context.GetIOUnit();
|
||||
_CellScheduler = ProcessManager.Instance.cellScheduler;
|
||||
|
||||
}
|
||||
|
||||
private bool CheckDeviceReady(SequenceContext context)
|
||||
@ -403,15 +397,13 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
_ModulationMode = false;
|
||||
}
|
||||
|
||||
//// PLC Initialize AutoRun Bit 최소화 작업 진행
|
||||
if (_PLC.ReadBit((int)eBitInput.PLC_AUTO_STATUS).data == false) // AutoRun Bit가 OFF인 경우
|
||||
{
|
||||
if (_PLC.ReadBit((int)eBitInput.PLC_AUTO_REQ).data == false) // AutoRun Request 상태 체크
|
||||
{
|
||||
///// AutoRun Bit가 OFF인 경우
|
||||
if (_PLC.ReadBit((int)eBitInput.PLC_AUTO_STATUS).data == false) {
|
||||
// AutoRun Request 상태 체크
|
||||
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 발생함.
|
||||
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를 켜지 않음.
|
||||
return (int)InitErrorList.PLC_AUTORUN_BIT_OFF;
|
||||
}
|
||||
@ -433,10 +425,6 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
string[] strArr = Dao.SystemRecipe.WorkRecipeFile.Split('\\');
|
||||
RecipeFileName = strArr[strArr.Length - 1];
|
||||
|
||||
_LastScannerParamNo = -1;
|
||||
|
||||
// 트럼프 TruDisk를 쓰기 위해서는 SetFirstPulseKiller를 사용해야 함.
|
||||
|
||||
// Rotary는 시작 트리거 미사용
|
||||
_Scanner.SetControlMode(0);
|
||||
UtilUnit.logUnit.SetLog(LogUnit.eLogType.DEBUG, MethodBase.GetCurrentMethod().Name, "[AutoRun] 외부 시작 트리거 DISABLE");
|
||||
@ -455,13 +443,20 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
|
||||
Log.I(string.Format($"ScannerUnit.InitRotaryOnTheFlyWeldingCount : m_abwRotaryEncoderOffset({_RotaryEncoderOffset}), weldingCount({_WeldingCount}), weldingJigNo({_WeldingJigNo}), rotaryJigCount({_RotaryJigCount})"));
|
||||
|
||||
// 용접 완료 대기 스캐너 List 리셋
|
||||
ResetInputScannerList();
|
||||
WaitingScannerList.Reset();
|
||||
CompleteScannerList.Reset();
|
||||
// JigInfo 풀 스케줄러 초기화 (전전/전/대기/완료 셀 파이프라인)
|
||||
// ── 재시작 전 미완료 보고 보존 ───────────────────────────────────────────────
|
||||
// ReportTarget이 있는 상태로 정지가 들어오면 Reset() 후 슬롯이 Clear()되어 보고 불가.
|
||||
// SavePendingComplete()로 _pendingSlot에 복사한 뒤 Reset()을 호출한다.
|
||||
|
||||
_CellScheduler.SavePendingComplete();
|
||||
if (_CellScheduler.HasPendingPrefetch)
|
||||
Log.I("[PendingRestore] 미용접 셀 보존됨 >> 재시작 후 JigNo 매칭 시 복원 예정");
|
||||
_CellScheduler.Reset();
|
||||
|
||||
// 정지 전 미저장 APD 잔존 데이터 클리어 — 재시작 시 중복 누적 방지
|
||||
Status.GetProcessingWeldingData().APD.Clear();
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
isTheFirstListWrite = true; // 작업 시작 시 처음 2개의 List는 입력하고 시작한다
|
||||
isTheSecondListWrite = true;
|
||||
isTheFirstListExecute = true; // 제일 첫 List는 ExecuteList 필요. 이후는 AutoChange
|
||||
|
||||
_PLC.WriteBit(eBitOutput.PC_AUTO_STATUS, true);
|
||||
@ -559,100 +554,80 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
|
||||
private SequenceActionResult CheckScannerListComplete(SequenceContext context, string id, SequenceActionResult param)
|
||||
{
|
||||
if (isTheFirstListWrite) // 작업 시작 시, 첫번째 리스트는 바로 쓰고, 바로 시작한다(ExecuteList). 다만 List 명령에 의해 Encoder가 들어올 때까지 대기.
|
||||
{
|
||||
isTheFirstListWrite = false;
|
||||
Log.I("Write the 1st scanner list");
|
||||
|
||||
// Prefetch1 = 2회 전 업로드된 지그 = 현재 물리적으로 레이저 통과 중 = 완료 체크 대상.
|
||||
// Shift()는 이 메서드 이후 ReadyScannerList에서 실행되므로, 이 시점의 Prefetch1이
|
||||
// 원본 코드의 InputScannerList[(listNo-1)]과 동일 대상이다.
|
||||
// 예열 구간: iter 1~2(Pf1=null) → 통과. iter 3~: Pf1=Jig1 → 실제 처리.
|
||||
var jigComplete = _CellScheduler.Prefetch1;
|
||||
if (jigComplete == null) {
|
||||
Log.I($"[Warmup] ScannerList {_WeldingCount}: pipeline not ready, skip complete check");
|
||||
return SequenceAction.Ok();
|
||||
}
|
||||
if (!CheckCurrentEncoderAngle(jigComplete.StartAngle)) {
|
||||
// IsCanExist=false(공 지그)는 리스트 실행은 하지만 용접이 없으므로
|
||||
// 엔코더 범위를 벗어나도 에러가 아님
|
||||
if (jigComplete.IsCanExist) {
|
||||
Log.I("ERR_SCANNER_LIST_PROCESSING_TIMEOVER");
|
||||
return SequenceAction.Error();
|
||||
}
|
||||
return SequenceAction.Ok();
|
||||
}
|
||||
else {
|
||||
if (isTheSecondListWrite) // 두번째 리스트는 바로 쓰지만, 첫번째 리스트 실행이 완료되면 자동으로 이어서 실행된다(AutoChange)
|
||||
{
|
||||
isTheSecondListWrite = false;
|
||||
Log.I("Write the 2nd scanner list");
|
||||
if (jigComplete.IsCanExist) {
|
||||
#region 용접 시간, 엔코더 측정/기록
|
||||
double elaspedTime = _Scanner.GetTime();
|
||||
|
||||
}
|
||||
else {
|
||||
isWeled = false;
|
||||
// 첫번째나 두번째가 아니라면, 실제 리스트 실행이 끝난 것이기 때문에 완료 처리가 필요
|
||||
CompleteScannerList = InputScannerList[(int)_WeldingScannerListNo - 1];
|
||||
if (jigComplete.WeldComplete) {
|
||||
jigComplete.WeldEndTime = DateTime.Now;
|
||||
jigComplete.WeldingSpanTime = TimeSpan.FromSeconds(elaspedTime);
|
||||
TimeSpan weldInterval = jigComplete.WeldEndTime - _prevWeldEndTime;
|
||||
_prevWeldEndTime = jigComplete.WeldEndTime;
|
||||
|
||||
if (!CheckCurrentEncoderAngle(CompleteScannerList.StartAngle)) {
|
||||
// 에러 상황(현재 Rotary Encoder 값이 정상적인 스캐너 리스트 각도 범위를 벗어남)
|
||||
Log.I("ERR_SCANNER_LIST_PROCESSING_TIMEOVER");
|
||||
// 보고 대상 슬롯 지정 (스케줄러가 관리)
|
||||
_CellScheduler.ReportTarget = jigComplete;
|
||||
|
||||
return SequenceAction.Error();
|
||||
Log.I(string.Format("JigNo : {0}, Weld start : {1}, Weld End : {2}, WeldTime : {3}, interval : {4:F3}",
|
||||
jigComplete.JigNo,
|
||||
jigComplete.WeldStartTime.ToString("HH:mm:ss.fff"),
|
||||
jigComplete.WeldEndTime.ToString("HH:mm:ss.fff"),
|
||||
jigComplete.WeldingSpanTime.TotalMilliseconds,
|
||||
weldInterval.TotalSeconds));
|
||||
|
||||
// WON : 2칸 전에 용접을 진행하지 않아 현재 Angle이 CompleteScannerList.StartAngle + 45 범위를 벗어난 경우라면 에러 상황이 아니므로 에러로 처리 할 필요가 없다
|
||||
// 위에 CheckCurrentEncoderAngle if문 조건 대신 아래 내용으로 테스트 해본 뒤에 적용 필요
|
||||
//if (!CheckCurrentEncoderAngle(CompleteScannerList.StartAngle)) {
|
||||
// // 에러 상황(현재 Rotary Encoder 값이 정상적인 스캐너 리스트 각도 범위를 벗어남)
|
||||
// if (CompleteScannerList.CanExist) {
|
||||
// Log.I("ERR_SCANNER_LIST_PROCESSING_TIMEOVER");
|
||||
// return SequenceAction.Error();
|
||||
// }
|
||||
// return SequenceAction.Ok();
|
||||
}
|
||||
else {
|
||||
if (CompleteScannerList.CanExist) {
|
||||
isWeled = true;
|
||||
#region 용접 시간, 엔코더 측정/기록
|
||||
//_WeldInterval = DateTime.Now - _WeldEndTime;
|
||||
//_WeldEndTime = DateTime.Now;
|
||||
//double elapsedTime = _Scanner.GetTime();
|
||||
//_WeldingSpanTime = TimeSpan.FromSeconds(elapsedTime); // Encoder 대기 넘어간 후의, 실제 스캐너 리스트 실행 시간
|
||||
//_WeldingStartTime = _WeldEndTime.Subtract(_WeldingSpanTime);
|
||||
|
||||
double elaspedTime = _Scanner.GetTime();
|
||||
|
||||
if (CompleteScannerList.WeldComplete) {
|
||||
_WeldInterval = DateTime.Now - _WeldEndTime;
|
||||
_WeldEndTime = DateTime.Now;
|
||||
_WeldingStartTime = CompleteScannerList.WeldStartTime;
|
||||
_WeldingSpanTime = TimeSpan.FromSeconds(elaspedTime);
|
||||
_LotId = CompleteScannerList.LotId;
|
||||
_CellId = CompleteScannerList.CellId;
|
||||
|
||||
Log.I(string.Format("JigNo : {0}, Weld start : {1}, Weld End : {2}, WeldTime : {3}, interval : {4:F3}",
|
||||
CompleteScannerList.JigNo, _WeldingStartTime.ToString("HH:mm:ss.fff"), _WeldEndTime.ToString("HH:mm:ss.fff"), _WeldingSpanTime.TotalMilliseconds, _WeldInterval.TotalSeconds));
|
||||
|
||||
if (_PLC.ReadBit((int)eBitInput.PLC_USE_WELD_JIG_1 + CompleteScannerList.JigNo - 1).data) {
|
||||
_PLC.WriteBit((int)eBitOutput.PC_WELD_COMPLETE_1 + CompleteScannerList.JigNo - 1, true);
|
||||
Log.I(string.Format($"PC_WELD_COMPLETE_{CompleteScannerList.JigNo} -> true)"));
|
||||
}
|
||||
UpdateProductCount(context);
|
||||
UpdateProductInfoForView();
|
||||
SaveCellAPD();
|
||||
}
|
||||
|
||||
//if (_SystemParameter.BypassModeLBAD == false) {
|
||||
// if (_StreamLightLBAD.SendWeldingStop() == false) {
|
||||
// Log.I(string.Format($"[LBAD Interface]SendWeldingStop null"));
|
||||
// //return null;
|
||||
// }
|
||||
//}
|
||||
|
||||
UtilUnit.logUnit.SetLog(LogUnit.eLogType.PRODUCT, MethodBase.GetCurrentMethod().Name, "UPDATE_WELDING_TIME;" + _WeldingSpanTime.TotalMilliseconds);
|
||||
UtilUnit.logUnit.SetLog(LogUnit.eLogType.PRODUCT, MethodBase.GetCurrentMethod().Name, "UPDATE_PRODUCT_COUNT;" + _WeldEndTime.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||
|
||||
double encoder0_0, encoder1_0, encoder0_1, encoder1_1;
|
||||
_Scanner.ReadEncoder(out encoder0_0, out encoder1_0, out encoder0_1, out encoder1_1, true);
|
||||
|
||||
double startEncoderCount = encoder0_0;
|
||||
double endEncoderCount = encoder0_1;
|
||||
double angularVelocity = (endEncoderCount - startEncoderCount) / elaspedTime; // 단위는 [degree/sec]
|
||||
|
||||
Log.I(string.Format("Encoder start : {0:F4}, end : {1:F4}, vel : {2:F2}", startEncoderCount, endEncoderCount, angularVelocity));
|
||||
#endregion
|
||||
#region 스캐너 리스트 Record 파일 기록
|
||||
if (_Scanner.Config.UseRecordSignal) {
|
||||
String RecordFileName = _RecipeManager.ActivatedRecipe().Name + "_Jig#" + CompleteScannerList.JigNo.ToString();
|
||||
string DataFilePath = ProjectUtil.GetDataLogSetting().GetFilePath_ScannerRecordLog(RecordFileName, true);
|
||||
_Scanner.SaveRecord(DataFilePath);
|
||||
}
|
||||
#endregion
|
||||
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);
|
||||
Log.I(string.Format($"PC_WELD_COMPLETE_{jigComplete.JigNo} -> true)"));
|
||||
}
|
||||
UpdateProductCount(context);
|
||||
UpdateProductInfoForView();
|
||||
SaveCellAPD();
|
||||
}
|
||||
|
||||
//if (_SystemParameter.BypassModeLBAD == false) {
|
||||
// if (_StreamLightLBAD.SendWeldingStop() == false) {
|
||||
// Log.I(string.Format($"[LBAD Interface]SendWeldingStop null"));
|
||||
// //return null;
|
||||
// }
|
||||
//}
|
||||
|
||||
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"));
|
||||
|
||||
double encoder0_0, encoder1_0, encoder0_1, encoder1_1;
|
||||
_Scanner.ReadEncoder(out encoder0_0, out encoder1_0, out encoder0_1, out encoder1_1, true);
|
||||
|
||||
double startEncoderCount = encoder0_0;
|
||||
double endEncoderCount = encoder0_1;
|
||||
double angularVelocity = (endEncoderCount - startEncoderCount) / elaspedTime; // 단위는 [degree/sec]
|
||||
|
||||
Log.I(string.Format("Encoder start : {0:F4}, end : {1:F4}, vel : {2:F2}", startEncoderCount, endEncoderCount, angularVelocity));
|
||||
#endregion
|
||||
#region 스캐너 리스트 Record 파일 기록
|
||||
if (_Scanner.Config.UseRecordSignal) {
|
||||
String RecordFileName = _RecipeManager.ActivatedRecipe().Name + "_Jig#" + jigComplete.JigNo.ToString();
|
||||
string DataFilePath = ProjectUtil.GetDataLogSetting().GetFilePath_ScannerRecordLog(RecordFileName, true);
|
||||
_Scanner.SaveRecord(DataFilePath);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
return SequenceAction.Ok();
|
||||
@ -668,14 +643,15 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
// Encoder 반전되는 순간이며, 이 때만 인터락 무시
|
||||
}
|
||||
else if (startAngle <= currentAngle) {
|
||||
if (currentAngle < startAngle + 45)// 다음 리스트 구간이 끝나기 전까지는 완료가 되어야 한다
|
||||
{
|
||||
// 다음 리스트 구간이 끝나기 전까지는 완료가 되어야 한다
|
||||
if (currentAngle < startAngle + 45) {
|
||||
Log.I(string.Format("Current encoder check OK, startAngle : {0}, currentAngle : {1})", startAngle, currentAngle));
|
||||
return true;
|
||||
}
|
||||
else Log.W(string.Format("Current encoder check NG(Too late), startAngle : {0}, currentAngle : {1})", startAngle, currentAngle));
|
||||
} else
|
||||
Log.W(string.Format("Current encoder check NG(Too late), startAngle : {0}, currentAngle : {1})", startAngle, currentAngle));
|
||||
}
|
||||
else Log.W(string.Format("Current encoder check NG(Too early), startAngle : {0}, currentAngle : {1})", startAngle, currentAngle));
|
||||
else
|
||||
Log.W(string.Format("Current encoder check NG(Too early), startAngle : {0}, currentAngle : {1})", startAngle, currentAngle));
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -725,7 +701,56 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
else
|
||||
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=false 지그도 Shift()해야 Prefetch1 타이밍이 올바르게 유지됨.
|
||||
_CellScheduler.Shift(_WeldingJigNo);
|
||||
|
||||
_CellScheduler.Prefetch2.JigNo = _WeldingJigNo;
|
||||
_CellScheduler.Prefetch2.ListNo = _WeldingScannerListNo;
|
||||
_CellScheduler.Prefetch2.WriteTime = DateTime.Now;
|
||||
_CellScheduler.Prefetch2.StartAngle = _WeldingStartAngle;
|
||||
_CellScheduler.Prefetch2.WeldingCount = _WeldingCount;
|
||||
_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 (canExist && 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;
|
||||
} else {
|
||||
_CellTracker.getDummyData(out string lotId, out string cellId);
|
||||
_CellScheduler.Prefetch2.LotId = lotId;
|
||||
_CellScheduler.Prefetch2.CellId = cellId;
|
||||
Status.GetProcessingWeldingData().WorkLotId = lotId;
|
||||
Status.GetProcessingWeldingData().WorkCellId = cellId;
|
||||
}
|
||||
|
||||
if (_CellScheduler.Prefetch2 != null)
|
||||
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})]");
|
||||
|
||||
if(_CellScheduler.Prefetch1 != null)
|
||||
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) {
|
||||
#region 용접할 Objects 선택
|
||||
@ -738,12 +763,7 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
Log.I(string.Format("Page 불러오기 : [0])"));
|
||||
}
|
||||
#endregion
|
||||
// 입력한 Scanner List를 완료대기열에 추가
|
||||
// Won : GetProcessingWeldingData().WorkLotId 는 CellTrakcer로 부터 받은 상태의 LotId
|
||||
// GetProcessingWeldingData().LotId 는 AutorunView에 표기할 용접이 완료 된 LotID
|
||||
string LotId = Status.GetProcessingWeldingData().WorkLotId; // CellTracker로 부터 WorkLotID, WorkCellID 받는 구문 추가 후 해당 데이터로 입력 필요
|
||||
string CellId = Status.GetProcessingWeldingData().WorkCellId;
|
||||
SetInputScannerList(_WeldingScannerListNo, DateTime.Now, _WeldingCount, _WeldingStartAngle, _WeldingJigNo, _RotaryJigCount, canExist, LotId, CellId);
|
||||
|
||||
_RecipeNo = _RecipeManager.ActivatedRecipe().Id;
|
||||
|
||||
SetWeldingData();
|
||||
@ -814,22 +834,22 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
public bool GetRotaryCanExist(int jigNo)
|
||||
{
|
||||
#region 지그 16개 요청기록 로그 남기기, 빠져나간 캔에 대한 Complete Bit 초기화
|
||||
string result = "";
|
||||
//string result = "";
|
||||
|
||||
for (int i = 1; i <= _RotaryJigCount; i++) {
|
||||
if (_PLC.ReadBit((int)eBitInput.PLC_USE_WELD_JIG_1 + i).data)
|
||||
result += "1, ";
|
||||
else {
|
||||
result += "0, ";
|
||||
//for (int i = 1; i <= _RotaryJigCount; i++) {
|
||||
// if (_PLC.ReadBit((int)eBitInput.PLC_USE_WELD_JIG_1 + i).data)
|
||||
// result += "1, ";
|
||||
// else {
|
||||
// result += "0, ";
|
||||
|
||||
string outId = string.Format("PC_WELD_COMPLETE_{0}", i);
|
||||
// string outId = string.Format("PC_WELD_COMPLETE_{0}", i);
|
||||
|
||||
if (_PLC.ReadBit((int)eBitInput.PLC_USE_WELD_JIG_1 + i).data) {
|
||||
_PLC.WriteBit((int)eBitOutput.PC_WELD_COMPLETE_1 + i, false);
|
||||
Log.I(string.Format($"PC_WELD_COMPLETE_{1 + i} -> FALSE)"));
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (_PLC.ReadBit((int)eBitInput.PLC_USE_WELD_JIG_1 + i).data) {
|
||||
// _PLC.WriteBit((int)eBitOutput.PC_WELD_COMPLETE_1 + i, false);
|
||||
// Log.I(string.Format($"PC_WELD_COMPLETE_{1 + i} -> FALSE)"));
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//UtilUnit.logUnit.SetLog(LogUnit.eLogType.DEBUG, MethodBase.GetCurrentMethod().Name, string.Format("PLC -> PC 용접 Cmd : ({0})", result));
|
||||
#endregion
|
||||
|
||||
@ -846,8 +866,8 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
SeqUploadWeldingList_InitParam seqParams = new SeqUploadWeldingList_InitParam() {
|
||||
NeedSetLaserTiming = _ModulationMode,
|
||||
IncludeListStartEnd = false,
|
||||
CellMeasureCenterOffsetX = _CellMeasureCenterOffsetX,
|
||||
CellMeasureCenterOffsetY = _CellMeasureCenterOffsetY,
|
||||
CellMeasureCenterOffsetX = 0,
|
||||
CellMeasureCenterOffsetY = 0,
|
||||
SelectedDrawObjectList = _SelectedDrawObjectList,
|
||||
WeldingScannerListNo = _WeldingScannerListNo,
|
||||
Rotation_Degree = 11.25,
|
||||
@ -864,26 +884,34 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
return SequenceAction.ForceStopByAlarm(AlarmCode.ALARM_SEQUENCE_UploadWeldingList_ResultFailed);
|
||||
//return null;
|
||||
}
|
||||
// 입력한 Scanner List를 완료대기열에 추가
|
||||
// Won : GetProcessingWeldingData().WorkLotId 는 CellTrakcer로 부터 받은 상태의 LotId
|
||||
// GetProcessingWeldingData().LotId 는 AutorunView에 표기할 용접이 완료 된 LotID
|
||||
string LotId = Status.GetProcessingWeldingData().WorkLotId; // CellTracker로 부터 WorkLotID, WorkCellID 받는 구문 추가 후 해당 데이터로 입력 필요
|
||||
string CellId = Status.GetProcessingWeldingData().WorkCellId;
|
||||
|
||||
_CellScheduler.Prefetch2.LotId = LotId;
|
||||
_CellScheduler.Prefetch2.CellId = CellId;
|
||||
Log.FuncI("CellTracker Load");
|
||||
return SequenceAction.Ok();
|
||||
}
|
||||
|
||||
private SequenceActionResult SetReceiveCellInfo_SeqParams(SequenceContext context, string id, SequenceActionResult param)
|
||||
{
|
||||
SeqReceiveCellInfo_InitParam seqParams = new SeqReceiveCellInfo_InitParam() {
|
||||
};
|
||||
//private SequenceActionResult SetReceiveCellInfo_SeqParams(SequenceContext context, string id, SequenceActionResult param)
|
||||
//{
|
||||
// SeqReceiveCellInfo_InitParam seqParams = new SeqReceiveCellInfo_InitParam() {
|
||||
// };
|
||||
|
||||
return SequenceAction.Ok(seqParams);
|
||||
}
|
||||
// return SequenceAction.Ok(seqParams);
|
||||
//}
|
||||
|
||||
private SequenceActionResult GetReceiveCellInfo_SeqResult(SequenceContext context, string id, SequenceActionResult param)
|
||||
{
|
||||
var resultOutParam = param.Param as SeqReceiveCellInfo_OutParam;
|
||||
if (resultOutParam.Success == false) {
|
||||
return null;
|
||||
}
|
||||
return SequenceAction.Ok();
|
||||
}
|
||||
//private SequenceActionResult GetReceiveCellInfo_SeqResult(SequenceContext context, string id, SequenceActionResult param)
|
||||
//{
|
||||
// var resultOutParam = param.Param as SeqReceiveCellInfo_OutParam;
|
||||
// if (resultOutParam.Success == false) {
|
||||
// return null;
|
||||
// }
|
||||
// return SequenceAction.Ok();
|
||||
//}
|
||||
|
||||
private SequenceActionResult ExecuteWelding(SequenceContext context, string id, SequenceActionResult param)
|
||||
{
|
||||
@ -919,7 +947,6 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
}
|
||||
private SequenceActionResult EncoderMonitor(SequenceContext context, string id, SequenceActionResult param)
|
||||
{
|
||||
int EncoderLogCount = 0;
|
||||
double send_time_offset = 0.1;
|
||||
string LotID = "", CellID = "";
|
||||
|
||||
@ -927,42 +954,55 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
double encoderX, currentAngle;
|
||||
_Scanner.GetEncoder(out encoderX, out currentAngle, true);
|
||||
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와의 경합 방지) ──────
|
||||
// Prefetch1: 2회 전 업로드된 지그 = 현재 물리적으로 실행 중인 지그.
|
||||
// 원본 코드의 InputScannerList[(listNo-1)]과 동일 대상.
|
||||
// Shift()는 메인 시퀀스에서만 호출되므로 루프 시작 시 캡처해도 안전.
|
||||
var executeTarget = _CellScheduler.Prefetch1;
|
||||
|
||||
if (WeldingInPosition) {
|
||||
if (InputScannerList[(int)_WeldingScannerListNo - 1].CanExist) {
|
||||
Log.I($"Fork Before Min Rotate Encoder X : ({encoderX}), Encoder Y : ({currentAngle}), PLC Rotary : ({CurrentPosPLC}), List {_WeldingScannerListNo}, JigNo : ({InputScannerList[(int)_WeldingScannerListNo - 1].JigNo})");
|
||||
if (executeTarget != null && executeTarget.IsCanExist) {
|
||||
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 (InputScannerList[(int)_WeldingScannerListNo - 1].CheckSendCellinfo == false) {
|
||||
LotID = InputScannerList[(int)_WeldingScannerListNo - 1].LotId;
|
||||
CellID = InputScannerList[(int)_WeldingScannerListNo - 1].CellId;
|
||||
if (currentAngle > InputScannerList[(int)_WeldingScannerListNo - 1].StartAngle) {
|
||||
InputScannerList[(int)_WeldingScannerListNo - 1].CheckSendCellinfo = _StreamLightLBAD.SendCellInfo(LotID, CellID, _RecipeNo, _ModelNo, InputScannerList[(int)_WeldingScannerListNo - 1].JigNo);
|
||||
if (!executeTarget.CheckSendCellinfo) {
|
||||
LotID = executeTarget.LotId;
|
||||
CellID = executeTarget.CellId;
|
||||
if (currentAngle > executeTarget.StartAngle) {
|
||||
executeTarget.CheckSendCellinfo = _StreamLightLBAD.SendCellInfo(LotID, CellID, _RecipeNo, _ModelNo, executeTarget.JigNo);
|
||||
|
||||
if (InputScannerList[(int)_WeldingScannerListNo - 1].CheckSendCellinfo == false)
|
||||
Log.I($"[LBAD Interface]SendCellInfo null, LotID [{LotID}], CellID [{CellID}], JigNo [{InputScannerList[(int)_WeldingScannerListNo - 1].JigNo}]");
|
||||
if (!executeTarget.CheckSendCellinfo)
|
||||
Log.I($"[LBAD Interface]SendCellInfo null, LotID [{LotID}], CellID [{CellID}], JigNo [{executeTarget.JigNo}]");
|
||||
else
|
||||
Log.I($"[StreamLight]SendCellInfo LotID [{LotID}], CellID [{CellID}], JigNo [{InputScannerList[(int)_WeldingScannerListNo - 1].JigNo}]");
|
||||
Log.I($"[StreamLight]SendCellInfo LotID [{LotID}], CellID [{CellID}], JigNo [{executeTarget.JigNo}]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_IO._iOUnit.ReadDiBit(Convert.ToInt32(eADIAddress.LaserOn))) {
|
||||
if (InputScannerList[(int)_WeldingScannerListNo - 1].WeldStartTime == DateTime.MinValue && InputScannerList[(int)_WeldingScannerListNo - 1].CanExist) {
|
||||
InputScannerList[(int)_WeldingScannerListNo - 1].WeldStartTime = DateTime.Now;
|
||||
InputScannerList[(int)_WeldingScannerListNo - 1].WeldComplete = true;
|
||||
EncoderLogCount = 0;
|
||||
Log.I($"Laser On, Welding Complete. JigNo : ({InputScannerList[(int)_WeldingScannerListNo - 1].JigNo})");
|
||||
var LaserIO = _IO._iOUnit.ReadDiBit(Convert.ToInt32(eADIAddress.LaserOn));
|
||||
var IsLaserOn = ChangeChecker.IsChangedBoolMonitoring("LaserOn", LaserIO, true);
|
||||
if (IsLaserOn) {
|
||||
if (executeTarget != null && executeTarget.IsCanExist && executeTarget.WeldStartTime == DateTime.MinValue) {
|
||||
executeTarget.WeldStartTime = DateTime.Now;
|
||||
executeTarget.WeldComplete = true;
|
||||
Log.I($"Laser On, Welding Complete. JigNo : ({executeTarget.JigNo})");
|
||||
}
|
||||
|
||||
if (EncoderLogCount == 0) {
|
||||
Log.I($"Fork Laser On Encoder X : ({encoderX}), Encoder Y : ({currentAngle}), PLC Rotary : ({CurrentPosPLC}), List {_WeldingScannerListNo}, JigNo : ({InputScannerList[(int)_WeldingScannerListNo - 1].JigNo})");
|
||||
}
|
||||
EncoderLogCount = (EncoderLogCount + 1) % 7;
|
||||
}
|
||||
|
||||
// List의 실행의 토글을 확인함
|
||||
_Scanner.GetListPointer(out eListNo curList, out uint pos);
|
||||
var isBusy = _Scanner.GetBusyStatus();
|
||||
if (!isBusy && (curList == eListNo.LIST1 || curList == eListNo.LIST2))
|
||||
curList = eListNo.NONE;
|
||||
|
||||
var IsToggleListState = ChangeChecker.IsChangedInt("ListState", (int)curList);
|
||||
if (IsToggleListState)
|
||||
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++) {
|
||||
if (_PLC.ReadBit((int)eBitInput.PLC_USE_WELD_JIG_1 + i).data == false) {
|
||||
_PLC.WriteBit((int)eBitOutput.PC_WELD_COMPLETE_1 + i, false);
|
||||
@ -999,48 +1039,95 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
{
|
||||
Status.GetProcessingWeldingData().TotalProduct = _TotalProduct;
|
||||
Status.GetProcessingWeldingData().TodayProduct = _TodayProduct;
|
||||
|
||||
Status.GetProcessingWeldingData().AutoRunStartTime = _AutoRunStartTime;
|
||||
|
||||
Status.GetProcessingWeldingData().WeldingStartTime = _WeldingStartTime;
|
||||
Status.GetProcessingWeldingData().WeldingEndTime = _WeldEndTime;
|
||||
Status.GetProcessingWeldingData().WeldingSpanTimeMilliseconds = _WeldingSpanTime.TotalMilliseconds.ToString();
|
||||
|
||||
// Status.GetProcessingWeldingData().LotId 는 Autorun View에 표기할 용접이 완료 된 LotId 이므로 WorkLotID 와의 구분 확인
|
||||
Status.GetProcessingWeldingData().LotId = _LotId;
|
||||
Status.GetProcessingWeldingData().CellId = _CellId;
|
||||
|
||||
Status.GetProcessingWeldingData().RecipeNo = _RecipeNo;
|
||||
Status.GetProcessingWeldingData().LaserPowerByLBAD = _LaserPowerByLBAD.ToString();
|
||||
|
||||
Status.GetProcessingWeldingData().WeldingJigNo = _CompletedJigNo.ToString();
|
||||
|
||||
// 보고 데이터는 스케줄러의 ActiveReportSlot(ReportTarget 또는 PendingComplete)에서 읽음
|
||||
var report = _CellScheduler.ActiveReportSlot;
|
||||
if (report != null) {
|
||||
Status.GetProcessingWeldingData().LotId = report.LotId;
|
||||
Status.GetProcessingWeldingData().CellId = report.CellId;
|
||||
Status.GetProcessingWeldingData().WeldingStartTime = report.WeldStartTime;
|
||||
Status.GetProcessingWeldingData().WeldingEndTime = report.WeldEndTime;
|
||||
Status.GetProcessingWeldingData().WeldingSpanTimeMilliseconds = report.WeldingSpanTime.TotalMilliseconds.ToString();
|
||||
Status.GetProcessingWeldingData().WeldingJigNo = report.JigNo.ToString();
|
||||
}
|
||||
}
|
||||
private SequenceActionResult SetReportCellResult_SeqParams(SequenceContext context, string id, SequenceActionResult param)
|
||||
|
||||
private SequenceActionResult ReportCellResult(SequenceContext context, string id, SequenceActionResult param)
|
||||
{
|
||||
Status.SetWorkingPosition(eWorkingPosition.REPORTING_RESULT);
|
||||
|
||||
SeqReportCellResult_InitParam seqParams = new SeqReportCellResult_InitParam() {
|
||||
EDC_Interface = new EDC(),
|
||||
};
|
||||
string strDate = DateTime.Now.Date.ToString("yyyyMMdd");
|
||||
string strTime = DateTime.Now.ToString("HHmmss");
|
||||
|
||||
return SequenceAction.Ok(seqParams);
|
||||
}
|
||||
var wd = Status.GetProcessingWeldingData();
|
||||
string reportDataLocalPath = _CellTracker._CellTrackerConfig.reportDataLocalPath;
|
||||
string equipName = _CellTracker._CellTrackerConfig.EquipmentName;
|
||||
|
||||
private SequenceActionResult GetReportCellResult_SeqResult(SequenceContext context, string id, SequenceActionResult param)
|
||||
{
|
||||
var resultOutParam = param.Param as SeqReportCellResult_OutParam;
|
||||
if (resultOutParam.Success == false) {
|
||||
return null;
|
||||
}
|
||||
string directory = string.Format(reportDataLocalPath + "{0}", strDate);
|
||||
if (!Directory.Exists(directory))
|
||||
Directory.CreateDirectory(directory);
|
||||
|
||||
// 중복 보고 방지 플래그 세팅
|
||||
CompleteScannerList.SetReportComplete(true);
|
||||
isWeled = false;
|
||||
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 + "");
|
||||
Log.I($"Report to CellTracker >> [LotID({wd.LotId.Replace("\0", "").Trim()})] [CellID({wd.CellId.Replace("\0", "").Trim()})]");
|
||||
|
||||
// 로컬 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)
|
||||
//{
|
||||
// Status.SetWorkingPosition(eWorkingPosition.REPORTING_RESULT);
|
||||
|
||||
// SeqReportCellResult_InitParam seqParams = new SeqReportCellResult_InitParam() {
|
||||
// EDC_Interface = new EDC(),
|
||||
// };
|
||||
|
||||
// return SequenceAction.Ok(seqParams);
|
||||
//}
|
||||
|
||||
//private SequenceActionResult GetReportCellResult_SeqResult(SequenceContext context, string id, SequenceActionResult param)
|
||||
//{
|
||||
// var resultOutParam = param.Param as SeqReportCellResult_OutParam;
|
||||
// if (resultOutParam.Success == false) {
|
||||
// return null;
|
||||
// }
|
||||
|
||||
// return SequenceAction.Ok();
|
||||
//}
|
||||
|
||||
private static string CheckCycleStop(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
|
||||
{
|
||||
Status.SetWorkingPosition(eWorkingPosition.CHECKING_CYCLE);
|
||||
@ -1063,19 +1150,20 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
#endregion
|
||||
private string CheckCanWelded(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
|
||||
{
|
||||
// 중복 보고 방지:
|
||||
// - CanExist=false (skip 대상) 는 보고하지 않음(미사용)
|
||||
// - WeldComplete=false (레이저 ON 감지/완료 처리 전) 는 보고하지 않음(미사용)
|
||||
// - ReportComplete=true (이미 보고 완료) 는 다시 보고하지 않음
|
||||
// .시퀀스가 너무 빨리 내려가서 보고하는 케이스로 예상
|
||||
// ── 재시작 전 미완료 보고 우선 처리 ─────────────────────────────────────────
|
||||
// SavePendingComplete()로 보존된 슬롯이 있으면 정상 파이프라인(ReportTarget)보다 우선.
|
||||
if (_CellScheduler.HasPendingComplete) {
|
||||
var p = _CellScheduler.PendingComplete;
|
||||
Log.I($"[PendingReport] 재시작 전 미완료 보고: LotId={p.LotId}, CellId={p.CellId}, JigNo={p.JigNo}");
|
||||
return SEQ_REPORT_CELL_RESULT;
|
||||
}
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
// 보고 누락:
|
||||
// - 첫번째, 두번째는 UploadWeldingList를 해야하기 때문에 일단 넘긴다.
|
||||
if (isWeled
|
||||
//CompleteScannerList.CanExist &&
|
||||
//CompleteScannerList.WeldComplete &&
|
||||
&& !CompleteScannerList.ReportComplete)
|
||||
return SEQ_SET_PARAMS_REPORT_CELL_RESULT_SEQ;
|
||||
// 정상 보고 경로:
|
||||
// - ReportTarget이 설정돼 있고 아직 보고 완료되지 않은 경우
|
||||
// - 첫번째, 두번째 반복은 SetReportTarget이 호출되지 않으므로 자연스럽게 통과
|
||||
if (_CellScheduler.HasReport)
|
||||
return SEQ_REPORT_CELL_RESULT;
|
||||
|
||||
return SEQ_CHECK_CYCLE_STOP;
|
||||
}
|
||||
@ -1091,7 +1179,6 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
}
|
||||
private SequenceActionResult SaveResultData(SequenceContext context, string id, SequenceActionResult param)
|
||||
{
|
||||
|
||||
context.PutValue(ContextKey.KEY_SEQUENCE_RESULT, true);
|
||||
return SequenceAction.Ok();
|
||||
}
|
||||
@ -1212,13 +1299,16 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
{
|
||||
Status.EquipmentMode = eEquipmentMode.MANUAL;
|
||||
|
||||
if((_CellTracker._CellTracker as CellTrackerDaekhon) != null && _CellTracker._CellTracker is CellTrackerDaekhon tracker){
|
||||
Log.I($"Stoped Seq >> CellTracker Recv Queue count ({tracker.CellInfoQueue.Count})");
|
||||
foreach (var info in tracker.CellInfoQueue.Select((value, index) => (value, index))) {
|
||||
Log.I($"[{info.index}]Queue >> CellId[{info.value.CellID}] / LotId[{info.value.LotID}]");
|
||||
}
|
||||
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})");
|
||||
}
|
||||
|
||||
// 정지 시점 파이프라인 상태 로그 (재시작 후 복원 여부 사전 확인용)
|
||||
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
|
||||
for (int i = 0; i < _RotaryJigCount; i++)
|
||||
_PLC.WriteBit(eBitOutput.PC_WELD_COMPLETE_1 + i, false);
|
||||
|
||||
@ -760,6 +760,7 @@ namespace ILSOS_CCW_H52A.Sequences
|
||||
if (laserParam != null) {
|
||||
// EDC 보내는 용도
|
||||
Status.GetProcessingWeldingData().LaserPowerCore = laserParam.LaserPower1.ToString();
|
||||
Status.GetProcessingWeldingData().LaserPowerRing = laserParam.LaserPower2.ToString();
|
||||
Status.GetProcessingWeldingData().MarkSpeed = laserParam.MarkSpeed.ToString();
|
||||
Status.GetProcessingWeldingData().FocalLength = (_PLC.ReadDWord((int)eWordInput.PLC_WELDING_FOCAL_LENGTH).data / 1000f).ToString();
|
||||
Status.GetProcessingWeldingData().WeldingJigNo = _WeldingJigNo.ToString();
|
||||
|
||||
@ -103,11 +103,34 @@ namespace WeldingCommon.Data
|
||||
|
||||
public WeldingData()
|
||||
{
|
||||
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()
|
||||
|
||||
@ -294,6 +294,7 @@ namespace WeldingCommon.Sequences {
|
||||
foreach (IDrawObject obj in objects) {
|
||||
drawObjectCount += FuncLoadDrawObjectScannerParamSelected(obj);
|
||||
}
|
||||
Debug.WriteLine($"Scanner Space Check({_Scanner.GetListSpace()})");
|
||||
|
||||
return drawObjectCount;
|
||||
}
|
||||
@ -307,7 +308,6 @@ namespace WeldingCommon.Sequences {
|
||||
count += FuncLoadDrawObjectScannerParamSelected(subObj);
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@ -635,6 +635,7 @@ namespace WeldingCommon.Sequences {
|
||||
int risingCount = (int)(StartDistance / length);
|
||||
int fallingCount = (int)(EndDistance / length);
|
||||
int totalCount = (int)(obj.Distance / length);
|
||||
Log.I($"Ramping count >> firstCount({firstCount}) / risingCount({risingCount}) / fallingCount({fallingCount}) / totalCount({totalCount})");
|
||||
|
||||
// Power1 A -> Start Power, B -> End Power
|
||||
float firstPower_A1 = percentLaser1 * (float)param.RampingStartAPower1 / 100; // Ramping First Power 1
|
||||
@ -668,27 +669,40 @@ namespace WeldingCommon.Sequences {
|
||||
float power1 = percentLaser1;
|
||||
float power2 = percentLaser2;
|
||||
|
||||
// first Ramping은 Start 지점의 연속으로 Start Ramping과 이어서 한다.
|
||||
if (iter <= (risingCount + firstCount)) {
|
||||
// power1은 startPower_A1 에서 startPower_B1 까지 변한다
|
||||
// float IntervalPerPower = (B - A) / Cnt
|
||||
// power1 = PowerA + (iter * IntervalPerPower);
|
||||
if (iter <= firstCount) {
|
||||
if (iter == 0) {
|
||||
if (iter == 0 || firstCount == 0) {
|
||||
power1 = firstPower_A1;
|
||||
power2 = firstPower_A2;
|
||||
} else {
|
||||
power1 = firstPower_A1 + (firstPower_B1 - firstPower_A1) * (iter / (float)firstCount);
|
||||
power2 = firstPower_A2 + (firstPower_B2 - firstPower_A2) * (iter / (float)firstCount);
|
||||
}
|
||||
} else if ((iter - firstCount) <= risingCount) {
|
||||
power1 = startPower_A1 + (startPower_B1 - startPower_A1) * ((iter - firstCount) / (float)risingCount);
|
||||
power2 = startPower_A2 + (startPower_B2 - startPower_A2) * ((iter - firstCount) / (float)risingCount);
|
||||
}
|
||||
} else if (iter >= totalCount - fallingCount) {
|
||||
// power1은 endPower_A1 에서 endPower_B1 까지 변한다
|
||||
power1 = endPower_B1 + (endPower_A1 - endPower_B1) * (totalCount - iter) / (float)fallingCount;
|
||||
power2 = endPower_B2 + (endPower_A2 - endPower_B2) * (totalCount - iter) / (float)fallingCount;
|
||||
else if ((iter - firstCount) <= risingCount) {
|
||||
if (risingCount == 0) {
|
||||
power1 = startPower_B1;
|
||||
power2 = startPower_B2;
|
||||
}
|
||||
else {
|
||||
power1 = startPower_A1 + (startPower_B1 - startPower_A1) * ((iter - firstCount) / (float)risingCount);
|
||||
power2 = startPower_A2 + (startPower_B2 - startPower_A2) * ((iter - firstCount) / (float)risingCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (iter >= totalCount - fallingCount) {
|
||||
if (fallingCount == 0) {
|
||||
power1 = endPower_A1;
|
||||
power2 = endPower_A2;
|
||||
}
|
||||
else {
|
||||
power1 = endPower_B1 + (endPower_A1 - endPower_B1) * (totalCount - iter) / (float)fallingCount;
|
||||
power2 = endPower_B2 + (endPower_A2 - endPower_B2) * (totalCount - iter) / (float)fallingCount;
|
||||
}
|
||||
}
|
||||
else {
|
||||
power1 = startPower_B1;
|
||||
power2 = startPower_B2;
|
||||
}
|
||||
|
||||
_Scanner.WriteDA((uint)eAnalogPortOut.DA1, power1, eFunctionType.LIST);
|
||||
|
||||
@ -41,5 +41,21 @@ namespace WeldingCommon.Utils
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Dictionary<string, int> mappingInt = new Dictionary<string, int>();
|
||||
public static bool IsChangedInt(string Resource, int value, int defaultVal = 0)
|
||||
{
|
||||
if (mappingInt.ContainsKey(Resource) == false) {
|
||||
mappingInt[Resource] = defaultVal;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mappingInt[Resource] == value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mappingInt[Resource] = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user