LGES-OC5-PtoP-Welder/docs/분석_HeavyAlarm_비트_동작_260810.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

8.0 KiB

Heavy(중)알람 비트 동작 분석 — 2026-08-10

대상: PC_HEAVY_ALARM_STATUS(PC→PLC) / PLC_HEAVY_ALARM_STATUS(PLC→PC) 질문: 어떤 경우에 Heavy Alarm 비트가 켜지고 꺼지는가


1. 한 줄 요약

"지금 떠 있는 알람 목록에 Level H가 하나라도 있으면 ON" 을 SeqStatusMonitor 가 매 주기 그대로 PLC에 덮어쓴다. 이벤트로 set/reset 하는 래칭 방식이 아니다.


2. 유일한 쓰기 지점

Machines/ILSOS_PrismaticRD_PTOP/Sequences/Monitoring/SeqStatusMonitor.cs:86-87

_plc.WriteBit(eBitOutput.PC_HEAVY_ALARM_STATUS, AlarmManager.HasAlarmLevelHigh());
_plc.WriteBit(eBitOutput.PC_LIGHT_ALARM_STATUS, AlarmManager.HasAlarmLevelLow());
항목 내용
주기 UpdateStatus 노드마다. 루프는 LoopFirst → UpdateStatus → UpdateUI → UpdateIO 이고 각 노드 NODE_SLEEP = 20ms → 약 60~80ms 주기 (SeqStatusMonitor.cs:32, 74-128)
방식 레벨 미러(매번 덮어쓰기). 조건이 사라지면 별도 클리어 없이 자동으로 내려간다
기동 EquipmentSetup.cs:106 에서 OnStartUp 때 Start
정지 EquipmentSetup.cs:116 에서 OnShutDown 때 Stop

판정 함수 (AlarmManager.cs:172-190)

if (ApplicationExt.IsSimulation) return false;     ← 시뮬은 무조건 false
GetCurrentAlarmCodes() 중 IsAlarmLevelHigh(code)==true 가 하나라도 있으면 true

개별 알람마다 비트를 켜는 게 아니라 활성 알람 전체에 대한 OR 집계다.


3. ★ 어떤 알람이 Level H인지는 소스에 없다

IsAlarmLevelHigh()(AlarmManager.cs:194-201)는 _AlarmService.GetAlarmDescription(code).Level 을 본다. 이 Level 은 Aurora AlarmService 가 런타임에 읽는 알람 설명 데이터에서 오며, 저장소에는 그 파일이 없다 (*larm*.{csv,xlsx,xml,json} 검색 0건 — _out_prismatic_rd_ptop/ 이 .gitignore 대상).

"어떤 알람이 중알람이냐"는 코드가 아니라 설정 데이터가 정한다. 확인하려면 현장 PC의 알람 설명 파일 또는 UI Alarm > Description 화면을 봐야 한다.


4. 상황별 ON / OFF 정리

4-1. ON 되는 경우

# 상황 조건
1 Level H 알람이 새로 발생 리얼 모드 + 활성 알람에 H 1개 이상 → 다음 주기(≈60~80ms)에 ON
2 PLC가 중알람 비트를 올림 PLC_HEAVY_ALARM_STATUS ON → SeqAlarmMonitor.cs:199-201 이 210005 발생 → 그 코드가 H면 §1로 이어져 PC 비트도 ON (PLC 중알람 → PC 중알람 미러링)
3 알람 리셋 후 원인이 그대로 리셋으로 목록이 비어도 감시 루프가 다음 회차에 같은 알람을 다시 올림 → 곧바로 재점등

주요 알람 발생원(발생 자체는 H/L 무관): SeqAlarmMonitor — PLC EMO·Heavy·Light·Door Interlock, Scanner/Laser/LBAD/OCT/Chiller/LeakSensor 상태 · PLCController.LiveStatusUpdate — 210002 · 각 시퀀스 내부 알람.

4-2. OFF 되는 경우

# 상황 조건
1 활성 알람에 H가 하나도 없음 목록이 비었거나 전부 Level L → 다음 주기에 OFF
2 시뮬레이션 모드 AlarmManager.cs:175-176 — 실제 알람이 떠 있어도 무조건 false
3 정상 종료 OnShutDown(EquipmentSetup.cs:115-118) → SeqStatusMonitor Stop → PLC DoDeactivate 의 AllBitClear()(PLCBase.cs:249-250)가 출력 비트를 전부 0으로 만든다

4-3. ⚠ 갱신이 멈춰 마지막 값이 그대로 남는 경우

레벨 미러 방식의 함정이다. 아래 상황에서는 ON/OFF 판정 자체가 일어나지 않는다.

# 상황 결과
1 SeqStatusMonitor 정지·미기동 비트가 갱신되지 않고 직전 값 유지
2 PLC 미연결/미활성 WriteBit 이 E2.NOT_READY/NOT_CONNECTED 로 조용히 반환(PLCBase.APIs.cs:334-341). PLC측은 마지막 값 유지
3 비정상 종료(강제 종료·크래시) AllBitClear() 가 돌지 않아 PLC에 ON이 남을 수 있음

5. 알람 목록이 비워지는 경로 (= 비트가 내려가는 유일한 방법)

AlarmManager.Alarm() 에는 짝이 되는 ClearAlarm 호출이 없다. 원인이 사라져도 알람은 목록에 남고, 따라서 비트도 계속 ON이다. 반드시 명시적 리셋이 필요하다.

경로 흐름
PLC 알람 리셋 PLC_ALARM_RESET(0x1E) 상승엣지 → SeqStatusMonitor.cs:89-92 가 EVENT_RESET_ALL_ALARMS_REQUEST 발행 → AlarmManager.cs:72-77 ClearAllAlarmRequest → _AlarmService.ClearAllAlarm()
UI 알람 리셋 Aurora SYS_ALARM_RESET_ALL_ALARM → AlarmManager.cs:39-41

리셋해도 원인이 살아 있으면 소용없다. 감시 루프가 다음 회차에 같은 알람을 다시 올린다(§4-1 #3). 먼저 원인(EMO·Door·디바이스 단선 등)을 해소한 뒤 리셋해야 비트가 실제로 내려간다.


6. 죽어 있는 경로 — 과거 방식의 잔재

AlarmManager.cs 에 같은 취지의 코드가 4곳 전부 주석 처리되어 있다.

위치 내용
:68-69 ClearAllAlarm → HeavyAlarmStatusAddr, false
:75-76 ClearAllAlarmRequest → HeavyAlarmStatusAddr, false
:99-103 Alarm() → Level H면 true
:134-138 ChangeAlarmDescription() → Level H면 true

:94·:129 주석: "PLC의 중알람의 경우 PC에서 Dialog만 발생하고 Alarm 중알람 Word를 써주지 않는다". 알람 발생 시점 직접 쓰기 → 주기 미러 방식으로 갈아탄 흔적이며, 현재 유효한 건 §2 한 곳뿐이다.


7. 주소

방향 심볼 오프셋 정의
PC→PLC PC_HEAVY_ALARM_STATUS 0x05 PLCController.Address.cs:60 (PTOP)
PLC→PC PLC_HEAVY_ALARM_STATUS 0x05 PLCController.Address.cs:20 (PTOP)
PLC→PC PLC_ALARM_RESET 0x1E PLCController.Address.cs:35 (PTOP)

[추론] M70015/M70515(bit15) 대응 관계를 따르면 각각 M70005 / M70505, 리셋은 M7051E. 메모리맵 CSV로 확인 필요.


8. ⚠ 발견 — 중알람이 떠도 자동운전 시퀀스가 정지되지 않는다

Level H 알람의 또 다른 소비처가 시퀀스 정지인데 대상 시퀀스가 어긋나 있다.

EquipmentSetup.cs:83-85      OnSetAlarm → isHeavy 면 AlarmManager_PTOP.StopSequenceByAlarm(code)
AlarmManager_PTOP.cs:25-27   Level H 면 StopSequence(SequenceIds.SeqAutoRun)     ← 대상

그러나 실제로 도는 자동운전 시퀀스는 SeqAutoRunPTOP 이다.

UCMainAutoRunViewModel.cs:338   //_SeqAutoRun.Start(param, OnCompleteAutoRun);       ← 주석
UCMainAutoRunViewModel.cs:342   _SeqAutoRunPTOP.Start(param, OnCompleteAutoRunPTOP); ← 실제 기동
UCMainAutoRunViewModel.cs:428   //_SeqAutoRun.Stop();                                ← 주석

StopSequence()(AlarmManager.cs:164-169)는 RunState == Running 일 때만 EmergencyStop() 을 호출한다. SeqAutoRun(Prismatic 빌더)은 등록(EquipmentSetup.cs:211)만 되고 한 번도 기동되지 않으므로 조건에 걸리지 않아 아무 일도 일어나지 않는다.

→ 현재는 중알람 시 PC_HEAVY_ALARM_STATUS 비트는 정상 ON 되지만 PC측 자동운전은 계속 돈다. 설비가 서는 것은 PLC가 그 비트를 보고 세우기 때문일 가능성이 크다.

[추론] SeqAutoRunTDC → SeqAutoRunPTOP 전환(260605) 때 AlarmManager_PTOP 가 함께 갱신되지 않은 잔재로 보인다. EquipmentSetup.cs:262 의 AutoRun 뷰 생성자도 아직 SequenceIds.SeqAutoRunTDC 를 넘긴다(다만 VM이 :100-101 에서 ID로 직접 해석하므로 무해).

확인 필요: PLC가 중알람 시 실제로 설비를 세우는가. 세운다면 이중 안전장치 하나가 죽어 있는 상태이고, 안 세운다면 실제 위험이다.


9. 상태

  • 분석만 수행. 소스 미수정.
  • §3(알람 Level 데이터) · §8(시퀀스 정지 대상) 두 건은 확인 필요 상태로 남김.