This commit is contained in:
to3796zw 2026-06-19 13:30:17 +09:00
commit eb307b459e
10 changed files with 514 additions and 23 deletions

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
*.suo
*.user
*_wpftmp.csproj
*.pdb
_ReSharper.*
obj/

View File

@ -497,6 +497,16 @@ namespace AuroraIO.AJINEXTEK
{
//현재 사용하지 않아서 추후 구현
return true;
// [추후 구현] return true 스텁 의존 코드 확인 후 아래로 교체 (ReadDiBit(int) 패턴)
//uint data = 0;
//
//int err = (int)CAXD.AxdoReadOutport(index, ref data);
//if (err != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
//{
// throw new Exception(string.Format("ERR_IO_FAIL_TO_GET_BIT;ERROR CODE:{0}", err));
//}
//return Convert.ToBoolean(data);
}
public override bool ReadDiBit(int index)
{

View File

@ -269,12 +269,13 @@ namespace ILSOS_PrismaticRD_PTOP.Sequences
private bool CheckCondition_Interlock()
{
//// PLC, Data, IO 등 Interlock checking
bool boolian = AlarmManager.HasAlarmLevelHigh();
if (boolian) {
Log.E($"Clear Heavy Alarms For Welding!");
MessageUtil.ShowWarningToast(string.Format("Clear Heavy Alarms For Welding!"));
return false;
}
// [임시 우회] 테스트용으로 High(중대) 알람 인터락 주석 처리 — 테스트 후 반드시 원복할 것!
//bool boolian = AlarmManager.HasAlarmLevelHigh();
//if (boolian) {
// Log.E($"Clear Heavy Alarms For Welding!");
// MessageUtil.ShowWarningToast(string.Format("Clear Heavy Alarms For Welding!"));
// return false;
//}
#warning to KSJ > 지워도 무방해보임
//boolian = AlarmManager.IsPlcDoorOpen();

View File

@ -171,22 +171,32 @@ namespace WeldingCommon.Views
private void OnMonitoring(object sender, EventArgs e)
{
// TODO: Laser Device 에 구현된 내용에 따르면, 일부 Laser Device 는 구현이 되어 있지 않은 상태. 항상 false
if (_Laser.GetPilotLaserStatus()) {
IsGuidBeam = true;
} else {
IsGuidBeam = false;
}
// Guide Beam: DI 결선 없음 → 가이드빔 제어 DO 17 명령 비트를 그대로 표시
// (기존 _Laser.GetPilotLaserStatus()는 DO 3=GuideLaserEnable 을 봤으나, 현장 가이드빔 제어선은 DO 17)
// IO 미연결 가드는 현장PC에서 동작 안 해 주석 (개발PC에서 주석 해제)
//if (_IODevice == null || !_IODevice.IsConnected()) {
// IsGuidBeam = false;
//} else {
// IsGuidBeam = _IODevice.ReadDO(17);
//}
IsGuidBeam = _IODevice.ReadDO(17);
// [기존 소스 보존] Laser 디바이스 기반 Pilot 상태 (DO 3=GuideLaserEnable) — 일부 Laser 미구현 시 항상 false
//if (_Laser.GetPilotLaserStatus()) {
// IsGuidBeam = true;
//} else {
// IsGuidBeam = false;
//}
try
{
// 시뮬 아님 + IO보드 없음 → _iOUnit == null → ReadDI에서 NRE로 꺼짐.
// 시뮬 아님 + IO보드 없음 → _iOUnit == null → ReadDI에서 NRE로 꺼짐. - 현장PC 아닌 경우 개발PC에서 주석 해제 (시뮬안하고 레시피 들어갔을 때 프로그램 종료 방지)
// IsConnected()가 _iOUnit null/미연결을 체크하므로, 미연결이면 폴링 스킵(꺼짐 방지).
if (_IODevice == null || !_IODevice.IsConnected())
{
IsLaserReady = false;
}
//if (_IODevice == null || !_IODevice.IsConnected())
//{
// IsLaserReady = false;
//}
// 변경 후 (260618: IO 결선 변경 12&24 → 11&15)
else if (_IODevice.ReadDI(11) && _IODevice.ReadDI(15))
if (_IODevice.ReadDI(11) && _IODevice.ReadDI(15))
{
IsLaserReady = true;
}
@ -455,11 +465,20 @@ namespace WeldingCommon.Views
private void PerformCmdLaserGuideBeam(object obj)
{
if (!_Laser.GetPilotLaserSetBitStatus()) {
_Laser.PilotLaserOn();
} else {
_Laser.PilotLaserOff();
}
// Guide Beam DO 17 토글 — 모니터링도 같은 DO 17 을 읽어 표시
// IO 미연결 가드는 현장PC에서 동작 안 해 주석 (개발PC에서 주석 해제)
//if (_IODevice == null || !_IODevice.IsConnected()) {
// return;
//}
bool cur = _IODevice.ReadDO(17);
_IODevice._iOUnit.WriteDoBit(17, !cur);
// [기존 소스 보존] Laser 디바이스 기반 Pilot On/Off 토글 (DO 3=GuideLaserEnable)
//if (!_Laser.GetPilotLaserSetBitStatus()) {
// _Laser.PilotLaserOn();
//} else {
// _Laser.PilotLaserOff();
//}
}
private void PerformCmdLaserReadyCheck(object obj)

View File

@ -0,0 +1,111 @@
# ILSOS PTOP 알람부(AlarmManager) 종합 분석 — 2026-06-19
> 계기: 현장 PLC 미연결 상태에서 `SeqComponentTeachingRun` 시작 시 H(중)알람 인터락(202003)으로 차단됨.
> 본 문서는 알람부 전체 구조·동작·시퀀스 참조·리스크·개선안을 정리한다.
---
## 1. 클래스 구조
| 클래스 | 위치 | 역할 |
|--------|------|------|
| `AlarmManager` (base) | `WeldingCommon/Alarm/AlarmManager.cs` | 정적 싱글톤(`_Instance`). 알람 set/조회/시퀀스 정지 |
| `AlarmManager_PTOP` | `PTOP/Alarm/AlarmManager_PTOP.cs` | `StopSequenceByAlarm` — H알람 시 AutoRun 정지 |
| `AlarmCode` / `AlarmCode_PTOP` | `.../Alarm/AlarmCode*.cs` | 알람 코드 상수. PTOP는 base 상속 후 21xxxx 추가 |
| `IAlarmService` (Aurora 프레임워크) | External/Aurora | **활성 알람 목록·설명·레벨(H/L)** 보유 |
- 알람 **레벨(H/L)** 은 소스 상수가 아니라 **Aurora 런타임 알람 테이블**에 정의됨(코드에 `AlarmLevel.H` 할당부 없음).
## 2. 핵심 메서드 동작 (주의점)
- **`Alarm(code)`** (79줄): 이미 활성이면 재set 안 함 → **set-once(중복 없음)**.
- **`HasAlarmLevelHigh()`** (172줄): 활성 알람 중 H 하나라도 있으면 true. **⚠️ Simulation이면 무조건 false**(시뮬은 인터락 우회).
- **`IsAlarmLevelHigh(code)`** (194줄): 설명 모르는 코드(`desc==null`)는 **위험으로 보고 H 취급** → 미정의 코드도 인터락 유발.
- **Clear**: 개별 `ClearAlarm()`은 **빈 함수**(주석만). 실제 해제는 **`ClearAllAlarm()`(전체 일괄)** 뿐.
- 트리거: `SYS_ALARM_RESET_ALL_ALARM` / `EVENT_RESET_ALL_ALARMS_REQUEST` → `_AlarmService.ClearAllAlarm()`.
- **PLC 알람워드 직접쓰기**(`WriteBit(HeavyAlarmStatusAddr..)`)는 AlarmManager 내에서 전부 **주석 처리**됨(대신 SeqStatusMonitor가 수행).
## 3. 알람 생성·소멸·전파 흐름
```
[생성] SeqAlarmMonitor (상시 주기 감시)
├ PLC: EMO / Heavy / Door / 통신끊김
├ Laser/Scanner/LBAD/OCT/Chiller: Deactivated/Disconnect/Error
└ IO: Leak / null / deactivated
→ AlarmManager.Alarm(code) ← set-only, ❌조건 해소 시 Clear 안 함(LATCH)
[전파] EquipmentSetup.OnSetAlarm(code, isHeavy) (EquipmentSetup.cs:82)
→ isHeavy 면 AlarmManager_PTOP.StopSequenceByAlarm(code) → H면 StopSequence(SeqAutoRun) 비상정지
[PLC보고] SeqStatusMonitor.UpdateStatus (SeqStatusMonitor.cs:86)
→ PC_HEAVY_ALARM_STATUS = HasAlarmLevelHigh(), PC_LIGHT_ALARM_STATUS = HasAlarmLevelLow()
→ PLC_ALARM_RESET 입력 시 EVENT_RESET_ALL_ALARMS_REQUEST 발행 → ClearAllAlarm()
[차단] 각 시퀀스 시작 시 CheckCondition_Interlock() → HasAlarmLevelHigh() H면 시작 거부
```
## 4. 주요 시퀀스별 알람 참조
| 시퀀스 | 인터락 체크 | 비고 |
|--------|------------|------|
| **SeqComponentTeachingRun** | `HasAlarmLevelHigh()` → "Clear Heavy Alarms" + 202003 (Door/EMO 주석) | **이번에 막힌 시퀀스** |
| SeqTeachingRun (Common) | `CheckCondition_Interlock()` = **빈 체크(true)** | 알람 체크 없음 |
| **SeqAutoRunPTOP** | `CheckCondition_Interlock()` = **빈 체크(true)** | 차단은 시작이 아니라 OnSetAlarm→StopSequence |
| SeqAutoRunPrismatic / ComponentWeld | 동일 패턴(빈 체크) | |
| ScoutNormal/FlyingVision, UploadWeldingList, ReceiveCellInfo, ReportCellResult, MarkGrid, ScannerCalibration | 대부분 빈 체크 | 공통 시퀀스 |
| **SeqStatusMonitor** | 알람을 **읽어 PLC 출력** + Reset 처리 | 차단 아님 |
| **SeqAlarmMonitor** | 알람을 **생성(set-only)** | latch 원인 |
> 실제 알람으로 "시작 차단"하는 곳은 `SeqComponentTeachingRun`이 거의 유일. AutoRun 계열은 "운전 중 H알람 발생 시 비상정지" 방식.
## 5. 알람 코드 표 (추정 레벨 — 권위값은 런타임 테이블)
| 코드 | 이름 | 용도 | 추정 |
|------|------|------|------|
| 200xxx~203xxx | ALARM_SEQUENCE_* | 시퀀스 결과/초기조건 실패 | 혼합 |
| 203004 | AutoRun_HeavyAlarmOccured | 자동운전 중 중알람 | H |
| 210001/2/3 | PLC Deactivated/Disconnect/**EMO** | PLC 상태/비상정지 | H |
| 210004/5/6 | PLC Light / **Heavy** / Door Interlock | PLC 경/중/도어 | 210005·6 H, 210004 L |
| 210101/2/3 | Scanner Deactivated/Disconnect/Error | 스캐너 | H/혼합 |
| 210201~205 | Laser Deactivated/Disconnect/Error/Warning/**EMO** | 레이저 | 205·201 H, 204 L |
| 210206/7 | Laser Warning/Error MSG | 레이저 메시지(동적) | L/H |
| 210301~303 | LBAD Deactivated/Disconnect/Error | LBAD | H/혼합 |
| 210401~403 | OCT Deactivated/Disconnect/Error | OCT | H/혼합 |
| 210501~503 | Chiller Deactivated/Disconnect/Error | 냉각기 | H/혼합 |
| 210600~604 | IO Null/Deactivated/Disconnect/**Leak**(Scanner/Chiller) | IO보드/누액 | H |
| 210605~614 | IO MC/BoxTemp/ChillerLeak/Fan1~6 | (현재 대부분 주석) | 혼합 |
| 210700~705 | RMS_* 타임아웃/설정 | 레시피 관리 | L 추정 |
## 6. 리스크 / 개선 포인트
1. **알람 Latch (최우선)** — `SeqAlarmMonitor`가 set만 하고 조건 정상화 시 `ClearAlarm` 안 함. → **이번 PLC 미연결 사례**가 정확히 이것: 연결 복구돼도 알람이 남아 차단, 수동 ClearAll 필요.
2. **개별 Clear 부재** — `ClearAlarm()`이 빈 함수 → 전체 일괄 해제만 가능, 특정 알람만 해제 불가.
3. **Unknown=H 취급** — 미정의 코드 활성 시 무조건 H 차단 → 알람 테이블 누락 시 의도치 않은 인터락.
4. **시뮬 우회** — `HasAlarmLevelHigh()`가 Simulation이면 false → 시뮬/현장 동작 차이.
5. **인터락 일관성 부재** — TeachingRun만 알람 차단, 나머지 시작 시퀀스는 빈 체크. 안전 정책 제각각.
6. **Door/EMO 주석** — SeqComponentTeachingRun·UCMainAutoRunViewModel의 Door/EMO 인터락 주석 → 현재 중알람 1종만 차단.
## 7. 개선 제안 — SeqAlarmMonitor self-clearing
각 검사 항목을 "조건 나쁨 → Alarm, 조건 좋음 → Clear" 대칭 구조로. 예(개념):
```csharp
// AS-IS
if (!_Laser.IsActivated) AlarmManager.Alarm(ALARM_DEVICE_LASER_DEACTIVATED);
else { /* clear 없음 → latch */ }
// TO-BE (self-clearing) — AlarmManager에 개별 ClearAlarm(code) 구현 전제
if (!_Laser.IsActivated) AlarmManager.Alarm(ALARM_DEVICE_LASER_DEACTIVATED);
else AlarmManager.ClearAlarm(ALARM_DEVICE_LASER_DEACTIVATED);
```
- 전제: `AlarmManager.ClearAlarm(int code)` 실구현 필요(현재 빈 함수). `_AlarmService`에 단건 해제 API 확인 후 연결.
- 효과: PLC 재연결 등 조건 복구 시 알람 자동 해제 → 수동 ClearAll 불필요, 인터락 latch 해소.
- 범위: AlarmManager(공통) 수정 → **승인 필요 영역**. 적용 전 별도 협의.
## 8. 부록 — 이번(PLC 미연결) 사례 요약
- PLC 미연결 → `SeqAlarmMonitor`가 PLC Deactivated/Disconnect(H) set → latch.
- `SeqComponentTeachingRun` 시작 → `HasAlarmLevelHigh()` true → 202003, FORCE_ERROR.
- 임시조치: `SeqComponentTeachingRun.CheckCondition_Interlock()`의 H알람 블록 주석(테스트용, **원복 예정**) → 레이저 출사 확인.
- 관련: [[axis-position-interlock-todo]]

View File

@ -0,0 +1,82 @@
# MX Component PLC 연결 설정 분석 — 2026-06-19
> 계기: 현장 PLC 미연결 → 중알람 latch → TeachingRun 인터락 차단.
> PLC를 정상 연결하려면 무엇을 PLC측에 요청하고, PC 소스/설정의 어떤 값을 맞춰야 하는지 분석(수정 없음).
> 관련: [[110333_alarm_subsystem_analysis]]
---
## 1. 연결 메커니즘 (소스 기준)
- 드라이버: `AuroraDevices/AuroraMXComponent/MXComponent.cs` — Mitsubishi **MX Component** .NET 컨트롤 `ActUtlType64Class` 사용.
- PTOP 등록(`EquipmentSetup.cs:158`):
`new PLCControllerPTOP(PLCDevice, ePLCNetType.MXComponent, IsSimulation, PLCMMapFileType.CSV, AuroraEnv)`
- 연결 흐름:
```
PLCBase.DoActivate (PLCBase.cs:80)
→ NetworkType == MXComponent
→ PLCNet.SetInitParams(connConfig.StationNumber) // = ActLogicalStationNumber
→ Open() → _actUtlType.ActLogicalStationNumber = N; _actUtlType.Open()
```
- **핵심 파라미터 = `StationNumber` (논리국번 / Logical Station Number)**.
`MXComponent.SetInitParams(int logicalStationNo)` → `_actUtlType.ActLogicalStationNumber = logicalStationNo` (MXComponent.cs:26~29).
- Open 결과: `0x00000000` 성공, 그 외 Hex 에러. `0x0180840B`(타임아웃) 시 1회 재시도(MXComponent.cs:48).
## 2. 맞춰야 하는 값 — PC측
### (A) MX Component "Communication Setup Utility" (별도 PC 도구)
- MX Component 설치 시 함께 깔리는 **통신 설정 유틸리티**에서 **Logical Station Number** 를 등록.
- 등록 시 입력: PLC **CPU 기종**, **접속 경로**(CPU 내장 이더넷 / 이더넷 모듈 / CC-Link IE / USB / 시리얼), **PLC IP/포트**, 네트워크/국번.
- 이 유틸리티에 등록된 논리국번이 실제 통신 경로를 정의함. (소스는 "번호"만 들고, 실 경로는 유틸리티가 보유)
### (B) 소스/설정 파일 — `StationNumber` 일치
- 정의: `AuroraDevices/AuroraPLC/PLCBase.Config.cs:37`
`PLCMXComponentConnConfig.StationNumber` 기본값 **1** (주석: "Logical station No. (By PC Tool: Communication Setting Utility)").
- 실제 값은 **디바이스 config 파일에 저장**: `_config_device/PLC.json`
```json
{ "ConnConfig": { "StationNumber": 22, "UpdateRateMS": 50 } }
```
(위는 Gun 예시 = 22. PTOP는 현장 값으로 별도 설정 필요)
- **편집 경로**: 프로그램 내 PLC 디바이스 설정 화면(`UCPLCDevice`)에서도 수정 가능, 또는 위 JSON 직접 편집.
- ⚠️ **(A)의 유틸리티 논리국번 == (B)의 PLC.json StationNumber** 이어야 연결됨. (현장 PLC.json은 repo에 없음 = 현장 전용)
## 3. PLC측에 요청해야 할 것
| 항목 | 내용 |
|------|------|
| CPU 기종 | Q / L / iQ-R / iQ-F 등 정확한 모델 |
| 접속 방식 | CPU 내장 이더넷 / 이더넷 모듈 / CC-Link IE / USB / 시리얼 중 무엇 |
| 네트워크 정보 | PLC **IP 주소 / 포트**, 서브넷, (CC-Link IE면) 네트워크No·국번 |
| MELSOFT 접속 허용 | 이더넷 "MELSOFT 접속" 오픈 설정, 포트 개방(보통 5007/5006 등), 방화벽 |
| 국번 구성 | 멀티 CPU/증설 시 대상 station |
→ 위 정보를 받아 **(A) Communication Setup Utility에 논리국번으로 등록**하고, 그 번호를 **(B) PLC.json StationNumber** 에 동일하게 넣으면 연결.
## 4. 메모리맵 CSV (연결과 별개, 데이터 정합용)
- `PLCMMapFileType.CSV` → `PLCBase.MemMapParser.cs`가 아래 8종 CSV를 읽어 디바이스 주소 매핑:
- `External/PLC/PLC_DeviceMap_Bit_Input_B_Device.csv` / `..._Output_B_Device`
- `..._Bit_Input_M_Device` / `..._Output_M_Device`
- `..._Word_Input_W_Device` / `..._Output_W_Device`
- `..._Word_Input_D_Device` / `..._Output_D_Device`
- 경로: recipePath 기준 `External\PLC\...` (현장 config 폴더).
- 연결(Open)과는 무관하지만, 연결 후 **읽고/쓰는 주소가 PLC 실제 디바이스와 맞아야** 알람/인터페이스가 정상. PTOP는 repo에 맵 CSV 없음(현장 전용) → [[plc-devicemap-260617-pending]] 참고.
## 5. 점검 순서 (현장)
1. PLC측에서 **CPU기종·접속방식·IP/포트·MELSOFT 접속 허용** 확보
2. PC에서 **MX Component Communication Setup Utility** 실행 → 위 정보로 **논리국번**(예: 1) 등록 → 유틸리티 내 "통신 테스트" 통과 확인
3. `_config_device/PLC.json` 의 `StationNumber` 를 그 논리국번과 동일하게 설정 (또는 PLC 디바이스 설정 화면)
4. 프로그램 재기동 → PLC Activate → 로그 `PLC Open success` 확인 (`Open: 0x00000000`)
5. 연결되면 SeqAlarmMonitor의 PLC Deactivated/Disconnect 알람 조건 해소 → (단, latch라 **ClearAll 1회** 필요할 수 있음, [[110333_alarm_subsystem_analysis]] 참고)
## 6. 참고 — 에러코드 / 매뉴얼
- Open/Close 반환값은 MX Component 표준 Hex 에러코드. `0x0180840B` = 타임아웃(소스에서 1회 재시도).
- 상세 절차·에러표: `Doc/메뉴얼/공통/PLC/21. MX_Component_V4_프로그래밍_매뉴얼.pdf` (Communication Setup Utility / ActUtlType / 에러코드 장 참조).
## 7. 요약
- **연결 핵심 = 논리국번 1개**. PC의 MX Component 유틸리티 등록값 ↔ 소스 `PLC.json StationNumber` 일치 + PLC측 이더넷/접속 허용.
- PLC.json·맵 CSV는 **현장 전용**(repo 없음) → 현장에서 값 세팅 필요.
- 연결되면 PLC 미연결 중알람 해소 → TeachingRun 인터락 정상화 (latch면 ClearAll 1회).

View File

@ -0,0 +1,68 @@
# AjinIO.ReadDoBit(int) 미구현 분석 — 2026-06-19
> 계기: `AjinIO.cs`의 `ReadDoBit(int index)`(bool 반환)가 미구현 스텁(`return true`).
> DI 패턴 대비 분석 후, 현 상태는 **스텁 유지 + 구현 주석 보존**으로 결정(현장 반영 예정).
> 관련: [[110333_alarm_subsystem_analysis]]
---
## 1. 현황
- 파일: `AuroraDevices/AuroraIO/Vendor/AJINEXTEK/AjinIO.cs` (보호 영역, 신중 수정)
- DI/DO 오버로드 4종(`IOUnit` 추상):
- `int ReadDoBit(int, ref bool)` (469줄) — `CAXD.AxdoReadOutport` 사용, **구현됨**
- `int ReadDiBit(int, ref bool)` (483줄) — `CAXD.AxdiReadInport`, 구현됨
- `bool ReadDoBit(int)` (496줄) — **미구현 스텁(`return true`)** ← 대상
- `bool ReadDiBit(int)` (501줄) — `CAXD.AxdiReadInport`, 구현됨(실패 시 throw)
- 즉 **DO 읽기 API(`AxdoReadOutport`)는 같은 파일에서 이미 검증**됨(469줄·`GetDoArray` 399줄). bool 반환 오버로드만 DO쪽이 비어 있었음.
## 2. 구현안 (DI 패턴 그대로)
```csharp
public override bool ReadDoBit(int index)
{
uint data = 0;
int err = (int)CAXD.AxdoReadOutport(index, ref data);
if (err != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
throw new Exception(string.Format("ERR_IO_FAIL_TO_GET_BIT;ERROR CODE:{0}", err));
return Convert.ToBoolean(data);
}
```
- `ReadDiBit(int)`(501줄)와 완전 동일 구조, API만 `AxdiReadInport → AxdoReadOutport`.
## 3. 스텁 의존 호출처 분석 (영향 범위)
`bool ReadDoBit(int)` 호출처 전수:
| 호출처 | 위치 | 용도 |
|--------|------|------|
| `UCInformationPanelViewModel.cs` | 46, 53, 82, 115, 132 (5곳) | ModeKeySolOn / SafetyDoorRelease **상태 표시** |
- 5곳 모두 **`ePDOAddress`(PAIX 주소)** 사용 → 실제 **PAIX 보드에서 실행**.
- **PAIX의 `ReadDoBit(int)`는 정상 구현**(PAIXIO.cs:288, `GetDoArray`로 읽음) → 이 호출처는 이미 정상 동작.
- `(int, ref bool)` 오버로드 호출(`UCTestDeviceViewModel.cs:264`)은 Ajin도 구현돼 있어 무관.
- **결론: Ajin 스텁(`return true`)에 실제 의존하는 코드는 사실상 없음.** 영향은 "Ajin 보드 장비에서 위 5개 호출이 도는 경우"로 한정되며, 그 경우 오히려 항상 true가 오표시였음(상태 표시용, 안전제어 아님 → 위험 낮음).
## 4. 현재 결정 상태 (스텁 유지 + 구현 주석 보존)
```csharp
public override bool ReadDoBit(int index)
{
//현재 사용하지 않아서 추후 구현
return true;
// [추후 구현] return true 스텁 의존 코드 확인 후 아래로 교체 (ReadDiBit(int) 패턴)
//uint data = 0;
//int err = (int)CAXD.AxdoReadOutport(index, ref data);
//if (err != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
// throw new Exception(...);
//return Convert.ToBoolean(data);
}
```
- 동작 변화 없음(`return true` 유지) → 현장 안전. 구현은 주석으로 보존해 추후 활성화 용이.
- 빌드 산출물: **AuroraIO.dll**.
## 5. 후속 (활성화 조건)
- Ajin 보드 장비에서 DO 상태 표시 정확성이 필요해질 때, 주석 해제 + 위 5개 호출처 회귀 확인.
- 활성화 시 실패 처리(throw) 영향 검토: `ReadDiBit(int)`와 동일 정책이라 일관성은 확보됨.

View File

@ -0,0 +1,59 @@
# 가이드빔(Guide Beam) 제어 경로 분석 — TruPulse — 2026-06-19
> 계기: 레시피 Guide Beam 버튼/상태가 현장에서 동작하지 않음. IO(DO)→Laser 순으로 추적.
> 결론: 가이드빔은 **Laser(TruPulse) 디바이스 기능**이며, 제어 콜백 **`ExtPilotOnOff`가 미구현(미할당)**.
> 관련: [[110333_alarm_subsystem_analysis]]
---
## 1. 잘못된 경로였던 IO(DO 17) 시도 요약
- 레시피 ViewModel(`UCScannerObjectTeachingControlBoxViewModel.cs`)에서 `_IODevice`(메인 IO_Board=PAIX_PTOP)의
**DO 17(EX_Red_Control)** 을 read/write 하도록 수정 → 상태 표시(읽기)는 동작 확인.
- 그러나 **물리적 가이드빔(적색광)은 출력 안 됨**.
- 현장 확인: 번들(DBW-MC Laser SW)의 `RedLight Opened/Closed` 이벤트는 **번들의 RedClosed 버튼 수동 조작** 결과로,
우리 DO 17과 무관. `Mod1_IO:000100↔000000` 비트만 DO 17과 일치.
- → **DO 17(IO) 경로는 가이드빔 제어가 아님.** (메인 IO_Board와 레이저 가이드빔 입력은 별개)
- 현 상태: 원복하지 않고 **주석 토글로 필요시 전환**(도연님 운용). 기존 `_Laser` 코드는 주석 보존됨.
## 2. 실제 경로 = Laser(TruPulse) 디바이스
레이저 타입 = **TruPulse** (`eLaserType.TruPulse`, `Laser.cs:70`).
```
_Laser.PilotLaserOn() (베이스 Laser, Laser.cs)
└ IsSimul 이면 return E1.OK (no-op) ← 현재 시뮬이라 여기서 멈춤
└ 실모드: TruPulse.PilotLaserOn() (TruPulse.cs:817)
└ return PilotOnOffFunc(true)
└ (Laser.cs:74) core.PilotOnOffFunc = (on) => ExtPilotOnOff(on)
└ ExtPilotOnOff(true) ← ★ 레이저 IO 보드 write 의도 콜백
```
상태 읽기:
```
GetPilotLaserStatus() → PilotLaserEnable ← (TruPulse.cs:174) Di2 & (1<<9)
(QueryStatusHwInterface 로 TruPulse 컨트롤러에서 직접 읽음)
```
## 3. ★ 핵심 문제: `ExtPilotOnOff` 미구현(미할당)
- `Laser.cs` 27~29줄에 `ExtLaserEnable` / `ExtLaserDisable` / `ExtPilotOnOff` **선언만** 존재.
- 전체 소스에 **`ExtPilotOnOff = ...` 할당부 없음**(검색 0건). `updateCore` 구독(`UCTruPulseManualViewModel`)도 core 참조만 받고 콜백 미주입.
- 결과:
- **시뮬(현재)**: 베이스에서 no-op → 빔 안 나옴, 상태 항상 true. (정상)
- **실모드**: `ExtPilotOnOff(true)` 호출 시 **null → NullReferenceException** 위험.
- → "레이저 IO 보드로 가이드빔 제어"는 **설계 의도이나 구현 미완(TODO)**.
## 4. 결론 / TODO
| 구간 | 상태 |
|------|------|
| 가이드빔 제어 의도 | TruPulse → `ExtPilotOnOff` → 레이저 IO 보드 DO |
| 실제 구현 | ❌ 미구현 (`ExtPilotOnOff` 미할당) |
| 현재 운영 | 시뮬 → no-op (물리 빔 안 나오는 게 정상) |
| 레시피 DO 17(`_IODevice`) 변경 | 잘못된 경로(메인 IO_Board), 원복 안 함 — 주석 토글로 운용 |
추후 실제 가이드빔 구현 시:
- `_Laser.ExtPilotOnOff = (on) => { 레이저IO보드._iOUnit.WriteDoBit(<가이드빔 DO>, on); return 0; };` 구현
- "레이저 IO 보드" 디바이스/DO 주소 확정 (메인 PAIX와 별개 여부)
- Laser 디바이스 **비시뮬 + Activated**

View File

@ -0,0 +1,140 @@
# 작업일지 — 2026-06-19
## 09:27
- External/Aurora/bin 을 git 커밋 대상에 포함시킴 (전역 `bin/` 무시는 유지, negation 예외 처리)
- `.gitignore`에 `!/External/Aurora/bin/`, `!/External/Aurora/bin/**` 두 줄 추가
- `.gitignore` 자체가 `/.gitignore`로 무시되어 `git add -f`로 강제 추가
- Aurora bin 산출물 14개 파일 + .gitignore 함께 커밋 (7f464ab)
- 위 커밋 규칙을 `docs/GIT_RULES.md`로 문서화
- bin 무시/예외, .gitignore 자체 커밋(-f) 규칙 정리
- `architecture.md`에 `@import ./GIT_RULES.md` 연결 (목차 7번 추가)
- 커밋 후 push (de0c1c2)
## 09:39
- WPF 빌드 자동 생성 임시 파일 `*_wpftmp.csproj`를 `.gitignore`에 추가
- `AuroraPLC_2pjacgrp_wpftmp.csproj`는 sln/csproj 어디에도 참조되지 않는 빌드 산출물 → 커밋 대상 아님
- 매번 git status에 안 뜨도록 `*_wpftmp.csproj` 무시 처리, push (3724007)
- 그 외 정리: rules.md 규칙 5번 .md 영문 작성 요건 제거(3293455), PtoP PLC 인터페이스 xlsx(260617) 삭제(7cb6525) 커밋·push
## 09:47
- 어제 필드가 좁았던 부분 Scan Field size 변경하던 곳 위치
- 프로그램상 Setting - SystemParameterILSOS - Scout 영역의 Scan field size (캔버스 영역 지정)
- 어제 그 레시피에서 캔버스 크기가 작았던 이슈 때문에 수정한 부분으로, 이 위치가 캔버스(Scan field) 크기를 수정하는 곳임
## 10:00
- Recipe > Laser Shot > Laser Control - Guide Beam Status 의 Guide Beam 버튼 동작 소스 분석
- **UI/바인딩**: `WeldingComponents/WeldingCommon/Views/Recipes/UCScannerObjectTeachingControlBox.xaml`
의 Guide Beam 버튼 → ViewModel `CMD_LaserGuideBeam`(DelegateCommand) → `PerformCmdLaserGuideBeam()` 호출
(ViewModel: 같은 폴더 `UCScannerObjectTeachingControlBoxViewModel.cs`)
- **버튼 핸들러(토글 동작)**: `PerformCmdLaserGuideBeam()` (456~463줄)
- `_Laser.GetPilotLaserSetBitStatus()` 가 false 면 `_Laser.PilotLaserOn()`, true 면 `_Laser.PilotLaserOff()`
- 즉 현재 파일럿(Guide) 레이저 set 비트 상태를 보고 ON/OFF 를 번갈아 보내는 토글 버튼
- **디바이스 추상화**: `_Laser` 는 `AuroraDevices/AuroraLaser/Laser.cs` 의 베이스 `Laser`
(`DeviceManager[CommonDeviceIds.Laser]`). 베이스는 IsSimul 이면 OK, 미활성/null 이면 GENERIC(GuideBeam 미동작),
아니면 내부 `ILaser` 구현체로 위임. 구체 타입은 `eLaserType` config 로 결정(ArmLaser/TruPulse/IPG_IO/Trumpf_IO 등)
- **실제 하드웨어 제어(예: IPG_IO `AuroraDevices/AuroraLaser/IPG/LaserIPG_IO.cs`)**:
- `PilotLaserOn()` → `SetLaserDOCommand(eADOAddress.GuideLaserEnable, true)` → IO보드 `WriteDoBit(GuideLaserEnable, true)`
- `PilotLaserOff()` → 같은 DO 비트를 false 로 Write → 가이드 빔 OFF
- **상태 표시(Guide Beam Status)**: ViewModel `OnMonitoring()` 타이머가 `_Laser.GetPilotLaserStatus()` 를
주기 폴링하여 `IsGuidBeam` 바인딩 갱신. IPG_IO 는 파일럿 DI 핀맵이 없어 `GuideLaserEnable` DO 상태를 그대로 읽어 표시
- **주의**: `OnMonitoring()` 의 TODO 주석대로 일부 Laser 디바이스는 `GetPilotLaserStatus()` 미구현 → 항상 false.
이 경우 버튼으로 DO 는 나가도 Status 표시는 갱신되지 않을 수 있음
## 10:21 — Guide Beam DO 주소 정합 (DO 3 → DO 17) 수정 및 현장 검증 대기
### 배경 / 문제
- 현장에서 **가이드빔(적색광)이 안 나옴** → 원인 분석 결과 모니터링/제어가 보던 DO 비트가 실제 제어선과 불일치
- 기존 소스: 버튼·모니터링 모두 `_Laser` 경로로 `eADOAddress.GuideLaserEnable`(Ajin enum = **raw 3**)을 사용
- 현장 확인(도연님): 실제 **가이드빔 제어선은 DO 17(EX_Red_Control)**. **DO 3 은 PLC 인터페이스3 용**으로 가이드빔과 무관
- DI 결선 없음 → 모니터링은 **DO(명령) 신호**를 그대로 표시하는 구조
### 분석 정리
- 동작 체인: Guide Beam 버튼 → `CMD_LaserGuideBeam` → `PerformCmdLaserGuideBeam()` → (기존)`_Laser.PilotLaserOn/Off`
→ IO Laser 는 `GuideLaserEnable`(raw 3) DO Write. 모니터링은 `OnMonitoring()` 타이머가 `GetPilotLaserStatus()`(raw 3 DO read) → `IsGuidBeam`
- `CommonDeviceIds.IODevice == "IO_Board"` (`EquipDefCommon.cs:115`) → ViewModel `_IODevice` 와 IO Laser 가 쓰는 보드 **동일**(PTOP=PAIX_PTOP)
- IO 기반 Laser(IPG_IO/TruPulse_IO/Trumpf_IO/Arm_IO)는 `GetPilotLaserStatus()` 구현되어 있음(미구현은 NL202/Rapid/YLPN/TrueDisk/TrumpfCore)
- 현장 Laser 타입 = **IO 기반**
### 수정 내용 (커밋 보류 — 현장 검증 후 결정)
- 파일: `WeldingComponents/WeldingCommon/Views/Recipes/UCScannerObjectTeachingControlBoxViewModel.cs`
- `OnMonitoring()` (174~181줄): `_Laser.GetPilotLaserStatus()` → `_IODevice.ReadDO(17)` + IO 미연결 가드(미연결 시 false)
- `PerformCmdLaserGuideBeam()` (457~464줄): `_Laser.PilotLaserOn/Off` → `_IODevice` **DO 17 토글**(현재값 읽어 반전)
- 효과: 버튼이 쓰는 비트와 모니터링이 읽는 비트가 **동일 DO 17** → 버튼/직접 SetBit 어느 쪽으로 켜도 Status 동기화
- 빌드 산출물: **WeldingCommon.dll** (현장 소스 덮어쓰기 시 재빌드 후 실행 폴더 반영 필요)
### 현장 검증 체크리스트
- [x] 현장 PC 에 수정 소스 덮어쓰기 후 WeldingCommon 재빌드
- [x] `WeldingCommon.dll` 실행 폴더 반영
- [x] Guide Beam 버튼 클릭 → 화면 Guide Beam Status 점등(ON) 확인 → **실패(변경 안 됨)**
- [ ] ~~Guide Beam 버튼 재클릭 → Status 소등(OFF) 확인~~
- [x] DO 17 직접 SetBit → Status 동기화 확인 → **실패(모니터링이 DO 17 을 보는 것도 아님)**
- [x] **실제 가이드빔(적색광) 점등** 여부 확인 → **점등 안 됨**
### 현장 검증 결과 (실패 → 원복)
- **결론: DO 17 은 가이드빔 제어선이 아님.** 버튼으로 변경도 안 되고, 모니터링이 DO 17 을 보는 것도 아니었음
- 수정분(`UCScannerObjectTeachingControlBoxViewModel.cs` OnMonitoring/PerformCmdLaserGuideBeam) **`git checkout` 으로 원복** (커밋 안 한 상태였음)
- DO 3 / DO 17 모두 실제 가이드빔 제어선이 아닌 것으로 확인 → **실제 제어선 DO 주소 재확인 필요**
### TODO / 후속
- 현장 IO 인터페이스(결선)에서 **실제 가이드빔 제어 DO 주소** 재확인 (DO 3·17 아님)
- 주소 확정 후 동일 방식(버튼 write + 모니터링 read 동일 비트)으로 재시도
- 추후 실제 점등 피드백 **DI 결선** 추가되면, 명령 DO 대신 피드백 DI 로 표시하도록 전환 검토
## 11:03 — TeachingRun 인터락 알람 분석 + 알람부 종합 분석
### TeachingRun 차단 원인 (현장 로그)
- `SeqComponentTeachingRun` 시작 시 `CheckCondition_Interlock()`의 `HasAlarmLevelHigh()`가 true → "Clear Heavy Alarms For Welding!" + 알람 202003 → FORCE_ERROR
- **원인 = 현장 PLC 미연결** → SeqAlarmMonitor가 PLC Deactivated/Disconnect(H) 알람 set → latch로 남아 인터락
- 임시조치: `SeqComponentTeachingRun.cs` CheckCondition_Interlock()의 H알람 블록 **주석 처리(테스트용, 원복 예정)** → 레이저 출사 확인 완료
### 알람부 종합 분석 문서 작성
- 문서: `docs/분석/2026/06/19/110333_alarm_subsystem_analysis.md`
- 내용: 클래스 구조, 핵심 메서드(set-once/시뮬우회/Unknown=H/Clear전체일괄), 생성·전파 흐름, 시퀀스별 알람 참조표, 알람 코드 표, 리스크 6종, SeqAlarmMonitor self-clearing 개선안
- 핵심 리스크: **알람 latch(조건 해소 시 자동 Clear 없음)** → PLC 재연결돼도 수동 ClearAll 전까지 인터락 지속
### TODO / 후속
- 현장 **MX Component 연결 설정** 후 PLC 연결 → 중알람 자연 해소 여부 확인 (별도 분석 진행 중)
- 알람 인터락 블록 **원복** (현장 PLC 정상화 후)
- `SeqAlarmMonitor` self-clearing 개선 검토 (AlarmManager 공통 수정 → 승인 필요)
## 11:13 — MX Component PLC 연결 설정 분석
- 문서: `docs/분석/2026/06/19/111326_mxcomponent_plc_connection_analysis.md`
- 핵심: 연결 = **논리국번(Logical Station Number)** 1개로 결정
- PC의 **MX Component Communication Setup Utility** 에 등록한 논리국번 ↔ 소스 `_config_device/PLC.json` 의 `ConnConfig.StationNumber`(기본 1, Gun 예시 22) **일치 필요**
- 드라이버: `AuroraMXComponent/MXComponent.cs` → `ActUtlType64Class.ActLogicalStationNumber` 설정 후 Open
- PLC측 요청: CPU 기종 / 접속방식(CPU내장이더넷·이더넷모듈·CC-Link IE 등) / **IP·포트** / MELSOFT 접속 허용
- 메모리맵 CSV 8종(`External/PLC/PLC_DeviceMap_*.csv`)은 연결과 별개지만 데이터 정합 필요 — PTOP는 repo에 없음(현장 전용)
- 연결되면 PLC 미연결 중알람 해소 → 단 latch라 **ClearAll 1회** 필요할 수 있음
## 12:22 — AjinIO.ReadDoBit(int) 미구현 분석 (스텁 유지 결정)
- 파일: `AuroraDevices/AuroraIO/Vendor/AJINEXTEK/AjinIO.cs` `ReadDoBit(int index)` (496줄~)
- 현황: bool 반환 `ReadDoBit(int)`만 미구현 스텁(`return true`). DO 읽기 API(`AxdoReadOutport`)는 같은 파일 469줄·GetDoArray에서 이미 검증됨
- 스텁 의존 호출처: `UCInformationPanelViewModel.cs` 5곳(ModeKeySolOn/SafetyDoorRelease 상태표시) — **전부 ePDOAddress(PAIX) → PAIX 보드 실행, PAIX는 정상 구현** → Ajin 스텁 실제 의존 코드 사실상 없음
- **결정: 스텁(`return true`) 유지 + 구현(ReadDiBit 패턴)은 주석으로 보존** → 동작 변화 없음(현장 안전), 추후 활성화 용이
- 빌드 산출물: **AuroraIO.dll**
- 분석 문서: `docs/분석/2026/06/19/122201_ajinio_readdobit_analysis.md`
## 12:47 — 가이드빔 제어 경로 추적 (IO → Laser/TruPulse) 및 미구현 확인
### 진행 경위
- 레시피 Guide Beam 을 `_IODevice` **DO 17(EX_Red_Control)** read/write 로 수정 → 상태표시(읽기)는 동작, **물리 빔은 안 나옴**
- 번들(DBW-MC) `RedLight Opened/Closed` 이벤트는 **번들 RedClosed 버튼 수동조작** 결과, DO 17과 무관 (Mod1_IO 비트만 일치)
- → **DO 17(IO) 경로는 가이드빔 제어가 아님.** 레이저 타입 = **TruPulse**
### 핵심 발견 (TruPulse 가이드빔 미구현)
- 경로: `_Laser.PilotLaserOn()` → (TruPulse)`PilotOnOffFunc` → `ExtPilotOnOff` (레이저 IO 보드 write 의도)
- 상태: `GetPilotLaserStatus()` → `PilotLaserEnable` ← TruPulse `Di2 bit9`
- **`ExtPilotOnOff`/`ExtLaserEnable`/`ExtLaserDisable` 가 선언만 되고 할당부 없음(미구현 TODO)**
- 시뮬(현재): 베이스 no-op → 빔 안 나옴(정상) / 실모드: null → NRE 위험
- 현재 Laser 디바이스 = **시뮬레이션**, 제어는 레이저 IO 보드로 한다고 함
### 처리 / 결정
- 레시피 DO 17 변경분 **원복 안 함** — 필요 시 도연님이 주석 토글로 운용 (기존 `_Laser` 코드 주석 보존됨)
- IO 미연결 가드(`IsConnected`)는 현장PC에서 동작 안 해 주석(개발PC에서 해제) — LaserReady 패턴과 동일
- 분석 문서: `docs/분석/2026/06/19/124752_guidebeam_trupulse_analysis.md`
### 금일 작업 정리 (커밋 대상)
- 코드(미커밋): `AjinIO.cs`(ReadDoBit 스텁 유지+구현 주석), `SeqComponentTeachingRun.cs`(중알람 인터락 임시 주석), `UCScannerObjectTeachingControlBoxViewModel.cs`(Guide Beam DO 17 + 가드 주석)
- 분석 문서 4종: 알람부 / MX Component / AjinIO ReadDoBit / 가이드빔 TruPulse