일어나지 않은 음의 유량
일일 보고서에 원수(原水) 미터가 밤새 −429만 갤런을 흘려보냈다고 찍힌다. 거꾸로 흐른 것은 아무것도 없다. 미터의 펄스 카운트가 32비트 레지스터의 꼭대기 4,294,967,295에 도달해 0으로 랩어라운드했고, 적산기가 새 값 - 이전 값을 계산해 카운터 전체 크기만 한 숫자를 앞에 마이너스를 붙여 뱉은 것이다.
보고서에 들어가는 SCADA 데이터의 상당수는 이런 카운터에서 나온다. 유량계 펄스 카운트, 전력량 kWh 적산값, 가동 시간계, 포장 라인의 생산 수량 같은 것이다. 장치는 오직 증가만 하는 숫자를 갖고 있고, 두 샘플의 차이를 사용량으로 읽는다. 카운터가 범위의 꼭대기에 도달해 0으로 되돌아가기 전까지는 잘 돌아간다. 그 뒤로는 누군가 그 모양을 알아챌 때까지 하류의 모든 적산이 틀린다.
해결은 작지만, 반드시 한 곳에서만 살아야 하고, 원시 태그가 절대 담지 않는 두 가지를 알아야 한다. 카운터의 폭이 얼마인지, 그리고 값이 내려간 것이 롤오버인지 리셋인지다.
레지스터 폭을 알아라
카운터는 데이터 타입의 꼭대기에서 랩어라운드한다. 그 천장을 모르면 롤오버를 올바르게 계산할 수 없다.
| 폭 | 최대값 | 랩어라운드 지점 |
|---|---|---|
| 16비트 부호 없음 | 65,535 | 65,536 |
| 32비트 부호 없음 | 4,294,967,295 | 4,294,967,296 |
| 32비트 부호 있음 | 2,147,483,647 | 음수로 넘어갔다가 되돌아옴 |
| 64비트 부호 없음 | 약 1.8 × 10^19 | 실무상 사실상 없음 |
바쁜 펄스 입력의 16비트 카운터는 몇 분 만에 랩어라운드할 수 있다. 같은 입력의 32비트 카운터는 1년에 한 번쯤 랩어라운드할 수 있다. 64비트 카운터는 플랜트 수명 동안 사실상 랩어라운드하지 않는다. 폭은 현장 장치와 레지스터 매핑 방식이 정하는 속성이며, 태그 옆에 기록해야 할 가장 중요한 사실이다.
여기에 함정이 둘 있다.
- 32비트 카운터를 Modbus로 읽으면 두 개의 16비트 레지스터로 도착한다. 워드 순서가 틀리면 쓰레기 값이 나오고, 하위 워드가 랩어라운드할 때마다 롤오버처럼 보일 수 있다. 값을 믿기 전에 바이트·워드 순서를 확인하라.
- 어떤 장치는 내부적으로 32비트 카운터를 두면서도 하위 16비트만 게시한다. 그러면 데이터시트가 32비트라고 해도 65,536에서 롤오버가 보인다. 카탈로그가 아니라 실제 회선을 믿어라.
랩어라운드를 넘는 델타 계산
적산 로직의 본질은 랩어라운드하는 원시 카운트를 단조 증가하는 사용량 수치로 바꾸는 것이다. 연속된 두 읽기값 사이의 델타는 보통 새 값 - 이전 값이다. 카운터가 랩어라운드하면 새 값은 작고 이전 값은 크므로 차이가 음수가 된다. 보정은 카운터의 전체 범위를 다시 더해 주는 것이다.
델타 = 새 값 - 이전 값
if 델타 < 0:
델타 = 델타 + 카운터_범위 # 카운터_범위 = 65536, 4294967296, ...
이 가드 하나가 깔끔한 롤오버를 처리한다. 카운트가 꼭대기 근처에서 바닥 근처로 갔고, 범위를 더하면 실제 증가분을 복원한다. 이 가드는 사용량 태그를 만드는 계산 태그 식이나 엣지 로직 안에 두고, 이 값을 읽는 모든 보고서에 흩어 놓지 마라. 한 곳, 한 규칙.
여기에는 미묘한 가정이 하나 깔려 있다. 두 읽기 사이에 카운터가 최대 한 번 랩어라운드했다는 것이다. 폴 주기가 느려서 빠른 카운터가 두 번 랩어라운드할 수 있다면, 범위 보정 한 번으로는 부족하고 매번 한 범위만큼의 카운트를 조용히 잃는다. 최대 카운트 속도에서도 한 주기에 랩어라운드가 최대 한 번만 일어나도록 샘플 주기를 잡거나, 이 문제가 절대 생기지 않을 만큼 자주 읽어라.
롤오버 대 리셋
카운트가 내려간 것은 아주 다른 두 가지를 뜻할 수 있고, 적산기는 둘을 같게 다루면 안 된다.
- 롤오버: 카운터가 천장에 도달해 랩어라운드했다. 실제 증가분은
새 값 + 범위 - 이전 값이다. 범위를 더한다. - 리셋: 누군가 미터를 지웠거나, 장치가 재부팅했거나, 정비 작업으로 적산기를 0으로 만들었다. 더할 잃어버린 범위가 없다. 올바른 증가분은 보통 그냥
새 값(0부터 올라감)이거나, 그 구간을 버리고 싶다면 0이다.
숫자만으로 둘을 구별하는 것이 늘 가능하지는 않으니 맥락을 써라.
이전 값이 범위의 꼭대기 근처였고새 값이 바닥 근처라면, 이 패턴은 롤오버에 맞는다.이전 값이 범위의 중간이었고새 값이 0 근처라면, 이는 랩어라운드가 아니라 거의 확실히 리셋이다.- 장치 재기동이나 통신 복구 플래그가 가장 강한 신호다. outstation이 재부팅을 보고하면, 복구 후 첫 델타를 랩어라운드가 아니라 리셋으로 다뤄라. DNP3는 이를 장치 재기동 표시로 노출하며, 많은 PLC는 첫 스캔 또는 전원 투입 비트를 준다.
어느 쪽으로든 틀리게 추측하면 실제 오류가 된다. 리셋을 롤오버로 다루면 한 범위만큼의 가짜 사용량을 주입하고, 롤오버를 리셋으로 다루면 한 범위만큼의 실제 사용량을 잃는다. 애매하면 거대한 숫자를 지어내기보다 애매한 구간을 버리는 편을 택하고, 검토 대상으로 표시하라.
나쁜 품질과 공백 처리
롤오버 로직은 믿을 만한 이전 값이 있다고 전제한다. 통신 공백은 그 전제를 깨뜨린다. 회선이 끊겨 여러 읽기를 놓쳤다면 그 사이 카운터가 몇 번 랩어라운드했는지 알 수 없으므로, 공백을 넘는 델타는 추측이다.
현실적인 처리.
- 두 개의 양호 품질 연속 샘플 사이에서만 델타를 계산한다. 이전이나 새 샘플 중 하나라도 나쁜 품질이면 그 구간을 적산하지 말고, 표시한 뒤 넘어간다. 나쁜 품질 공백을 넘어 델타를 이어가는 것이 가짜 사용량이 적산에 들어가는 경로다.
- 마지막 양호 원시 카운트와 그 타임스탬프를 보관한다. 양호 데이터가 돌아오면 공백 길이와 카운트 속도로부터 델타 하나가 방어 가능한지, 아니면 그 구간을 추정치로 표시할지 정한다.
- 적산기가 절대 음수가 되게 하지 마라. 단조 증가해야 할 적산이 갑자기 감소하는 것은 상류에 문제가 있다는 신호이며, 게시가 아니라 포착해야 한다.
적산기를 어디에 둘까
적산이 어디에 사는지는 선택이며, 그 선택이 적산의 견고함을 좌우한다.
- 현장 장치 / PLC 안: 장치가 넓은 레지스터에 자체 적산 총량을 유지한다. 카운트가 취약한 델타 형태로 장치를 떠나지 않으므로 가장 견고하다. 공학 단위 적산 총량을 직접 읽고 히스토리언이 트렌드하게 하라. 장치가 이를 제공하면 이 편을 택하라.
- SCADA / 엣지 계층 안: 랩어라운드하는 원시 카운트를 읽어 누적 총량을 직접 계산한다. 위의 모든 롤오버·리셋·공백 처리가 여기에 살아야 한다. 장치가 원시 카운터만 노출할 때 필요하다.
- 히스토리언의 계산 태그로: 히스토리언 자체의 델타 함수로 원시 카운터에서 적산한다. 쓸 만하지만, 다른 계산 태그처럼 검증하라. 여기서 롤오버 규칙이 틀리면 장기 적산이 조용히 오염된다.
어디에 살든 권위 있는 총량은 정확히 하나여야 한다. 같은 카운터를 읽는 두 개의 독립 적산기는 하나가 랩어라운드나 공백을 다르게 처리하는 첫 순간부터 서로 어긋나고, 그러면 어느 숫자가 맞는지 아무도 말할 수 없다.
시운전 체크리스트
- 모든 카운터 태그에 대해 카운터 폭(16/32/64비트)과 단위를 포인트 맵 옆에 기록한다.
- Modbus 32비트 카운터는 하위 워드 랩어라운드가 롤오버로 오인되지 않도록 워드 순서를 확인한다.
- 원시 값이 전체 폭 카운터인지 잘린 하위 워드인지 확인한다.
- 롤오버 보정을 정확히 한 곳에, 그 폭에 맞는 올바른 범위로 둔다.
- 최대 속도에서도 카운터가 한 주기에 한 번을 넘겨 랩어라운드할 수 없을 만큼 샘플 주기가 빠른지 확인한다.
- 장치 재기동이나 첫 스캔 신호를 적산기에 연결해, 리셋이 롤오버로 다뤄지지 않게 한다.
- 적산을 양호 품질에 게이트한다. 통신 공백을 넘어 델타를 이어가지 않는다.
- 누적 총량이 단조 증가하고 절대 음수가 되지 않음을 단언하고, 그렇지 않으면 알람한다.
- 가능하면 벤치에서 롤오버를 강제하거나 시뮬레이션해, 총량이 음의 스파이크 없이 매끄럽게 올라가는지 확인한다.
- 미터를 일부러 리셋해, 총량이 한 범위만큼 튀지 않는지 확인한다.
현장을 떠나기 전에 딱 하나를 시험한다면, 랩어라운드를 강제하라. 카운터를 천장 바로 아래로 미리 설정하고 — 실제 장치가 허용하면 장치에서, 아니면 Modbus 시뮬레이터로 레지스터에 써서 — 롤오버시킨 뒤 총량이 아래로 꺼지지 않고 매끄럽게 올라가는지 지켜보라. 적산기의 나머지는 다 종이 위에서 따져볼 수 있다. 랩어라운드만은 한 번은 직접 봐야 한다.