같은 펌프를 두 화면이 다르게 표시한다. 개요 화면은 stopped, 정비 리포트는 faulted. 둘 다 raw signal에서 상태를 각자 계산했기 때문이다. 고치는 방법은 상태를 한 곳에서 만들고 판정 우선순위를 문서에 적어 두는 것이다. BadQuality, Unavailable, Faulted, Local, Starting, Stopping, Running, Stopped, Unknown 순으로 위에서부터 보고 처음 걸리는 곳에서 멈춘다. 이 순서가 값을 하는 순간은 통신이 나쁠 때다. Bad quality는 running보다 우선이다.
Raw signal 그대로는 운전 상태가 아니다
현장 장비 하나가 SCADA로 보내는 signal은 생각보다 많다. Run feedback, stop feedback, fault, remote mode, local mode, permissive OK, command active, communication quality, actual speed 같은 값이 따로 들어온다. 운전자가 장애 상황에서 이 값을 머릿속으로 조합하게 만들면 화면 설계가 부족한 것이다.
Derived status tag는 이런 raw signal을 하나의 상태로 정리한다. 이름보다 중요한 것은 정의다. HMI, alarm logic, historian, report가 같은 정의를 써야 한다. ISA-101.01이 말하는 일관된 상태 표현도 결국 화면 규칙이 아니라 상태를 만드는 지점이 하나뿐이라는 뜻이다.
우선순위를 먼저 정하고 문서에 남긴다
설비 상태는 동등하지 않다. Fault는 보통 normal stopped보다 우선이다. Communication bad quality는 독립된 안전 계통에서 상태를 증명하지 않는 한 running 표시보다 우선으로 다루는 편이 안전하다.
Motor 기준으로 위 그림의 아홉 단계는 이렇게 읽는다.
- 필요한 signal이 stale 또는 invalid이면
BadQuality. - 승인된 정비 상태나 out-of-service이면
Unavailable. - Trip 또는 drive fault가 active이면
Faulted. - Remote control이 불가능하면
Local. - Start command가 active이고 run feedback을 기다리면
Starting. - Stop command가 active인데 run feedback이 아직 있으면
Stopping. - Run feedback이 true이면
Running. - 설계상 검증된 stopped feedback이 있거나 run feedback false가 stopped 의미이면
Stopped. - 어떤 정상 조합에도 들어가지 않으면
Unknown.
이 순서는 tag 문서에 남겨야 한다. Script 안에만 있으면 나중에 이상한 표시가 bug인지 의도된 동작인지 알기 어렵다. 실제로 여기서 시간을 제일 많이 버린다.
Raw, normalized, derived tag를 분리한다
Tag model은 층을 나누면 유지보수가 편하다.
| 층 | 예 | 목적 |
|---|---|---|
| Raw input | P101_DI_RunFb, P101_DI_Fault | PLC, I/O, protocol driver에서 받은 원본 값 |
| Normalized input | P101_RunFb, P101_Faulted, P101_Remote | 장비별 polarity와 이름을 정리한 값 |
| Derived status | P101_Status, P101_StatusCode | 화면과 report가 같이 쓰는 설비 상태 |
| Diagnostic detail | P101_StatusReason, P101_LastTransitionTime | 문제 해결에 필요한 설명 |
이렇게 나누면 signal inversion, protocol quality, business logic이 한 화면 expression 안에 섞이지 않는다. Faceplate는 status를 표시해야지, status를 계산하는 유일한 장소가 되면 안 된다.
품질은 특히 raw 층에 남겨 둔다. OPC UA는 값마다 StatusCode를 같이 실어 보내고 Good, Uncertain, Bad를 구분한다. 그 구분을 derived status 안에 녹여 버리면 되돌릴 수 없다.
Text와 numeric code를 같이 둔다
Text는 사람이 보기 좋고 numeric code는 historian, dashboard, MES interface에서 안정적으로 쓰기 좋다. 가능하면 둘 다 둔다.
| Status code | Status text | 설명 |
|---|---|---|
| 0 | Unknown | 유효한 상태가 없거나 입력이 충돌함 |
| 10 | Stopped | 정상 정지 상태 |
| 20 | Starting | Start 명령 후 feedback 대기 |
| 30 | Running | Run feedback으로 운전 증명 |
| 40 | Stopping | Stop 명령 후 feedback 해제 대기 |
| 50 | Faulted | Trip, drive fault, package fault active |
| 60 | Local | Remote command 대상이 아님 |
| 70 | BadQuality | 필요한 signal이 stale이거나 통신 품질 bad |
10 단위로 띄워 둔 이유는 나중에 Unavailable 같은 상태가 늘어나기 때문이다. Code table은 한번 정하면 쉽게 바꾸지 않는다. 50을 Faulted에서 Maintenance로 바꾸는 순간 과거 report와 현재 report가 같은 숫자를 다른 뜻으로 읽는다.
불가능한 조합을 그냥 넘기지 않는다
Field signal은 서로 맞지 않을 수 있다. Valve가 open과 closed를 동시에 줄 수 있다. Motor stopped feedback이 있는데 current는 running 수준일 수 있다. Drive는 running이라고 하는데 PLC 통신 품질은 bad일 수 있다.
이런 조합을 normal state로 흘려보내면 안 된다. 별도 diagnostic state나 reason code를 둔다.
- Valve limit가 둘 다 들어오면
OpenAndClosedFeedback. - Travel time 뒤에도 open/closed 어느 쪽도 아니면
NoEndPosition. - Command 없이 run feedback이 들어오면
RunFeedbackWithoutCommand. - Start 또는 open request 후 feedback이 없으면
CommandedButNoFeedback. - 마지막 update가 허용 시간을 넘으면
FeedbackStale.
정비팀에는 "bad status" 하나보다 이런 reason code가 훨씬 도움이 된다.
Delay는 장비 동작에 맞게 넣는다
Derived status logic에는 delay가 필요할 때가 있다. 접점이 튈 수 있고, VFD는 running bit를 세우기까지 몇 초가 걸릴 수 있다. Pneumatic valve는 움직이는 동안 open도 closed도 아닌 구간을 지난다.
Delay 값은 장비별로 잡는다.
- 노이즈가 있는 discrete input에는 contact debounce.
- Motor, drive, skid 응답 시간에 맞춘 start feedback timeout.
- Actuator 크기와 air supply 상태에 맞춘 valve travel timeout.
- Scan period와 protocol retry 시간을 고려한 communication stale timeout.
- Report bucket이 흔들릴 때만 쓰는 report state hold time.
모든 status에 전역 5초 delay를 넣는 설계를 자주 본다. DOL contactor는 run feedback을 1초 안에 증명하고, ramp가 긴 VFD는 그보다 훨씬 오래 걸린다. 하나의 값으로 둘을 다 맞출 수 없다. 빠른 장비는 답답해지고 느린 장비는 너무 빨리 alarm이 난다.
알람과 리포트에 쓰기 전에 현장에서 확인한다
Derived status를 alarm이나 OEE report의 기준으로 쓰기 전에 실제 전환을 보면서 확인해야 한다.
- Start, stop, fault, reset, local mode, communication loss가 서로 다른 결과를 만든다.
- HMI faceplate, overview graphic, alarm message, historian trend가 같은 status를 보여준다.
- State transition timestamp 기준이 controller인지 SCADA인지 정해져 있다.
- Bad quality가 의도 없이 stopped production으로 집계되지 않는다.
- Maintenance bypass 또는 out-of-service 상태가 화면에 보이고 기록으로 남는다.
- SCADA restart 후 false transition이 생기지 않는다.
가장 좋은 검사는 짧은 transition log다. 같은 시간대에 raw input, derived status, command bit, alarm event를 같이 잡는다. 그 타임라인을 운전자와 제어 엔지니어가 같이 봤을 때 말이 되면 현장에서 쓸 수 있는 모델에 가깝다.
흔한 실수
HMI graphic 안에서만 status를 계산한다. 그러면 trend, alarm, mobile view, report가 각자 다른 로직을 쓴다. PLC, SCADA tag engine, 공통 계산 계층 중 한 곳에서 derived tag를 만들어 공유하는 편이 낫다.
Bad quality를 stopped로 처리한다. 통신 장애를 숨기고 downtime data도 틀어진다. 공장 표준이 따로 있지 않다면 bad quality는 별도 상태로 보여준다.
Local mode를 무시한다. 장비가 정상이어도 remote command 대상이 아닐 수 있다. 운전자는 Stopped와 Local의 차이를 알아야 한다.
Report에서 상태를 다시 만든다. OEE나 MES가 다른 bucket을 필요로 하면 raw bit에서 새로 만들지 말고 공통 status code를 mapping한다.
색상만 보여준다. 회색 motor가 stopped, disabled, local, bad quality, not installed 중 무엇인지 알 수 없다. Derived status에는 읽을 수 있는 label과 diagnostic reason이 있어야 한다.
다음에 확인할 것 하나. 현재 쓰는 status 계산식을 열어서, 통신이 끊겼을 때 어떤 값이 나오는지 손으로 따라가 본다. Stopped가 나오면 그 화면의 downtime 리포트는 이미 틀려 있다.