Buka Senin - Jumat jam 08.30 s/d jam 16.30 , Sabtu Jam 8.30 s/d jam 13.00 , Minggu tutup
  • Selamat Datang di Indomaker ❯ Silahkan pesan produk sesuai kebutuhan anda, kami siap melayani.
  • Selamat Datang di Indomaker ❯ Silahkan pesan produk sesuai kebutuhan anda, kami siap melayani.
Beranda » Blog » Jaga Kolam Ikan Tetap Stabil Pakai Arduino dan PID Biar Ikan Makin Happy

Jaga Kolam Ikan Tetap Stabil Pakai Arduino dan PID Biar Ikan Makin Happy

Diposting pada 18 September 2026 oleh indo maker / Dilihat: 11 kali / Kategori:

Halo Sobat Maker! Teman-teman pernah ngerasa ribet gak sih kalau harus bolak-balik ngecek ketinggian air kolam ikan secara manual? Apalagi kalau cuaca lagi panas banget, penguapan air bisa bikin volume kolam drop drastis. Kalau telat ngisi, risikonya fatal banget: kadar oksigen berkurang, suhu air jadi nggak stabil, dan konsentrasi amonia hasil sisa metabolisme ikan bisa meningkat tajam. Kalau sudah begini, ikan bisa stres, sakit, bahkan mati massal. Duh, jangan sampai deh!

Nah, buat kalian yang pengen budidaya ikannya naik level dan anti-ribet, kita bisa bikin Sistem Pengendalian Ketinggian Air yang cerdas. Kita nggak cuma pakai sensor nyala-mati biasa, tapi kita bakal pakai “otak” Arduino Uno dan algoritma PID. Tujuannya? Biar ketinggian air tetap stabil di titik ideal secara otomatis dan real-time. Ikan pun bakal makin happy karena lingkungan hidupnya konsisten terus!

Kenapa Harus PID? Biar Pompa Gak “Kaget” & Lebih Sat-Set!

Mungkin teman-teman mikir, “Kenapa nggak pakai saklar pelampung atau sensor on/off biasa aja?”. Masalahnya, kontrol biasa sering bikin pompa bekerja kasar—sebentar nyala kencang, sebentar mati. Ini bisa bikin pompa cepat rusak dan level air nggak presisi. Dengan algoritma PID (Proportional-Integral-Derivative), respon sistem jadi jauh lebih halus:

  • Proportional (P): Ini adalah respon gercep. Dia melihat seberapa jauh selisih air sekarang dengan target. Makin jauh selisihnya, pompa bakal lari makin kencang.
  • Integral (I): Tugasnya menghapus “dosa” masa lalu alias steady-state error. Kalau air cuma kurang dikit tapi nggak sampai-sampai ke target, komponen I bakal pelan-pelan menambah tenaga sampai tepat di titik yang kita mau.
  • Derivative (D): Ini adalah sang peramal. Dia melihat laju perubahan air dan bakal “ngerem” pompa sebelum airnya kelewat batas (overshoot).

Hasilnya? Pengendalian air jadi super presisi, stabil, dan nggak pakai drama air tumpah-tumpah atau pompa yang nyala-mati mendadak.

Alat dan Bahan Anti-Gagal

Berdasarkan spesifikasi teknis dari riset sistem ini, Sobat Maker perlu menyiapkan komponen berikut. Perlu diperhatikan, sistem ini dirancang tangguh dengan dua jalur aktuasi (isi dan buang) agar level air benar-benar terjaga.

Komponen Jumlah Keterangan
Arduino Uno 1 buah Otak utama untuk memproses algoritma PID.
Pompa DC 5V 2 buah Digunakan sebagai pompa pengisi (ISI) dan pembuang (BUANG).
Selang Pompa Secukupnya Jalur aliran air masuk dan keluar kolam.
Potensiometer 1 buah Input untuk mengatur setpoint ketinggian air (target).
Sensor Ultrasonik HY-SRF05 1 buah Sensor pengukur jarak air dengan akurasi tinggi.
MOSFET IRLZ44N 2 buah Driver saklar elektronik untuk mengontrol daya pompa.
Resistor 220 Ohm 2 buah Pelindung arus untuk jalur gate MOSFET.
Resistor 10k Ohm 2 buah Resistor pull-down agar sinyal kontrol stabil.
Dioda 1N4007 2 buah Pengaman arus balik (flyback) dari motor pompa.
Kabel Jumper Secukupnya Penghubung antar komponen di sirkuit.

Skematik Rangkaian Jalur Sat-Set Gak Pake Ribet

Menyusun rangkaiannya sebenarnya cukup straightforward. Arduino Uno akan membaca nilai target dari Potensiometer melalui Pin A0. Untuk “mata” sistem, sensor HY-SRF05 dipasang dengan pin Trig ke Pin 2 dan Echo ke Pin 3.

Nah, karena kita pakai dua pompa (isi dan buang), kita butuh MOSFET IRLZ44N sebagai driver-nya. Pin 9 pada Arduino digunakan sebagai output PWM untuk mengendalikan kecepatan pompa pengisi via MOSFET. Pastikan pasang dioda 1N4007 secara paralel pada beban motor pompa supaya Arduino kamu nggak kena noise atau lonjakan listrik balik.

Konsep kendali presisi seperti ini sebenarnya mirip banget sama proyek IoT lainnya, lho. Kalau tertarik belajar kontrol cahaya yang halus, kamu bisa cek cara bikin lampu belajar pintar pakai PID Arduino biar mata nggak gampang lelah pas lagi ngoding.

Sensor HY-SRF05 vs HC-SR04: Kenapa HY-SRF05 Lebih Pro?

Banyak maker pemula pakai HC-SR04 karena harganya miring, tapi untuk sistem PID yang butuh data akurat, HY-SRF05 adalah pilihan mutlak. Ini alasannya:

  1. Akurasi Mantap: Kesalahan absolut HY-SRF05 cuma 0,20 cm, lebih presisi dibanding HC-SR04 yang ada di angka 0,233 cm.
  2. Jangkauan Lebih Luas: Bisa baca sampai 450 cm (HC-SR04 cuma sampai 400 cm).
  3. Sinyal Stabil: HY-SRF05 punya gangguan fluktuasi (jitter) yang sangat minim. Kalau sensornya “goyang-goyang” bacaannya, algoritma PID bakal bingung dan bikin pompa nyala-mati nggak jelas (bikin boros listrik dan hardware cepat rusak).

Logika Program Biar Sistem Gak “Mabuk” & Tetap Presisi

Sistem ini berjalan dengan prinsip closed-loop feedback. Secara teknis, Arduino melakukan siklus: Baca Sensor -> Bandingkan dengan Target -> Hitung PID -> Gerakkan Pompa. Tapi ada beberapa fitur “Pro” di dalam kodenya:

  • Median & Low-pass Filter: Biar data sensor nggak “lompat-lompat” karena riak air, kita ambil nilai tengahnya (median) lalu dihaluskan lagi.
  • Hysteresis: Ini biar pompa nggak “galau” atau bergetar saat air pas di titik target. Ada sedikit toleransi (threshold) biar pompa nggak nyala-mati terlalu sering.
  • Anti-Windup: Fitur ini penting banget biar hitungan Integral nggak numpuk sampai berlebihan (over-accumulate) yang bisa bikin sistem “mabuk” dan overshoot parah.
  • Watchdog Timer (WDT): Fitur keamanan yang otomatis me-reset Arduino kalau tiba-tiba program freeze atau crash gara-gara gangguan listrik (noise).

Full Script Arduino (Copy-Paste Ready!)

Berikut adalah kode lengkapnya. Perhatikan bagian computePID dan getMedian yang bikin sistem ini jauh lebih stabil dibanding kontrol biasa.

#include <avr/wdt.h>

// ================================================================
// KONFIGURASI PIN
// ================================================================
#define TRIG_PIN 2
#define ECHO_PIN 3
#define POT_PIN A0
#define PUMP_PIN 9

// ================================================================
// KONFIGURASI SISTEM
// ================================================================
#define TINGGI_GALON 14.0
#define MIN_PWM 60
#define TURN_ON_THRESHOLD 1.5

// ================================================================
// VARIABEL PID
// ================================================================
double Setpoint, Input, Output;

double Kp = 40.0;
double Ki = 0.5;
double Kd = 1.0;

// Variabel tambahan untuk PID manual
double lastInput = 0;
double integralTerm = 0;
unsigned long lastPIDTime = 0;

// ================================================================
// VARIABEL FILTER & SENSOR
// ================================================================
double filteredLevel = 0;
int rawDistance = 0;
bool pumpRunning = false;
unsigned long lastPrintTime = 0;


// ================================================================
// SETUP
// ================================================================
void setup() {

  // Konfigurasi Watchdog Timer
  MCUSR &= ~(1 << WDRF);
  wdt_disable();
  wdt_enable(WDTO_2S);

  Serial.begin(115200);

  // Cek apakah terjadi reset akibat watchdog
  if (MCUSR & (1 << WDRF)) {

    Serial.println(
      "!!! RESET OTOMATIS (TERDETEKSI NOISE/CRASH) !!!"
    );

    MCUSR &= ~(1 << WDRF);

  } else {

    Serial.println(
      "Sistem PID MANUAL (TANPA LIBRARY) + WDT Siap!"
    );
  }

  // Konfigurasi pin
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  pinMode(PUMP_PIN, OUTPUT);

  // Pembacaan awal level air
  filteredLevel = getWaterLevel();
  Input = filteredLevel;

  Setpoint = 0;
}


// ================================================================
// LOOP UTAMA
// ================================================================
void loop() {

  // Reset watchdog agar Arduino tetap berjalan
  wdt_reset();


  // ==============================================================
  // 1. BACA SENSOR & LOW-PASS FILTER
  // ==============================================================
  double rawLevel = getWaterLevel();

  filteredLevel =
    (0.3 * rawLevel) +
    ((1.0 - 0.3) * filteredLevel);

  Input = filteredLevel;


  // ==============================================================
  // 2. BACA POTENSIOMETER UNTUK SETPOINT
  // ==============================================================
  long potSum = 0;

  for (int i = 0; i < 10; i++) {
    potSum += analogRead(POT_PIN);
  }

  int targetCm =
    map(
      potSum / 10,
      0,
      1023,
      0,
      14
    );

  Setpoint = (double)targetCm;


  // ==============================================================
  // 3. LOGIKA KENDALI POMPA
  //    PID + HISTERESIS
  // ==============================================================
  if (pumpRunning) {

    if (Input >= Setpoint || Output <= 5) {

      pumpRunning = false;

      // Reset integral untuk mencegah wind-up
      integralTerm = 0;

      Output = 0;
    }

  } else {

    if (Input <= (Setpoint - TURN_ON_THRESHOLD)) {
      pumpRunning = true;
    }
  }


  // ==============================================================
  // 4. HITUNG PID MANUAL
  // ==============================================================
  computePID();


  // ==============================================================
  // 5. MAPPING OUTPUT PID KE PWM
  // ==============================================================
  int actualPWM = 0;

  if (pumpRunning) {

    int outVal = (int)Output;

    if (outVal > 0) {

      actualPWM =
        map(
          outVal,
          1,
          255,
          MIN_PWM,
          255
        );

      if (actualPWM > 255) {
        actualPWM = 255;
      }

      if (actualPWM < MIN_PWM) {
        actualPWM = MIN_PWM;
      }

    } else {

      actualPWM = 0;
    }

  } else {

    actualPWM = 0;
  }

  // Kirim PWM ke pompa
  analogWrite(PUMP_PIN, actualPWM);


  // ==============================================================
  // 6. MONITORING SERIAL
  // ==============================================================
  if (millis() - lastPrintTime >= 1000) {

    Serial.print("SP:");
    Serial.print(Setpoint);

    Serial.print(" | Lvl:");
    Serial.print(Input);

    Serial.print(" | Err:");
    Serial.print(Setpoint - Input);

    Serial.print(" | Out:");
    Serial.print((int)Output);

    Serial.print(" | Jrk:");
    Serial.print(rawDistance);

    Serial.print("cm | PWM:");
    Serial.print(actualPWM);

    Serial.print(" | Stat:");
    Serial.println(
      pumpRunning ? "ON" : "OFF"
    );

    lastPrintTime = millis();
  }


  delay(50);
}


// ================================================================
// FUNGSI PID MANUAL DENGAN ANTI-WINDUP
// ================================================================
void computePID() {

  unsigned long now = millis();

  double timeChange =
    (now - lastPIDTime);


  // Jalankan PID setiap minimal 100 ms
  if (timeChange >= 100) {

    double error =
      Setpoint - Input;


    // ------------------------------------------------------------
    // PROPORTIONAL
    // ------------------------------------------------------------
    double P =
      Kp * error;


    // ------------------------------------------------------------
    // INTEGRAL
    // ------------------------------------------------------------
    integralTerm +=
      (Ki * error * timeChange / 1000.0);


    // ------------------------------------------------------------
    // ANTI-WINDUP
    // ------------------------------------------------------------
    if (integralTerm > 255) {
      integralTerm = 255;
    }

    if (integralTerm < 0) {
      integralTerm = 0;
    }


    // ------------------------------------------------------------
    // DERIVATIVE
    // ------------------------------------------------------------
    double dInput =
      (Input - lastInput);

    double D =
      Kd *
      (dInput / (timeChange / 1000.0));


    // ------------------------------------------------------------
    // OUTPUT PID
    // ------------------------------------------------------------
    Output =
      P +
      integralTerm -
      D;


    // ------------------------------------------------------------
    // CLAMPING OUTPUT PWM
    // ------------------------------------------------------------
    if (Output > 255) {
      Output = 255;
    }

    if (Output < 0) {
      Output = 0;
    }


    // Simpan nilai untuk perhitungan berikutnya
    lastInput = Input;
    lastPIDTime = now;
  }
}


// ================================================================
// FUNGSI BACA SENSOR DENGAN MEDIAN FILTER
// ================================================================
double getWaterLevel() {

  int distances[3];
  int validCount = 0;


  // Ambil 3 sampel sensor
  for (int i = 0; i < 3; i++) {

    digitalWrite(TRIG_PIN, LOW);
    delayMicroseconds(2);

    digitalWrite(TRIG_PIN, HIGH);
    delayMicroseconds(10);

    digitalWrite(TRIG_PIN, LOW);


    long duration =
      pulseIn(
        ECHO_PIN,
        HIGH,
        25000
      );


    if (duration > 0) {

      distances[validCount++] =
        duration * 0.034 / 2;
    }


    delay(5);
  }


  // Jika tidak ada data valid,
  // gunakan data jarak sebelumnya
  if (validCount == 0) {

    return TINGGI_GALON - rawDistance;
  }


  // Cari nilai median
  int medianDist =
    getMedian(
      distances,
      validCount
    );


  // Tolak perubahan jarak yang terlalu besar
  if (
    abs(medianDist - rawDistance) > 2 &&
    rawDistance > 0
  ) {

    return TINGGI_GALON - rawDistance;
  }


  // Simpan jarak terbaru
  rawDistance = medianDist;


  // Hitung level air
  double level =
    TINGGI_GALON - rawDistance;


  // Batasi level agar tidak melebihi tinggi galon
  if (level > TINGGI_GALON) {
    level = TINGGI_GALON;
  }

  if (level < 0) {
    level = 0;
  }


  return level;
}


// ================================================================
// FUNGSI MENCARI NILAI MEDIAN
// ================================================================
int getMedian(int arr[], int size) {

  for (int i = 0; i < size - 1; i++) {

    for (int j = i + 1; j < size; j++) {

      if (arr[i] > arr[j]) {

        int temp = arr[i];

        arr[i] = arr[j];
        arr[j] = temp;
      }
    }
  }


  return arr[size / 2];
}

Hasil Akhir Ikan Happy, Owner Santuy

Dengan menerapkan Sistem Pengendalian Ketinggian Air berbasis PID ini, Sobat Maker sudah melakukan langkah besar untuk efisiensi budidaya. Sistem ini terbukti mampu menjaga ketinggian air sangat dekat dengan target, merespon gangguan dengan halus, dan yang paling penting: menghilangkan kesalahan menetap (steady-state error).

Selain bikin ikan makin sehat karena kondisi kolam yang stabil, kamu juga bisa menghemat energi listrik dan bikin pompa lebih awet. Jadi nggak perlu lagi was-was setiap ninggalin kolam. Gimana, tertarik buat coba? Yuk, saatnya bikin kolam kamu makin pintar dan sat-set!

Bagikan ke

Jaga Kolam Ikan Tetap Stabil Pakai Arduino dan PID Biar Ikan Makin Happy

Saat ini belum tersedia komentar.

Silahkan tulis komentar Anda

Jaga Kolam Ikan Tetap Stabil Pakai Arduino dan PID Biar Ikan Makin Happy

Produk yang sangat tepat, pilihan bagus..!

Berhasil ditambahkan ke keranjang belanja
Lanjut Belanja
Checkout
Produk Quick Order

Pemesanan dapat langsung menghubungi kontak dibawah: