K_LOOKUP_LINEAR: Function Block untuk Interpolasi Linear Dinamis
`K_LOOKUP_LINEAR` adalah Function Block modular untuk interpolasi linear dinamis. Dengan dukungan hingga 32 titik, proteksi berlapis, dan flag audit. Implementasi ini memudahkan standardisasi lookup kurva, mempercepat commissioning, dan memastikan transparansi hasil perhitungan dalam operasi plant.
Photo by Antoine Dautry / Unsplash
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
- Tentukan jumlah titik referensi aktual → set
N. - Isi
X_REF[0..N-1]danY_REF[0..N-1]dengan data kurva. - Biarkan
X_REF[N..31]danY_REF[N..31]default (tidak dipakai). - Set
THRESHOLDsesuai toleransi deviasi audit. - 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
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_INTERP14adalah versi statis dengan 14 titik, cocok untuk kurva performa yang sudah baku.K_LOOKUP_LINEARadalah 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