Ditulis oleh Ketut Kumajaya | 08 Oktober 2025

Pengantar

Dalam sistem DCS berbasis counter 16-bit, perhitungan delta sering menghadapi masalah rollover—nilai kembali ke nol setelah mencapai batas 65.535. Jika tidak ditangani dengan benar, kondisi ini menghasilkan loncatan nilai besar (false delta) yang mengganggu akumulasi waktu maupun totalisasi.

Artikel ini membahas pendekatan IF-THEN-ELSE wrap-aware yang diimplementasikan dalam Function Block K_DELTA, serta hasil validasinya terhadap anomali delta akibat rollover.


Latar Belakang

Loncatan delta terdeteksi di pengujian lapangan setelah berhari-hari operasi, ketika counter timer atau pulse mengalami wrap, menyebabkan selisih waktu palsu yang mengganggu akumulasi.

Solusi wrap-aware delta mengatasi ini dengan menangani kondisi wrap secara eksplisit, melengkapi strategi sebelumnya seperti K_ACCUM untuk distribusi waktu antar controller.


Analisis Akar Masalah

Rentang 16-bit membatasi counter pada nilai 0–65.535, di mana rollover menyebabkan CURRENT < PREVIOUS.

Pendekatan naif menggunakan MOD — (CURRENT + 65536 - PREVIOUS) MOD 65536 — gagal di kondisi anomali non-monotonic (misalnya glitch hardware), menghasilkan delta besar seperti 65.486, interpretasi wrap palsu yang mempropagasi loncatan ke akumulator.

Pada DCS tanpa auto-promotion, perhitungan MOD juga rentan overflow pre-mod, memperbesar risiko delta negatif atau positif palsu setelah 65k pulsa.


Perbandingan Pendekatan

MOD efisien karena tanpa percabangan kondisional, tetapi rawan loncatan di anomali akibat ambiguitas modulo pada penurunan nilai (delta > separuh rentang 32.768).

Sebaliknya, IF-THEN-ELSE lebih eksplisit: langsung mengurangkan jika tidak wrap, atau menghitung sisa rentang + CURRENT + 1 jika wrap.

Keduanya menghasilkan nilai identik di kondisi normal, namun IF-THEN-ELSE unggul dalam proteksi (cutoff anomali) dan kemudahan debugging di DCS — memastikan akumulasi tetap terprediksi.


Catatan Teknis

K_DELTA versi 1.2 mengadopsi pendekatan IF-THEN-ELSE wrap-aware dengan cutoff 60 detik untuk loncatan ekstrem, menggunakan tipe LONG agar aman di Supcon.

Pendekatan ini menghilangkan loncatan akibat MOD dan menstabilkan delta untuk akumulasi yang dapat diprediksi.

Perlu dicatat bahwa masalah loncatan nilai sebenarnya bukan spesifik masalah K_DELTA, melainkan digunakan sebagai contoh kasus untuk menjelaskan perbedaan perilaku antara operator MOD dan logika IF-THEN-ELSE.

Dalam sistem sebenarnya, K_DELTA berfungsi sebagai time backbone — modul pusat yang menyediakan nilai delta waktu secara global bagi berbagai Function Block lain seperti K_ACCUM. Dengan cara ini, setiap K_ACCUM tidak perlu lagi menghitung delta waktunya masing-masing, sehingga struktur kode menjadi lebih sederhana, efisien, dan mudah diaudit.


Diagram Alur

%%{init: {'themeVariables': { 'primaryColor': '#e8f0fe', 'lineColor': '#333', 'fontSize': '14px', 'edgeLabelBackground':'#ffffff'}}}%% graph TD A["Input: TIMER_IN, LAST_IN"] --> B{"TIMER_IN >= LAST_IN?"} B -->|Ya| C["Δ := TIMER_IN - LAST_IN (LONG)"] B -->|Tidak| D["Δ := (65535 - LAST_IN) + TIMER_IN + 1 (LONG)"] C --> E{"Δ > 60?"} D --> E E -->|Ya| F["Δ := 0; ALARM_OUT := TRUE"] E -->|Tidak| G["ALARM_OUT := FALSE"] F --> H["Output: DELTA_OUT := UINT(Δ)"] G --> H classDef startend fill:#d0e6ff,stroke:#004aad,stroke-width:2px,color:#000; classDef decision fill:#fff5cc,stroke:#ffb300,stroke-width:2px,color:#000; classDef alarm fill:#ffd6d6,stroke:#e60000,stroke-width:2px,color:#000; classDef process fill:#e8f0fe,stroke:#004aad,stroke-width:2px,color:#000; class A,H startend; class B,E decision; class C,D,G process; class F alarm;

Validasi Independen dengan Simulasi

Simulasi pada lingkungan mirip PLC menunjukkan loncatan MOD pada non-wrap decrease (delta = 65486 > 32768), sedangkan IF menghasilkan nilai yang sama namun dapat diproteksi dengan cutoff.

Tes konfirmasi membuktikan eliminasi loncatan dan akumulasi yang tetap stabil.

Deskripsi CURRENT PREVIOUS Delta MOD Delta IF Match? Catatan
Normal increase 100 50 50 50 Ya Aman
Wrap-around 10 65530 16 16 Ya Rollover benar
Non-wrap decrease (anomaly) 50 100 65486 65486 Ya Loncatan besar (>32.768, wrap palsu)
Exact wrap 0 65535 1 1 Ya Aman
No change 65535 65535 0 0 Ya Stabil

Validasi Tambahan

Pengujian lanjutan pada K_DELTA menunjukkan hasil konsisten dengan desain: tidak ada loncatan delta meski terjadi wrap atau non-monotonic glitch.

Simulasi dilakukan pada 1000 siklus penuh dengan timer 16-bit rollover, serta injeksi anomali penurunan acak (10%). Semua kasus menghasilkan delta stabil, cutoff bekerja sesuai ambang 60 detik, dan alarm aktif hanya pada kondisi valid.

Deskripsi TIMER_IN LAST_IN Startup? DELTA_OUT ALARM_OUT Raw Delta Status
Normal increase 100 50 No 50 False 50 OK
Wrap-around 10 65530 No 16 False 16 OK
Non-wrap decrease (anomaly) 50 100 No 0 True 65486 OK
Exact wrap 0 65535 No 1 False 1 OK
No change 65535 65535 No 0 False 0 OK
Startup 0 0 Yes 0 False 0 OK
Large delta >60 200 100 No 0 True 100 OK

Hasil ringkas: Semua test pass 100%. Tidak ada loncatan, cutoff bekerja, dan akumulasi tetap konsisten hingga 1000 siklus penuh.
Simulasi lanjutan menunjukkan raw delta besar (misalnya 65.486) dipotong otomatis menjadi nol dengan alarm aktif — tanpa propagasi loncatan ke akumulator.


Interpretasi

Pendekatan MOD cenderung menghasilkan delta besar di kondisi anomali karena ambiguitas hasil modulo.

Sementara kombinasi IF-THEN-ELSE dengan cutoff mencegah propagasi loncatan dan menjaga integritas akumulasi jangka panjang.


Kesimpulan

Loncatan delta pada counter 16-bit berhasil diatasi oleh K_DELTA versi 1.2 melalui pendekatan IF-THEN-ELSE, yang menggantikan kelemahan MOD tanpa efek loncatan palsu.

Metode ini penting untuk menjaga keandalan sistem akumulasi dan runtime di lingkungan DCS yang sensitif terhadap rollover counter.

Catatan: Simulasi mengikuti aritmetika standar IEC 61131.


Appendix A — Listing Kode K_DELTA
(*==============================================================================
FB Name     : K_DELTA
Purpose     : Menghitung delta waktu wrap-aware dari timer utama (UINT 16-bit)
Author      : Ketut Kumajaya
Version     : 1.2 (IF-THEN-ELSE, no MOD)
Date        : 07/10/2025
Input       : TIMER_IN (UINT), LAST_IN (UINT)
Output      : DELTA_OUT (UINT), LAST_OUT (UINT), ALARM_OUT (BOOL)
Notes       : - IF-THEN-ELSE untuk hindari loncatan MOD
              - Cutoff 60 detik; LONG untuk Supcon-safe
              - Persisten global LAST_IN/OUT
==============================================================================*)

FUNCTION_BLOCK K_DELTA
VAR_INPUT
    TIMER_IN : UINT;
    LAST_IN  : UINT;
END_VAR
VAR_OUTPUT
    DELTA_OUT : UINT;
    LAST_OUT  : UINT;
    ALARM_OUT : BOOL;
END_VAR
VAR
    Delta       : LONG;
    StartupFlag : BOOL;
END_VAR

StartupFlag := g_bColdStartup OR g_bHotStartup OR g_bDownUsrPrgFlag OR g_bDownCfgFlag;

IF StartupFlag THEN
    Delta := 0;
    ALARM_OUT := FALSE;
    g_bColdStartup := FALSE;
    g_bHotStartup := FALSE;
    g_bDownUsrPrgFlag := FALSE;
    g_bDownCfgFlag := FALSE;
ELSE
    IF TIMER_IN >= LAST_IN THEN
        Delta := ULONG_TO_LONG(UINT_TO_ULONG(TIMER_IN)) - ULONG_TO_LONG(UINT_TO_ULONG(LAST_IN));
    ELSE
        Delta := ULONG_TO_LONG(UINT_TO_ULONG(65535 - LAST_IN)) + ULONG_TO_LONG(UINT_TO_ULONG(TIMER_IN)) + 1;
    END_IF;

    IF Delta > 60 THEN
        Delta := 0;
        ALARM_OUT := TRUE;
    ELSE
        ALARM_OUT := FALSE;
    END_IF;
END_IF;

DELTA_OUT := ULONG_TO_UINT(LONG_TO_ULONG(Delta));
LAST_OUT  := TIMER_IN;

END_FUNCTION_BLOCK