feat: 확정 PLC 인터페이스와 레시피(가접용접 레시피 추가)

This commit is contained in:
노도연 2026-06-21 16:31:02 +09:00
parent ff4fc03d2e
commit 1a92f19364
2 changed files with 39 additions and 67 deletions

View File

@ -1,79 +1,51 @@
# 작업일지 — 2026-06-21
## 가접 → 레시피 추가 방식 확정 (시퀀스 무수정)
## 1. 가접 레시피(20~23) 추가 — 시퀀스 무수정 방식 확정
- 가접을 시퀀스로 추가하지 않고, **레시피 번호만 추가**해서 프로그램상 처리하기로 함.
- 20번 PRE가접 전면용접 / 21번 U-Frame 전면 용접 / 22번 PRE가접 후면용접 / 23번 U-Frame 후면 용접
- 어차피 현재 시퀀스 그대로 가도 되는 이유: **레시피 활성화하고 페이지별로 용접하는 행위는 똑같으니까.**
- 코드 검증 결과: 레시피 조회가 `.Id` 1:1(하드코딩 없음), 페이지 검증도 `Layers.Count()` 가변 → **시퀀스 노드 수정 불필요. 레시피 데이터만 추가하면 됨.**
- 가접을 시퀀스로 추가하지 않고 **레시피 번호만 추가**해서 처리. (레시피 활성화+페이지별 용접 행위가 동일하므로)
- 코드 검증: 레시피 조회 `.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).
## Recipe/Page 핸드셰이크 = 이미 구현·커밋 완료 확인 (커밋 25edd79)
## 2. Recipe/Page 핸드셰이크 — 이미 구현·커밋 확인 (`25edd79`)
- PLC가 **전환마다 RECIPE_REQ는 안 주고, 양쪽에서 PAGE_REQ만** 주기로 함.
- 그래서 동작은: **Page change 신호만 체크 → 체크되면 RecipeNum/PageNum WORD값 읽기 → RecipeNum 체크해서 활성화 → 페이지넘버 받고 → 페이지 신호 ACK 송신.**
- 확인 결과 이 설계가 이미 `SeqAutoRunPTOP.cs`에 들어가 커밋(`25edd79 feat: Page Change bit로 Recipe+Page 전환 통합`)되어 있음.
- `CheckPageNo`: `PLC_PAGE_CHANGE_REQ`만 대기 (RECIPE_REQ 미감시)
- `CheckRecipeNoComp`: `PLC_RECIPE_NO` 읽기 → 0/미등록/현재활성과 동일이면 전환 스킵, 다를 때만 `ActivateRecipe` + `Dispatcher.Invoke(RecipeHelper.OnActiveReloaded())`로 Model.Layers 동기 재로드(레시피축 stale/race 방지) + `PC_RECIPE_NO` 에코
- 현장 결정: 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)
- 레시피 COMP 비트는 미사용(워드 에코만), 구 데드코드(CheckRecipeNo peek 노드) 정리됨
- 남은 건 검증: 빌드 0오류 / 동일레시피 스킵·레시피변경 시 Layers 교체 후 용접 / 페이지수 다른 레시피 전환 / 핸드셰이크 PLC 정상 종결 / 실제 Laser 발진 정합.
- 인터페이스와 1:1 일치: PAGE 핸드셰이크 `M70508/M70608`(REQ)·`M70008/M70108`(COMPLETE), 워드 `D70502/D70501`(PLC) ↔ `D70002/D70001`(PC 에코). 레시피 COMP 비트(`M70509/M70009`)는 미사용(워드 에코만).
## 기동 시 디바이스 연결 vs 알람체크 타이밍 분석 (소스 미수정, 분석단계)
## 3. 기동 시 디바이스 연결 vs 알람체크 타이밍 (분석단계, 소스 미수정)
- 증상: 맨 처음 프로그램 켰을 때 연결은 어느 정도 바로 붙는데, **알람체크가 너무 빨리 돌아서** 연결 확립 전에 알람이 뜸. 연결된 다음에 알람체크가 되면 될 것 같음.
- `EquipmentSetup.cs`에 자동 연결 시도 부분(`OnStartUp` → `ActivateDevices`) 있음. 등록된 Device들을 Activate한 뒤 AlarmManager(알람모니터)가 돌아야 하는데, 이 타이밍을 조작할 수 있는지 분석.
- 증상: 기동 직후 연결 확립 전에 알람이 뜸.
- 결론: 순서는 이미 "활성화 → 알람모니터"로 맞음(`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.
### 분석 결론
- **순서 자체는 이미 "활성화 먼저 → 알람모니터"로 맞음.** `OnStartUp`은 `await ActivateDevices()`(모든 `device.Activate()` 완료 대기) 후에 `SeqAlarmMonitor.Start()` 호출(EquipmentSetup.cs:92→105).
- **진짜 갭은 "Activate ≠ Connected"**: `Activate()`는 연결 개시까지만 보장. 알람 체크 코드가 `IsActivated`와 `GetConnected()`를 따로 봄(프레임워크가 활성화/연결 구분) → 첫 루프가 연결 확립 전 `GetConnected()=false`를 읽어 오알람.
- **비대칭**: PLC는 `PLC_LIVE_STATUS` 2000ms 타임아웃 폴링이라 grace 있음. **Laser/OCT/Chiller/LBAD는 `!GetConnected()` 즉시 알람(grace 없음)** → 기동 직후 오알람은 주로 이쪽.
## 4. bit15(MODECHANGE) 기능 구현 — 팝업 + Auto→Manual + Resume (빌드 0오류, 커밋 `ff4fc03`)
### 타이밍 조작 레버 (우선순위)
1. **(권장) `SeqAlarmMonitor.StartNode`에 "연결 확립 대기" 게이트 추가** — 시퀀스 진입 1회 실행 지점에서 활성 디바이스 `GetConnected()`/`IsActivated`(PLC는 live bit) true까지 타임아웃 폴링 후 루프 진입. 연결 상태 기준이라 견고.
2. 비어 있는 `WaitTime` 노드(현재 no-op) 활용 — 손쉽지만 고정시간이라 추측값.
3. `OnStartUp`에서 연결 확인까지 await 후 `Start()` — 단 `Activate()`가 연결완료까지 동기인지 확인 필요.
4. `OnPostDeviceActivated` 훅 — "활성화"지 "연결완료"가 아니라 게이트로는 부적절.
보완항목 확정: 1=작업지시서, 2=(나)작업자 수동 RunWelding, 3=작업지시서, 4=작업지시서, 5=현행유지.
### 적용 전 확인 포인트
- `device.Activate()`가 연결완료까지 동기인가, 개시만인가 (디바이스별: Laser OPCUA/IO, PLC MXComponent, Chiller 등).
- **bit 정의**: 입력 `PLC_MODE_CHANGE=0x0F(M70515)`/`_P=0x73(M70615)`, 출력 `PC_MODE_CHANGE=0x0F(M70015)`/`_P=0x73(M70115)`.
- **정지 보존(#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).
## 10:19 — 가접 레시피 추가된 PLC 인터페이스 문서 확인
## 5. 미확정 / 확인 필요 (다음 액션)
대상: `docs/PtoP 유니셀 용접기 PLC 인터페이스/유니셀 PtoP 단동기 Laser Interface_260621_가접용접추가.xlsx` (시트: M70K 비트 / D70K 워드 / Recipe Number)
### Recipe Number 시트 — 가접 레시피 추가 구조
- 11: 양극/음극 탭 비드 용접 (page 1~2, 기존)
- **20: Pre 가변 전면 용접 (page 1~5)** ← 신규, PRE(가접) 전면
- **21: 전면 용접 (page 1~5)** ← 신규, 본접 전면(U-Frame 전면)
- **22: Pre 가변 후면 용접 (page 1~5)** ← 신규, PRE(가접) 후면
- **23: 후면 용접 (page 1~5)** ← 신규, 본접 후면(U-Frame 후면)
- 31: 상면 용접 (page 1~2, 기존) / 32: 하면 용접 (page 1~2, 기존)
- → 가접을 시퀀스 아닌 **레시피 번호(20~23)** 로 추가, PRE(가접)→본접을 레시피 쌍으로 분리(전면 20→21, 후면 22→23).
### 신호 인터페이스 — 그대로(가접 추가로 신호 신설 없음), 커밋 25edd79 코드와 1:1 일치
- PAGE 핸드셰이크만 사용: `M70508`(-)/`M70608`(+) PLC→PC Page_CHG Request, `M70008`/`M70108` PC→PLC Page_CHG Complete(ACK)
- 레시피·페이지는 워드: `D70502` PLC_RecipeNo, `D70501` PLC_PageNo / 에코 `D70002` PC_RecipeNo, `D70001` PC_PageNo
- `M70509/M70009` Recipe_CHG Req/Comp 비트는 표에 있으나 현장 결정대로 게이트 미사용 → RecipeNo는 PAGE_REQ 시점 워드(D70502)로 읽음.
### 확인 필요
- 셀 표기 "Pre **가변** 전면/후면 용접" → 의도는 PRE **가접**(tack)일 텐데 오타인지 확인 필요.
- 20~23 페이지 수 미확정(표상 1~5). 코드는 `Layers.Count()` 가변이라 2↔5페이지 혼재 자동 대응.
- 음극(-)/양극(+) 비대칭: -측은 Page+Recipe CHG 둘 다, +측은 Page_CHG만(기존 단동기 구조, 가접이 바꾸지 않음).
## bit15(MODECHANGE) 기능 구현 — 팝업 + Auto→Manual + Resume (빌드 0오류)
작업지시서 2종(`bit15_resume_재진입_문제분석…`, `2026_06_21_bit15_resume_구현.md`) 기준 보완 구현. 보완항목 사용자 확정: 1=작업지시서, 2=(나)작업자 수동 RunWelding, 3=작업지시서, 4=작업지시서, 5=현행유지.
- **bit 정의**(PLCController.Address.cs): 입력 `PLC_MODE_CHANGE=0x0F(M70515)`/`PLC_MODE_CHANGE_P=0x73(M70615)`, 출력 `PC_MODE_CHANGE=0x0F(M70015)`/`PC_MODE_CHANGE_P=0x73(M70115)`.
- **#1 정지 보존**: `SeqAutoRunPTOP.OnSeqActionStop`에서 `ResumeMode`면 `PC_PAGE_NO/PC_RECIPE_NO=0` 쓰기 스킵(에코 보존).
- **#2(나)**: 확인 핸들러 = `ResumeMode=true`→Stop(보존)→팝업(`MessageDialog.Show` OK-only)→Manual 전환. 레시피 이미 활성이라 `ActivateRecipe/OnActiveReloaded` 제거. 가변 용접은 작업자가 Manual에서 직접.
- **#3 핸드셰이크 스킵**: `CheckInitCondition`에서 `ResumeMode`면 `SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ`로 분기(+Builder Flow 엣지).
- **#4 출력 bit15 수명**: `OnAutoRunReStart`에서 `PC_MODE_CHANGE ON`+Auto 재개, `CheckCycleStop`에서 한 사이클 후 OFF+`ResumeMode=false`.
- **#5**: 감지는 `UCMainAutoRunViewModel.OnMonitoring`(화면 타이머) 현행 유지.
- ReStart는 "자동운전 시작?" 확인창 없이 즉시 재개(전용 경로)로 변경.
- 재용접 중복: option2 채택, **PLC측이 레이저 차단**하기로 함.
- ReStart 버튼 = AutoRun 화면 Equipment Status 그룹 좌측, `IsModeChangeActive`(bit15 ON) 때만 표시.
### PLC 협의 대기 (기록)
- **출력 PC_MODE_CHANGE(bit15) false 처리 위치**: 현재 `CheckCycleStop`에서 OFF. **대안** — 시퀀스 1바퀴 후 다시 PageChange 신호를 보고 있을 때(다음 `PAGE_CHANGE_REQ`가 true로 들어오는 코드블록 안)에서 false 처리. PLC가 출력 bit15 클리어를 인식하는 타이밍과 맞춰야 하므로 **PLC측과 합의 후 위치 확정.**
- bit15 PLC 주소(M70515/M70615/M70015/M70115) 실제 맵 대조 필요.
- **현장 실증 전** — 빌드만 통과. bit15 흐름·레시피 전환·실제 Laser 발진은 현장 테스트 필요.
- **PLC 협의**:
- 출력 `PC_MODE_CHANGE`(bit15) false 처리 위치 — 현재 `CheckCycleStop`. 대안: 다음 `PAGE_CHANGE_REQ` 수신 블록에서 false (PLC 인식 타이밍과 합의 후 확정).
- bit15 주소(M70515/M70615/M70015/M70115) 실맵 대조.
- bit15 발생 정책: 가변 페이지마다 vs 가변 레시피당 1회.
- 레시피 시트 "Pre **가변**" 표기가 PRE **가접** 오타인지 확인.
- 20~23 페이지 수 미확정(코드는 `Layers.Count()` 가변 대응).
- 알람 타이밍: `device.Activate()`가 연결완료까지 동기인지/개시만인지 디바이스별 확인.
- 제품 1개 = Recipe×Page 사이클 예상 시나리오: `docs/분석/2026/06/21/121750_제품1개_recipe_page_사이클_예상시나리오.md`.