Upload files to "/"
This commit is contained in:
commit
6f61202865
|
@ -0,0 +1,183 @@
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <LiquidCrystal_I2C.h>
|
||||||
|
#include <DHT.h>
|
||||||
|
#include <Firebase_ESP_Client.h>
|
||||||
|
#include "addons/TokenHelper.h"
|
||||||
|
#include "addons/RTDBHelper.h"
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
// WiFi
|
||||||
|
#define WIFI_SSID "redmii"
|
||||||
|
#define WIFI_PASSWORD "87654321"
|
||||||
|
|
||||||
|
// Firebase
|
||||||
|
#define API_KEY "AIzaSyAEe82VtGAo4Q1zA1UPGWvLjJ0Bh_7ogdU"
|
||||||
|
#define DATABASE_URL "https://amonia-a027f-default-rtdb.asia-southeast1.firebasedatabase.app/"
|
||||||
|
#define USER_EMAIL "ardhaxiomi11@gmail.com"
|
||||||
|
#define USER_PASSWORD "Ayam.1234"
|
||||||
|
|
||||||
|
FirebaseData fbdo;
|
||||||
|
FirebaseAuth auth;
|
||||||
|
FirebaseConfig config;
|
||||||
|
|
||||||
|
// DHT11
|
||||||
|
#define DHTPIN 14
|
||||||
|
#define DHTTYPE DHT11
|
||||||
|
DHT dht(DHTPIN, DHTTYPE);
|
||||||
|
|
||||||
|
// MQ135
|
||||||
|
#define MQ135_PIN 34
|
||||||
|
const float R0 = 9.50;
|
||||||
|
const float RL = 10.0;
|
||||||
|
|
||||||
|
// Aktuator
|
||||||
|
#define RELAY1_PIN 4
|
||||||
|
#define RELAY2_PIN 12
|
||||||
|
#define BUZZER_PIN 13
|
||||||
|
|
||||||
|
// LCD
|
||||||
|
LiquidCrystal_I2C lcd(0x27, 16, 2);
|
||||||
|
|
||||||
|
// Interval pengiriman history (5 menit)
|
||||||
|
unsigned long lastHistorySendTime = 0;
|
||||||
|
const unsigned long historyInterval = 5 * 60 * 1000; // 5 menit
|
||||||
|
|
||||||
|
// Tambahan: kendali manual buzzer
|
||||||
|
int buzzerOverride = -1; // -1 = otomatis, 0 = buzzer mati manual
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
dht.begin();
|
||||||
|
lcd.init();
|
||||||
|
lcd.backlight();
|
||||||
|
pinMode(RELAY1_PIN, OUTPUT);
|
||||||
|
pinMode(RELAY2_PIN, OUTPUT);
|
||||||
|
pinMode(BUZZER_PIN, OUTPUT);
|
||||||
|
digitalWrite(RELAY1_PIN, LOW);
|
||||||
|
digitalWrite(RELAY2_PIN, LOW);
|
||||||
|
digitalWrite(BUZZER_PIN, LOW);
|
||||||
|
|
||||||
|
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||||
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
|
delay(500);
|
||||||
|
Serial.print(".");
|
||||||
|
}
|
||||||
|
Serial.println("\nWiFi Connected");
|
||||||
|
|
||||||
|
// Sinkronisasi waktu NTP (GMT+7)
|
||||||
|
configTime(25200, 0, "pool.ntp.org", "time.nist.gov");
|
||||||
|
struct tm timeinfo;
|
||||||
|
while (!getLocalTime(&timeinfo)) {
|
||||||
|
Serial.println("Gagal sinkronisasi waktu");
|
||||||
|
delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Firebase
|
||||||
|
config.api_key = API_KEY;
|
||||||
|
config.database_url = DATABASE_URL;
|
||||||
|
auth.user.email = USER_EMAIL;
|
||||||
|
auth.user.password = USER_PASSWORD;
|
||||||
|
config.token_status_callback = tokenStatusCallback;
|
||||||
|
Firebase.begin(&config, &auth);
|
||||||
|
Firebase.reconnectWiFi(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// Baca waktu
|
||||||
|
struct tm timeinfo;
|
||||||
|
if (!getLocalTime(&timeinfo)) {
|
||||||
|
Serial.println("Gagal dapat waktu");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t nowEpoch = mktime(&timeinfo);
|
||||||
|
char datetimeStr[25];
|
||||||
|
|
||||||
|
// ✅ Ganti separator waktu ke titik: YYYY-MM-DD-HH.MM.SS
|
||||||
|
strftime(datetimeStr, sizeof(datetimeStr), "%Y-%m-%d-%H.%M.%S", &timeinfo);
|
||||||
|
|
||||||
|
// Baca sensor
|
||||||
|
float temp = dht.readTemperature();
|
||||||
|
float hum = dht.readHumidity();
|
||||||
|
int analogValue = analogRead(MQ135_PIN);
|
||||||
|
float voltage = analogValue * (3.3 / 4095.0);
|
||||||
|
float Rs = ((3.3 * RL) / voltage) - RL;
|
||||||
|
float ratio = Rs / R0;
|
||||||
|
float ppm = 116.6020682 * pow(ratio, -2.769034857);
|
||||||
|
float correctedPPM = ppm - 41.0;
|
||||||
|
if (correctedPPM < 0) correctedPPM = 0;
|
||||||
|
|
||||||
|
// 🔔 Ambil status buzzer manual dari Firebase
|
||||||
|
if (Firebase.ready()) {
|
||||||
|
if (Firebase.RTDB.getString(&fbdo, "/amonia_monitoring_realtime/buzzer")) {
|
||||||
|
String sValue = fbdo.stringData();
|
||||||
|
int overrideValue = sValue.toInt();
|
||||||
|
buzzerOverride = overrideValue;
|
||||||
|
Serial.print("Buzzer Override (from Firebase): ");
|
||||||
|
Serial.println(buzzerOverride);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aktuator
|
||||||
|
if (correctedPPM > 25.0) {
|
||||||
|
digitalWrite(RELAY1_PIN, HIGH); // Kipas selalu ON jika ppm tinggi
|
||||||
|
if (buzzerOverride == 0) {
|
||||||
|
digitalWrite(BUZZER_PIN, LOW); // Manual matikan buzzer
|
||||||
|
} else {
|
||||||
|
digitalWrite(BUZZER_PIN, HIGH); // Otomatis ON buzzer
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
digitalWrite(RELAY1_PIN, LOW); // Kipas OFF jika ppm aman
|
||||||
|
digitalWrite(BUZZER_PIN, LOW); // Buzzer OFF
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relay2 otomatisasi lampu
|
||||||
|
if (temp < 30.0) {
|
||||||
|
digitalWrite(RELAY2_PIN, HIGH); // Lampu ON
|
||||||
|
} else {
|
||||||
|
digitalWrite(RELAY2_PIN, LOW); // Lampu OFF
|
||||||
|
}
|
||||||
|
|
||||||
|
// LCD realtime
|
||||||
|
lcd.clear();
|
||||||
|
lcd.setCursor(0, 0);
|
||||||
|
lcd.print("T:");
|
||||||
|
lcd.print(temp, 1);
|
||||||
|
lcd.print((char)223); // derajat
|
||||||
|
lcd.print("C H:");
|
||||||
|
lcd.print(hum, 0);
|
||||||
|
lcd.print("%");
|
||||||
|
|
||||||
|
lcd.setCursor(0, 1);
|
||||||
|
char buffer[9];
|
||||||
|
sprintf(buffer, "%02d:%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
|
||||||
|
lcd.print(buffer);
|
||||||
|
lcd.print(" ");
|
||||||
|
lcd.print((int)correctedPPM); // ✅ PPM ditampilkan sebagai bulat
|
||||||
|
lcd.print("ppm");
|
||||||
|
|
||||||
|
// Kirim data realtime (SETIAP DETIK)
|
||||||
|
if (Firebase.ready()) {
|
||||||
|
String realtimePath = "/amonia_monitoring_realtime";
|
||||||
|
Firebase.RTDB.setFloat(&fbdo, realtimePath + "/temperature", temp);
|
||||||
|
Firebase.RTDB.setFloat(&fbdo, realtimePath + "/humidity", hum);
|
||||||
|
Firebase.RTDB.setFloat(&fbdo, realtimePath + "/ppm", (int)correctedPPM); // ✅ Bulatkan
|
||||||
|
Firebase.RTDB.setString(&fbdo, realtimePath + "/waktu", String(datetimeStr));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kirim data historis (TIAP 5 MENIT)
|
||||||
|
unsigned long currentMillis = millis();
|
||||||
|
if (currentMillis - lastHistorySendTime >= historyInterval || lastHistorySendTime == 0) {
|
||||||
|
lastHistorySendTime = currentMillis;
|
||||||
|
String timestamp = String(nowEpoch);
|
||||||
|
String historyPath = "/amonia_monitoring_history/" + timestamp;
|
||||||
|
|
||||||
|
Firebase.RTDB.setFloat(&fbdo, historyPath + "/temperature", temp);
|
||||||
|
Firebase.RTDB.setFloat(&fbdo, historyPath + "/humidity", hum);
|
||||||
|
Firebase.RTDB.setFloat(&fbdo, historyPath + "/ppm", (int)correctedPPM); // ✅ Bulatkan
|
||||||
|
Firebase.RTDB.setString(&fbdo, historyPath + "/waktu", String(datetimeStr));
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(1000); // Loop delay 1 detik
|
||||||
|
}
|
Loading…
Reference in New Issue