#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <OneWire.h>
#include <DallasTemperature.h>
// Konfigurasi WiFi dan Blynk
#define BLYNK_TEMPLATE_ID "TMPL6d6dZd9Gy"
#define BLYNK_TEMPLATE_NAME "Monitoring Kolam ikan"
#define BLYNK_AUTH_TOKEN "CfKEODfnRxw62UHqlN1OiyCwNDs7Tcbb"
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
// Pin Definition
#define RELAY_POMPA 25 // Relay pompa air
#define RELAY_SOLENOID 26 // Relay solenoid pakan
#define ALARM_PIN 27 // Buzzer alarm
#define TRIG_PIN 5 // Ultrasonic trigger
#define ECHO_PIN 18 // Ultrasonic echo
#define TEMP_SENSOR_PIN 4 // DS18B20 data pin
#define LIMIT_SWITCH_PIN 19 // Limit switch pakan
// Setup sensor suhu DS18B20
OneWire oneWire(TEMP_SENSOR_PIN);
DallasTemperature sensors(&oneWire);
// Variabel global
float waterLevel = 0; // Level air dalam cm
float waterTemp = 0; // Suhu air dalam °C
bool feedStock = false; // Status stok pakan
bool pumpState = false; // Status pompa
bool alarmState = false; // Status alarm
bool manualPump = false; // Kontrol manual pompa
bool manualAlarm = false; // Kontrol manual alarm
unsigned long lastFeedTime = 0;
const unsigned long FEED_INTERVAL = 120000; // 2 menit
const unsigned long FEED_DURATION = 3000; // 3 detik
bool feedingInProgress = false;
unsigned long feedStartTime = 0;
BlynkTimer timer;
// Virtual Pins Blynk
#define VPIN_WATER_LEVEL V0
#define VPIN_WATER_TEMP V1
#define VPIN_FEED_STOCK V2
#define VPIN_PUMP_STATUS V3
#define VPIN_ALARM_STATUS V4
#define VPIN_PUMP_CONTROL V5
#define VPIN_ALARM_CONTROL V6
void setup() {
Serial.begin(115200);
// Setup pin modes
pinMode(RELAY_POMPA, OUTPUT);
pinMode(RELAY_SOLENOID, OUTPUT);
pinMode(ALARM_PIN, OUTPUT);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(LIMIT_SWITCH_PIN, INPUT_PULLUP);
// Inisialisasi relay dalam kondisi OFF
digitalWrite(RELAY_POMPA, LOW);
digitalWrite(RELAY_SOLENOID, LOW);
digitalWrite(ALARM_PIN, LOW);
// Inisialisasi sensor suhu
sensors.begin();
// Koneksi ke Blynk
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
// Setup timer untuk pembacaan sensor
timer.setInterval(1000L, readSensors); // Baca sensor setiap 1 detik
timer.setInterval(500L, controlSystem); // Kontrol sistem setiap 0.5 detik
timer.setInterval(100L, handleFeeding); // Handle feeding setiap 0.1 detik
Serial.println("Sistem Monitoring Kolam Ikan Started");
}
void loop() {
Blynk.run();
timer.run();
}
// Fungsi membaca sensor ultrasonic (level air)
float readWaterLevel() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH, 30000);
if (duration == 0) {
return waterLevel; // Kembalikan nilai sebelumnya jika gagal baca
}
float distance = duration * 0.034 / 2; // Jarak sensor ke permukaan air (cm)
float level = 150 - distance; // Asumsi tinggi kolam 150cm
// Filter nilai yang tidak masuk akal
if (level < 0) level = 0;
if (level > 150) level = 150;
return level;
}
// Fungsi membaca sensor suhu DS18B20
float readWaterTemp() {
sensors.requestTemperatures();
float temp = sensors.getTempCByIndex(0);
// Validasi pembacaan
if (temp == DEVICE_DISCONNECTED_C || temp < 0 || temp > 50) {
return waterTemp; // Kembalikan nilai sebelumnya jika gagal baca
}
return temp;
}
// Fungsi membaca limit switch pakan
bool readFeedStock() {
// LOW = ada pakan (switch tertekan), HIGH = tidak ada pakan
return digitalRead(LIMIT_SWITCH_PIN) == LOW;
}
// Fungsi membaca semua sensor
void readSensors() {
waterLevel = readWaterLevel();
waterTemp = readWaterTemp();
feedStock = readFeedStock();
// Kirim data ke Blynk
Blynk.virtualWrite(VPIN_WATER_LEVEL, waterLevel);
Blynk.virtualWrite(VPIN_WATER_TEMP, waterTemp);
Blynk.virtualWrite(VPIN_FEED_STOCK, feedStock ? 1 : 0);
// Debug
Serial.printf("Level: %.1f cm | Suhu: %.1f °C | Pakan: %s\n",
waterLevel, waterTemp, feedStock ? "Ada" : "Habis");
}
// Fungsi kontrol sistem otomatis
void controlSystem() {
bool pumpNeeded = false;
bool alarmNeeded = false;
// Logika pompa air
// 1. Jika level air < 100cm, nyalakan pompa
if (waterLevel < 100) {
pumpNeeded = true;
}
// 2. Jika suhu > 28°C, nyalakan pompa untuk sirkulasi
if (waterTemp > 28) {
pumpNeeded = true;
}
// 3. Jika level air >= 100cm DAN suhu <= 28°C, matikan pompa
if (waterLevel >= 100 && waterTemp <= 28) {
pumpNeeded = false;
}
// Logika alarm
// Alarm bunyi jika pakan habis ATAU level air < 40cm
if (!feedStock || waterLevel < 40) {
alarmNeeded = true;
}
// Terapkan kontrol (kecuali jika manual override aktif)
if (!manualPump) {
setPump(pumpNeeded);
}
if (!manualAlarm) {
setAlarm(alarmNeeded);
}
}
// Fungsi handle pemberian pakan otomatis
void handleFeeding() {
unsigned long currentTime = millis();
// Cek apakah sedang dalam proses feeding
if (feedingInProgress) {
if (currentTime - feedStartTime >= FEED_DURATION) {
// Matikan solenoid setelah 3 detik
digitalWrite(RELAY_SOLENOID, LOW);
feedingInProgress = false;
Serial.println("Feeding selesai");
}
} else {
// Cek apakah sudah waktunya feeding (setiap 2 menit)
if (currentTime - lastFeedTime >= FEED_INTERVAL) {
// Beri pakan hanya jika stok pakan masih ada
if (feedStock) {
digitalWrite(RELAY_SOLENOID, HIGH);
feedingInProgress = true;
feedStartTime = currentTime;
lastFeedTime = currentTime;
Serial.println("Memberi pakan...");
} else {
Serial.println("Pakan habis! Tidak bisa memberi pakan.");
lastFeedTime = currentTime; // Reset timer
}
}
}
}
// Fungsi kontrol pompa
void setPump(bool state) {
if (pumpState != state) {
pumpState = state;
digitalWrite(RELAY_POMPA, state ? HIGH : LOW);
Blynk.virtualWrite(VPIN_PUMP_STATUS, state ? 1 : 0);
Serial.printf("Pompa: %s\n", state ? "ON" : "OFF");
}
}
// Fungsi kontrol alarm
void setAlarm(bool state) {
if (alarmState != state) {
alarmState = state;
digitalWrite(ALARM_PIN, state ? HIGH : LOW);
Blynk.virtualWrite(VPIN_ALARM_STATUS, state ? 1 : 0);
Serial.printf("Alarm: %s\n", state ? "ON" : "OFF");
}
}
// Blynk: Kontrol manual pompa dari dashboard
BLYNK_WRITE(VPIN_PUMP_CONTROL) {
int value = param.asInt();
manualPump = (value == 1);
if (manualPump) {
setPump(true);
Serial.println("Pompa: Manual ON");
} else {
Serial.println("Pompa: Mode Otomatis");
}
}
// Blynk: Kontrol manual alarm dari dashboard
BLYNK_WRITE(VPIN_ALARM_CONTROL) {
int value = param.asInt();
manualAlarm = (value == 1);
if (manualAlarm) {
setAlarm(true);
Serial.println("Alarm: Manual ON");
} else {
Serial.println("Alarm: Mode Otomatis");
}
}
// Blynk: Sinkronisasi saat connect
BLYNK_CONNECTED() {
Serial.println("Connected to Blynk!");
Blynk.syncVirtual(VPIN_PUMP_CONTROL);
Blynk.syncVirtual(VPIN_ALARM_CONTROL);
}Loading
ds18b20
ds18b20