LGES-OC5-PtoP-Welder/docs/분석_bit15_Resume_핸드셰이크_260805.md
NohDoyeon241104 a43a531e00 docs: 미커밋 분석·작업지시서·작업일지 반영 (260805~260810)
- 분석_bit15_Resume_핸드셰이크_260805.md
- 작업지시서_PTOP_PLC핸드셰이크_260805.md
- 분석_HeavyAlarm_비트_동작_260810.md
- 작업일지 2026_08_06.md
2026-08-11 09:46:02 +09:00

9.1 KiB

분석 — bit15 Resume 핸드셰이크 교착

  • 작성일: 2026-08-05
  • 근거 로그: docs/Aurora_20260805.log (현장 PC, CP949)
  • 대상: SeqAutoRunPTOP.cs / UCMainAutoRunViewModel.cs
  • 증상: [AutoRun Resume]를 눌러도 PLC bit15(PLC_WELD_READY_REQ)가 안 내려가고 진행이 멈춤. 모니터링에서 PC 15번 비트를 수동으로 살리면 진행됨

1. 근본 원인 — Resume 스킵 분기가 죽어 있다 ★

Builder()에 Resume 시 핸드셰이크를 건너뛰는 경로가 선언되어 있다:

// SeqAutoRunPTOP.cs:224
sb.Flows(sb[SEQ_CHECK_INIT_CONDITION] > sb[SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ]);
// 260621: Resume 시 핸드셰이크 스킵

그런데 그 분기를 선택하는 코드가 없다:

// SeqAutoRunPTOP.cs:322-337  CheckInitCondition (Decision 노드)
private string CheckInitCondition(...)
{
    Log.I($"[CheckInitCondition] 초기 조건 확인 중");
    Status.SetWorkingPosition(eWorkingPosition.CHECKING_CONDITION);
    Thread.Sleep(5);
    Log.I($"[CheckInitCondition] 조건 확인 완료 → CheckPageNo 이동");
    return SEQ_CHECK_PAGENO;        // ← 무조건. ResumeMode 를 보지 않는다
}

ResumeMode 참조처는 CheckCycleStop(:883) 하나뿐이고, 흐름 분기에는 전혀 쓰이지 않는다.

→ 길(sb.Flows)은 깔려 있는데 그 길로 가라고 말하는 코드가 없어서, Resume이든 일반 시작이든 똑같이 CheckPageNo로 가서 PLC의 PAGE_CHANGE_REQ를 기다린다.

교착 구조

PC  : PLC 가 PAGE_CHANGE_REQ(M70508) 줄 때까지 대기   (CheckPageNo)
PLC : PC 가 용접 완료(또는 다른 조건) 줄 때까지 bit15 유지
      → 서로 기다림
  • 평소: PLC가 마침 PAGE_CHANGE_REQ를 줌 → 진행 → 정상으로 보였음
  • 18:36: PLC가 안 줌 → PC 무한 대기 → TIMEOUT 2회 → Resume 연타

18:36:05 실측 (레시피 31)

18:36:05.828  AutoRun Resume Clicked!
18:36:05.853  sequence started - 'SeqAutoRunPTOP'
18:36:05.854  [Bit15] AutoRun Resume → PC_WELD_READY_ACK ON
18:36:05.855  [Sequence_Enter] 레시피 [31], Top_Frame_Welding 활성화
18:36:05.866  [CheckPageNo] PLC_PAGE_CHANGE_REQ 신호 대기 중...   ← 정체
18:37:05.874  W [CheckPageNo] Waiting for PLC_PAGE_CHANGE_REQ -> TIMEOUT...
18:38:05.880  W [CheckPageNo] Waiting for PLC_PAGE_CHANGE_REQ -> TIMEOUT...

이 상태에서 Resume을 7회 연타 → 전부 ERROR: sequence is not ready - Running.


2. 검토했으나 주원인이 아닌 것

가설 판정
PC가 ACK를 안 보냈다 아니다. 클릭 46회 = PC_WELD_READY_ACK ON 46회
1초 펄스가 짧아 PLC가 놓친다 근거 부족. 46회 중 45회는 버튼으로 정상 진행
수동/버튼 차이가 레벨 vs 펄스 근거 부족. 위와 같은 이유

초기 분석에서 펄스 가설을 원인으로 제시했으나 철회한다. 버튼으로 대부분 정상 동작했다.


3. 부수 결함 (교착 상태에서 증상을 악화시킴)

3-1. ResumeMode가 안 풀린다

CheckCycleStop(:883-887)이 하루 종일 실행 0회라, 그 안의 두 줄이 한 번도 안 돌았다:

if (ResumeMode) { WriteBit(PC_WELD_READY_ACK, false); ResumeMode = false; }

해제 경로가 OnAutoRunStartRequest:301(일반 시작)뿐이라, OnAutoRunResume의 if (!ResumeMode) 가드(:264)가 무력화 → 연타가 전부 통과.

3-2. OnAutoRunResume에 Running 체크 없음 + 거짓 성공 로그

:270  WriteBit(PC_WELD_READY_ACK, true);   ← ACK 는 나감
:283  RunSequenceAutoRun();                 ← Start 실패해도 반환값 확인 안 함
:284  Log.I("... Auto 재개(정상 핸드셰이크)"); ← 무조건 찍힘

OnAutoRunStartRequest는 ApproveAutorunByUserOrAuto():411에서 Running을 체크하는데 여기엔 없다.

3-3. 타이머 중첩으로 ACK 펄스 축소

클릭마다 새 DispatcherTimer 생성, 기존 취소 없음(:272-279). 18:38:24~26 실측 — 의도 1초가 161ms로 축소. 연타할 때만 발생하므로 부차적.

3-4. 로그 태그 함정

[ExecuteWelding] 각도 offset 적용…은 ExecuteWelding 노드가 아니다. SetUploadWeldingList_SeqParams:651의 LaserAngleOffsetSelector.Select(…, "ExecuteWelding") 호출자 태그 하드코딩. 이 로그로 "용접까지 갔다"고 읽으면 안 된다 (rules.md #1).


4. 로그 통계 (하루 전체)

패턴 건수
AutoRun Resume Clicked! / PC_WELD_READY_ACK ON / OFF 46 / 46 / 46
GetUploadWeldingList_SeqResult 82
WeldingStartReadBit · WaitWeldingStart · WriteWeldComplete · CheckCycleStop 전부 0
OnStopped 84
ERROR: sequence is not ready - Running 9

모든 사이클이 「업로드 완료 → 즉시 OnStopped」로 끝났다. AutoRun 시퀀스가 용접 단계에 진입한 적이 없고, 출사는 전부 Manual 수동이었다.

[CheckPageNoComp] List 30건은 전부 3값 일치(1/1/1, 2/2/2, …) — 페이지 읽기 자체는 안정적.

페이지 정체 구간 (16:56~17:40, 레시피 21)

List 1/1/1이 16:56:50 / 17:04:31 / 17:23:05 / 17:34:49 — 44분간 페이지 1을 4회 반복. 17:40:21 Resume(ACK) 직후 List 2/2/2로 진행. 이후 페이지마다 Resume 필요.


5. PLC 제어팀 질문 목록 (2026-08-06)

A. Resume 시나리오 — 최우선

  1. 작업자가 수동 가접을 끝내고 Resume 하면, PLC는 그다음에 무엇을 줍니까?
    • PAGE_CHANGE_REQ(M70508)를 다시 줍니까? 아니면 이미 준 것으로 간주합니까?
    • → PC는 지금 무조건 PAGE_CHANGE_REQ를 기다립니다. 안 주시면 교착입니다.
  2. Resume 때 PC가 핸드셰이크(Page/Recipe 확인)를 건너뛰고 바로 용접해도 됩니까?
    • → 260621 설계 의도가 이것인데 코드가 빠져 있습니다. 이대로 살릴지 결정 필요.
  3. M70515(bit15)를 내리는 조건 전부를 알려주십시오. ACK 수신만입니까?
    • → 근거: 18:36:16에 977ms 정상 ACK 펄스를 받고도 유지됐습니다.
  4. bit15가 ON인 동안 PAGE_CHANGE_REQ를 안 주는 게 맞습니까?

B. 용접 트리거

  1. M70516(PLC_WELD_TRIGGER_REQ)를 실제로 주신 적이 있습니까?
    • → PC 로그상 WeldingStartReadBit·WaitWeldingStart가 하루 종일 0건입니다.
  2. 가접(bit15) 운용 최종 시나리오 — 자동 재개입니까 작업자 버튼입니까? 현재는 매 페이지 [AutoRun Resume]를 눌러야 넘어갑니다.

C. 페이지 / 워드

  1. PLC가 페이지 번호(D70501)를 올리는 조건은 무엇입니까? ACK 수신입니까?
    • → 근거: 4사이클 페이지 1 고정 → ACK 1회 → 즉시 페이지 2.
  2. 정지 시 PC측 에코 워드(PC_PAGE_NO/PC_RECIPE_NO)를 0으로 지워도 됩니까? 현재는 지우지 않고 유지합니다. PLC가 0을 "무효"로 봅니까 "0번"으로 봅니까?
  3. M70008(PC_PAGE_CHANGE_COMPLETE)를 실제로 감시하십니까? M70009(PC_RECIPE_CHANGE_COMPLETE)는 미사용이 맞습니까?

D. ACK 신호 특성 (보조)

  1. M70015(ACK)를 레벨로 보십니까 엣지로 보십니까? 최소 유지 시간은요?
    • → 현재 PC는 1초 펄스. 주원인은 아니나 연타 시 161ms까지 줄어듭니다.

E. 함께 대조할 주소

PC 심볼 주소 방향
PLC_WELD_READY_REQ / PC_WELD_READY_ACK M70515 / M70015 PLC→PC / PC→PLC
PLC_PAGE_CHANGE_REQ / PC_PAGE_CHANGE_COMPLETE M70508 / M70008 PLC→PC / PC→PLC
PLC_WELD_TRIGGER_REQ M70516 PLC→PC
PLC_PAGE_NO / PLC_RECIPE_NO D70501 / D70502 PLC→PC
PC_PAGE_NO / PC_RECIPE_NO D70001 / D70002 PC→PLC

주소는 Device/PLC/PLCController.Address.cs 주석 기준이며 enum은 offset 표기다. 실제 디바이스 번호는 미검증 — 현장 맵과 직접 대조할 것.


6. PC측 수정 후보 (미적용)

# 내용 PLC 협의
1 CheckInitCondition이 ResumeMode일 때 SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ 반환 필요 (질문 1·2)
2 OnAutoRunResume에 RunState == Running 체크 + 실패 시 Log.E·토스트 불필요
3 타이머를 필드 1개로 두고 재클릭 시 Stop() 후 재시작 불필요
4 [ExecuteWelding] 호출자 태그를 실제 호출부 이름으로 수정 불필요
5 ResumeMode 해제 경로 보강 질문 6 결과에 따름

1번이 본질. sb.Flows는 이미 있으므로 Decision 반환값만 추가하면 된다:

if (ResumeMode)
{
    Log.I("[CheckInitCondition] ResumeMode → 핸드셰이크 스킵, 업로드로 직행");
    return SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ;
}
return SEQ_CHECK_PAGENO;

2~4는 PLC 프로토콜을 건드리지 않으므로 선반영 가능.


관련 문서