// Blynk credentials #define BLYNK_TEMPLATE_ID "TMPL6TZRl9SiF" #define BLYNK_TEMPLATE_NAME "Monitoring Ketersediaan Pakan Ikan" #define BLYNK_AUTH_TOKEN "W0ak_qwmrPkN8hVrmptQDG_2IYXu3Ftu" #include #include #include #include "RTClib.h" #include #include #include // WiFi credentials char ssid[] = "dewi"; char pass[] = "dewi1234"; // Blynk virtual pins #define V1_DISTANCE V1 #define V2_MANUAL_FEED V2 // Tampilan LCD LiquidCrystal_I2C lcd(0x27, 16, 2); // Alamat I2C 0x27, LCD 16x2 // RTC RTC_DS3231 rtc; char hariDalamSeminggu[7][12] = {"Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu"}; // Servo dan Buzzer Servo servoKatup; const int SERVO_PIN = 17; const int BUZZER_PIN = 16; // Sensor Ultrasonik const int TRIG_PIN = 19; const int ECHO_PIN = 18; long durasi; float jarak; const float MAKS_JARAK = 200.0; // Batas maksimum pembacaan jarak yang masuk akal // Waktu pemberian pakan const int JAM_PAGI = 7; const int MENIT_PAGI = 0; const int JAM_SORE = 16; const int MENIT_SORE = 0; // Fungsi untuk memperbarui jarak void updateJarak() { // Kirim pulsa ultrasonik digitalWrite(TRIG_PIN, LOW); delayMicroseconds(2); digitalWrite(TRIG_PIN, HIGH); delayMicroseconds(10); digitalWrite(TRIG_PIN, LOW); // Hitung durasi pulsa dan konversi ke jarak durasi = pulseIn(ECHO_PIN, HIGH); jarak = durasi * 0.034 / 2; // Saring pembacaan jarak yang tidak masuk akal if (jarak > MAKS_JARAK) { jarak = MAKS_JARAK; } } // Fungsi untuk mengonversi jarak ke ukuran pakan int konversiUkuranPakan(float x) { x = 10 - jarak; if (jarak > 1) { return x; } delay(1000); } // Fungsi untuk menampilkan informasi di LCD void tampilkanInformasi(DateTime sekarang, int ukuranPakan) { lcd.clear(); // Tampilkan hari di pojok kiri atas lcd.setCursor(0, 0); lcd.print(hariDalamSeminggu[sekarang.dayOfTheWeek()]); // Tampilkan jam di pojok kanan atas lcd.setCursor(7, 0); // Sesuaikan posisi agar muat di layar if (sekarang.hour() < 10) lcd.print('0'); // Tambahkan nol di depan jam jika kurang dari 10 lcd.print(sekarang.hour(), DEC); lcd.print(':'); if (sekarang.minute() < 10) lcd.print('0'); // Tambahkan nol di depan menit jika kurang dari 10 lcd.print(sekarang.minute(), DEC); lcd.print(':'); if (sekarang.second() < 10) lcd.print('0'); // Tambahkan nol di depan detik jika kurang dari 10 lcd.print(sekarang.second(), DEC); // Tampilkan tanggal di pojok kiri bawah lcd.setCursor(0, 1); if (sekarang.day() < 10) lcd.print('0'); // Tambahkan nol di depan tanggal jika kurang dari 10 lcd.print(sekarang.day(), DEC); lcd.print('/'); if (sekarang.month() < 10) lcd.print('0'); // Tambahkan nol di depan bulan jika kurang dari 10 lcd.print(sekarang.month(), DEC); lcd.print('/'); lcd.print(sekarang.year(), DEC); } // Fungsi untuk menampilkan informasi pemberian pakan void tampilkanPemberianPakan() { lcd.clear(); lcd.setCursor(0, 0); lcd.print("Pemberian Pakan"); lcd.setCursor(0, 1); lcd.print("Sedang Diberikan"); } // Fungsi untuk membuka katup pakan void bukaKatupPakan() { tampilkanPemberianPakan(); // Putar servo untuk membuka dan menutup katup beberapa kali for (int i = 0; i < 5; i++) { servoKatup.write(90); // Sesuaikan sudut untuk membuka katup delay(1000); // Tunggu sampai katup terbuka servoKatup.write(0); // Tutup kembali katup delay(1000); // Tunggu sebelum putaran berikutnya } } // Fungsi untuk mengisi pakan void isiPakan() { // Bunyikan buzzer jika jarak lebih dari 10 cm if (jarak > 8) { digitalWrite(BUZZER_PIN, HIGH); // Aktifkan buzzer delay(1000); // Bunyikan buzzer selama 1 detik digitalWrite(BUZZER_PIN, LOW); // Matikan buzzer } } // Blynk virtual pin handler BLYNK_WRITE(V2_MANUAL_FEED) { int state = param.asInt(); if (state == 1) { bukaKatupPakan(); } } void setup() { Serial.begin(115200); lcd.init(); // Inisialisasi LCD lcd.backlight(); // Aktifkan backlight LCD // Menampilkan pesan koneksi Wi-Fi di LCD lcd.setCursor(0, 0); lcd.print("Menghubungkan ke"); lcd.setCursor(0, 1); lcd.print("WiFi..."); // WiFi setup WiFi.begin(ssid, pass); // Tunggu sampai terhubung ke WiFi while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); lcd.setCursor(0, 1); lcd.print("WiFi..."); } lcd.clear(); lcd.setCursor(0, 0); lcd.print("Terhubung ke WiFi"); lcd.setCursor(0, 1); lcd.print(WiFi.localIP()); // Blynk setup Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass); if (!rtc.begin()) { Serial.println("RTC tidak ditemukan"); while (1); } if (rtc.lostPower()) { Serial.println("RTC kehilangan daya, mari kita atur waktunya!"); rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // Atur RTC ke waktu saat ini dari komputer } // Inisialisasi servo, buzzer, dan sensor ultrasonik servoKatup.attach(SERVO_PIN); pinMode(BUZZER_PIN, OUTPUT); servoKatup.write(0); // Pastikan katup tertutup pada awalnya pinMode(TRIG_PIN, OUTPUT); pinMode(ECHO_PIN, INPUT); } void loop() { Blynk.run(); DateTime sekarang = rtc.now(); updateJarak(); // Perbarui pembacaan jarak int ukuranPakan = konversiUkuranPakan(jarak); // Konversi jarak ke ukuran pakan Serial.print("Jarak: "); Serial.print(jarak); Serial.print(" cm, Ukuran Pakan: "); Serial.println(ukuranPakan); // Cetak jarak dan ukuran pakan di Serial Monitor tampilkanInformasi(sekarang, ukuranPakan); // Tampilkan informasi di LCD // Kirim data ke Blynk Blynk.virtualWrite(V1_DISTANCE, ukuranPakan); // Berikan pakan sesuai jadwal if ((sekarang.hour() == JAM_PAGI && sekarang.minute() == MENIT_PAGI && sekarang.second() == 0) || (sekarang.hour() == JAM_SORE && sekarang.minute() == MENIT_SORE && sekarang.second() == 0)) { bukaKatupPakan(); } // Periksa jarak dan bunyikan buzzer jika perlu isiPakan(); delay(1000); }