← 전체 글
히스토리언/약 17분 읽기/ 조회

히스토리언은 왜 압력 하락을 trip 뒤로 찍는가

SCADA 히스토리언 타임스탬프가 틀어지는 원인 — 클록 드리프트, NTP와 PTP, OPC UA 소스 시간, 지연 데이터, 서머타임 — 을 보고서 분쟁 전에 잡는 법.

히스토리언SCADA문제 해결네트워킹트렌드

컴프레서가 trip 한다. PLC는 그 trip 이벤트를 09:58:12로 찍는다. 곧 토출 압력이 무너지고, SCADA는 그 하락을 수신 시각 10:02:40으로 찍는다. 이제 보고서는 압력이 기계 trip 뒤 4분 반이 지나서 떨어진 것처럼 말한다. 물리적으로 말이 안 되는 이야기다. 신뢰성 담당자는 있지도 않은 두 번째 고장을 찾아 헤맨다. 두 시계가 4분 어긋나 있었을 뿐이다. 공정에는 문제가 없었고, 틀린 것은 공정 이야기였다.

타임스탬프가 틀린 히스토리언 값은 살짝 어긋난 계측값이 아니다. 그런데도 깨끗한 트렌드 선을 그려내는 가짜 계측값이고, 신뢰할 만해 보이기 때문에 더 나쁘다. 보고서, 배치 이력, first-out 알람 분석, 정지 시간 집계가 그 오류를 그대로 물려받는다.

함정은 히스토리언이 시간을 소유한다고 여기는 것이다. 그렇지 않다. 센서에서 트렌드까지 오는 동안 값은 PLC, 엣지 게이트웨이, OPC UA 서버, MQTT publisher, SCADA 드라이버, 또는 히스토리언 저장 시각 중 어디서든 찍힐 수 있고, 그중 무엇이든 틀린 시계 위에서 돌 수 있다.

센서에서 트렌드까지 값이 받을 수 있는 타임스탬프와, 컴프레서 예에서 PLC의 trip 스탬프와 SCADA 수신 스탬프가 4분 어긋난 지점 센서에서 트렌드까지 PLC / 장치 시간 엣지 게이트웨이 시간 OPC UA SCADA 수신 시간 히스토리언 저장 시간 SourceTimestamp 09:58:12 10:02:40 두 시계가 4분 어긋나

누가 값을 찍었는가

히스토리언 설정을 하나라도 만지기 전에, 각 데이터 경로에서 시간이 어디서 오는지부터 정한다. 이 질문이 하류의 모든 것을 결정한다.

시간 출처맞는 곳물리는 지점
PLC / 장치 시간시퀀스 이벤트, 배치 마커, 빠른 tripPLC 시계가 밀리면 모든 이벤트가 같이 밀린다
엣지 게이트웨이 시간MQTT / 프로토콜 변환도착 시 재스탬프하며 장치 시계 오류를 가린다
OPC UA SourceTimestampOPC UA 서버에서 받은 값서버 품질에 달렸다. ServerTimestamp는 도착 시각이지 공정 시각이 아니다
SCADA 수신 시간단순 폴링 드라이버폴링 주기와 네트워크 지연이 타임스탬프에 섞여 들어간다
히스토리언 저장 시간마지막 fallback"언제 도착했나"에는 되지만 "언제 일어났나"에는 못 쓴다

공장 전체에 맞는 하나의 정답은 없다. 보호 계전 trip은 그것을 본 장치의 소스 시간이 필요하다. 10초마다 읽는 탱크 레벨은 SCADA 수신 시간으로 충분하다. 폴링 지터 200 ms는 분 단위로 움직이는 레벨 옆에서는 잡음이다. 중요한 건 그 선택이 드라이버 기본값이 아니라 의도된 것이고 문서에 남아 있다는 점이다.

OPC UA에서 꼭 확인할 것 하나. 구독은 SourceTimestampServerTimestamp를 둘 다 돌려주는데, 히스토리언마다 어느 쪽을 저장하는지 다르다. 보통은 SourceTimestamp를 원한다. 수집기가 조용히 ServerTimestamp를 저장하고 있다면, 자기도 모르는 사이 모든 값을 수신 시간으로 바꿔 놓은 것이다.

시간 구조는 하나로 잡고 보이게 만든다

작은 시스템은 시간 동기가 우연히 자란다. 이 서버는 도메인 컨트롤러를, 저 서버는 pool.ntp.org를, PLC는 출하 기본값을 본다. 시운전은 지나가지만 조용히 썩는다. 방화벽이 UDP 123을 막거나, 도메인 컨트롤러가 교체되거나, 격리된 장비가 8개월 동안 아무도 모르게 밀린다.

실제로 유지보수 가능한 구조는 계층이 분명하다.

  1. 현장에서 승인한 기준 하나 — PPS 출력이 있는 GPS, 도메인 계층, 또는 관리되는 NTP 장비. 하나를 골라 루트로 삼는다.
  2. SCADA, 히스토리언, 브로커 서버가 그 기준에 동기화한다.
  3. 지원하는 PLC, 게이트웨이, 현장 장치가 동기화한다.
  4. "동기 실패"뿐 아니라 offset을 알리는 모니터링.

네 번째를 사람들은 건너뛰고, 그게 바로 살려주는 항목이다. NTP 데몬은 멀쩡히 돌지만 기준에서 900 ms 벗어난 장치는 정상이라고 보고한다. 동기가 완전히 끊길 때만이 아니라 offset이 임계값을 넘으면 알람을 걸어라. SCADA LAN에서는 100 ms를 쓰고, 사이트가 SOE 작업을 한다면 더 조인다.

동기 방식 자체는 이렇다. 괜찮은 LAN 위의 일반 NTP는 수십 ms를 유지하고, 대부분의 히스토리언 트렌드에는 그걸로 충분하다. 여기서 늘 실망시키는 게 Windows w32time이다. 기본 도메인 설정은 공정 데이터가 아니라 Kerberos용으로 만들어져 수백 ms 벗어나기도 한다. 중요한 서버는 도메인 기본값을 믿지 말고 실제 NTP 소스를 보게 하고 offset을 확인하라. 밀리초 이하 정렬이 정말 필요하다면 — 여러 bay에 걸친 SOE, 라인축 모션, IEC 61850 sampled value — 그건 PTP(IEEE 1588)이고, 스위치가 boundary/transparent clock으로 받쳐줘야 제대로 나온다. 엄격해 보인다는 이유로 PTP를 넣지 마라. 요구사항이 거기까지 몰고 갔을 때만 넣어라.

드리프트는 천천히 소설을 쓴다

맨 위 컴프레서 예가 실패 방식의 전부다. 몇 분 밀린 시계는 아무것도 죽이지 않고, 원인과 결과만 다시 쓴다. 그리고 아무 알람도 없으니, 1년 뒤 보고서 분쟁이 났을 때 — 컨트롤러가 내내 4분 빨랐다는 사실을 그제야 — 알게 된다.

시운전 때 싸게 잡아라. SAT에서 PLC 시간과 SCADA 서버 시간을 직접 비교하고 그 offset을 번호가 붙은 항목으로 기록하라. "통신 OK" 밑에 묻지 마라. 전원 재투입과 펌웨어 업데이트마다 다시 확인하라. 배터리 백업 RTC가 없거나 죽은 장치는 epoch로 돌아오거나 닿는 아무 소스에서나 다시 맞춘다. 로컬 시간을 쓰는 PLC라면 서머타임 전환을 정확히 어떻게 처리하는지 확인한 뒤에 그 스탬프를 믿어라. 플랫폼이 허용하면 내부는 UTC로 두고 장치 단에서 서머타임을 아예 생각하지 마라.

어떤 프로토콜은 드리프트 점검을 공짜로 준다. DNP3 outstation은 IIN1.4(NEED_TIME) 비트를 세워 시계를 맞춰 달라고 master에게 알리고, master는 time-sync write로 응답한다. 이 비트가 계속 켜져 있으면 동기가 깨진 것이고 outstation이 그걸 알고 있다는 뜻이다. 지켜봐라.

시간대: UTC로 저장, 로컬로 표시, 전환을 테스트

저장과 표시는 각각 시간대를 명확히 해야 하고, 안전한 방식은 지루하다. UTC로 저장하고, 표시와 리포트 계층에서만 사이트 로컬로 변환한다. 그 규율이 흔들릴 때 문제가 시작된다.

  • offset 없는 로컬 시간을 저장해, fall-back 전환 때 01:30이 정말로 모호해진다.
  • 한 테이블에 UTC와 로컬 행이 섞여 있고 어느 쪽인지 알려주는 컬럼이 없다.
  • 리포트 계층이 이미 한 번 한 시간대 변환 위에 한 번 더 적용한다.
  • 알람 로그는 이 기준, 트렌드는 저 기준으로 두고 나란히 비교한다.
  • CSV 내보내기에 시간대 표시가 없어, 자기 시간대로 가정하는 고객에게 메일로 나간다.

제품이 로컬 저장을 강제한다면 어쩔 수 없다. 대신 그 사실을 문서화하고, 믿기 전에 spring-forward와 fall-back 전환에 값을 실제로 통과시켜 봐라. "서머타임은 처리될 것"은 테스트 결과가 아니다.

지연 데이터와 순서가 뒤집힌 데이터

store-and-forward 게이트웨이, MQTT 수집기, 불안정한 무선망은 전부 데이터를 늦게 올려보내고, 히스토리언마다 이걸 어떻게 처리할지 크게 다르다. 운영 전에 구체적인 답을 받아라.

  • 그 태그에 더 새로운 데이터가 이미 있는데 더 오래된 timestamp를 받을 수 있는가?
  • 같은 태그, 같은 시간, 새 값 — overwrite, reject, duplicate 중 무엇인가?
  • compression과 deadband가 backfill 데이터에도 같은 방식으로 적용되는가?
  • 과거 구간에 backfill이 들어오면 보고서가 다시 계산되는가, 아니면 오래된 결과를 내는가?
  • 최대 허용 나이가 있는가, 그걸 넘긴 샘플은 어떻게 되는가?

이 전부를 드러내는 시나리오. 원격 펌프장이 끊긴 링크 동안 네 시간을 버퍼링하다가 복구되자 한꺼번에 쏟아낸다. 이건 원래 timestamp를 단 네 시간짜리 과거 데이터로 저장돼야 한다. 순진한 수집기가 하는 것처럼 "지금" 네 시간이 한 순간에 몰려 들어오면 안 된다. 그러면 한 시각에 샘플 벽이 생긴다.

알람과 first-out은 순수한 타임스탬프 문제다

알람 분석은 1초의 skew가 더 이상 장식이 아니게 되는 지점이다. 느린 트렌드에서 1초는 아무것도 아니다. trip에서 1초는 first-out 알람 순서를 바꾸고, first-out은 분석의 전부다. 그걸 믿기 전에, 알람 시간이 어디서 찍히는지(PLC, SCADA 알람 엔진, 히스토리언), 확인 시간과 복귀 시간이 같은 시계를 쓰는지, 이중화 알람 서버가 충돌하는 이벤트 시간을 어떻게 조정하는지, SOE 모듈이 자체 동기 경로를 갖는지(많은 경우 SCADA급 NTP로는 부족해서 IRIG-B나 PTP를 쓴다), 운전자 워크스테이션 시간이 감사 로그에 새어 들어가는지 알아야 한다.

원인 분석이 정말 중요한 설비라면, 동기화된 출처에서 나온 정의된 first-out 기준을 써라. 동기화되지 않은 로그 더미에서 첫 원인을 추측하는 건 절차만 늘어난 추측이다.

오후 한 나절이면 하는 시간 테스트

동기가 된다고 가정하지 말고, 시운전 때 한 번 증명하고 그 결과를 프로젝트 파일에 남겨라.

  1. 히스토리언, SCADA 서버, 엔지니어링 PC, PLC, 게이트웨이, 브로커 서버의 현재 시간을 한꺼번에 기록한다.
  2. 장치가 노출하는 곳마다 NTP/PTP 상태와 현재 offset을 확인한다.
  3. 테스트 태그를 강제로 바꾸고 트렌드 timestamp가 기대한 출처와 맞는지 확인한다.
  4. store-and-forward 장치의 네트워크를 뽑았다 복구하고 지연 데이터가 어떻게 저장되는지 본다.
  5. 트렌드 구간을 CSV로 내보내 시간대가 모호하지 않은지 확인한다.
  6. 알람 이벤트, 그 공정값, PLC 시퀀스 마커를 나란히 놓고 순서를 확인한다.
  7. 장치 하나를 재부팅하고, 운영 데이터를 publish하기 전에 올바른 시계로 돌아오는지 확인한다.

어떤 히스토리언 경로든 세 가지 답이 필요하다. 누가 값을 찍었는가, 그 시스템은 어떤 시계로 도는가, 데이터가 늦게 오면 어떻게 되는가. 셋을 다 답할 수 없으면 트렌드는 그래도 선을 그린다. 다만 그 선이 사실을 말하는지 아닌지를 당신이 모를 뿐이다.