NohDoyeon241104 e0e5416975 fix: PLC 기동 시 210002 오알람 차단 — Livetimer 초기화 및 모니터 타이머 기동 위치 이동
PLCController.DoActivate() 가 PLC 연결을 열기 전에 _monitorPlcInterfaceMap 을
기동해, 연결 확립 전 LiveStatusUpdate() 가 돌면서
ALARM_DEVICE_PLC_DISCONNECT(210002) 오알람이 매 기동마다 발생했다.

원인
- Livetimer 가 초기화되지 않아 DateTime.MinValue 상태 → (Now - MinValue) 가
  항상 10000ms 를 초과해 워치독이 오판. 임계값 조정으로는 해결 불가.
- MicroTimer 첫 콜백이 주기(100ms) 뒤가 아니라 Start() 직후(약 1ms)라
  경합이 아니라 100% 재현되는 결정적 버그.

실측 (2026-08-10 16:12:25.904)
  Livetimer=0001-01-01, elapsed=63921975145904ms,
  isLive=False, IsActivated=False, IsConnected=False

조치
- _monitorPlcInterfaceMap.Start() 를 base.DoActivate() 성공 이후로 이동
- Livetimer = DateTime.Now 로 기준시각 확보 후 타이머 기동
- 두 조치는 각각 단독으로는 무효. 반드시 함께 적용해야 한다.
- 수정 전/후를 #region 2개(검색: 260810 기동 오알람)로 기록해 원복 가능

검증: 2026-08-10 현장 재기동 확인 — 기동 시 210002 미발생

미해결(별건): Livetimer 이중 용도, ReadBit .err 무시, ClearAlarm 부재,
SeqAlarmMonitor 의 무지연 루프 및 Laser/Chiller 즉시 알람

상세: docs/분석_PLC210002_기동오알람_260810.md
작업일지: docs/작업일지/2026_08_10.md
2026-08-10 16:37:27 +09:00

4.7 KiB

작업일지 — 2026-08-10

1. PLC 기동 오알람 210002 — 원인 확정 및 해결

증상

프로그램 첫 기동 시 PLC 연결이 열리기도 전에 ALARM_DEVICE_PLC_DISCONNECT(210002) 발생. 연결은 곧 붙지만 알람은 남는다(자동 해제 없음). 시뮬 모드에서는 무발생.

210002를 올리는 경로가 2개였음

위치 판정 임계 상태
A PLCController.Config.cs:146 (디바이스, 100ms 타이머) 엣지 — 비트가 바뀌어야 정상 10000ms 활성
B SeqAlarmMonitor.cs:182 (시퀀스) 레벨 — 2초 안에 true면 정상 2000ms 활성
— AlarmMonitoring.cs:169 (공통 시퀀스) — — 죽은 코드
  • AlarmCode_PTOP : AlarmCode(AlarmCode_PTOP.cs:10) 상속이고 210002는 재정의 없음 → A와 B가 같은 코드를 써서 화면만 봐서는 구분 불가.
  • AlarmMonitoring.Builder() 호출처는 SequenceManager.cs:83 주석 한 줄뿐(등록 0건). 주석을 풀어도 동작하지 않는다.

근본 원인

PLCController.Config.cs

  • DateTime Livetimer(:33)가 초기화되지 않아 DateTime.MinValue. 대입 지점은 토글 감지 시(:138) 한 곳뿐이라, 기동 직후에는 값이 들어가지 않는다. → (Now - MinValue)가 항상 10000ms를 초과 → 워치독 오판. 임계값 10000을 20000으로 키우는 방식은 원리적으로 무효(MinValue 앞에서는 어떤 값이든 초과).
  • _monitorPlcInterfaceMap.Start()(:185)가 base.DoActivate()(:187)보다 앞에 있어 연결 확립 전에 타이머가 돌았다. beforeLiveStatus 리셋(:195)도 그보다 뒤.

진단 계측 (적용 → 결과 확보 → 원복 완료)

A/B 중 어느 쪽인지 확정하기 위해 두 곳에 임시 로그를 넣고 재기동. 현장 로그:

16:12:25.903  MicroTimer: timer interval: 100 [ms]
16:12:25.904  E PLCController: [210002][A:PLCController.LiveStatusUpdate]
              Livetimer=0001-01-01 00:00:00.000, elapsed=63921975145904ms,
              isLive=False, beforeLiveStatus=False, IsActivated=False, IsConnected=False
  • Livetimer=0001-01-01 → 미초기화 확정.
  • IsActivated=False, IsConnected=False → 연결 확립 전 발생 확정. 사전에 [추론]으로 달아 뒀던 "Aurora가 IsActivated를 DoActivate 반환 뒤에 세팅한다"도 함께 검증됨.
  • [B:...] 로그 미출현 → A 단독. 시퀀스 계층은 이번 건과 무관.
  • 타이머 기동(.903)과 알람(.904) 간격이 1ms → MicroTimer 첫 콜백이 주기(100ms) 뒤가 아니라 Start() 직후에 발생. 경합이 아니라 100% 재현되는 결정적 버그였다.

계측 코드는 결과 확보 후 전량 원복(.cs 잔존 0건 확인).

로그 파일에서 한글이 깨진다([진단210002] → [ 210002], 위치: → ġ:). 검색어는 210002][ 를 쓸 것.

수정 (최소 수정)

WeldingComponents/WeldingCommon/Devices/PLC/PLCController.Config.cs 의 DoActivate() 1개 메서드만 변경. SeqAlarmMonitor.cs 등 다른 파일 미변경.

  • _monitorPlcInterfaceMap.Start() 를 base.DoActivate() 성공 이후로 이동
  • Livetimer = DateTime.Now 로 기준시각 확보 후 타이머 기동
  • 두 조치는 각각 단독으로는 무효 — 타이머만 옮기면 Livetimer가 여전히 MinValue, 초기화만 하면 타이머가 그 앞에서 이미 발화. 반드시 함께 적용해야 한다.
  • 수정 전/후를 #region 2개로 기록해 원복 가능하게 함 (검색어: 260810 기동 오알람)

부수 효과: Activate 실패 시 타이머가 계속 돌던 문제 해소. [추론] LoadMemoryMapFromFiles() 중 타이머가 같은 맵을 읽던 겹침도 함께 사라진다.

검증

현장 재기동 확인 — 기동 시 210002 미발생. 해결 완료.

잔여 과제 (별건)

  • Livetimer 가 에코 1초 타이머(:130)와 워치독 10초 기준시각(:144)을 겸용하는 구조
  • LiveStatusUpdate 가 ReadBit 의 .err 를 버려 "PLC 미송신"과 "PC 미수신"이 구분 안 됨
  • AlarmManager.Alarm(AlarmManager.cs:79-104)에 짝이 되는 ClearAlarm 이 없어 통신 복구 후에도 알람 잔존
  • SeqAlarmMonitor — WaitTime 무지연 루프(:145-148), Laser/Chiller 즉시 알람(grace 없음), :190-193 _Laser null 시 NRE 위험, InitDev 진입 1회만 실행
  • AlarmMonitoring.cs 죽은 코드 정리
  • Light 디바이스 SerialPort.Open() 실패 (16:12:25.875 E EquipmentSetup: Light connect fail.) — 본 건과 무관, 미확인

산출

  • docs/분석_PLC210002_기동오알람_260810.md (분석 상세)
  • 커밋 대상: 위 분석 문서 + PLCController.Config.cs