# 작업일지 — 2026-06-21 ## 1. 가접 레시피(20~23) 추가 — 시퀀스 무수정 방식 확정 - 가접을 시퀀스로 추가하지 않고 **레시피 번호만 추가**해서 처리. (레시피 활성화+페이지별 용접 행위가 동일하므로) - 코드 검증: 레시피 조회 `.Id` 1:1(하드코딩 없음), 페이지 검증 `Layers.Count()` 가변 → **노드 수정 불필요, 레시피 데이터만 추가.** - Recipe Number 시트 구조 (`…_260621_가접용접추가.xlsx`): - 11: 양극/음극 탭 비드(기존, 2P) · 31: 상면(기존, 2P) · 32: 하면(기존, 2P) - **20: Pre 가변 전면(가접) / 21: 전면 본접 / 22: Pre 가변 후면(가접) / 23: 후면 본접** (각 1~5P) - PRE(가접)→본접을 레시피 쌍으로 분리(전면 20→21, 후면 22→23). ## 2. Recipe/Page 핸드셰이크 — 이미 구현·커밋 확인 (`25edd79`) - 현장 결정: PLC가 전환마다 RECIPE_REQ는 안 주고 **양극에서 PAGE_REQ만** 줌. - 동작 = Page 신호만 체크 → Recipe/Page WORD 읽기 → RecipeNum 변화 시 활성화 → PageNum 받고 → ACK 송신. (이미 `SeqAutoRunPTOP.cs`에 반영됨) - `CheckPageNo`: `PLC_PAGE_CHANGE_REQ`만 대기 - `CheckRecipeNoComp`: `PLC_RECIPE_NO` 읽기 → 0/미등록/현재활성 동일이면 스킵, 다를 때만 `ActivateRecipe` + `Dispatcher.Invoke(OnActiveReloaded)` 동기 Layers 재로드(stale 방지) + `PC_RECIPE_NO` 에코 - `CheckPageNoComp`: `PLC_PAGE_NO` 3회 검증 → `Layers.Count()` 범위검증 → `PC_PAGE_NO` 에코 + `PC_PAGE_CHANGE_COMPLETE`(ACK) - 인터페이스와 1:1 일치: PAGE 핸드셰이크 `M70508/M70608`(REQ)·`M70008/M70108`(COMPLETE), 워드 `D70502/D70501`(PLC) ↔ `D70002/D70001`(PC 에코). 레시피 COMP 비트(`M70509/M70009`)는 미사용(워드 에코만). ## 3. 기동 시 디바이스 연결 vs 알람체크 타이밍 (분석단계, 소스 미수정) - 증상: 기동 직후 연결 확립 전에 알람이 뜸. - 결론: 순서는 이미 "활성화 → 알람모니터"로 맞음(`OnStartUp` `await ActivateDevices()` 후 `SeqAlarmMonitor.Start()`). **진짜 갭은 `Activate()≠Connected`** — 첫 알람 루프가 연결 전 `GetConnected()=false`를 읽어 오알람. - 비대칭: PLC는 `PLC_LIVE_STATUS` 2000ms grace 있음 / **Laser·OCT·Chiller·LBAD는 즉시 알람(grace 없음)** → 오알람 주범. - 권고 레버: **`SeqAlarmMonitor.StartNode`에 연결확립 대기 게이트 추가**(권장) > no-op `WaitTime` 노드 활용 > `OnStartUp`에서 연결 await. ## 4. bit15(MODECHANGE) 기능 구현 — 팝업 + Auto→Manual + Resume (빌드 0오류, 커밋 `ff4fc03`) 보완항목 확정: 1=작업지시서, 2=(나)작업자 수동 RunWelding, 3=작업지시서, 4=작업지시서, 5=현행유지. - **bit 정의** (※ 현장 확정맵 반영해 명칭 정정 — 아래 6장 참고): bit15(0x0F) = **Weld_01 Ready** (`PLC_WELD_READY_REQ`/`PC_WELD_READY_ACK`, M70515/M70015). 가변용접 시 PLC가 ON → 확인 팝업 + Resume 트리거 겸용. (임시명 `MODE_CHANGE`였음) - **정지 보존(#1)**: `OnSeqActionStop`에서 `ResumeMode`면 `PC_PAGE_NO/RECIPE_NO=0` 쓰기 스킵(에코 보존). - **확인 핸들러(#2-나)**: `ResumeMode=true`→Stop(보존)→팝업(`MessageDialog.Show` OK-only)→Manual 전환. 레시피 이미 활성이라 재활성/롤백 안 함. 가변 용접은 작업자가 Manual에서 직접. - **핸드셰이크 스킵(#3)**: `CheckInitCondition`에서 `ResumeMode`면 `SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ`로 분기(+Flow 엣지). - **출력 bit15 수명(#4)**: `OnAutoRunResume`에서 ON+Auto 재개, `CheckCycleStop`에서 한 사이클 후 OFF+`ResumeMode=false`. - **감지(#5)**: `UCMainAutoRunViewModel.OnMonitoring`(화면 타이머) 현행 유지. - 버튼 **[AutoRun Resume]** = Equipment Status 그룹 좌측, `IsModeChangeActive`(bit15 ON) 때만 표시. 확인창 없이 즉시 재개. - 재용접 중복은 **PLC가 레이저 차단**으로 합의(option2). ## 6. 현장 확정 PLC DeviceMap 반영 — bit15 명칭/용접비트 정정 (빌드 0오류) 현장 확정 CSV(`Doc/ILSOSConfig/.../External/PLC/PLC_DeviceMap_*_M/D_Device.csv`) 확인 결과, 임시명 `MODE_CHANGE`로 잡았던 bit15가 **Weld_01 Ready로 확정**됨. 또 원래 Ready(0x10)는 **Trigger**로 밀림. 전 파일 일괄 정정. - 0x0F (M70515/M70015): `MODE_CHANGE` → **`WELD_READY_REQ`/`WELD_READY_ACK`** (Weld_01 Ready, Resume 트리거 겸용) - 0x10 (M70516/M70016): 기존 `WELD_READY_REQ`/`ACK` → **`WELD_TRIGGER_REQ`/`ACK`** (원래 Ready, 용접 발진 신호) - **주소(0x0F/0x10) 불변 = 런타임 동작 동일**, 심볼 이름만 정정. 단 양극 `_P`(0x73) 미러는 제거(현장 단일블록). - 수정 범위: 공통 enum(`WeldingCommon/.../PLCController.Address.cs`) + PTOP enum + 시퀀스 5종(SeqAutoRunPTOP/ComponentWeld/Prismatic/TestRun/WaitWeldOrChangePage) + `UCMainAutoRunViewModel`. 타 머신 영향 없음(심볼 미참조 확인). - 레시피 번호도 변경됨: **21 전면Pre / 22 후면Pre / 23 전면 / 24 후면** (20 폐지). 코드는 데이터구동이라 영향 없음. ## 7. 미확정 / 확인 필요 (다음 액션) - **현장 실증 전** — 빌드만 통과. bit15(Weld Ready) 흐름·레시피 전환·실제 Laser 발진은 현장 테스트 필요. - **PLC 협의**: - 출력 `PC_WELD_READY_ACK`(bit15) false 처리 위치 — 현재 `CheckCycleStop`. 대안: 다음 `PAGE_CHANGE_REQ` 수신 블록에서 false (CSV 노트 "15bit page change 때 init 0"과 정합 — 위치 확정 필요). - bit15 발생 정책: CSV 노트상 **레시피 21·22(가변) 시 PLC가 ON** → 가변 페이지마다인지 레시피당 1회인지 세부 확인. - 용접 핸드셰이크 Ready(0x0F)→Trigger(0x10) 2단계 프로토콜 — 기존 용접시작 로직 현장 동작 확인. - 레시피 시트 "Pre **가변**" 표기가 PRE **가접** 오타인지 확인. - 21~24 페이지 수 미확정(코드는 `Layers.Count()` 가변 대응). - 알람 타이밍: `device.Activate()`가 연결완료까지 동기인지/개시만인지 디바이스별 확인. - 제품 1개 = Recipe×Page 사이클 예상 시나리오: `docs/분석/2026/06/21/121750_제품1개_recipe_page_사이클_예상시나리오.md`. ## 8. 현장 피드백 반영 SW 수정 (5건, 빌드 0오류·미커밋) > 모두 MSBuild Debug|x64 EXITCODE=0 확인. 현장 런타임 검증 대기. 1. **D70002(PC_RECIPE_NO) 에코 누락 수정** — `SeqAutoRunPTOP.cs` `CheckRecipeNoComp` - 증상: Page CHG Request 수신·레시피는 그대로인데 `PC_RECIPE_NO`(D70002)가 안 바뀜. - 원인: "이미 활성 레시피" 분기가 에코 없이 조기 return → 정지 시 0으로 지워진 값이 그대로 남음(PageNo는 매번 에코라 비대칭). - 조치: 동일 레시피여도 `WriteWord(PC_RECIPE_NO, plcRecipeNo)` 에코 유지(재활성/reload는 계속 생략). 2. **bit15 Manual 전환 시 레시피 활성화+로드 추가** — `UCMainAutoRunViewModel.cs` `ShowRecipePageConfirmAndSwitchManual` - 증상: bit15 팝업 후 Manual로 가도 레시피 비활성화되어 해당 Recipe/Page로 이동·수동용접 불가. - 원인: "레시피 이미 활성" 가정으로 ActivateRecipe/OnActiveReloaded 생략 → 티칭/캔버스(SelectedRecipe)가 PLC 레시피로 로드 안 됨. - 조치: `ActivateRecipe(recipe.Id)` + `RecipeHelper.OnActiveReloaded()` 추가(미등록/0이면 현재 활성 레시피 폴백). 3. **bit15 ON 중 AUTO_REQ 자동시작 무시** — `UCMainAutoRunViewModel.cs` `OnAutoRunStartRequest` - 증상: bit15 살아있을 때 Recipe/Page 팝업과 "자동운전 시작?" 팝업이 동시에 뜨고, Manual이 아닌 Auto로 복귀. - 원인: AutoRun 팝업은 `PLC_AUTO_REQ`(0x02) rising edge로 트리거(bit15와 별개·무가드), TimerMessageBox default=true(5초 자동확인)가 Manual을 덮어씀. - 조치: `OnAutoRunStartRequest` 진입부에 `PLC_WELD_READY_REQ`(0x0F=bit15) ON이면 즉시 return. (Resume 버튼 경로는 별개라 무관) 4. **정지 시 에코 워드 0 초기화 제거** — `SeqAutoRunPTOP.cs` `OnSeqActionStop` - `if(!ResumeMode){ PC_PAGE_NO=0; PC_RECIPE_NO=0; }` 블록 제거 → 모든 정지에서 D70001·D70002 보존(다음 사이클 재에코). `PC_ERROR_CODE=0`은 유지. 5. **[AutoRun Resume] PC bit15 1초 펄스 OFF** — `UCMainAutoRunViewModel.cs` `OnAutoRunResume` - `PC_WELD_READY_ACK`(PC쪽 bit15) ON 직후 one-shot DispatcherTimer로 1초 뒤 자동 false. - 참고: 시퀀스 `CheckCycleStop`의 동일 OFF는 이제 중복(무해) — 정리는 별도 검토. ### 검증 메모 (bit15 흐름) - bit15 감지는 `OnMonitoring`이 **실 PLC(비-Simul)** 에서만 동작(Simul 가드) → 벤치 검증 불가, 실 PLC 필요. - 코드는 입력 **0x0F(`PLC_WELD_READY_REQ`)** 를 봄 → PLC의 "15번 bit" 실주소가 0x0F(M70515)인지 디바이스맵 대조 필요(안 먹히면 1순위 원인). - 확인 로그: `[Bit15] ModeChange…` / `[Bit15] Recipe 활성화+로드…` / `[Bit15] bit15 ON 중 → AUTO_REQ 자동시작 무시` / `[Bit15] PC_WELD_READY_ACK OFF (1초 펄스)`. ## 9. 양극(P) 미사용 정리 + eCommon READY 제거 + 로그 개편 (빌드 0오류·미커밋) ### 9-1. 공유 enum eCommon READY(0x0F) 제거 — `WeldingCommon/Devices/PLC/PLCController.Address.cs` - `eCommonBitInput.PLC_WELD_READY_REQ` / `eCommonBitOutput.PC_WELD_READY_ACK` (0x0F) **제거**(`// 0x0A~0x0F` 예약범위로). 공유 enum의 READY는 미사용 항목(실제 bit15는 PTOP enum 0x0F 사용)이라 제거 안전. `PC_WELD_TRIGGER_ACK`(0x10)는 유지. - **PTOP enum의 READY(0x0F)는 유지** → bit15/Resume 코드 영향 없음. ### 9-2. 양극(P) PC→PLC 출력 전체 제거 (현장: 현재 장비 P 미사용) - 증상: `Out of Range: 0x0065 (WriteBit)` — 0x65=`PC_AUTO_STATUS_P`(양극 Auto, M70601)가 출력맵에 없는데 코드가 씀. - **PC_AUTO_STATUS_P(0x65) 쓰기 8곳 제거** — `SeqAutoRunPTOP`(Sequence_Enter/InitAutoRunBit/OnSeqActionStop) + `UCMainAutoRunViewModel`(bit15핸들러/OnAutoRunResume/OnAutoRunStartRequest×2/OnStopSequenceAutoRun). - **양극 용접 핸드셰이크(PC_WELD_P_* 0x74~76) 제거** — `WaitWeldingStart`·`ExecuteWelding`의 `plcPageNo==2` 양극 분기 삭제 → **모든 페이지 음극 비트(0x10~12)로 통일**(용접 트리거가 음극 `PLC_WELD_TRIGGER_REQ`라 정합). `RestoreDeviceStatus`·`InitAutoRunBit` 양극 리셋도 제거. - 검증: 두 파일에 `PC_AUTO_STATUS_P`/`PC_WELD_P_` 0건. - ⚠️ PLC 확인: 이제 page2 용접 완료도 음극 COMPLETE(0x12)로 송신 → PLC가 전 페이지를 음극 완료로 받는지 정합 확인 필요. (보조 `SeqAutoRunPrismatic`의 양극 비트는 미변경.) ### 9-3. SeqAutoRunPTOP 로그 개편 (로그만 수정, 로직 무변경) - 제네릭 `[X] 노드 Start/End` 전부 제거 → 각 노드 동작을 설명하는 로그로 교체(InitSequenceVariable/LaserReadyResponse/SaveScannerRecordFileForamt/RestoreDeviceStatus/InitDev/CheckDeviceReady/CheckCondition/CheckCondition_Interlock/InitializeDeviceStatus/InitAutoRunBit/OnForceError/OnStopped). 잘못된 프리픽스(`SaveScannerRecordFileForamt` 내 `[SaveResultData]`) 정정. - 핵심 동작 노드는 기존 촘촘한 로그 유지 → 로그만으로 시퀀스 어느 구간인지 추적 가능. ## 10. 현장 진행 상황 / 이어서 할 일 - **확인 완료(현장)**: 앞서 수정분으로 해당 구간 **정상 통과** 확인, **Auto↔Manual 모드 전환** 동작 확인. - **보류**: Recipe No / Page No 관련 **이번 세션 수정 코드는 아직 현장 미적용** → 추후 현장에 적용 후 검증 예정. - **이어서 할 일(다음)**: 수정 코드(D70002 에코, 정지 시 에코워드 보존, 양극 제거/음극 통일, bit15 흐름, 로그 개편) 현장 반영 → Recipe/Page 핸드셰이크 + 용접 완료신호(음극) PLC 정합 재확인부터 이어감. - 상태: 이번 세션 변경 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 포함).