← 전체 글
MES/약 12분 읽기/ 조회

PLC와 MES 교대 수량이 안 맞는 이유는 대부분 counter가 아니라 시간 경계다

야간 교대 report에서 good count가 4개 어긋난다. PLC counter, historian delta, S6F11 event time, spool drain 중 어디를 먼저 봐야 하는지 정리한다.

MESSCADA히스토리언태그프로젝트 노트

야간 교대 report에 good count가 1,738로 찍혔다. 설비 HMI에는 1,742다. 4개.

이 4개 때문에 이틀을 쓴 적이 있다. PLC counter는 멀쩡했고, historian도 sample을 빠뜨리지 않았고, MES transaction도 다 들어와 있었다. 문제는 06:00이라는 숫자를 네 개의 system이 서로 다른 순간으로 이해하고 있었다는 것이다.

수량 대사에서 counter 자체가 틀린 경우는 생각보다 드물다. 대부분은 경계 문제다. 어디서 시작하고, 어디서 끝나고, 그 시각을 누구 시계로 재느냐.

교대 경계 06:00을 지나는 count가 거치는 시계 네 개와, spool drain이 event time과 도착 시각을 벌려 놓는 지점 교대 경계 06:00 — 시계 네 개 PLC 시계SCADA collector HistorianMES 설비 내부읽은 시각 저장 시각 UTCcommit 시각 SPOOL DRAIN S6F11 spool drain 05:50 event time 06:10 도착

먼저 수량별 기준 데이터를 못 박는다

"MES가 맞다" "아니다 PLC가 맞다"로 시작하면 회의가 두 시간이 된다. 수량 종류별로 하나씩 정하고 끝내는 게 빠르다.

수량기준으로 쓸 곳이유
Machine cyclePLC설비 동작에 가장 가깝다
Good countPass/fail 판정하는 stationPacker가 아니라 test station이다
Reject countTest system + operator reason entryReason code mapping이 따로 필요하다
ReworkMES 또는 operator stationPLC logic에는 대개 안 보인다
Shift totalReporting layer경계와 order context에 종속된다

Good을 packer에서 세고 reject를 test station에서 세는 라인은 good + reject가 절대 cycle count와 같아지지 않는다. 그 사이에 빠진 것들이 있기 때문이다. 이건 버그가 아니라 설계인데, 문서에 없으면 매번 버그로 신고된다.

Operator가 MES에서 수량을 고쳤을 때 그게 correction인지 override인지 별도 adjustment record인지도 여기서 같이 정한다. 나중에 정하면 이미 데이터가 섞인 뒤다.

Counter 형태를 모르고 report를 짜지 않는다

같은 "good count" tag라도 움직이는 방식이 다르다.

Shift start나 power cycle에 reset되는 counter, 숫자 한계에서만 wrap하는 lifetime totalizer, 제품당 one-shot pulse, order change에 reset되는 batch counter. Good과 reject의 reset 시점이 아예 다른 구성도 흔하다.

Reporting 관점에서는 lifetime totalizer가 낫다. Shift start와 end의 delta만 빼면 되고, 누가 언제 reset했는지 신경 쓸 필요가 없다. Reset counter를 쓸 거면 reset 시점이 통제되고 event로 남아야 한다는 조건이 붙는다. 그 조건을 못 지킬 것 같으면 처음부터 totalizer를 요구하는 편이 싸다.

16-bit counter는 60 ppm 라인에서 약 18시간마다 wrap한다. 하루 3교대 안에서 한 번은 넘어간다는 뜻이다. Rollover 값과 delta 처리를 문서에 적고, 라인이 그 값에 실제로 도달할 수 있으면 simulation으로 한 번 넘겨 본다.

시간 경계: 여기서 시간을 제일 많이 버린다

교대 시간이 됐다고 라인이 멈추지 않는다. 06:00에 report window가 닫혀도 설비는 진행 중인 part를 마저 뱉는다. 여기에 얽히는 시계가 최소 네 개다.

  • PLC/설비의 내부 시계.
  • SCADA collector가 값을 읽은 시각.
  • Historian의 저장 시각 — 대개 UTC.
  • MES가 transaction을 commit한 시각.

SECS/GEM으로 붙는 설비라면 하나 더 있다. S6F11 event report에 실린 clock SV는 설비 시계의 시각이지 host가 받은 시각이 아니다. Host 수신 시각으로 shift를 가르면 설비 시계가 3초 밀린 날 경계의 part 몇 개가 옆 shift로 넘어간다. GEM은 이걸 위해 S2F31 Date and Time Set Request를 두고 있으니, host connect마다 시계를 맞추고 보정한 delta를 log에 남긴다. 하루 4초씩 밀리는 설비는 RTC battery가 다 됐다는 뜻이라 대사 문제로 오기 전에 잡을 수 있다.

더 고약한 건 spool drain이다. Link가 끊겼다 붙으면 설비가 spool에 쌓아 둔 S6F11을 한꺼번에 밀어낸다. 이 message들의 event time은 과거고 도착 시각은 현재다. 도착 순서로 shift를 배정하는 report는 여기서 조용히 틀린다. 05:50에 발생한 event가 06:10에 도착해서 야간 shift 대신 주간 shift에 얹힌다. Report logic이 event time 기준인지 arrival time 기준인지, 코드에서 직접 확인해야 한다. 문서 말고 코드다.

문서로 고정할 것:

  • Shift start/end timestamp와 timezone, 그리고 그 시각을 재는 기준 시계.
  • Operator login이나 order close 지연에 대한 grace period.
  • 경계 시각과 정확히 같은 count는 이전 shift인지 다음 shift인지 (>=> 냐, 한 줄로 적어 둔다).
  • DST를 쓰는 site라면 1년에 한 번은 야간 shift가 9시간, 한 번은 7시간이 된다. 시간당 생산량 KPI가 그날 튄다.
  • Shift handover 중 planned downtime을 어느 쪽에 넣을지.

고속 라인에서 경계 시점의 sampled value 하나만 믿는 report는 쓰지 않는 게 좋다. Historian의 compression과 interpolation rule이 그 한 점을 어떻게 만드는지 시험해 보면 이유를 알게 된다.

Count에 order context를 붙여 둔다

Context 없는 raw count는 나중에 못 맞춘다. Count event에는 shift ID, work order, lot/carrier ID, product code와 recipe version, count 시점의 equipment state, quality state(good/reject/hold/rework/sample)가 같이 있어야 한다.

Shift는 06:00에 시작했는데 product change가 06:02에 났다면 그 2분이 보여야 한다. 총수량은 맞는데 제품별 수량만 틀린 report가 나오는 경로가 정확히 이거다.

Reset과 rollover는 숨기지 말고 event로 남긴다

Counter reset이 조용히 지나가면 delta 계산이 그대로 망가진다. 최소한 shift reset command, order/batch reset, PLC download와 cold restart, counter rollover, manual adjustment, SCADA-PLC 간 communication gap은 event로 남긴다.

Delta 계산에서 설명 없는 negative change는 채택하지 않는다. Reset이나 rollover event가 짝으로 있어야 정상 변화로 인정하고, 없으면 review 상태로 보낸다. 자동으로 절댓값을 취하거나 0으로 clamp하는 코드를 본 적이 있는데, 그 라인은 3개월간 아무도 문제를 몰랐다.

덮어쓰지 말고 차이를 남긴다

Report 숫자를 맞추려고 한 값을 다른 값으로 덮어쓰면 당장은 조용해지고 원인은 사라진다. Shift summary는 measured value와 adjustment를 둘 다 들고 있어야 한다.

  • PLC measured good / reject count
  • MES accepted good count
  • Manual adjustment와 그 reason, operator
  • Reconciled final count
  • Reconciliation status: matched, adjusted, late data, missing data, under review

생산팀은 final count만 보면 되고, 엔지니어는 왜 달라졌는지 추적할 수 있다. 이 두 요구는 충돌하지 않는다. 한 칸으로 합치려고 할 때만 충돌한다.

Go-live 전 30분짜리 검증

Production report를 믿기 전에 짧은 controlled trial을 한 번 돌린다. 오래 걸리지 않는다.

  1. 짧은 reporting window를 하나 잡는다.
  2. 아는 수량의 good part와 reject를 만든다.
  3. Window 중간에 product나 order를 한 번 바꾼다.
  4. Procedure가 허용하면 operator correction을 한 건 넣는다.
  5. Collector를 restart하거나 network를 뽑아 communication gap을 만든다. SECS/GEM이면 여기서 spool이 쌓이고 재접속 후 drain된다.
  6. PLC, SCADA, historian, MES, final report 값을 비교한다.

5번을 빼면 이 검증은 의미가 거의 없다. 정상 운전에서 안 맞는 report는 애초에 드물다.

목표는 총수량을 맞추는 것만이 아니다. 안 맞을 때 그 이유가 사람이 읽을 수 있게 남는지를 본다. 최종 숫자 하나만 출력하는 report는 맞는 게 아니라 숨기고 있을 가능성이 높다.

설비 쪽 event 흐름을 실제 wire에서 확인하고 싶으면 SECS/GEM simulator로 link를 끊었다 붙이면서 event time과 arrival time이 어떻게 벌어지는지 먼저 보는 편이 빠르다.