Upload files to "Kode Program Arduino IDE"
This commit is contained in:
parent
77e61b6faf
commit
5d4a945c07
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue