- 분석_bit15_Resume_핸드셰이크_260805.md - 작업지시서_PTOP_PLC핸드셰이크_260805.md - 분석_HeavyAlarm_비트_동작_260810.md - 작업일지 2026_08_06.md
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 시나리오 — 최우선
- 작업자가 수동 가접을 끝내고 Resume 하면, PLC는 그다음에 무엇을 줍니까?
PAGE_CHANGE_REQ(M70508)를 다시 줍니까? 아니면 이미 준 것으로 간주합니까?- → PC는 지금 무조건
PAGE_CHANGE_REQ를 기다립니다. 안 주시면 교착입니다.
- Resume 때 PC가 핸드셰이크(Page/Recipe 확인)를 건너뛰고 바로 용접해도 됩니까?
- → 260621 설계 의도가 이것인데 코드가 빠져 있습니다. 이대로 살릴지 결정 필요.
M70515(bit15)를 내리는 조건 전부를 알려주십시오. ACK 수신만입니까?- → 근거: 18:36:16에 977ms 정상 ACK 펄스를 받고도 유지됐습니다.
- bit15가 ON인 동안
PAGE_CHANGE_REQ를 안 주는 게 맞습니까?
B. 용접 트리거
M70516(PLC_WELD_TRIGGER_REQ)를 실제로 주신 적이 있습니까?- → PC 로그상
WeldingStartReadBit·WaitWeldingStart가 하루 종일 0건입니다.
- → PC 로그상
- 가접(bit15) 운용 최종 시나리오 — 자동 재개입니까 작업자 버튼입니까? 현재는 매 페이지 [AutoRun Resume]를 눌러야 넘어갑니다.
C. 페이지 / 워드
- PLC가 페이지 번호(D70501)를 올리는 조건은 무엇입니까? ACK 수신입니까?
- → 근거: 4사이클 페이지 1 고정 → ACK 1회 → 즉시 페이지 2.
- 정지 시 PC측 에코 워드(
PC_PAGE_NO/PC_RECIPE_NO)를 0으로 지워도 됩니까? 현재는 지우지 않고 유지합니다. PLC가 0을 "무효"로 봅니까 "0번"으로 봅니까? M70008(PC_PAGE_CHANGE_COMPLETE)를 실제로 감시하십니까?M70009(PC_RECIPE_CHANGE_COMPLETE)는 미사용이 맞습니까?
D. ACK 신호 특성 (보조)
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 프로토콜을 건드리지 않으므로 선반영 가능.
관련 문서
- 작업지시서_PTOP_PLC핸드셰이크_260805.md — 읽기 검증(err 체크) 작업지시
- harness-ptop.md · ../rules.md