From 5d4a945c07a7ceb448662ec9f6894ac69acc87f4 Mon Sep 17 00:00:00 2001 From: Muhammad_Egardy_H <18.megardy@gmail.com> Date: Tue, 30 Jul 2024 10:31:54 +0700 Subject: [PATCH] Upload files to "Kode Program Arduino IDE" --- .../sketch_jun7bMANUAL1.ino | 382 ++++++++++++++++++ 1 file changed, 382 insertions(+) create mode 100644 Kode Program Arduino IDE/sketch_jun7bMANUAL1.ino diff --git a/Kode Program Arduino IDE/sketch_jun7bMANUAL1.ino b/Kode Program Arduino IDE/sketch_jun7bMANUAL1.ino new file mode 100644 index 0000000..cb1e1b7 --- /dev/null +++ b/Kode Program Arduino IDE/sketch_jun7bMANUAL1.ino @@ -0,0 +1,382 @@ +#include +#include +#include +#include +#include +#include +#include +#include "addons/TokenHelper.h" +#include "addons/RTDBHelper.h" +#include + +#define LCD_ADDR 0x27 +#define LCD_COLS 16 +#define LCD_ROWS 2 + +#define API_KEY "AIzaSyBvMyCNKKCBrSjDaArHc3VF7TpjqJOYNS4" +#define DATABASE_URL "https://jam-makan-default-rtdb.asia-southeast1.firebasedatabase.app" + +// Pin konfigurasi +#define SERVO_PIN 13 + +// Inisialisasi komponen +Servo servo; +RTC_DS3231 rtc; +LiquidCrystal_I2C lcd(LCD_ADDR, LCD_COLS, LCD_ROWS); + +FirebaseData fbdo; +FirebaseAuth auth; +FirebaseConfig config; +#define JSON_DOCUMENT_SIZE 1024 +StaticJsonDocument doc; + +// Deklarasi Fungsi +String hitungWaktuPakanTerdekat(int jam, int menit, int pagi_hour, int pagi_minute, int siang_hour, int siang_minute, int malam_hour, int malam_minute); +DateTime kalibrasiWaktu(const DateTime& dt); // Tambahkan deklarasi fungsi kalibrasiWaktu + +unsigned long sendDataPrevMillis = 0; +bool signupOK = false; +unsigned long servoFinishTime = 0; +const unsigned long fetchInterval = 15000; // 15 detik +String waktuPakanTerdekat; +bool servoFinished = false; + +// Variabel untuk menyimpan jumlah putaran servo untuk setiap waktu makan +int pagiPutaran = 0; +int siangPutaran = 0; +int malamPutaran = 0; + +// Variabel status untuk melacak aktivasi servo +bool pagiPakanDiberikan = false; +bool siangPakanDiberikan = false; +bool malamPakanDiberikan = false; +const char* mqtt_server = "broker.hivemq.com"; +const char* topic = "piCo/manualFeed"; +WiFiClient espClient; +PubSubClient client(espClient); + +// Fungsi untuk kalibrasi waktu RTC +DateTime kalibrasiWaktu(const DateTime& dt) { + int seconds = dt.second() + 15; + int minutes = dt.minute(); + int hours = dt.hour(); + int days = dt.day(); + int months = dt.month(); + int years = dt.year(); + + // Atur detik + if (seconds >= 60) { + seconds -= 60; + minutes++; + if (minutes >= 60) { + minutes -= 60; + hours++; + if (hours >= 24) { + hours -= 24; + days++; + // Anda bisa menambahkan kode untuk menangani bulan dan tahun jika diperlukan + } + } + } + + return DateTime(years, months, days, hours, minutes, seconds); +} + +void setup() { + Serial.begin(57600); + Wire.begin(); + servo.attach(SERVO_PIN); + if (!rtc.begin()) { + Serial.println("RTC tidak ditemukan!"); + while (1); + } + if (rtc.lostPower()) { + Serial.println("RTC kehilangan daya, set waktu ke waktu kompilasi!"); + rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); + } + lcd.init(); + lcd.backlight(); + + // Tampilkan pesan selamat datang + lcd.setCursor(0, 0); + lcd.print(" PiCo"); + lcd.setCursor(0, 1); + lcd.print(" Initializing"); + + // Tunggu beberapa detik + delay(2000); + + // Inisialisasi WiFi + Serial.println(); + Serial.println("Menghubungkan ke WiFi..."); + WiFi.begin("POCO F4", "123456789"); // Ganti SSID dan password dengan yang sesuai + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(""); + Serial.println("WiFi terhubung"); + Serial.println("Alamat IP: "); + Serial.println(WiFi.localIP()); + Serial.println("Menghubungkan ke Firebase..."); + setupFirebase(); + + client.setServer(mqtt_server, 1883); + client.setCallback(callback); + + while (!client.connected()) { + String client_id = "esp32-client-"; + client_id += String(WiFi.macAddress()); + Serial.printf("The client %s connects to the public mqtt broker\n", client_id.c_str()); + if (client.connect(client_id.c_str())) { + Serial.println("Public emqx mqtt broker connected"); + } else { + Serial.print("failed with state "); + Serial.print(client.state()); + delay(2000); + } + } + // publish and subscribe + client.publish(topic, "Hi EMQX I'm ESP32 ^^"); + client.subscribe(topic); +} + +void reconnect() { + // Loop until we're reconnected + while (!client.connected()) { + Serial.print("Attempting MQTT connection..."); + // Attempt to connect + if (client.connect("ESP32Client")) { + Serial.println("connected"); + // Subscribe + client.subscribe("piCo/manualFeed"); + } else { + Serial.print("failed, rc="); + Serial.print(client.state()); + Serial.println(" try again in 5 seconds"); + // Wait 5 seconds before retrying + delay(5000); + } + } +} + +void callback(char* topic, byte* message, unsigned int length) { + Serial.print("Message arrived on topic: "); + Serial.print(topic); + Serial.print(". Message: "); + String messageTemp; + + for (int i = 0; i < length; i++) { + Serial.print((char)message[i]); + messageTemp += (char)message[i]; + } + Serial.println(); + + if (String(topic) == "piCo/manualFeed") { + if (messageTemp == "Makan") { + Serial.println("Pemberian pakan manual"); + activateServo(1); // Ganti angka dengan jumlah putaran servo yang diinginkan + } + } +} + +void loop() { + DateTime now = rtc.now(); + // Kalibrasi waktu + DateTime kalibrasiNow = kalibrasiWaktu(now); + + if (!client.connected()) { + reconnect(); + } + client.loop(); + getDataFromFirebase(kalibrasiNow); + tampilkanWaktuDanJadwal(kalibrasiNow); + delay(1000); +} + +// Fungsi untuk mengaktifkan servo +void activateServo(int putaran) { + Serial.print("Makan Done"); + servo.write(90); // Putar servo ke posisi tengah (contoh) + delay(1000); // Tunggu satu detik + for (int i = 0; i < putaran; i++) { + servo.write(90); // Putar servo ke posisi maksimal + delay(1000); // Tunggu satu detik + servo.write(0); // Kembalikan servo ke posisi awal (contoh) + delay(1000); // Tunggu satu detik + } + servo.write(90); // Kembalikan servo ke posisi tengah (contoh) + Serial.println("Makan selesai"); + servoFinished = true; // Set flag untuk menampilkan notifikasi "selesai" + servoFinishTime = millis(); // Catat waktu selesai servo +} + +// Fungsi untuk mengonfigurasi Firebase +void setupFirebase() { + config.api_key = API_KEY; + config.database_url = DATABASE_URL; + + if (Firebase.signUp(&config, &auth, "", "")) { + Serial.println("Signup berhasil"); + signupOK = true; + } else { + Serial.printf("Signup gagal, %s\n", config.signer.signupError.message.c_str()); + } + + config.token_status_callback = tokenStatusCallback; // Mengatur callback status token + + Firebase.begin(&config, &auth); + Firebase.reconnectWiFi(true); +} + +void getDataFromFirebase(const DateTime& dt) { + Serial.println("Masuk ke fungsi getDataFromFirebase"); + + if (Firebase.ready() && signupOK) { + Serial.println("Firebase siap dan signup berhasil"); + + if (Firebase.RTDB.getJSON(&fbdo, "/jam_makan")) { + Serial.println("Data diambil dari Firebase"); + + // Deserialisasi JSON + DeserializationError error = deserializeJson(doc, fbdo.to()); + if (error) { + Serial.print("deserializeJson() gagal: "); + Serial.println(error.c_str()); + } else { + Serial.println("deserializeJson() berhasil"); + + const char* malam = doc["malam"]; + const char* pagi = doc["pagi"]; + const char* siang = doc["siang"]; + pagiPutaran = doc["pagiPutaran"]; + siangPutaran = doc["siangPutaran"]; + malamPutaran = doc["malamPutaran"]; + + Serial.print("Malam: "); + Serial.println(malam); + Serial.print("Pagi: "); + Serial.println(pagi); + Serial.print("Siang: "); + Serial.println(siang); + Serial.print("Putaran Pagi: "); + Serial.println(pagiPutaran); + Serial.print("Putaran Siang: "); + Serial.println(siangPutaran); + Serial.print("Putaran Malam: "); + Serial.println(malamPutaran); + + int jam = dt.hour(); + int menit = dt.minute(); + + String malamStr = String(malam); + String pagiStr = String(pagi); + String siangStr = String(siang); + + int malam_hour = malamStr.substring(0, malamStr.indexOf(":")).toInt(); + int malam_minute = malamStr.substring(malamStr.indexOf(":") + 1).toInt(); + int pagi_hour = pagiStr.substring(0, pagiStr.indexOf(":")).toInt(); + int pagi_minute = pagiStr.substring(pagiStr.indexOf(":") + 1).toInt(); + int siang_hour = siangStr.substring(0, siangStr.indexOf(":")).toInt(); + int siang_minute = siangStr.substring(siangStr.indexOf(":") + 1).toInt(); + + // Menghitung waktu pakan terdekat + waktuPakanTerdekat = hitungWaktuPakanTerdekat(jam, menit, pagi_hour, pagi_minute, siang_hour, siang_minute, malam_hour, malam_minute); + + // Memastikan servo hanya berputar sekali pada waktu yang ditentukan + if (jam == malam_hour && menit == malam_minute && !malamPakanDiberikan) { + activateServo(malamPutaran); + malamPakanDiberikan = true; + } else if (jam != malam_hour || menit != malam_minute) { + malamPakanDiberikan = false; + } + + if (jam == pagi_hour && menit == pagi_minute && !pagiPakanDiberikan) { + activateServo(pagiPutaran); + pagiPakanDiberikan = true; + } else if (jam != pagi_hour || menit != pagi_minute) { + pagiPakanDiberikan = false; + } + + if (jam == siang_hour && menit == siang_minute && !siangPakanDiberikan) { + activateServo(siangPutaran); + siangPakanDiberikan = true; + } else if (jam != siang_hour || menit != siang_minute) { + siangPakanDiberikan = false; + } + + Serial.println("Waktu pakan terdekat: " + waktuPakanTerdekat); + Serial.print("Jam RTC: "); + Serial.print(jam); + Serial.print(":"); + Serial.println(menit); + } + } else { + Serial.println("Gagal mengambil data dari Firebase: " + fbdo.errorReason()); + } + } else { + Serial.println("Firebase tidak siap atau signup gagal"); + } +} + +String hitungWaktuPakanTerdekat(int jam, int menit, int pagi_hour, int pagi_minute, int siang_hour, int siang_minute, int malam_hour, int malam_minute) { + int currentMinutes = jam * 60 + menit; + int pagiMinutes = pagi_hour * 60 + pagi_minute; + int siangMinutes = siang_hour * 60 + siang_minute; + int malamMinutes = malam_hour * 60 + malam_minute; + + int minDiff = 1440; // Jumlah menit dalam satu hari + String nearestTime; + + if (pagiMinutes > currentMinutes && pagiMinutes - currentMinutes < minDiff) { + minDiff = pagiMinutes - currentMinutes; + nearestTime = String(pagi_hour) + ":" + (pagi_minute < 10 ? "0" : "") + String(pagi_minute); + } + if (siangMinutes > currentMinutes && siangMinutes - currentMinutes < minDiff) { + minDiff = siangMinutes - currentMinutes; + nearestTime = String(siang_hour) + ":" + (siang_minute < 10 ? "0" : "") + String(siang_minute); + } + if (malamMinutes > currentMinutes && malamMinutes - currentMinutes < minDiff) { + minDiff = malamMinutes - currentMinutes; + nearestTime = String(malam_hour) + ":" + (malam_minute < 10 ? "0" : "") + String(malam_minute); + } + + // Jika tidak ada waktu pakan tersisa untuk hari ini, set ke jadwal pakan pertama besok + if (nearestTime == "") { + nearestTime = String(pagi_hour) + ":" + (pagi_minute < 10 ? "0" : "") + String(pagi_minute); + } + + return nearestTime; +} + +void tampilkanWaktuDanJadwal(const DateTime& dt) { + char currentTime[16]; + snprintf(currentTime, sizeof(currentTime), "%02d:%02d:%02d", dt.hour(), dt.minute(), dt.second()); + + lcd.clear(); + lcd.setCursor(0, 0); + lcd.print("Waktu: "); + lcd.print(currentTime); + + lcd.setCursor(0, 1); + if (servoFinished) { + if (millis() - servoFinishTime < 5000) { + lcd.print("Pakan selesai"); + } else { + servoFinished = false; + waktuPakanTerdekat = hitungWaktuPakanTerdekat(dt.hour(), dt.minute(), + doc["pagi"].as(), doc["pagi"].as(), + doc["siang"].as(), doc["siang"].as(), + doc["malam"].as(), doc["malam"].as()); // Perbarui jadwal berikutnya + } + } else { + // Tambahkan 0 di depan jam jika jam kurang dari 10 + if (waktuPakanTerdekat[1] == ':') { + lcd.print("Pakan: 0"); + lcd.print(waktuPakanTerdekat); + } else { + lcd.print("Pakan: "); + lcd.print(waktuPakanTerdekat); + } + } +}