← 전체 글
트렌드/약 13분 읽기/— 조회

네트워크가 10분 끊겼는데 HMI 트렌드는 왜 직선을 그렸을까

마지막 값 유지, 버려진 quality code, 도착 시간에 찍힌 지연 샘플. 장애 후 트렌드가 거짓말하는 세 가지 원인과 어느 쪽인지 가려내는 방법.

HMI트렌드히스토리언SCADA문제 해결

펌프 토출 압력 펜이 4.18 bar에서 11분 동안 완전히 평평했다. 운전자는 공정이 안정적이라고 봤다. 실제로는 관리형 스위치가 펌웨어 업데이트 후 재부팅 중이었고, 그 11분 동안 SCADA 서버는 아무것도 받지 못했다. 압력은 그 사이에 릴리프까지 올라갔다 왔다.

다음 날 누군가 raw sample을 뽑아 보고 나서야 그 구간에 행이 하나도 없다는 걸 알았다.

이 평평한 선이 트렌드에서 가장 비싼 값을 치르는 결함인데, 히스토리언 탓인 경우는 거의 없다. 원인은 셋 중 하나다. HMI가 펜을 끊는 대신 마지막 값을 유지했거나, 히스토리언이 값은 저장하고 같이 온 quality code는 버렸거나, backfill된 샘플이 측정 시각이 아니라 도착 시각에 찍혔거나. 조치 방법이 각각 다르니 벤더에 티켓을 넣기 전에 어느 쪽인지 먼저 가려야 한다.

먼저: quality가 끝까지 살아왔는가

체인의 모든 계층에 quality 개념이 있고, 모든 계층이 그걸 잃어버릴 기회다. OPC DA는 quality byte를 쓴다. 192는 good, 24는 bad/comm failure, 28은 bad/last known value다. OPC UA는 이걸 32비트 StatusCode로 바꿨고 — Bad_NoCommunication, Bad_OutOfService, Uncertain_LastUsableValue — IEC 62541-8은 Uncertain 상태로 전달된 값을 클라이언트가 측정값처럼 다뤄서는 안 된다고 명시한다.

문제는 하류로 갈수록 quality가 선택 사항이라는 점이다. 값만 저장하고 status는 버리도록 설정된 히스토리언 인터페이스가 흔하다. value만 플롯하고 status 컬럼은 읽지도 않는 트렌드 컨트롤도 흔하다. 둘 중 하나라도 해당되면, 상류에서 아무리 제대로 처리해도 화면에는 나타나지 않는다.

직접 확인하는 게 빠르다. 태그 하나에 일부러 bad quality를 만들고 — 케이블을 뽑거나 OPC item을 out-of-service로 두고 — 그 구간의 raw value를 히스토리언에서 조회해 본다. 그럴듯한 숫자만 있고 status 필드가 없다면 원인을 찾은 것이고, 이건 표시 문제가 아니라 설정 문제다.

마지막 값 유지는 표시 방식의 선택이고, 대개 틀린 선택이다

값이 비면 고장처럼 보이는 개요 화면에서는 마지막 값 유지가 나쁘지 않다. 진단용 트렌드에서는 변명의 여지가 없다. 유지된 펜과 진짜 안정적인 공정은 픽셀 단위로 똑같고, 그 트렌드를 보는 사람은 보통 뭔가 잘못됐기 때문에 보고 있다.

내 기준은 이렇다. 사고 분석 때 엔지니어가 여는 트렌드는 bad quality에서 펜을 끊는다. 점선도, 연한 색도 아니고 공백이다. 점선은 트렌드를 캡처해서 60% 크기로 메일에 붙이는 순간 사라진다. 공백은 캡처에서도 살아남는다.

Stale은 bad와 다른 경우다. 구독이 30초째 갱신되지 않아서 마지막 값을 보여 주는 거라면, 화면에 그렇게 적혀 있는 한 정직하다. 값 옆에 작은 "stale" 표시나 경과 초를 붙이면 된다. 하면 안 되는 건 조용히 유지하는 것이다.

늦게 온 샘플은 원래 timestamp 자리에 들어가야 한다

시운전 때 안 걸리는 결함이다. 장애가 나야 드러나기 때문이다. 장애 동안 edge gateway가 버퍼링하고, 링크가 복구되고, 버퍼가 쏟아지고, HMI는 복구된 한 시간치 데이터를 현재 시각에 수직에 가까운 스파이크로 그린다.

원인은 대부분 쓰기 경로가 샘플에 딸려 온 timestamp 대신 서버 수신 시각을 쓰기 때문이다. OPC UA는 SourceTimestamp와 ServerTimestamp 두 개를 준다. history write는 SourceTimestamp를 기준으로 해야 한다. Sparkplug B가 metric마다 payload에 timestamp를 싣는 이유도 같다. 받는 쪽이 그걸 무시하면 gateway의 store-and-forward는 아무 의미가 없다.

다시 그리지 않는 문제도 있다. 별개지만 못지않게 흔하다. HMI가 데이터가 아직 없을 때 그 구간을 조회해서 결과를 캐시했고, 그 뒤로 다시 조회하지 않는 경우다. 히스토리언에는 이미 값이 채워졌는데 화면만 공백이고, 누군가 시간 범위를 바꿨다가 되돌리기 전까지 그대로다. 트렌드 컨트롤에 캐시를 무효화할 방법이 없다면 화면에 refresh 버튼을 눈에 띄게 놓고 언제 누르는지 운전자에게 알려 줘야 한다.

어디까지 복구 가능한지 숫자로 알고 있어야 한다

Backfill은 샘플이 어딘가에 남아 있어야만 된다. 그런데 현장의 버퍼 깊이는 자릿수가 세 개쯤 차이난다. PLC 데이터 블록은 보통 현재값 하나뿐이다. Edge gateway는 한 시간일 수도 있고 디스크가 찰 때까지일 수도 있다. 버퍼링을 켠 PI나 FactoryTalk Historian 인터페이스 노드는 디스크가 허락하는 한 며칠도 버틴다. 이 숫자를 외우고 다니는 사람은 없다. 그래서 네트워크 도면에 해당 링크 옆에 적어 두는 게 맞다.

데이터 경로마다 적을 것: 샘플이 어디에 버퍼링되는지, 시간이나 레코드 수의 상한, 넘칠 때 오래된 것을 버리는지 새 것을 거부하는지, 그리고 flush할 때 source timestamp와 quality를 보존하는지. 마지막 항목이 다들 그냥 그러려니 하고 넘어가는 부분이다.

효과는 작업 계획할 때 나온다. 스위치 교체가 4시간인데 gateway 버퍼가 1시간이면, 트렌드의 3시간 공백은 받아들이기로 결정한 결과이지 다음 주 생산 리포트에서 튀어나오는 사고가 아니다.

복구 구간을 조용히 망가뜨리는 두 가지

압축. Swinging-door나 exception/deviation 압축을 쓰는 히스토리언은 들어오는 스트림의 모양을 보고 무엇을 남길지 정한다. Backfill 샘플이 순서가 뒤섞인 채로 몰려 들어오면 같은 샘플이 실시간으로 들어올 때와 다르게 평가될 수 있다. 그리고 가장 보고 싶은 전환점 — 장애 구간의 이탈 — 이 바로 deviation 필터가 버리기 쉬운 점이다. 사고 분석에 쓰는 태그라면 재생된 버스트에 압축이 무슨 짓을 하는지 먼저 확인하고 믿어야 한다.

타임존과 서머타임. UTC로 저장하고 표시할 때 변환한다. 로컬 시간으로 저장하는 시스템은 언젠가 반드시 backfill 데이터에서 한 시간 오차를 낸다. 가을 DST 되감기 때는 같은 시각이 실제로 두 번 생기는데, 트렌드에서는 중복 샘플이 겹친 것처럼 보인다. PLC나 gateway에 타임존 개념이 없어서 로컬 시간으로 찍는다면, 변환 지점을 체인 안에서 한 곳으로 정하고 문서에 남겨야 한다. 안 그러면 두 엔지니어가 변환을 두 번 건다.

체인 전체가 같은 시계를 보는지도 확인한다. 공통 소스로 NTP는 최소 조건이고, 장비 간 sequence-of-events 분석을 한다면 IEEE 1588(PTP)가 답이다. 변전소 쪽이면 IEC 61850-5가 정확도 등급 기준을 제시한다.

시운전 때 일부러 끊어 본다

첫 실제 장애가 첫 시험이 되면 안 된다. 20분이면 된다.

  1. 태그 세 개를 고른다. 빠른 analog, 느린 analog, discrete state.
  2. 정상 상태에서 기준 트렌드를 저장한다.
  3. 정해진 시간 동안 링크를 끊는다. 폴링 주기보다 충분히 길게, edge 버퍼 안에는 들어오게.
  4. 안전하다면 장애 중에 값을 움직인다. 아무것도 안 움직인 backfill 시험은 증명하는 게 거의 없다.
  5. 링크를 복구하고 live 값이 다시 들어오는지 확인한다.
  6. 누락 구간이 올바른 timestamp에 backfill되는지, 아니면 공백으로 남는지 확인한다. 그 외는 전부 버그다.
  7. timestamp, value, quality를 포함한 raw sample을 export해서 소스와 대조한다.

그 다음에 버퍼보다 긴 장애로 한 번 더 돌려서, 복구 불가능한 공백이 화면에 어떻게 보이는지 확인한다. 운전자가 그 모양을 알아볼 수 있어야 한다.

생산 리포트가 같은 히스토리언을 쓴다면 교대 경계에서도 한 번 해 본다. 06:00을 걸치는 공백에서 교대 적산값이 조용히 0을 대입하고 있다는 사실이 드러난다.

운전 화면에 필요한 것

메커니즘까지는 필요 없다. 지금 보는 구간을 믿어도 되는지만 알면 된다. 눈에 보이는 공백, 장애 구간 marker, stale 표시, refresh 동작, 통신 상태 화면 링크 정도면 충분하다.

거기에 하나 더 붙일 값어치가 있는 건 backfill 대기 표시다. 이게 없으면 복구 2분 뒤에 트렌드를 본 운전자가 공백을 보고 데이터가 영영 없어졌다고 판단하고 더 안 본다. 10분 뒤에 히스토리언이 채워 넣었는데 아무도 다시 보지 않는다.