first init github
This commit is contained in:
commit
e335d76ba1
|
@ -0,0 +1,320 @@
|
|||
code asli
|
||||
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <Firebase_ESP_Client.h>
|
||||
#include <OneWire.h>
|
||||
#include <DallasTemperature.h>
|
||||
#include <time.h>
|
||||
#include <Wire.h>
|
||||
#include <LiquidCrystal_I2C.h>
|
||||
#include <ESP32Servo.h>
|
||||
#include <RTClib.h>
|
||||
#include <HTTPClient.h>
|
||||
|
||||
|
||||
// WiFi credentials
|
||||
const char* ssid = "HIDROFISH";
|
||||
const char* password = "ikan1234";
|
||||
|
||||
// Firebase config
|
||||
#define API_KEY "AIzaSyCIJ5xVWDHHuhLGKV-OFYlLXBvjrKtI7ic"
|
||||
#define DATABASE_URL "https://hydrofish-e00a3-default-rtdb.firebaseio.com/"
|
||||
#define LEGACY_TOKEN "m2l1lmVvUrVTfUmwfkN5bVNKzifh2nM8DNLSd3c2"
|
||||
|
||||
// Pin definitions
|
||||
#define TDS_PIN 34
|
||||
#define TURBIDITY_PIN 33
|
||||
#define PH_PIN 35
|
||||
#define TRIG_PIN 26
|
||||
#define ECHO_PIN 25
|
||||
#define DS18B20_PIN 32
|
||||
#define BUZZER_PIN 15
|
||||
#define LED_PIN 2
|
||||
#define SERVO_PIN 19
|
||||
|
||||
// Objects
|
||||
RTC_DS3231 rtc;
|
||||
FirebaseData fbdo;
|
||||
FirebaseAuth auth;
|
||||
FirebaseConfig config;
|
||||
OneWire oneWire(DS18B20_PIN);
|
||||
DallasTemperature sensors(&oneWire);
|
||||
LiquidCrystal_I2C lcd(0x27, 16, 2);
|
||||
Servo feederServo;
|
||||
|
||||
// Variables
|
||||
bool firebaseConnected = false;
|
||||
int lcdScreen = 0;
|
||||
String pagiTime = "08:00";
|
||||
String soreTime = "13:00";
|
||||
String malemTime = "19:00";
|
||||
int jumlahTakar = 1;
|
||||
String lastFeedingTime = "";
|
||||
unsigned long previousMillis = 0;
|
||||
const long interval = 5000;
|
||||
|
||||
float ph_slope = -6.548;
|
||||
float ph_offset = 25.69;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
unsigned long lastHistorySentMillis = 0;
|
||||
int intervalHistoryMinutes = 5; // default 5 menit
|
||||
|
||||
|
||||
// ===================== SETUP =====================
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Wire.begin(22, 21);
|
||||
sensors.begin();
|
||||
lcd.init();
|
||||
lcd.backlight();
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
pinMode(TRIG_PIN, OUTPUT);
|
||||
pinMode(ECHO_PIN, INPUT);
|
||||
pinMode(BUZZER_PIN, OUTPUT);
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
|
||||
analogReadResolution(12);
|
||||
feederServo.attach(SERVO_PIN);
|
||||
feederServo.write(0);
|
||||
|
||||
setupWiFi();
|
||||
|
||||
if (!rtc.begin()) {
|
||||
Serial.println("RTC tidak ditemukan!");
|
||||
while (1);
|
||||
}
|
||||
|
||||
if (rtc.lostPower()) {
|
||||
Serial.println("RTC kehilangan daya, set waktu ke waktu compile.");
|
||||
rtc.adjust(DateTime(F(_DATE), F(TIME_)));
|
||||
}
|
||||
|
||||
configTime(7 * 3600, 0, "pool.ntp.org", "time.nist.gov");
|
||||
|
||||
setupFirebase();
|
||||
}
|
||||
|
||||
// ===================== WIFI SETUP =====================
|
||||
void setupWiFi() {
|
||||
Serial.print("Menghubungkan ke WiFi...");
|
||||
WiFi.begin(ssid, password);
|
||||
unsigned long startTime = millis();
|
||||
while (WiFi.status() != WL_CONNECTED && millis() - startTime < 10000) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
Serial.println("\nWiFi terhubung!");
|
||||
Serial.print("IP: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
} else {
|
||||
Serial.println("\nGagal terhubung ke WiFi.");
|
||||
}
|
||||
}
|
||||
|
||||
// ===================== FIREBASE SETUP =====================
|
||||
void setupFirebase() {
|
||||
config.api_key = API_KEY;
|
||||
config.database_url = DATABASE_URL;
|
||||
config.signer.tokens.legacy_token = LEGACY_TOKEN;
|
||||
Firebase.begin(&config, &auth);
|
||||
Firebase.reconnectWiFi(true);
|
||||
}
|
||||
|
||||
void getIntervalHistory() {
|
||||
if (WiFi.status() != WL_CONNECTED) return;
|
||||
if (Firebase.RTDB.getInt(&fbdo, "/setting/interval_history")) {
|
||||
intervalHistoryMinutes = fbdo.intData();
|
||||
Serial.print("Interval history diambil dari Firebase: ");
|
||||
Serial.print(intervalHistoryMinutes);
|
||||
Serial.println(" menit");
|
||||
} else {
|
||||
Serial.println("Gagal ambil interval_history: " + fbdo.errorReason());
|
||||
}
|
||||
}
|
||||
|
||||
void kirimHistoryKeServer(float ph, float suhu, float tds, float tinggi, String turbidity) {
|
||||
if (WiFi.status() != WL_CONNECTED) return;
|
||||
|
||||
HTTPClient http;
|
||||
http.begin("https://hydrofish-api-2ywj.vercel.app/api/kirimdata");
|
||||
http.addHeader("Content-Type", "application/json");
|
||||
|
||||
// Dapatkan waktu UTC ISO 8601
|
||||
time_t now;
|
||||
struct tm timeinfo;
|
||||
if (!getLocalTime(&timeinfo)) {
|
||||
Serial.println("Gagal mendapatkan waktu");
|
||||
return;
|
||||
}
|
||||
char timestamp[30];
|
||||
strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%S.000Z", &timeinfo);
|
||||
|
||||
String json = "{";
|
||||
json += "\"ph_air\":" + String(ph, 2) + ",";
|
||||
json += "\"suhu_air\":" + String(suhu, 2) + ",";
|
||||
json += "\"tds\":" + String(tds, 2) + ",";
|
||||
json += "\"timestamp\":\"" + String(timestamp) + "\",";
|
||||
json += "\"tinggi_air\":" + String(tinggi, 1) + ",";
|
||||
json += "\"turbidity\":\"" + turbidity + "\"";
|
||||
json += "}";
|
||||
|
||||
int httpResponseCode = http.POST(json);
|
||||
if (httpResponseCode > 0) {
|
||||
Serial.print("Data history terkirim: ");
|
||||
Serial.println(httpResponseCode);
|
||||
} else {
|
||||
Serial.print("Gagal kirim data history: ");
|
||||
Serial.println(httpResponseCode);
|
||||
}
|
||||
http.end();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ===================== WAKTU =====================
|
||||
String getRTCTime() {
|
||||
DateTime now = rtc.now();
|
||||
char buffer[6];
|
||||
sprintf(buffer, "%02d:%02d", now.hour(), now.minute());
|
||||
return String(buffer);
|
||||
}
|
||||
|
||||
String getCurrentTime() {
|
||||
struct tm timeinfo;
|
||||
if (WiFi.status() == WL_CONNECTED && getLocalTime(&timeinfo)) {
|
||||
char buffer[6];
|
||||
sprintf(buffer, "%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min);
|
||||
return String(buffer);
|
||||
} else {
|
||||
return getRTCTime(); // fallback ke RTC
|
||||
}
|
||||
}
|
||||
|
||||
// ===================== SENSOR =====================
|
||||
float konversiKeNTU(float voltage) {
|
||||
float ntu = -1120.4 * voltage * voltage + 5742.3 * voltage - 4352.9;
|
||||
return (ntu < 0) ? 0 : ntu;
|
||||
}
|
||||
|
||||
String bacaKekeruhan(float voltage) {
|
||||
return (konversiKeNTU(voltage) < 1500.0) ? "Keruh" : "Jernih";
|
||||
}
|
||||
|
||||
void cekKekeruhan(float voltage) {
|
||||
digitalWrite(BUZZER_PIN, (konversiKeNTU(voltage) < 1500.0) ? HIGH : LOW);
|
||||
}
|
||||
|
||||
void updateLCD(float tds, float turbidity, float phV, float ph, float tinggi, float suhu) {
|
||||
lcd.clear();
|
||||
switch (lcdScreen) {
|
||||
case 0: lcd.setCursor(0, 0); lcd.print("Hydrofish"); lcd.setCursor(0, 1); lcd.print("Monitoring..."); break;
|
||||
case 1: lcd.setCursor(0, 0); lcd.print("pH Air: "); lcd.print(ph, 2); break;
|
||||
case 2: lcd.setCursor(0, 0); lcd.print("Suhu: "); lcd.print(suhu, 1); lcd.print((char)223); lcd.print("C"); break;
|
||||
case 3: lcd.setCursor(0, 0); lcd.print("TDS: "); lcd.print(tds, 2); lcd.print(" ppm"); break;
|
||||
case 4: lcd.setCursor(0, 0); lcd.print("Tinggi: "); lcd.print(tinggi, 1); lcd.print(" cm"); break;
|
||||
case 5: lcd.setCursor(0, 0); lcd.print("Kekeruhan: "); lcd.setCursor(0, 1); lcd.print(bacaKekeruhan(turbidity)); break;
|
||||
}
|
||||
lcdScreen = (lcdScreen + 1) % 6;
|
||||
}
|
||||
|
||||
void kirimKeFirebase(float tds, String status, float phV, float ph, float tinggi, float suhu) {
|
||||
if (WiFi.status() != WL_CONNECTED || !Firebase.ready()) return;
|
||||
|
||||
FirebaseJson json;
|
||||
json.set("tds", tds);
|
||||
json.set("turbidity", status);
|
||||
json.set("ph_voltage", phV);
|
||||
json.set("ph", ph);
|
||||
json.set("tinggi_air", tinggi);
|
||||
json.set("suhu", suhu);
|
||||
|
||||
if (Firebase.RTDB.setJSON(&fbdo, "/sensor_data", &json)) {
|
||||
Serial.println("Data terkirim ke Firebase");
|
||||
} else {
|
||||
Serial.println("Gagal kirim: " + fbdo.errorReason());
|
||||
}
|
||||
}
|
||||
|
||||
void getFeedingSchedule() {
|
||||
if (WiFi.status() != WL_CONNECTED) return;
|
||||
|
||||
if (Firebase.RTDB.getString(&fbdo, "/jadwal_pakan/pagi")) pagiTime = fbdo.stringData();
|
||||
if (Firebase.RTDB.getString(&fbdo, "/jadwal_pakan/sore")) soreTime = fbdo.stringData();
|
||||
if (Firebase.RTDB.getString(&fbdo, "/jadwal_pakan/malem")) malemTime = fbdo.stringData();
|
||||
if (Firebase.RTDB.getInt(&fbdo, "/jadwal_pakan/jumlah_takar")) jumlahTakar = fbdo.intData();
|
||||
}
|
||||
|
||||
void sendFeedingStatus(bool status) {
|
||||
if (WiFi.status() != WL_CONNECTED) return;
|
||||
FirebaseJson json;
|
||||
json.set("status_pakan", status);
|
||||
Firebase.RTDB.setJSON(&fbdo, "/sensor_data", &json);
|
||||
}
|
||||
|
||||
void performFeeding() {
|
||||
for (int i = 0; i < jumlahTakar; i++) {
|
||||
feederServo.write(180);
|
||||
delay(2000);
|
||||
feederServo.write(0);
|
||||
delay(2000);
|
||||
}
|
||||
}
|
||||
|
||||
// ===================== LOOP =====================
|
||||
void loop() {
|
||||
if (!firebaseConnected && WiFi.status() == WL_CONNECTED && Firebase.ready()) {
|
||||
firebaseConnected = true;
|
||||
digitalWrite(LED_PIN, HIGH);
|
||||
Serial.println("Firebase connected.");
|
||||
}
|
||||
|
||||
String currentTime = getCurrentTime();
|
||||
getFeedingSchedule();
|
||||
getIntervalHistory(); // Ambil interval dari Firebase
|
||||
|
||||
|
||||
if ((currentTime == pagiTime || currentTime == soreTime || currentTime == malemTime) && lastFeedingTime != currentTime) {
|
||||
performFeeding();
|
||||
sendFeedingStatus(true);
|
||||
lastFeedingTime = currentTime;
|
||||
}
|
||||
|
||||
float tdsV = (analogRead(TDS_PIN) / 4095.0) * 3.3;
|
||||
float turbV = (analogRead(TURBIDITY_PIN) / 4095.0) * 3.3;
|
||||
float phV = (analogRead(PH_PIN) / 4095.0) * 3.3;
|
||||
float ph = ph_slope * phV + ph_offset;
|
||||
|
||||
digitalWrite(TRIG_PIN, LOW); delayMicroseconds(2);
|
||||
digitalWrite(TRIG_PIN, HIGH); delayMicroseconds(10);
|
||||
digitalWrite(TRIG_PIN, LOW);
|
||||
long duration = pulseIn(ECHO_PIN, HIGH);
|
||||
float tinggiAir = duration * 0.034 / 2;
|
||||
|
||||
sensors.requestTemperatures();
|
||||
float suhu = sensors.getTempCByIndex(0);
|
||||
|
||||
cekKekeruhan(turbV);
|
||||
updateLCD(tdsV, turbV, phV, ph, tinggiAir, suhu);
|
||||
|
||||
Serial.print("Jam Sekarang: "); Serial.println(currentTime);
|
||||
Serial.print("pH Tegangan: "); Serial.print(phV, 3); Serial.print(" V | pH: "); Serial.println(ph, 2);
|
||||
|
||||
if (millis() - previousMillis >= interval) {
|
||||
previousMillis = millis();
|
||||
kirimKeFirebase(tdsV, bacaKekeruhan(turbV), phV, ph, tinggiAir, suhu);
|
||||
}
|
||||
if (millis() - lastHistorySentMillis >= intervalHistoryMinutes * 60000UL) {
|
||||
lastHistorySentMillis = millis();
|
||||
kirimHistoryKeServer(ph, suhu, tdsV, tinggiAir, bacaKekeruhan(turbV));
|
||||
}
|
||||
|
||||
|
||||
delay(500);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 72e55ccf30d98f11d2c1048799b5ebac5eff3251
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 9243200aa6e33b4f2389040f214390dd04d36dba
|
Loading…
Reference in New Issue