fix: RecipeNo 재폴링 널가드 + PC_PAGE_NO 보존 + 새 Page 정상 처리

- CheckRecipeNoComp: 동일레시피 시 PLC_RECIPE_NO 재폴링(늦은 갱신 대응),
  recipe==null(0/미등록) 널 가드 추가, 에코는 활성 레시피 기준으로 null-safe 처리
- OnSeqActionStop: PC_ERROR_CODE 0 쓰기 삭제(WriteDWord가 인접 PC_PAGE_NO까지
  0으로 덮던 버그 해소) → 정지 시 에코워드 보존
- CheckInitCondition: ResumeMode 핸드셰이크 스킵 제거(옵션A) → bit15 후 PLC가
  주는 새 Recipe/Page를 정상 핸드셰이크로 처리. Resume 주석/로그도 정정
- 빌드 0오류

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
to3796zw 2026-06-21 23:17:41 +09:00
parent e61e99f9ab
commit 159eda2d4d
3 changed files with 44 additions and 12 deletions

View File

@ -283,11 +283,6 @@ namespace ILSOS_PrismaticRD_PTOP.Sequences
// return SEQ_COMPLETE; // return SEQ_COMPLETE;
//} //}
Thread.Sleep(5); Thread.Sleep(5);
if (ResumeMode)
{
Log.I("[CheckInitCondition] ResumeMode → 페이지 핸드셰이크 스킵, 용접리스트 업로드로 이동");
return SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ;
}
Log.I($"[CheckInitCondition] 조건 확인 완료 → CheckPageNo 이동"); Log.I($"[CheckInitCondition] 조건 확인 완료 → CheckPageNo 이동");
return SEQ_CHECK_PAGENO; return SEQ_CHECK_PAGENO;
} }
@ -325,10 +320,35 @@ namespace ILSOS_PrismaticRD_PTOP.Sequences
var preActivated = _RecipeManager.ActivatedRecipe(); var preActivated = _RecipeManager.ActivatedRecipe();
if (preActivated != null && preActivated.Id == recipe.Id) if (preActivated != null && preActivated.Id == recipe.Id)
{ {
_PLC.WriteWord(eWordOutput.PC_RECIPE_NO, plcRecipeNo); bool bRecipeCheck = true;
Log.I($"[CheckRecipeNoComp] 이미 활성 레시피({recipe.Id}) → 재활성화 생략, PC_RECIPE_NO 에코({plcRecipeNo}) 유지 → CheckPageNoComp 이동"); int count = 0;
while(bRecipeCheck)
{
plcRecipeNo = _PLC.ReadWord(eWordInput.PLC_RECIPE_NO).data;
recipe = _RecipeManager.Recipes().FirstOrDefault(x => x.Id == plcRecipeNo);
// 널 가드: 재폴링 중 0/미등록이면 recipe==null → 전환하지 않고 계속 재확인
if (recipe != null && recipe.Id != preActivated.Id)
{
bRecipeCheck = false;
break;
}
Thread.Sleep(200);
if(count++ < 3) // 3번 체크하자
{
Log.I($"[CheckRecipeNoComp] RecipeCheckCount : {count} -> {recipe?.Id}");
continue;
}
// 끝까지 동일/무효 → 현 활성 레시피(preActivated) 번호로 에코 (null-safe)
_PLC.WriteWord(eWordOutput.PC_RECIPE_NO, (short)preActivated.Id);
Log.I($"[CheckRecipeNoComp] 이미 활성 레시피({preActivated.Id}) → 재활성화 생략, PC_RECIPE_NO 에코({preActivated.Id}) 유지 → CheckPageNoComp 이동");
return SequenceAction.Ok(); return SequenceAction.Ok();
} }
}
// ── 실제 전환 ── // ── 실제 전환 ──
_RecipeManager.ActivateRecipe(recipe.Id, "PLC Recipe Change"); _RecipeManager.ActivateRecipe(recipe.Id, "PLC Recipe Change");
@ -1043,7 +1063,6 @@ namespace ILSOS_PrismaticRD_PTOP.Sequences
Log.I("[OnSeqActionStop] PLC IO Output PAGECHANGE Init"); Log.I("[OnSeqActionStop] PLC IO Output PAGECHANGE Init");
// 260512 워드 // 260512 워드
_PLC.WriteDWord((int)eWordOutput.PC_ERROR_CODE, 0);
// 260621: 에코 워드(PC_PAGE_NO/PC_RECIPE_NO)는 정지 시 0으로 지우지 않음 — PLC가 정합 확인에 쓰는 // 260621: 에코 워드(PC_PAGE_NO/PC_RECIPE_NO)는 정지 시 0으로 지우지 않음 — PLC가 정합 확인에 쓰는
// 마지막 핸드셰이크 값을 보존(다음 사이클에 어차피 재에코). 기존 0 초기화 2줄 제거. // 마지막 핸드셰이크 값을 보존(다음 사이클에 어차피 재에코). 기존 0 초기화 2줄 제거.
Log.I("[OnSeqActionStop] PLC IO Output Word Init"); Log.I("[OnSeqActionStop] PLC IO Output Word Init");

View File

@ -277,11 +277,11 @@ namespace ILSOS_PrismaticRD_PTOP.Views
Log.I("[Bit15] PC_WELD_READY_ACK OFF (1초 펄스)"); Log.I("[Bit15] PC_WELD_READY_ACK OFF (1초 펄스)");
}; };
bit15OffTimer.Start(); bit15OffTimer.Start();
// Auto 복귀 (ResumeMode=true → CheckInitCondition에서 핸드셰이크 스킵하고 업로드→용접) // Auto 재개 (옵션A: 정상 핸드셰이크 — bit15 후 PLC가 주는 새 Page Change를 정상 처리)
_Plc.WriteBit(eBitOutput.PC_AUTO_STATUS, true); _Plc.WriteBit(eBitOutput.PC_AUTO_STATUS, true);
Status.GetProcessingWeldingData().AutoRunStartTime = DateTime.Now; Status.GetProcessingWeldingData().AutoRunStartTime = DateTime.Now;
RunSequenceAutoRun(); RunSequenceAutoRun();
Log.I("[Bit15] AutoRun Resume → PC_WELD_READY_ACK ON + Auto 이어하기(핸드셰이크 스킵)"); Log.I("[Bit15] AutoRun Resume → PC_WELD_READY_ACK ON + Auto 재개(정상 핸드셰이크)");
} }
// PLC 비트에 의한 AutoRun 실행의 경우, PLC 인터페이스 이후 AutoRun 필요 // PLC 비트에 의한 AutoRun 실행의 경우, PLC 인터페이스 이후 AutoRun 필요

View File

@ -113,4 +113,17 @@
- **확인 완료(현장)**: 앞서 수정분으로 해당 구간 **정상 통과** 확인, **Auto↔Manual 모드 전환** 동작 확인. - **확인 완료(현장)**: 앞서 수정분으로 해당 구간 **정상 통과** 확인, **Auto↔Manual 모드 전환** 동작 확인.
- **보류**: Recipe No / Page No 관련 **이번 세션 수정 코드는 아직 현장 미적용** → 추후 현장에 적용 후 검증 예정. - **보류**: Recipe No / Page No 관련 **이번 세션 수정 코드는 아직 현장 미적용** → 추후 현장에 적용 후 검증 예정.
- **이어서 할 일(다음)**: 수정 코드(D70002 에코, 정지 시 에코워드 보존, 양극 제거/음극 통일, bit15 흐름, 로그 개편) 현장 반영 → Recipe/Page 핸드셰이크 + 용접 완료신호(음극) PLC 정합 재확인부터 이어감. - **이어서 할 일(다음)**: 수정 코드(D70002 에코, 정지 시 에코워드 보존, 양극 제거/음극 통일, bit15 흐름, 로그 개편) 현장 반영 → Recipe/Page 핸드셰이크 + 용접 완료신호(음극) PLC 정합 재확인부터 이어감.
- 상태: 이번 세션 변경 4개 파일 + 작업일지 **미커밋**. - 상태: 이번 세션 변경 4개 파일 + 작업일지 커밋·푸시 완료(`e61e99f`).
### 10-1. 현장 후속 이슈 수정 (빌드 0오류)
- **증상①**: bit15 들어올 때 `PC_PAGE_NO`(D70001)가 0으로 바뀜.
- **진짜 원인(현재 코드 버그)**: `OnSeqActionStop`의 `_PLC.WriteDWord(PC_ERROR_CODE, 0)`가 **32비트(2워드)** 쓰기라 인접 `PC_PAGE_NO`(idx1)까지 0으로 덮음. `PC_RECIPE_NO`(idx2)는 무영향 → PAGE_NO만 0이 된 현상과 일치. (정지 시마다 발생)
- **조치**: `PC_ERROR_CODE` 미사용 → 정지 시 0 쓰기 **줄 삭제**(WriteDWord 제거). 인접 PC_PAGE_NO 클로버 문제 해소 + 에코 워드는 그대로 보존.
- **증상②**: bit15 이후 Page Change bit가 와도 PageNo 안 바뀌고 시퀀스 미동작.
- 원인: bit15 후 [AutoRun Resume]가 `ResumeMode`로 **핸드셰이크를 스킵**하고 직전 `_CurrentPageNo`로 용접 → 새 Page 미반영.
- **조치(옵션A 채택)**: `CheckInitCondition`의 ResumeMode 스킵 분기 **제거** → 재개 시에도 `CheckPageNo`부터 정상 핸드셰이크 → PLC가 주는 새 Page Change 정상 처리. (ResumeMode는 Resume 버튼 게이트 + CheckCycleStop 정리 용도로만 잔존)
- 미커밋. 현장 검증(① PAGE_NO 보존, ② bit15→Resume→새 Page 정상 처리) 후 커밋 예정.
### 10-2. 다음 점검 항목 (TODO)
- [ ] **PLC 시퀀스 체크** — Recipe/Page 핸드셰이크 + 용접 트리거/완료(음극 0x10~12) PLC↔PC 신호 정합 전체 점검(에코·완료비트 타이밍, page2 음극 완료 수용 여부 포함).
- [ ] **신규 가변 용접 시나리오 체크** — bit15(가변 페이지)에서 정지·팝업 → Manual 티칭 → [AutoRun Resume] → 새 Recipe/Page 정상 핸드셰이크 → 용접까지 1사이클 end-to-end 검증(가접 레시피 21~24 포함).