← 전체 글
SCADA/약 14분 읽기/— 조회

밸브가 한계에 닿을 때마다 PID 루프가 오버슈트하는 이유

포화, 수동→자동 전환, 기동 램프 뒤 오버슈트는 reset windup이다. anti-windup, external reset, bumpless transfer로 잡는다.

SCADA제어PLC문제 해결시운전

출력이 클램핑되기 전까지는 루프가 멀쩡하다

하루 종일 설정값을 0.5% 이내로 따라가던 레벨 루프가 가끔씩 설정값을 10% 지나쳐 올라가고, 2분에 걸쳐 겨우 되돌아온다. 이런 일은 거의 늘 같은 몇 가지 상황 뒤에 벌어진다. 큰 수요에 제어 밸브가 완전 개방까지 갔거나, 운전자가 루프를 한동안 Manual로 잡고 있다가 Auto로 넘겼거나, 콜드 스타트 직후 설정값이 0에서 램프로 올라가는 중이거나.

튜닝이 문제가 아니다. 문제는 적분기다. 출력은 움직일 수 없는데 편차가 사라지지 않으면, 적분항은 벽에 대고 계속 쌓인다. 그리고 이렇게 쌓인 요구량은 출력이 다시 제어 범위로 들어오기 전에 전부 되감아야 한다. 이것이 reset windup이며, 하필 당신이 신경 쓰는 순간마다 "잘 튜닝된" 루프가 오작동하는 가장 흔한 원인이다.

출력이 막혀 있을 때 적분은 어디로 가는가

교과서적인 PID를 positional(절대값) 형태로 놓고 보자. 적분항은 편차 곱하기 시간의 누적합이다. 출력(컨트롤러 출력, CV, 밸브로 나가는 0–100%)이 한계 사이 어딘가에 있는 한, 이 합은 편차 0으로 밸브를 잡아 두는 데 필요한 값에 정착한다. 정상이다.

이제 포화시켜 보자. 레벨이 설정값보다 한참 아래이고, 루프가 100%를 넘는 출력을 요구하는데 밸브는 이미 완전 개방이라고 하자. 물리적으로 루프가 더 할 수 있는 일은 없다. 그런데 편차는 여전히 크고 양수이므로 적분기는 매초 계속 쌓인다. 내부 CV는 코드가 허용하는 만큼 140%, 180%까지 올라갈 수 있다. 밸브는 신경 쓰지 않는다 — 100%에 못 박혀 있다.

그러다 레벨이 마침내 설정값을 넘어선다. 편차 부호가 뒤집힌다. 건강한 루프라면 즉시 밸브를 닫기 시작한다. 이 루프는 그러지 못한다. 적분기가 180%에 앉아 있어서, 밸브가 스톱에서 떨어지기 시작하려면 그 합을 100% 아래로 끌어내릴 때까지 편차가 한참 동안 음수로 있어야 하기 때문이다. 그 되감기 내내 밸브는 완전 개방으로 남아 있고 레벨은 계속 올라간다. 이것이 당신의 오버슈트다. 루프가 굼뜬 게 아니라, 출력이 포화돼 있는 동안 스스로 판 구덩이에서 빠져나오는 중이다.

같은 함정은 0/100%뿐 아니라 어떤 출력 한계에서도 작동한다. 출력 변화율 제한, 기동 중 "밸브는 80% 이상 열지 못함" 클램프, 이미 최대인 캐스케이드 2차 루프 — 컨트롤러가 계산한 CV가 액추에이터에 도달하지 못하는 곳이면 어디서든 적분기는 그 틈에 대고 windup할 수 있다.

Anti-windup: 벽에 대고 적분하지 마라

제대로 된 컨트롤러는 모두 이 문제를 해결한다. 차이는 얼마나 매끄럽게 손을 떼는가에 있다.

Clamping / conditional integration은 투박한 방식이다. 출력이 포화되면 그냥 적분기 갱신을 멈춘다 — 얼려 버린다 — 또는 출력을 포화에서 빠져나오게 하는 방향으로만 적분을 허용한다. if (CV >= CV_max && error > 0) hold_integral; 몇 줄과 하한에서의 대칭 케이스면 된다. 동작하고, 싸고, 많은 자작 PLC PID 블록이 이렇게 한다. 약점은 이진적이라는 것이다. 적분기가 한계에 닿았을 때의 값에 그대로 얼어붙는데, 그 값이 여전히 필요한 것보다 훨씬 높을 수 있어서, 앞서와 같은 지연 복구가 작은 버전으로 다시 나타난다.

Back-calculation은 벤더 블록이 제공한다면 내가 손이 가는 방식이다. 얼리는 대신, 제한된 출력과 제한 전 출력의 차이를 이득을 거쳐 적분기로 되먹여, 적분기가 포화된 출력과 일관된 값 쪽으로 계속 끌려가게 한다. 튜닝 노브는 tracking time constant, Tt다 — 적분기가 얼마나 빨리 desaturate되는가. 흔한 시작점은 Tt를 적분시간 Ti 근처로, 미분 동작이 있으면 Ti와 미분시간 Td의 기하평균으로 잡는 것이다. Tt가 작으면 더 빨리 되감기지만 포화 탈출이 신경질적일 수 있다. 얻는 것은, 출력이 한계에서 떨어질 때 적분기가 이미 온전한 값에 앉아 있어서, 루프가 홱 튀지 않고 매끄럽게 제어권을 돌려받는다는 점이다.

**External reset(reset feedback)**은 같은 발상을 별도 부착물이 아니라 루프 구조로 구현한 것이다. 적분을 필터링된 출력 신호의 양성 피드백으로 구성하고, 그 신호로 실제 액추에이터나 하류 측정값을 되먹인다. 밸브가 100%에 걸려 있으면 되먹임 값이 100%이고, 적분기는 자연히 그 이상을 요구할 수 없다. DeltaV나 Foxboro 계열 컨트롤러가 이 방식을 강하게 활용하며, 이것이 캐스케이드의 올바른 뼈대다 — 1차의 external reset을 2차의 측정 PV에서 가져오면, 2차가 따라오지 못할 때마다 1차가 자동으로 windup을 멈춘다. windup 클램프만 걸린 독립 블록 두 개를 사이의 reset feedback 없이 캐스케이드로 엮으면, windup 문제를 한 단계 위에서 다시 만든 것이다.

루프를 직접 짜고 형태를 고를 수 있다면, velocity(incremental) 형태가 이 문제의 최악을 공짜로 피해 간다. 절대 출력을 계산하는 대신 매 스캔 출력의 변화량을 계산해 이전 출력에 더한다. 저장되는 명시적 적분합이 없으므로 windup할 대상이 없다 — 출력이 한계에 클램핑되면 누적 위치가 그냥 그 이상 나아가지 않는다. 여전히 한계 처리는 필요하지만, 180%에서 되감아 내려오는 추한 거동은 구조적으로 사라진다. IEC 61131-3은 PID 블록을 표준화하지 않으므로, 무엇을 얻는지는 전적으로 플랫폼 라이브러리에 달려 있다. 신뢰하기 전에 내부가 어떤 형태인지 알아 둘 값어치가 있다.

수동→자동 전환은 옷만 갈아입은 같은 버그다

운전자가 Manual → Auto로 넘긴 뒤의 오버슈트는 windup의 쌍둥이다. Manual에서는 운전자가 출력을 직접 움직이고 적분기는 아무것도 제어하지 않는다. 블록이 Manual에 있는 내내 편차를 계속 적분한다면, 전환 순간 적분기는 현재 출력과 아무 상관 없는 엉뚱한 값에 있을 수 있고, CV가 튄다 — "bump."

해법은 bumpless transfer이고, 그 메커니즘은 anti-windup과 같은 tracking 장치다. 루프가 Manual에 있는(또는 강제/오버라이드되는) 동안 계산된 auto 출력이 현재 manual 출력과 같아지도록 적분기를 tracking시킨다. 그러면 전환 순간 auto가 manual이 놓아둔 바로 그 지점에서 이어받아 점프가 0이고, 루프는 거기서부터 부드럽게 움직인다. bumpless transfer를 표방하는 블록은 내부에서 출력 tracking을 하고 있으며, 같은 기능이 보통 "인터록에 의한 출력 강제"와 "하류가 제어권을 가져감"까지 평범한 Manual/Auto 케이스와 함께 커버한다.

벤더마다 구현이 고르지 않아서 시운전 때 확인하는 몇 가지:

  • 출력을 한계로 강제하고 되감기를 지켜본다. PV를 몰아 루프를 포화시키고, 유지한 뒤, 놓는다. PV가 설정값을 넘는 순간 밸브가 움직이기 시작하지 않으면 windup 처리가 꺼져 있거나 잘못 설정된 것이다. 2분짜리 테스트인데, 운전자가 불평하는 바로 그 실패를 잡아낸다.
  • Manual → Auto 전환을 여러 출력 값에서 해 본다, 50%에서만 하지 말고. PV가 설정값 위에 있을 때와 벗어나 있을 때 둘 다 해 본다. 출력이 튀지 않아야 한다. 튀면 tracking이 연결되지 않은 것이다.
  • 기동 케이스를 확인한다. 콜드 스타트에서 0부터 램프로 올라가는 설정값은 슬로모션 포화다 — 램프 동안 루프가 windup해서 프로세스가 살아나는 순간 쌓인 요구량을 통째로 쏟아내지 않는지 확인한다.
  • 캐스케이드에서는 2차를 망가뜨려 본다. 2차를 Manual에 두거나 한계로 몰고, 1차를 지켜본다. 제대로 된 external reset이면 1차는 windup을 멈춰야 한다. 없으면 1차는 faceplate에서 멀쩡해 보이면서 조용히 포화된다.

사람들이 손대는 노브는 대개 틀린 노브다

루프가 오버슈트하면 반사적으로 detune하려 든다 — 이득을 낮추고, reset을 길게 늘인다. 맞을 때도 있다. 하지만 오버슈트가 포화나 모드 전환 뒤에만 나타나고 루프가 그 외에는 날렵하다면, detuning은 증상을 다루는 것이다. 한계에서만 벌어지는 오작동을 덮으려고 루프를 어디서나 굼뜨게 만들 뿐이고, 적분기가 여전히 자기가 감아 올라간 값에서 되감기고 있으니 오버슈트는 완전히 사라지지도 않는다. windup부터 잡아라 — back-calculation이나 reset feedback을 켜고, bumpless transfer를 검증하라 — 그다음에 튜닝이 정말 바뀌어야 하는지 판단하라. 대개는 그럴 필요가 없다.

신뢰하기 전에 알아 둘 것 하나 더: 미분을 편차가 아니라 측정값에 걸어라. 편차 미분은 운전자가 설정값을 움직일 때마다 거대한 스파이크(derivative kick)를 주고, 밸브에서는 그 스파이크가 물리적 강타가 된다. 거의 모든 산업용 블록이 이 이유로 derivative-on-PV를 기본으로 하지만, 설정 가능한 옵션인 경우도 충분히 많아서 가정하지 말고 확인할 값어치가 있다 — PID 블록의 다른 모든 것과 마찬가지로, 세 글자짜리 이름이 주는 인상보다 훨씬 덜 표준화돼 있다.