← 전체 글
HMI/약 11분 읽기/ 조회

HMI에서 모드와 상태를 한 칸에 합치면 안 되는 이유

모드는 누가 명령할 수 있는가, 상태는 지금 뭘 하고 있는가다. SEMI E30 GEM 제어 상태 모델에 맞춰 HMI 표시 칸을 나누는 방법과 커미셔닝 확인 항목.

HMISCADA알람문제 해결프로젝트 노트체크리스트

새벽 두 시에 설비가 멈춰 있다. HMI에는 "정지"라고만 떠 있다. 작업자가 세운 건지, LOCAL이라 호스트 명령을 안 받은 건지, 인터록에 걸린 건지, 통신이 끊겨서 30분 전 값이 그대로 굳어 있는 건지는 화면 어디에도 없다. 여기서 무전이 시작되고 20분이 날아간다.

데이터가 없어서 생기는 문제가 아니다. 축을 합쳐 놔서 생기는 문제다. 모드는 "누가 명령할 수 있는가"고 상태는 "지금 실제로 뭘 하고 있는가"다. 둘은 독립이고, 조합이 이상해질 때 비로소 값어치가 생긴다. SEMI E30(GEM)은 이 구분을 아예 별도의 상태 모델 두 개로 못 박아 뒀다 — control state model이 모드 축, processing state model이 상태 축이다. 호스트 쪽 코드가 이미 두 축으로 돌아가는데 HMI만 한 칸으로 합치면, 있는 정보를 화면에서 버리는 셈이다.

GEM control state model: OFFLINE 아래에 EQUIPMENT OFFLINE, ATTEMPT ONLINE, HOST OFFLINE이 있고 ONLINE 아래에 LOCAL과 REMOTE가 있다. 호스트는 S1F17로 ONLINE을, S1F15로 OFFLINE을 요청한다. LOCAL은 호스트 조회에는 응답하지만 remote command는 거절하고, REMOTE는 명령을 수락한다. 모드 축 — GEM control state model (SEMI E30) OFFLINE ONLINE EQUIPMENT OFFLINE ATTEMPT ONLINE HOST OFFLINE LOCAL REMOTE S1F17 S1F15 명령은 거절, 조회는 응답 명령 수락

모드 축은 이미 표준이 그려 놨다

GEM control state model은 위 그림이 전부다. OFFLINE 아래에 EQUIPMENT OFFLINE, ATTEMPT ONLINE, HOST OFFLINE이 있고, ONLINE 아래에 LOCAL과 REMOTE가 있다. 둘을 가르는 기준은 딱 하나다. LOCAL은 호스트 조회에는 응답하지만 remote command는 거절한다. REMOTE는 명령을 수락한다. "왜 호스트에서 START가 안 먹히나"의 절반은 알람 문제가 아니라 이 한 칸을 화면에 안 띄운 탓이다.

호스트가 ONLINE을 요청할 때 쓰는 게 S1F17이고 응답이 S1F18(ONLACK)이다. 반대 방향은 S1F15 / S1F16. 여기서 호스트 개발자가 제일 자주 밟는 지뢰가 ONLACK 처리다. 0은 수락이지만, 0이 아닌 값이 전부 "장비가 응답 안 함"은 아니다. 이미 ONLINE인 장비에 S1F17을 다시 던지면 "이미 온라인"이라는 별도 응답이 돌아오는데, 이걸 실패로 묶어서 재시도 루프를 도는 코드를 여러 번 봤다. 거절과 이미-온라인은 다른 사건이다. 값별로 나눠서 처리해야 한다.

축은 사실 세 개다. communication state model이 따로 있다 — DISABLED / ENABLED이고 ENABLED 안에 NOT COMMUNICATING과 COMMUNICATING이 있다. HSMS 세션이 붙은 것, GEM이 COMMUNICATING인 것, control state가 ONLINE인 것은 전부 다른 사실이다. 소켓은 살아 있는데 S1F13 / S1F14가 안 끝나서 COMMUNICATING이 아닐 수 있고, COMMUNICATING인데 LOCAL이라 명령이 안 먹힐 수 있다. HMI에 "통신 정상" 램프 하나만 놓으면 이 셋이 한 칸으로 뭉개지고, 뭉개진 칸은 정확히 이상할 때 못 읽는다.

상태 축은 반대다. E30은 processing state model의 값을 정해 주지 않는다. 장비가 자기 모델을 정의하고 GEM manual에 문서화하도록 요구할 뿐이다. Idle / Setup / Ready / Executing 같은 이름이 장비마다 다른 건 그래서고, 호스트가 문자열을 하드코딩하면 다음 장비에서 깨진다. 여기에 SEMI E10이 또 다른 축으로 겹친다 — 가동률 계산용 6개 기본 상태(Non-Scheduled, Unscheduled Downtime, Scheduled Downtime, Engineering, Standby, Productive)다. E10 상태는 processing state에서 유도하는 값이지 같은 값이 아니다. 한 칸에 몰아넣으면 나중에 가동률 숫자를 놓고 싸운다.

화면에 필요한 칸은 다섯이다

예시답해 주는 질문
ModeOnline Remote지금 누가 명령할 수 있나
StateStarting설비가 지금 뭘 하고 있나
Command기동 요청, 시퀀스뭘 시키려는 중인가, 누가 시켰나
Blocked by토출 밸브 열림 아님왜 아직 안 되나
Fault드라이브 고장손 대기 전에 뭘 풀어야 하나

실제로 무전을 줄이는 건 Blocked by 한 칸이다. "기동 실패" 알람은 이미 늦었고 원인도 안 알려 준다. "토출 밸브 열림 아님"은 작업자가 그 자리에서 다음 행동을 정할 수 있다. 퍼미시브 전체 목록을 개요 화면에 뿌릴 필요는 없다. 실패한 조건만, 위에서부터 하나. 전체 목록은 팝업으로 미뤄 두고 시운전 때만 펼치면 된다.

통신이 끊긴 걸 정지로 그리지 마라

가장 흔한 버그는 화면 스크립트의 default case다. PLC 상태값이 정의 안 된 숫자로 오거나, 통신이 끊겨 0이 남으면, 표시는 "정지"로 떨어진다. 정지는 정상 상태라 색도 조용하고 알람도 안 난다. 그래서 아무도 눈치채지 못한다.

이건 화면에서 고칠 문제가 아니라 태그에서 고칠 문제다. 판정 우선순위를 태그 쪽에 먼저 박아 둬야 한다 — 파생 상태 태그에서 정리한 대로 BadQuality가 Running보다 위에 있어야 한다.

내 기준 하나. 모르는 값은 회색으로 칠하지 않는다. 회색은 이미 유지보수 모드가 쓰고 있다. 사선 해칭에 "값 없음"을 붙이면 작업자가 최소 한 번은 물어보게 되고, 그게 맞다. 조용히 정상처럼 보이는 것보다 낫다.

커미셔닝에서 실제로 해보는 것

한 대만 보지 말고 설비 클래스마다.

  • PLC 상태값을 전 범위로 강제로 넣어 본다. 정의 안 된 값이 "정지"가 아니라 "값 없음"으로 나오는지 확인한다.
  • 통신 케이블을 뽑는다. 화면이 몇 초 만에 바뀌는지, 정지와 눈으로 구분되는지 본다.
  • 퍼미시브를 하나씩 false로 만들고 Blocked by 문구가 맞는지 본다. 목록 순서를 바꾸면 엉뚱한 조건이 뜨는 구현이 많다.
  • 장비를 LOCAL에 놓고 호스트에서 remote command를 보낸다. 화면이 "LOCAL이라 거절됨"이라고 말하는지, 그냥 아무 일도 안 일어나는지 본다. 후자면 칸이 모자란 것이다.
  • 기동 실패 타이머를 실제 지연 시간으로 시험한다. 책상에서 정한 3초는 대개 짧다.
  • 모드 변경이 이벤트로 남는지, 누가 언제 바꿨는지가 같이 남는지 본다.

마지막 항목이 나중에 제일 자주 쓰인다. "누가 원격을 껐나"는 로그가 없으면 끝나지 않는 논쟁이다.

남는 문제 하나

HMI의 모드 칸과 호스트가 들고 있는 control state는 같은 사실을 두 번 그린 것이다. 둘이 다르게 보이는 순간은 반드시 온다. 장비가 LOCAL로 넘어갔는데 호스트는 아직 REMOTE라고 알고 있는 구간이 대표적이다. 그래서 양쪽 다 timestamp와 출처를 달아 이벤트로 남겨야 한다. 나중에 알고 싶은 건 어느 쪽이 틀렸느냐가 아니라 언제 갈라졌느냐다.

호스트 코드를 붙여서 이 전이를 직접 눌러 보고 싶으면 SECS/GEM 시뮬레이터에 HSMS로 연결해서 시험할 수 있다.