feat: M70509 기반 용접 전/후 Scout 추가
M70509(Scout Enable) 상시 ON 시, 용접 트리거(M70516) 감지 후 pre scout,
발진 완료 후 완료비트 송신 전 post scout 수행(각각 SeqScoutNormal 재사용,
0.1초 후 진행). M70509 OFF면 기존과 동일하게 용접만.
- eBitInput 0x09: PLC_RECIPE_CHANGE_REQ(미사용) → PLC_SCOUT_ENABLE 재정의
- 용접 완료비트(ACK off/BUSY off/COMPLETE on)를 WriteWeldComplete 노드로
분리해 post scout 뒤에 송신
- 이미지 파일명 접미어: {기존}_auto_{recipeNo}_{pageNo}_{pre|post}.PNG
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
15e5f5ba27
commit
4f03a0a7ce
@ -8,7 +8,7 @@ M70505,Heavy_ALStatus,Heavy_ALStatus
|
||||
M70506,Door Interlok,Door Interlok
|
||||
M70507,EMO Status,EMO Status
|
||||
M70508,Page_CHGRequest,Page_CHGRequest
|
||||
M70509,Recipe_CHGRequest,Recipe_CHGRequest
|
||||
M70509,Scout Enable,Scout Enable(상시 ON 시 용접 전/후 Scout)
|
||||
M70510,,
|
||||
M70511,,
|
||||
M70512,,
|
||||
|
||||
|
@ -22,8 +22,9 @@ namespace ILSOS_PrismaticRD_PTOP.Device
|
||||
PLC_EMO_STATUS = 0x07,
|
||||
PLC_PAGE_CHANGE_REQ = 0x08,
|
||||
|
||||
// 260618: M70509 Recipe 변경 요청 (구 PLC_RMS_USED, RMS 미사용으로 폐기 후 재정의)
|
||||
PLC_RECIPE_CHANGE_REQ = 0x09,
|
||||
// 260622: M70509 = Scout Enable 플래그 (PLC가 상시 ON 유지 시 용접 전/후 Scout 수행)
|
||||
// 구 PLC_RECIPE_CHANGE_REQ/RMS_USED 모두 미사용 → 재정의. Recipe 전환은 PAGE_CHANGE_REQ + RECIPE_NO 워드로 처리.
|
||||
PLC_SCOUT_ENABLE = 0x09,
|
||||
// 0x0A ~ 0x0E
|
||||
// 260621: M70515 확정 = Weld_01 Ready (가변용접 시 PLC ON → Recipe/Page 확인 팝업 + Resume 트리거)
|
||||
PLC_WELD_READY_REQ = 0x0F,
|
||||
|
||||
@ -76,6 +76,23 @@ namespace ILSOS_PrismaticRD_PTOP.Sequences
|
||||
const string SEQ_WRITE_COMPLETION_PLC_BIT = "[SeqAutoRunPTOP] Write Completion PLC Bit";
|
||||
const string SEQ_COMPLETE = "[SeqAutoRunPTOP] SEQ_COMPLETE"; // 완료
|
||||
|
||||
#region 260622: M70509(Scout Enable) 기반 용접 전/후 Scout
|
||||
// 용접 전: M70516(Weld Trigger) 감지 후 M70509 ON이면 scout(pre) → 0.1s → 용접
|
||||
const string SEQ_PRE_SCOUT_CHECK = "[SeqAutoRunPTOP] Pre-Weld Scout Check"; // 분기: M70509 ON/OFF
|
||||
const string SEQ_PRE_SCOUT_SET_PARAMS = "[SeqAutoRunPTOP] Pre-Weld Scout SetParams";
|
||||
const string SEQ_PRE_SCOUT_RUN = "[SeqAutoRunPTOP] Pre-Weld Scout Run"; // SeqScoutNormal 서브시퀀스
|
||||
const string SEQ_PRE_SCOUT_DONE = "[SeqAutoRunPTOP] Pre-Weld Scout Done"; // 0.1s 후 진행
|
||||
// 용접 후: 발진 완료 후 완료비트 송신 전 M70509 ON이면 scout(post) → 0.1s → 완료비트
|
||||
const string SEQ_POST_SCOUT_CHECK = "[SeqAutoRunPTOP] Post-Weld Scout Check";
|
||||
const string SEQ_POST_SCOUT_SET_PARAMS = "[SeqAutoRunPTOP] Post-Weld Scout SetParams";
|
||||
const string SEQ_POST_SCOUT_RUN = "[SeqAutoRunPTOP] Post-Weld Scout Run";
|
||||
const string SEQ_POST_SCOUT_DONE = "[SeqAutoRunPTOP] Post-Weld Scout Done"; // 0.1s 후 진행
|
||||
// 용접 완료 비트 송신(post-scout 분기 뒤로 분리): TriggerACK off / BUSY off / COMPLETE on
|
||||
const string SEQ_WRITE_WELD_COMPLETE = "[SeqAutoRunPTOP] Write Weld Complete";
|
||||
|
||||
private const int SCOUT_PROCEED_DELAY_MS = 100; // scout 완료 후 진행 지연(0.1초)
|
||||
#endregion
|
||||
|
||||
public enum ePrismaticDOAddress
|
||||
{
|
||||
CoreLaser_Control = 9,
|
||||
@ -138,11 +155,26 @@ namespace ILSOS_PrismaticRD_PTOP.Sequences
|
||||
sb.AddAction(SEQ_GET_RESULT_UPLOAD_WELDING_LIST_SEQ, GetUploadWeldingList_SeqResult);
|
||||
#endregion
|
||||
|
||||
// 260513 plc
|
||||
// 260513 plc
|
||||
sb.AddAction(SEQ_CHECK_WELDING_START_READ_BIT, WeldingStartReadBit);
|
||||
|
||||
// 260622: 용접 전 Scout (M70509 ON 시)
|
||||
sb.AddDecision(SEQ_PRE_SCOUT_CHECK, PreScoutCheck);
|
||||
sb.AddAction(SEQ_PRE_SCOUT_SET_PARAMS, PreScoutSetParams);
|
||||
sb.AddSubsequence(SEQ_PRE_SCOUT_RUN, SequenceManager.GetSeqBuilder_SeqScoutNormal());
|
||||
sb.AddAction(SEQ_PRE_SCOUT_DONE, PreScoutDone);
|
||||
|
||||
sb.AddAction(SEQ_WAIT_WELDING_START, WaitWeldingStart);
|
||||
sb.AddAction(SEQ_EXECUTE_WELDING, ExecuteWelding);
|
||||
sb.AddDecision(SEQ_CHECK_CYCLE_STOP, CheckCycleStop); // 체크페이지
|
||||
|
||||
// 260622: 용접 후 Scout (M70509 ON 시) → 완료비트 송신
|
||||
sb.AddDecision(SEQ_POST_SCOUT_CHECK, PostScoutCheck);
|
||||
sb.AddAction(SEQ_POST_SCOUT_SET_PARAMS, PostScoutSetParams);
|
||||
sb.AddSubsequence(SEQ_POST_SCOUT_RUN, SequenceManager.GetSeqBuilder_SeqScoutNormal());
|
||||
sb.AddAction(SEQ_POST_SCOUT_DONE, PostScoutDone);
|
||||
sb.AddAction(SEQ_WRITE_WELD_COMPLETE, WriteWeldComplete);
|
||||
|
||||
sb.AddDecision(SEQ_CHECK_CYCLE_STOP, CheckCycleStop); // 체크페이지
|
||||
|
||||
sb.AddAction(SEQ_SAVE_RESULT_DATA, SaveResultData); // 해당 공정의 정보를 기록 함.
|
||||
sb.AddAction(SEQ_WRITE_COMPLETION_PLC_BIT, WriteCompletionPLCBit); // 정상적으로 종료 되면, complete bit write
|
||||
@ -161,16 +193,33 @@ namespace ILSOS_PrismaticRD_PTOP.Sequences
|
||||
> sb[SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ] // 2 리스트 업로드 (서브시퀀스) - TeachingRun 노드 참고
|
||||
> sb[SEQ_GET_RESULT_UPLOAD_WELDING_LIST_SEQ] // 3 업로드 결과 확인 - TeachingRun 노드 참고
|
||||
#endregion
|
||||
> sb[SEQ_CHECK_WELDING_START_READ_BIT] // while read bit
|
||||
> sb[SEQ_CHECK_WELDING_START_READ_BIT] // while read bit (M70516 대기)
|
||||
|
||||
> sb[SEQ_PRE_SCOUT_CHECK] // 260622: M70509 ON → pre scout
|
||||
> sb[SEQ_PRE_SCOUT_SET_PARAMS]
|
||||
> sb[SEQ_PRE_SCOUT_RUN]
|
||||
> sb[SEQ_PRE_SCOUT_DONE] // 0.1s 후 용접
|
||||
|
||||
> sb[SEQ_WAIT_WELDING_START] // 4 업로드 완료 PLC 완료 신호 및 BUSY 신호로 변경
|
||||
> sb[SEQ_EXECUTE_WELDING] // 5 Scanner 실행 (실제 용접)
|
||||
> sb[SEQ_EXECUTE_WELDING] // 5 Scanner 실행 (실제 용접, 완료비트는 보류)
|
||||
|
||||
> sb[SEQ_POST_SCOUT_CHECK] // 260622: M70509 ON → post scout
|
||||
> sb[SEQ_POST_SCOUT_SET_PARAMS]
|
||||
> sb[SEQ_POST_SCOUT_RUN]
|
||||
> sb[SEQ_POST_SCOUT_DONE] // 0.1s 후 완료비트
|
||||
> sb[SEQ_WRITE_WELD_COMPLETE] // 용접 완료 비트 송신 → 다음 시퀀스
|
||||
|
||||
> sb[SEQ_CHECK_CYCLE_STOP]
|
||||
|
||||
> sb[SEQ_SAVE_RESULT_DATA]
|
||||
> sb[SEQ_WRITE_COMPLETION_PLC_BIT] // PLC 비트 완료 신호 보내기
|
||||
> sb[SEQ_COMPLETE] // 다시 enter로 올리기
|
||||
> sb[SEQ_WRITE_COMPLETION_PLC_BIT] // PLC 비트 완료 신호 보내기
|
||||
> sb[SEQ_COMPLETE] // 다시 enter로 올리기
|
||||
> sb.Final);
|
||||
|
||||
// 260622: Scout 스킵 분기 (M70509 OFF → 기존과 동일하게 용접만)
|
||||
sb.Flows(sb[SEQ_PRE_SCOUT_CHECK] > sb[SEQ_WAIT_WELDING_START]);
|
||||
sb.Flows(sb[SEQ_POST_SCOUT_CHECK] > sb[SEQ_WRITE_WELD_COMPLETE]);
|
||||
|
||||
sb.Flows(sb[SEQ_CHECK_CYCLE_STOP] > sb[SEQ_CHECK_PAGENO]); // 루프백: 매 사이클 Page Change bit(0x08) 대기부터 재확인
|
||||
sb.Flows(sb[SEQ_CHECK_INIT_CONDITION] > sb[SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ]); // 260621: Resume 시 핸드셰이크 스킵
|
||||
sb.Flows(sb[SEQ_CHECK_INIT_CONDITION] > sb[SEQ_COMPLETE] > sb.Final);
|
||||
@ -787,21 +836,10 @@ namespace ILSOS_PrismaticRD_PTOP.Sequences
|
||||
Log.D(string.Format($"[ExecuteWelding] Change SelectCorrectionTable Time : {_WeldingSpanTime.TotalMilliseconds}"));
|
||||
|
||||
Thread.Sleep(500);
|
||||
// 양극(P) 미사용 → 모든 페이지 음극 완료 비트로 응답
|
||||
_PLC.WriteBit((int)eBitOutput.PC_WELD_TRIGGER_ACK, false);
|
||||
Log.I($"[ExecuteWelding] 용접완료 송신 - READY_ACK=false (PageNo:{plcPageNo})");
|
||||
Thread.Sleep(50);
|
||||
_PLC.WriteBit((int)eBitOutput.PC_WELD_BUSY, false);
|
||||
Log.I($"[ExecuteWelding] 용접완료 송신 - BUSY=false (PageNo:{plcPageNo})");
|
||||
Thread.Sleep(50);
|
||||
_PLC.WriteBit((int)eBitOutput.PC_WELD_COMPLETE, true);
|
||||
Log.I($"[ExecuteWelding] 용접완료 송신 - COMPLETE=true (PageNo:{plcPageNo})");
|
||||
Thread.Sleep(5);
|
||||
|
||||
Status.SetWorkingPosition(eWorkingPosition.UNLOADING_CELL);
|
||||
#endregion
|
||||
|
||||
Log.I($"[ExecuteWelding] 완료 → CheckCycleStop 이동");
|
||||
// 260622: 완료비트(TriggerACK off/BUSY off/COMPLETE on) 송신은 post-scout(M70509) 분기 뒤로 분리 → WriteWeldComplete 노드
|
||||
Log.I($"[ExecuteWelding] 발진 완료 (완료비트 송신 보류) → PostScoutCheck 이동");
|
||||
return SequenceAction.Ok();
|
||||
}
|
||||
|
||||
@ -822,6 +860,91 @@ namespace ILSOS_PrismaticRD_PTOP.Sequences
|
||||
return SEQ_CHECK_PAGENO;
|
||||
}
|
||||
|
||||
#region 260622: M70509(Scout Enable) 기반 용접 전/후 Scout
|
||||
// 이미지 파일명 접미어: auto_{recipeNo}_{pageNo}_{pre|post} → 최종 {기존}_auto_{recipeNo}_{pageNo}_{phase}.PNG
|
||||
private string ScoutSaveTag(string phase) => $"auto_{plcRecipeNo}_{plcPageNo}_{phase}";
|
||||
|
||||
private SeqScoutNormal_InitParam BuildScoutParams(string saveTag)
|
||||
{
|
||||
return new SeqScoutNormal_InitParam()
|
||||
{
|
||||
IsRealTimeScout = false,
|
||||
ScoutSeqParams = new ScoutSeqParams(VisionRecipeManager.GetFovInfos()[0], eDisplayType.Machine_B),
|
||||
PageIndex = _CurrentPageNo, // 현재 처리 중인 페이지(0-base)
|
||||
SaveTag = saveTag,
|
||||
};
|
||||
}
|
||||
|
||||
// ── 용접 전 Scout (M70516 감지 후) ──────────────────────────
|
||||
private string PreScoutCheck(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
|
||||
{
|
||||
bool scout = _PLC.ReadBit(eBitInput.PLC_SCOUT_ENABLE).data; // M70509
|
||||
Log.I($"[PreScoutCheck] M70509(Scout Enable) = {scout}");
|
||||
// M70509 ON → pre scout / OFF → 기존과 동일하게 바로 용접
|
||||
return scout ? SEQ_PRE_SCOUT_SET_PARAMS : SEQ_WAIT_WELDING_START;
|
||||
}
|
||||
private SequenceActionResult PreScoutSetParams(SequenceContext context, string id, SequenceActionResult param)
|
||||
{
|
||||
Log.I("[PreScout] Scout 파라미터 구성(pre)");
|
||||
return SequenceAction.Ok(BuildScoutParams(ScoutSaveTag("pre")));
|
||||
}
|
||||
private SequenceActionResult PreScoutDone(SequenceContext context, string id, SequenceActionResult param)
|
||||
{
|
||||
var result = param.Param as SeqScoutNormal_OutParam;
|
||||
if (result == null || result.Success == false)
|
||||
{
|
||||
Log.E("[PreScout] Scout 실패 → 시퀀스 중단");
|
||||
return null;
|
||||
}
|
||||
Thread.Sleep(SCOUT_PROCEED_DELAY_MS); // 0.1초 후 용접 진행
|
||||
Log.I($"[PreScout] 완료 → {SCOUT_PROCEED_DELAY_MS}ms 후 WaitWeldingStart 이동");
|
||||
return SequenceAction.Ok();
|
||||
}
|
||||
|
||||
// ── 용접 후 Scout (완료비트 송신 전) ────────────────────────
|
||||
private string PostScoutCheck(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
|
||||
{
|
||||
bool scout = _PLC.ReadBit(eBitInput.PLC_SCOUT_ENABLE).data; // M70509
|
||||
Log.I($"[PostScoutCheck] M70509(Scout Enable) = {scout}");
|
||||
// M70509 ON → post scout / OFF → 바로 완료비트 송신
|
||||
return scout ? SEQ_POST_SCOUT_SET_PARAMS : SEQ_WRITE_WELD_COMPLETE;
|
||||
}
|
||||
private SequenceActionResult PostScoutSetParams(SequenceContext context, string id, SequenceActionResult param)
|
||||
{
|
||||
Log.I("[PostScout] Scout 파라미터 구성(post)");
|
||||
return SequenceAction.Ok(BuildScoutParams(ScoutSaveTag("post")));
|
||||
}
|
||||
private SequenceActionResult PostScoutDone(SequenceContext context, string id, SequenceActionResult param)
|
||||
{
|
||||
var result = param.Param as SeqScoutNormal_OutParam;
|
||||
if (result == null || result.Success == false)
|
||||
{
|
||||
Log.E("[PostScout] Scout 실패 → 시퀀스 중단");
|
||||
return null;
|
||||
}
|
||||
Thread.Sleep(SCOUT_PROCEED_DELAY_MS); // 0.1초 후 완료비트 송신
|
||||
Log.I($"[PostScout] 완료 → {SCOUT_PROCEED_DELAY_MS}ms 후 WriteWeldComplete 이동");
|
||||
return SequenceAction.Ok();
|
||||
}
|
||||
|
||||
// 용접 완료 비트 송신(post-scout 분기 뒤로 분리). 음극 비트로 응답(양극 P 미사용).
|
||||
private SequenceActionResult WriteWeldComplete(SequenceContext context, string id, SequenceActionResult param)
|
||||
{
|
||||
_PLC.WriteBit((int)eBitOutput.PC_WELD_TRIGGER_ACK, false);
|
||||
Log.I($"[WriteWeldComplete] 용접완료 송신 - READY_ACK=false (PageNo:{plcPageNo})");
|
||||
Thread.Sleep(50);
|
||||
_PLC.WriteBit((int)eBitOutput.PC_WELD_BUSY, false);
|
||||
Log.I($"[WriteWeldComplete] 용접완료 송신 - BUSY=false (PageNo:{plcPageNo})");
|
||||
Thread.Sleep(50);
|
||||
_PLC.WriteBit((int)eBitOutput.PC_WELD_COMPLETE, true);
|
||||
Log.I($"[WriteWeldComplete] 용접완료 송신 - COMPLETE=true (PageNo:{plcPageNo})");
|
||||
Thread.Sleep(5);
|
||||
Status.SetWorkingPosition(eWorkingPosition.UNLOADING_CELL);
|
||||
Log.I($"[WriteWeldComplete] 완료 → CheckCycleStop 이동");
|
||||
return SequenceAction.Ok();
|
||||
}
|
||||
#endregion
|
||||
|
||||
private SequenceActionResult SaveResultData(SequenceContext context, string id, SequenceActionResult param)
|
||||
{
|
||||
Log.I($"[SaveResultData] 용접 결과 데이터 저장 시작");
|
||||
|
||||
@ -296,8 +296,14 @@ namespace WeldingCommon.Sequences
|
||||
|
||||
//4.스캐너 필드 이미지 파일 저장
|
||||
// TODO: Path 설정하는 것 따로 만들어서 넣기. 여기저기 흩어져 있음...
|
||||
// 디렉터리는 기존 그대로(날짜 폴더). SaveTag 가 있으면 기존 파일명 뒤에 '_접미어' 추가.
|
||||
// 기존: {_ScoutNo+1}_{HHmmss}.PNG
|
||||
// SaveTag 적용: {_ScoutNo+1}_{HHmmss}_{SaveTag}.PNG (예: 1_143052_auto_11_2_pre.PNG)
|
||||
string dateDir = $"{DateTime.Now.Year}_{DateTime.Now.Month}_{DateTime.Now.Day}";
|
||||
string baseName = $"{_ScoutNo + 1}_{DateTime.Now.ToString("HHmmss")}";
|
||||
string fileName = string.IsNullOrEmpty(_InitParam.SaveTag) ? $"{baseName}.PNG" : $"{baseName}_{_InitParam.SaveTag}.PNG";
|
||||
string fieldScanImageFile = Path.Combine(ConfigurationManager.AppSettings.Get("DATA_PATH"), "_vision", "FieldScanImage",
|
||||
string.Format($"{DateTime.Now.Year}_{DateTime.Now.Month}_{DateTime.Now.Day}/{_ScoutNo + 1}_{DateTime.Now.ToString("HHmmss")}.PNG"));
|
||||
dateDir, fileName);
|
||||
_SystemParameter.ScannerFieldImageFile = fieldScanImageFile;
|
||||
|
||||
//5.압축하여 저장
|
||||
@ -385,6 +391,10 @@ namespace WeldingCommon.Sequences
|
||||
// 기존: SeqScoutNormal 이 MainPage.selectedIndexNo(GUI 전역 상태)에만 의존 → 페이지 이동/자동운전 시 stale.
|
||||
// 변경: 호출부가 "현재 처리/표시 중인 페이지 번호"를 명시 주입.
|
||||
public int PageIndex { get; set; } = 0;
|
||||
|
||||
// [추가 2026-06-22] 파일명 접미어. 디렉터리는 기존 날짜 폴더 그대로, 비면(기본) 기존 파일명 유지(하위호환).
|
||||
// 적용 시: {기존파일명}_{SaveTag}.PNG (호출부에서 예: "auto_{recipeNo}_{pageNo}_pre" 전달)
|
||||
public string SaveTag { get; set; } = "";
|
||||
}
|
||||
|
||||
public class SeqScoutNormal_OutParam : OutParam
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user