Upload files to "Kode Program Arduino IDE"

This commit is contained in:
Muhammad_Egardy_H 2024-07-30 10:31:54 +07:00
parent 77e61b6faf
commit 5d4a945c07
1 changed files with 382 additions and 0 deletions

View File

@ -0,0 +1,382 @@
#include <WiFi.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <ESP32Servo.h>
#include <RTClib.h>
#include <Firebase_ESP_Client.h>
#include <ArduinoJson.h>
#include "addons/TokenHelper.h"
#include "addons/RTDBHelper.h"
#include <PubSubClient.h>
#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<JSON_DOCUMENT_SIZE> 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<String>());
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<int>(), doc["pagi"].as<int>(),
doc["siang"].as<int>(), doc["siang"].as<int>(),
doc["malam"].as<int>(), doc["malam"].as<int>()); // 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);
}
}
}