Ditulis oleh Ketut P. Kumajaya | 4 Oktober 2025

Latar Belakang

Interpolasi linear adalah metode sederhana namun krusial dalam otomasi proses. Banyak kurva performa peralatan—seperti garis surge centrifugal compressor, karakteristik valve, atau profil efisiensi pompa—tidak tersedia dalam bentuk persamaan matematis, melainkan tabel titik data.

Function Block K_LOOKUP_LINEAR dirancang di Supcon DCS menggunakan Structured Text (ST) untuk melakukan interpolasi linear berbasis array dinamis. Berbeda dengan K_LIN_INTERP14 yang statis dengan 14 titik, FB ini mendukung hingga 32 titik referensi, dilengkapi proteksi multi‑lapis dan flag audit agar siap digunakan lintas plant.

Sebagai catatan, K_LIN_INTERP14 telah diimplementasikan di salah satu plant untuk lookup kurva anti-surge dan terbukti stabil dalam operasi harian. Block ini sendiri merupakan implementasi bebas dari fungsi serupa yang tersedia di Yokogawa Centum VP, dan pengalaman lapangan inilah yang menjadi dasar pengembangan K_LOOKUP_LINEAR sebagai versi yang lebih fleksibel dan modular.


Listing Function Block

(*=============================================================================
  Function Block Name : K_LOOKUP_LINEAR
  Author              : Ketut P. Kumajaya
  Date Created        : 04/10/2025
  Description         : Interpolasi linear dinamis berbasis array referensi
                        dengan proteksi multi-lapis dan flag audit.
  Inputs              : Enable     - Aktivasi interpolasi (BOOL)
                        X          - Nilai input yang akan diinterpolasi (FLOAT)
                        N          - Jumlah titik referensi aktif (INT, min 2)
                        THRESHOLD  - Ambang deviasi audit (FLOAT)
                        X_REF      - array32FLOAT (koordinat X referensi)
                        Y_REF      - array32FLOAT (koordinat Y referensi)
  Outputs             : Y          - Hasil interpolasi linear (FLOAT)
                        X1_used    - Titik awal X interval aktif (FLOAT)
                        Y1_used    - Titik awal Y interval aktif (FLOAT)
                        X2_used    - Titik akhir X interval aktif (FLOAT)
                        Y2_used    - Titik akhir Y interval aktif (FLOAT)
                        Valid      - Flag validasi hasil interpolasi (BOOL)
                        AuditFlag  - Flag audit deviasi/ketidakrapihan data (BOOL)
                        DensityValid - Flag validasi monotoni X_REF (BOOL)
  Artefak Pairing     : array32FLOAT - ARRAY [0..31] OF FLOAT
  Proteksi Audit      : Clamp jika X di luar range; fallback pada interval
                        degenerat; AuditFlag aktif jika deviasi ekstrem atau
                        data tidak monoton; N dikunci dalam rentang aman.
=============================================================================*)

FUNCTION_BLOCK K_LOOKUP_LINEAR

VAR_INPUT
    Enable    : BOOL;
    X         : FLOAT;
    N         : INT;
    THRESHOLD : FLOAT;
    X_REF     : array32FLOAT;
    Y_REF     : array32FLOAT;
END_VAR

VAR_OUTPUT
    Y           : FLOAT;
    X1_used     : FLOAT;
    Y1_used     : FLOAT;
    X2_used     : FLOAT;
    Y2_used     : FLOAT;
    Valid       : BOOL;
    AuditFlag   : BOOL;
    DensityValid: BOOL;
END_VAR

VAR
    i       : INT;
    n_eff   : INT;
    slope   : FLOAT;
    found   : BOOL;
END_VAR

(* --- Inisialisasi status --- *)
Valid        := FALSE;
AuditFlag    := FALSE;
DensityValid := TRUE;
found        := FALSE;

IF NOT Enable THEN
    RETURN;
END_IF;

(* --- Kunci N dalam rentang aman [2..32] --- *)
n_eff := N;
IF n_eff < 2 THEN
    n_eff := 2;
ELSIF n_eff > 32 THEN
    n_eff := 32;
END_IF;

(* --- Validasi monotoni X_REF --- *)
FOR i := 0 TO n_eff - 2 DO
    IF X_REF[i] > X_REF[i + 1] THEN
        DensityValid := FALSE;
    END_IF;
END_FOR;

(* --- Cari interval aktif --- *)
FOR i := 0 TO n_eff - 2 DO
    IF (X >= X_REF[i]) AND (X <= X_REF[i+1]) THEN
        X1_used := X_REF[i];     Y1_used := Y_REF[i];
        X2_used := X_REF[i+1];   Y2_used := Y_REF[i+1];
        found := TRUE;
        EXIT;
    END_IF;
END_FOR;

(* --- Clamp jika X di luar range --- *)
IF NOT found THEN
    IF X < X_REF[0] THEN
        X1_used := X_REF[0];       Y1_used := Y_REF[0];
        X2_used := X_REF[1];       Y2_used := Y_REF[1];
    ELSIF X > X_REF[n_eff - 1] THEN
        X1_used := X_REF[n_eff - 2]; Y1_used := Y_REF[n_eff - 2];
        X2_used := X_REF[n_eff - 1]; Y2_used := Y_REF[n_eff - 1];
    ELSE
        X1_used := X_REF[0];       Y1_used := Y_REF[0];
        X2_used := X_REF[1];       Y2_used := Y_REF[1];
    END_IF;
END_IF;

(* --- Hitung interpolasi linear --- *)
IF (X2_used - X1_used) = 0.0 THEN
    Y := Y1_used;
    Valid := FALSE;
ELSE
    slope := (Y2_used - Y1_used) / (X2_used - X1_used);
    Y := Y1_used + slope * (X - X1_used);
    Valid := TRUE;
END_IF;

(* --- Flag audit --- *)
IF (ABS(Y2_used - Y1_used) > THRESHOLD) OR (NOT DensityValid) THEN
    AuditFlag := TRUE;
ELSE
    AuditFlag := FALSE;
END_IF;

END_FUNCTION_BLOCK

Cara Penggunaan

  1. Tentukan jumlah titik referensi aktual → set N.
  2. Isi X_REF[0..N-1] dan Y_REF[0..N-1] dengan data kurva.
  3. Biarkan X_REF[N..31] dan Y_REF[N..31] default (tidak dipakai).
  4. Set THRESHOLD sesuai toleransi deviasi audit.
  5. Aktifkan Enable := TRUE.

Contoh Tabel Input

Index X_REF Y_REF
0 0 0
1 10 5
2 20 15
3 30 25
4 40 35
5 50 50

Jika N = 6 dan X = 22, maka interval aktif [20,30] → hasil interpolasi Y ≈ 17.


Flowchart Pairing

flowchart TD A(["Start"]) --> B{"Enable?"} B -- "No" --> Z(["Return"]) B -- "Yes" --> C["Set n_eff = N (clamp 2..32)"] C --> D["Check monotoni X_REF"] D --> E{"X in interval?"} E -- "Yes" --> F["Set X1_used,Y1_used,X2_used,Y2_used"] E -- "No" --> G{"X < X_REF[0]?"} G -- "Yes" --> H["Clamp ke interval awal"] G -- "No" --> I{"X > X_REF[n_eff-1]?"} I -- "Yes" --> J["Clamp ke interval akhir"] I -- "No" --> K["Fallback konservatif"] F --> L{"Degenerate interval?"} H --> L J --> L K --> L L -- "Yes" --> M["Set Y=Y1_used, Valid=FALSE"] L -- "No" --> N["Hitung slope dan Y, Valid=TRUE"] M --> O{"Audit check"} N --> O{"Audit check"} O -- "Deviasi > THRESHOLD atau monotoni gagal" --> P["AuditFlag=TRUE"] O -- "Normal" --> Q["AuditFlag=FALSE"] P --> Z(["End"]) Q --> Z(["End"])

Kesimpulan

K_LOOKUP_LINEAR adalah artefak modular untuk interpolasi linear dinamis di Supcon DCS.
Dengan fleksibilitas jumlah titik, proteksi multi-lapis, dan flag audit, FB ini memperkuat transparansi serta efisiensi sistem kontrol.

Mengapa hal ini penting bagi operasi plant?

  • Mengurangi duplikasi: tidak perlu lagi membuat FB statis dengan jumlah titik berbeda (misalnya 14, 20, dsb).
  • Seragam lintas plant: format array 32 titik menjadi standar implementasi yang mudah diaudit dan diajarkan.
  • Mempercepat commissioning: kurva peralatan baru dapat langsung dimasukkan tanpa modifikasi FB.
  • Lebih aman: proteksi multi-lapis memastikan output stabil meski data referensi tidak sempurna.
  • Audit-grade: adanya flag audit (AuditFlag, DensityValid) memberi transparansi penuh pada kualitas data dan hasil interpolasi.

Sebagai ilustrasi nyata, lookup kurva anti-surge kompresor sentrifugal dengan 8–10 titik dapat langsung diakomodasi, tanpa harus menulis ulang FB baru seperti pada pendekatan statis K_LIN_INTERP14.

Catatan praktis: Untuk anti-surge, interpolasi linear adalah pilihan terbaik karena:

  • Perhitungan cepat dan ringan, tidak membebani CPU.
  • Mudah diverifikasi dan dipahami operator maupun engineer.
  • Transisi antar titik berjalan cepat sehingga stabil untuk kontrol real-time.
  • Cukup akurat untuk merepresentasikan performa kompresor di antara titik vendor.

Appendix — Referensi K_LIN_INTERP14

  • K_LIN_INTERP14 adalah versi statis dengan 14 titik, cocok untuk kurva performa yang sudah baku.
  • K_LOOKUP_LINEAR adalah versi dinamis dengan jumlah titik fleksibel (2–32).
  • Menyertakan keduanya dalam artikel membantu pembaca memahami evolusi desain FB dari statis → dinamis, sekaligus memberi referensi audit.
K_LIN_INTERP14 Function Block (klik untuk membuka)
(*=============================================================================
  Function Block Name : K_LIN_INTERP14
  Author              : Ketut P. Kumajaya
  Date Created        : 04/10/2025
  Description         : Melakukan interpolasi linear berdasarkan 14 pasang titik
                        (X0..X13, Y0..Y13). Umumnya digunakan untuk lookup
                        kurva performa peralatan proses (misalnya garis surge
                        centrifugal compressor).
  Inputs              : X        - Nilai input yang akan diinterpolasi (FLOAT)
                        X0..X13  - Koordinat X referensi (FLOAT)
                        Y0..Y13  - Koordinat Y referensi (FLOAT)
  Outputs             : Y        - Hasil interpolasi linear (FLOAT)
                        X1_used  - Titik awal X interval aktif (FLOAT)
                        Y1_used  - Titik awal Y interval aktif (FLOAT)
                        X2_used  - Titik akhir X interval aktif (FLOAT)
                        Y2_used  - Titik akhir Y interval aktif (FLOAT)
  Artefak Pairing     : X_ARRAY  - ARRAY [0..13] OF FLOAT
                        Y_ARRAY  - ARRAY [0..13] OF FLOAT
  Proteksi Audit      : Jika X di luar range, output dikunci pada ujung tabel.
                        Pembagian dengan nol dicegah dengan fallback ke nilai
                        tetap agar algoritma selalu stabil.
=============================================================================*)

FUNCTION_BLOCK K_LIN_INTERP14

VAR_INPUT
    X   : FLOAT;
    X0  : FLOAT;   Y0  : FLOAT;
    X1  : FLOAT;   Y1  : FLOAT;
    X2  : FLOAT;   Y2  : FLOAT;
    X3  : FLOAT;   Y3  : FLOAT;
    X4  : FLOAT;   Y4  : FLOAT;
    X5  : FLOAT;   Y5  : FLOAT;
    X6  : FLOAT;   Y6  : FLOAT;
    X7  : FLOAT;   Y7  : FLOAT;
    X8  : FLOAT;   Y8  : FLOAT;
    X9  : FLOAT;   Y9  : FLOAT;
    X10 : FLOAT;   Y10 : FLOAT;
    X11 : FLOAT;   Y11 : FLOAT;
    X12 : FLOAT;   Y12 : FLOAT;
    X13 : FLOAT;   Y13 : FLOAT;
END_VAR

VAR_OUTPUT
    X1_used : FLOAT;
    Y1_used : FLOAT;
    X2_used : FLOAT;
    Y2_used : FLOAT;
    Y       : FLOAT;
END_VAR

VAR
    X_ARRAY : array14FLOAT; (* user defined data type *)
    Y_ARRAY : array14FLOAT; (* user defined data type *)
    i       : INT;
    slope   : FLOAT;
END_VAR

(* --- Inisialisasi array --- *)
X_ARRAY[0] := X0;   Y_ARRAY[0] := Y0;
X_ARRAY[1] := X1;   Y_ARRAY[1] := Y1;
...
X_ARRAY[13] := X13; Y_ARRAY[13] := Y13;

(* --- Cari interval aktif --- *)
FOR i := 0 TO 12 DO
    IF (X >= X_ARRAY[i]) AND (X <= X_ARRAY[i+1]) THEN
        X1_used := X_ARRAY[i];   Y1_used := Y_ARRAY[i];
        X2_used := X_ARRAY[i+1]; Y2_used := Y_ARRAY[i+1];
        EXIT;
    END_IF;
END_FOR;

(* --- Clamp jika X di luar range --- *)
IF X < X_ARRAY[0] THEN
    X1_used := X_ARRAY[0];   Y1_used := Y_ARRAY[0];
    X2_used := X_ARRAY[1];   Y2_used := Y_ARRAY[1];
ELSIF X > X_ARRAY[13] THEN
    X1_used := X_ARRAY[12];  Y1_used := Y_ARRAY[12];
    X2_used := X_ARRAY[13];  Y2_used := Y_ARRAY[13];
END_IF;

(* --- Hitung interpolasi linear --- *)
IF (X2_used - X1_used) = 0 THEN
    Y := Y1_used; (* fallback jika interval degenerat *)
ELSE
    slope := (Y2_used - Y1_used) / (X2_used - X1_used);
    Y := Y1_used + slope * (X - X1_used);
END_IF;

END_FUNCTION_BLOCK