#include #include #include #include // Konfigurasi Firebase #define FIREBASE_HOST "airsavvy-6e5e1-default-rtdb.firebaseio.com" #define FIREBASE_AUTH "AIzaSyDDmW_TPBKMVyrCKse2kI2Z4j-1ssUKAcc" #define USER_EMAIL "airsavvy@gmail.com" #define USER_PASSWORD "bismillah" FirebaseData fbdo; FirebaseAuth auth; FirebaseConfig config; // Konfigurasi Wifi #define WIFI_SSID "Jalak Teras" #define WIFI_PASSWORD "J@lakTer@s" // Konfigurasi MQTT const char* mqtt_server = "192.168.0.106"; // Sesuaikan dengan IP address broker MQTT Anda const char* mqtt_username = "airsavvy"; const char* mqtt_password = "bismillah"; // Pin sensor dan lampu #define MQ135_PIN A0 // A0 untuk MQ135 #define MQ7_PIN 17 // GPIO17 (D3) #define LAMPU_HIJAU_PIN 2 // GPIO2 (D4) #define LAMPU_KUNING_PIN 3 // GPIO3 (RX0) #define LAMPU_MERAH_PIN 4 // GPIO4 (D2) #define BUZZER_PIN 5 // GPIO5 (D1) // Pin relay #define RELAY_PIN_1 12 // GPIO12 (D6) #define RELAY_PIN_2 13 // GPIO13 (D7) #define RELAY_PIN_3 14 // GPIO14 (D5) #define RELAY_PIN_4 15 // GPIO15 (D8) // Konfigurasi MQ135 int Rload = 20000; float ro; double ppm = 414.38; float a_mq135 = 110.7432567; float b_mq135 = -2.856935538; const long MAX_VALUES_NUM = 10; AverageValue averageValue(MAX_VALUES_NUM); // Konfigurasi MQ7 int RL = 10000; float Ro = 10; float Vcc = 3.3; WiFiClient espClient; PubSubClient client(espClient); FirebaseData firebaseData; int mode = 0; // Default mode 0 void setup_wifi() { delay(10); Serial.println(); Serial.print("Connecting to "); Serial.println(WIFI_SSID); WiFi.mode(WIFI_STA); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } void callback(char* topic, byte* payload, unsigned int length) { if (strcmp(topic, "control/mode") == 0) { mode = payload[0] - '0'; // Convert char to int } else if (mode == 1) { if (strcmp(topic, "control/relay1") == 0) { digitalWrite(RELAY_PIN_1, payload[0] == '1' ? HIGH : LOW); Firebase.RTDB.setString(&fbdo, "Relay1", payload[0] == '1' ? "OFF" : "ON"); } else if (strcmp(topic, "control/relay2") == 0) { digitalWrite(RELAY_PIN_2, payload[0] == '1' ? HIGH : LOW); Firebase.RTDB.setString(&fbdo, "Relay2", payload[0] == '1' ? "OFF" : "ON"); } else if (strcmp(topic, "control/relay3") == 0) { digitalWrite(RELAY_PIN_3, payload[0] == '1' ? HIGH : LOW); Firebase.RTDB.setString(&fbdo, "Relay3", payload[0] == '1' ? "OFF" : "ON"); } else if (strcmp(topic, "control/relay4") == 0) { digitalWrite(RELAY_PIN_4, payload[0] == '1' ? HIGH : LOW); Firebase.RTDB.setString(&fbdo, "Relay4", payload[0] == '1' ? "OFF" : "ON"); } } } int calibrateSensor() { int readings = 0; for (int i = 0; i < 50; i++) { int sensorValue = analogRead(MQ7_PIN); float Rs = (Vcc * RL / (sensorValue * (Vcc / 1023.0))) - RL; readings += Rs; delay(500); } readings /= 50; int Ro = readings / 3.5; // Rasio Rs/Ro dalam udara bersih adalah 3.5 untuk MQ-7 return Ro; } void setup() { Serial.begin(9600); // Koneksi Wifi setup_wifi(); // Koneksi ke Firebase config.api_key = FIREBASE_AUTH; config.database_url = FIREBASE_HOST; auth.user.email = USER_EMAIL; auth.user.password = USER_PASSWORD; Firebase.reconnectNetwork(true); fbdo.setBSSLBufferSize(4096, 1024); fbdo.setResponseSize(2048); Firebase.begin(&config, &auth); Firebase.setDoubleDigits(5); config.timeout.serverResponse = 10 * 1000; // Setting mode pin pinMode(LAMPU_HIJAU_PIN, OUTPUT); pinMode(LAMPU_KUNING_PIN, OUTPUT); pinMode(LAMPU_MERAH_PIN, OUTPUT); pinMode(BUZZER_PIN, OUTPUT); pinMode(RELAY_PIN_1, OUTPUT); pinMode(RELAY_PIN_2, OUTPUT); pinMode(RELAY_PIN_3, OUTPUT); pinMode(RELAY_PIN_4, OUTPUT); // Kalibrasi nilai Ro untuk MQ135 int adcRaw; float rs; for (int i = 0; i < 10; i++) { adcRaw = analogRead(MQ135_PIN); rs = ((1024.0 * Rload) / adcRaw) - Rload; ro += rs * exp(log(a_mq135 / ppm) / b_mq135); // Hitung nilai Ro delay(2000); // Jeda 2 detik } ro /= 10.0; // Ambil rata-rata dari 10 pengukuran Ro Serial.print("Ro: "); Serial.println(ro); // Inisialisasi dan kalibrasi sensor MQ7 Ro = calibrateSensor(); // Kalibrasi sensor untuk mendapatkan nilai Ro // Set callback dan koneksi ke broker MQTT client.setServer(mqtt_server, 1883); client.setCallback(callback); Serial.println("Setup Selesai"); } void loop() { if (!client.connected()) { reconnect(); } client.loop(); // Membaca nilai dari sensor MQ135 untuk CO2 int adcRaw = analogRead(MQ135_PIN); float rs = ((1024.0 * Rload) / adcRaw) - Rload; float rsro = rs / ro; float co2ppm = a_mq135 * pow((float)rs / (float)ro, b_mq135); averageValue.push(co2ppm); // Membaca nilai dari sensor MQ7 untuk CO float sensorValue = analogRead(MQ7_PIN); float Rs = (Vcc * RL / (sensorValue * (Vcc / 1023.0))) - RL; float ratio = Rs / Ro; float ppm_mq7 = (pow(10, ((log10(ratio) - 0.08) / -0.42))) * 100; // Menentukan kategori kualitas udara untuk CO2 String kategoriCO2; float avgCO2ppm = averageValue.average(); if (avgCO2ppm >= 0 && avgCO2ppm <= 600) { kategoriCO2 = "Baik"; } else if (avgCO2ppm > 600 && avgCO2ppm <= 1000) { kategoriCO2 = "Kurang Baik"; } else if (avgCO2ppm > 1000) { kategoriCO2 = "Buruk"; } // Menentukan kategori kualitas udara untuk CO String kategoriCO; if (ppm_mq7 >= 0 && ppm_mq7 <= 9) { kategoriCO = "Baik"; } else if (ppm_mq7 > 9 && ppm_mq7 <= 24) { kategoriCO = "Kurang Baik"; } else if (ppm_mq7 > 24) { kategoriCO = "Buruk"; } // Menyalakan lampu dan relay berdasarkan kategori kualitas udara if (mode == 0) { // Kirim status mode ke Firebase if (Firebase.RTDB.setInt(&fbdo, "Mode", 0)) { Serial.println("Set Mode success"); } else { Serial.print("Set Mode failed: "); Serial.println(fbdo.errorReason()); } if (kategoriCO2 == "Buruk" || kategoriCO == "Buruk") { digitalWrite(LAMPU_HIJAU_PIN, LOW); // Matikan lampu hijau digitalWrite(LAMPU_KUNING_PIN, LOW); // Matikan lampu kuning digitalWrite(LAMPU_MERAH_PIN, HIGH); // Hidupkan lampu merah digitalWrite(BUZZER_PIN, HIGH); // Hidupkan buzzer digitalWrite(RELAY_PIN_1, LOW); // Hidupkan relay 1 digitalWrite(RELAY_PIN_2, LOW); // Hidupkan relay 2 digitalWrite(RELAY_PIN_3, LOW); // Hidupkan relay 3 digitalWrite(RELAY_PIN_4, LOW); // Hidupkan relay 4 // Kirim status relay ke Firebase if (Firebase.RTDB.setString(&fbdo, "Relay1", "ON")) { Serial.println("Set Relay1 success"); } else { Serial.print("Set Relay1 failed: "); Serial.println(fbdo.errorReason()); } if (Firebase.RTDB.setString(&fbdo, "Relay2", "ON")) { Serial.println("Set Relay2 success"); } else { Serial.print("Set Relay2 failed: "); Serial.println(fbdo.errorReason()); } if (Firebase.RTDB.setString(&fbdo, "Relay3", "ON")) { Serial.println("Set Relay3 success"); } else { Serial.print("Set Relay3 failed: "); Serial.println(fbdo.errorReason()); } if (Firebase.RTDB.setString(&fbdo, "Relay4", "ON")) { Serial.println("Set Relay4 success"); } else { Serial.print("Set Relay4 failed: "); Serial.println(fbdo.errorReason()); } } else if (kategoriCO2 == "Kurang Baik" || kategoriCO == "Kurang Baik") { digitalWrite(LAMPU_HIJAU_PIN, LOW); // Matikan lampu hijau digitalWrite(LAMPU_KUNING_PIN, HIGH); // Hidupkan lampu kuning digitalWrite(LAMPU_MERAH_PIN, LOW); // Matikan lampu merah digitalWrite(BUZZER_PIN, LOW); // Matikan buzzer jika kualitas udara tidak buruk digitalWrite(RELAY_PIN_1, LOW); // Hidupkan relay 1 digitalWrite(RELAY_PIN_2, LOW); // Hidupkan relay 2 digitalWrite(RELAY_PIN_3, LOW); // Hidupkan relay 3 digitalWrite(RELAY_PIN_4, HIGH); // Matikan relay 4 // Kirim status relay ke Firebase if (Firebase.RTDB.setString(&fbdo, "Relay1", "ON")) { Serial.println("Set Relay1 success"); } else { Serial.print("Set Relay1 failed: "); Serial.println(fbdo.errorReason()); } if (Firebase.RTDB.setString(&fbdo, "Relay2", "ON")) { Serial.println("Set Relay2 success"); } else { Serial.print("Set Relay2 failed: "); Serial.println(fbdo.errorReason()); } if (Firebase.RTDB.setString(&fbdo, "Relay3", "ON")) { Serial.println("Set Relay3 success"); } else { Serial.print("Set Relay3 failed: "); Serial.println(fbdo.errorReason()); } if (Firebase.RTDB.setString(&fbdo, "Relay4", "OFF")) { Serial.println("Set Relay4 success"); } else { Serial.print("Set Relay4 failed: "); Serial.println(fbdo.errorReason()); } } else if (kategoriCO2 == "Baik" || kategoriCO == "Baik") { digitalWrite(LAMPU_HIJAU_PIN, HIGH); // Hidupkan lampu hijau digitalWrite(LAMPU_KUNING_PIN, LOW); // Matikan lampu kuning digitalWrite(LAMPU_MERAH_PIN, LOW); // Matikan lampu merah digitalWrite(BUZZER_PIN, LOW); // Matikan buzzer jika kualitas udara tidak buruk digitalWrite(RELAY_PIN_1, HIGH); // Matikan relay 1 digitalWrite(RELAY_PIN_2, HIGH); // Matikan relay 2 digitalWrite(RELAY_PIN_3, HIGH); // Matikan relay 3 digitalWrite(RELAY_PIN_4, HIGH); // Matikan relay 4 // Kirim status relay ke Firebase if (Firebase.RTDB.setString(&fbdo, "Relay1", "OFF")) { Serial.println("Set Relay1 success"); } else { Serial.print("Set Relay1 failed: "); Serial.println(fbdo.errorReason()); } if (Firebase.RTDB.setString(&fbdo, "Relay2", "OFF")) { Serial.println("Set Relay2 success"); } else { Serial.print("Set Relay2 failed: "); Serial.println(fbdo.errorReason()); } if (Firebase.RTDB.setString(&fbdo, "Relay3", "OFF")) { Serial.println("Set Relay3 success"); } else { Serial.print("Set Relay3 failed: "); Serial.println(fbdo.errorReason()); } if (Firebase.RTDB.setString(&fbdo, "Relay4", "OFF")) { Serial.println("Set Relay4 success"); } else { Serial.print("Set Relay4 failed: "); Serial.println(fbdo.errorReason()); } } } else if (mode == 1) { // Kirim status mode ke Firebase if (Firebase.RTDB.setInt(&fbdo, "Mode", 1)) { Serial.println("Set Mode success"); } else { Serial.print("Set Mode failed: "); Serial.println(fbdo.errorReason()); } // Mode 1: Mengontrol relay manual melalui MQTT digitalWrite(LAMPU_HIJAU_PIN, kategoriCO2 == "Baik" || kategoriCO == "Baik" ? HIGH : LOW); digitalWrite(LAMPU_KUNING_PIN, kategoriCO2 == "Kurang Baik" || kategoriCO == "Kurang Baik" ? HIGH : LOW); digitalWrite(LAMPU_MERAH_PIN, kategoriCO2 == "Buruk" || kategoriCO == "Buruk" ? HIGH : LOW); digitalWrite(BUZZER_PIN, kategoriCO2 == "Buruk" || kategoriCO == "Buruk" ? HIGH : LOW); } // Kirim nilai ke Firebase if (Firebase.RTDB.setFloat(&fbdo, "CO2_ppm", (int)avgCO2ppm)) { Serial.print("Set CO2_ppm success: "); Serial.println(avgCO2ppm); } else { Serial.print("Set CO2_ppm failed: "); Serial.println(fbdo.errorReason()); } if (Firebase.RTDB.setFloat(&fbdo, "CO_ppm", (int)ppm_mq7)) { Serial.print("Set CO_ppm success: "); Serial.println(ppm_mq7); } else { Serial.print("Set CO_ppm failed: "); Serial.println(fbdo.errorReason()); } if (Firebase.RTDB.setString(&fbdo, "Kategori_CO2", kategoriCO2)) { Serial.print("Set Kategori_CO2 success: "); Serial.println(kategoriCO2); } else { Serial.print("Set Kategori_CO2 failed: "); Serial.println(fbdo.errorReason()); } if (Firebase.RTDB.setString(&fbdo, "Kategori_CO", kategoriCO)) { Serial.print("Set Kategori_CO success: "); Serial.println(kategoriCO); } else { Serial.print("Set Kategori_CO failed: "); Serial.println(fbdo.errorReason()); } delay(1000); // Memberi jeda sejenak sebelum membaca ulang sensor } void reconnect() { while (!client.connected()) { Serial.print("Attempting MQTT connection..."); if (client.connect("ESP8266Client", mqtt_username, mqtt_password)) { Serial.println("connected"); client.subscribe("control/mode"); client.subscribe("control/relay1"); client.subscribe("control/relay2"); client.subscribe("control/relay3"); client.subscribe("control/relay4"); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); delay(5000); } } }