diff --git a/src/main.cpp b/src/main.cpp index 0e34339..6e8410a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,34 +1,23 @@ #include // ===================================================== // ESP32 + MQ-135 + MQ-7 + OLED SSD1306 (0.96" 128x64) -// Bahasa Indonesia | Stabil | Client-ready +// WiFi Version // ===================================================== -#define TINY_GSM_MODEM_SIM800 -#define TINY_GSM_RX_BUFFER 650 - +#include +#include #include -#include #include #include #include -// ================== SIM800L ================= -#define MODEM_RX 16 // ESP32 GPIO16 ← SIM800L TX -#define MODEM_TX 17 // ESP32 GPIO17 → SIM800L RX (via resistor) - -HardwareSerial SerialAT(2); -TinyGsm modem(SerialAT); -TinyGsmClient client(modem); - -// APN Indonesia (change if needed) -const char apn[] = "internet"; -const char user[] = ""; -const char pass[] = ""; +// ================== WIFI ================== +const char* ssid = "KARAN"; +const char* password = "12345679"; // Server -const char server[] = "k-dummy.my.id"; -const int port = 8080; +const char server[] = "http://leman.k-dummy.my.id"; +const int port = 80; // ================= OLED CONFIG ================= #define SCREEN_WIDTH 128 @@ -53,45 +42,121 @@ MQUnifiedsensor MQ135(BOARD, VOLTAGE, ADC_BITS, PIN_MQ135, "MQ-135"); MQUnifiedsensor MQ7(BOARD, VOLTAGE, ADC_BITS, PIN_MQ7, "MQ-7"); // ================== HELPER ================== -void oledGSMStatus(const String &msg) +void oledWiFiStatus(const String &msg) { display.clearDisplay(); display.setTextSize(1); display.setTextColor(SSD1306_WHITE); display.setCursor(0, 0); - display.println("STATUS GSM:"); + + display.println("STATUS WIFI:"); display.println(msg); + display.display(); + delay(500); } -void oledMQStatus(const String &msg1, const String &msg2, const String &msg3, const String &msg4, String msg5 = "") +void oledMQStatus( + const String &msg1, + const String &msg2, + const String &msg3, + const String &msg4, + String msg5 = "") { display.clearDisplay(); display.setTextSize(1); display.setTextColor(SSD1306_WHITE); display.setCursor(0, 0); + display.println("MQ STATUS:"); display.println(msg1); display.println(msg2); display.println(msg3); display.println(msg4); display.println(msg5); + display.display(); + delay(500); } // ================= HELPER ====================== float readAverage(MQUnifiedsensor &sensor, int samples = 5) { float sum = 0; + for (int i = 0; i < samples; i++) { sensor.update(); sum += sensor.readSensor(); delay(50); } + return sum / samples; } +// ===================================================== +// WIFI CONNECTION +// ===================================================== +bool connectWiFi() +{ + Serial.println("[WiFi] Connecting..."); + Serial.print("[WiFi] SSID: "); + Serial.println(ssid); + + oledWiFiStatus("Menghubungkan..."); + + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + + unsigned long startAttempt = millis(); + + while (WiFi.status() != WL_CONNECTED && + millis() - startAttempt < 30000) + { + delay(500); + Serial.print("."); + } + + Serial.println(); + + if (WiFi.status() == WL_CONNECTED) + { + Serial.println("[WiFi] CONNECTED"); + Serial.print("[WiFi] IP: "); + Serial.println(WiFi.localIP()); + + oledWiFiStatus("WIFI TERHUBUNG"); + + delay(1000); + + return true; + } + + Serial.println("[WiFi] Connection failed!"); + oledWiFiStatus("WIFI GAGAL"); + + return false; +} + +// ===================================================== +// ENSURE WIFI +// ===================================================== +bool ensureWiFi() +{ + if (WiFi.status() == WL_CONNECTED) + { + return true; + } + + Serial.println("[WiFi] Connection lost!"); + oledWiFiStatus("WIFI PUTUS"); + + WiFi.disconnect(); + delay(1000); + + return connectWiFi(); +} + // ===================================================== void setup() { @@ -99,184 +164,184 @@ void setup() delay(500); // ================= OLED INIT ================= + Wire.begin(21, 22); + if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) { - Serial.println("❌ OLED tidak ditemukan!"); + Serial.println("OLED tidak ditemukan!"); + while (true) delay(1000); } - // SIM800L UART - Serial.println("[GSM] Init UART..."); - oledGSMStatus("Init GSM..."); + // ================= WIFI INIT ================= - SerialAT.begin(9600, SERIAL_8N1, MODEM_RX, MODEM_TX); - delay(3000); + Serial.println("[WiFi] Init WiFi..."); - Serial.println("[GSM] Hidupkan modem..."); - oledGSMStatus("Hidupkan modem..."); - if (!modem.restart()) + if (!connectWiFi()) { - Serial.println("[ERROR] Modem restart failed!"); - oledGSMStatus("MODEM GAGAL"); - oledGSMStatus("RESTART ESP32..."); - ESP.restart(); // Restart ESP32 + Serial.println("[ERROR] WiFi gagal!"); + + oledWiFiStatus("RESTART ESP32"); + + delay(2000); + + ESP.restart(); } - Serial.println("[GSM] Waiting for network..."); - oledGSMStatus("Menunggu jaringan..."); - delay(2000); - if (!modem.waitForNetwork()) - { - Serial.println("[ERROR] No network!"); - oledGSMStatus("GAGAL JARINGAN"); - oledGSMStatus("RESTART ESP32..."); - ESP.restart(); // Restart ESP32 - } + // ================= MQ INIT ================= - Serial.println("[GSM] Network OK"); - oledGSMStatus("JARINGAN OK"); - delay(2000); - - Serial.println("[GSM] Connecting GPRS..."); - oledGSMStatus("Menghubungkan GPRS..."); - if (!modem.gprsConnect(apn, user, pass)) - { - Serial.println("[ERROR] GPRS failed!"); - oledGSMStatus("GAGAL GPRS"); - oledGSMStatus("RESTART ESP32..."); - ESP.restart(); // Restart ESP32 - } - - Serial.println("[GSM] GPRS CONNECTED"); - oledGSMStatus("GPRS OK"); - delay(2000); - - // MQ init Serial.println("[MQ] Init MQ135 & MQ7"); - oledMQStatus("Init MQ135 & MQ7", "Mulai kalibrasi sensor...", "Pastikan udara bersih", "(±1-2 menit)"); + oledMQStatus( + "Init MQ135 & MQ7", + "Mulai kalibrasi sensor...", + "Pastikan udara bersih", + "(±1-2 menit)"); // ================= KALIBRASI ================= + Serial.println("Mulai kalibrasi sensor..."); Serial.println("Pastikan udara bersih (±1-2 menit)"); - // MQ135 + // ================= MQ135 ================= + MQ135.setRegressionMethod(1); MQ135.init(); + float r0_135 = 0; + for (int i = 0; i < 10; i++) { MQ135.update(); + r0_135 += MQ135.calibrate(RATIO_CLEAN_MQ135); + delay(600); } + r0_135 /= 10; + MQ135.setR0(r0_135); - // MQ7 + // ================= MQ7 ================= + MQ7.setRegressionMethod(1); MQ7.init(); + float r0_7 = 0; + for (int i = 0; i < 10; i++) { MQ7.update(); + r0_7 += MQ7.calibrate(RATIO_CLEAN_MQ7); + delay(600); } + r0_7 /= 10; + MQ7.setR0(r0_7); + // ================= CHECK CALIBRATION ================= + if (r0_135 <= 0 || r0_7 <= 0) { - Serial.println("❌ Kalibrasi gagal!"); - oledMQStatus("KALIBRASI GAGAL", "", "", "RESTART ESP32..."); + Serial.println("Kalibrasi gagal!"); + + oledMQStatus( + "KALIBRASI GAGAL", + "", + "", + "RESTART ESP32..."); + + delay(2000); + ESP.restart(); } Serial.println("Kalibrasi selesai!"); - oledMQStatus("KALIBRASI OK", "...", "Mulai Monitoring", "..."); -} + Serial.print("MQ135 R0 = "); + Serial.println(r0_135); -bool ensureGPRS() -{ - if (!modem.isNetworkConnected()) - { - Serial.println("[GSM] Network lost, waiting..."); - oledGSMStatus("NET PUTUS"); + Serial.print("MQ7 R0 = "); + Serial.println(r0_7); - if (!modem.waitForNetwork(60000L)) - { - Serial.println("[GSM] Network still down!"); - return false; - } - } + oledMQStatus( + "KALIBRASI OK", + "...", + "Mulai Monitoring", + "..."); - if (!modem.isGprsConnected()) - { - Serial.println("[GSM] GPRS lost, reconnecting..."); - oledGSMStatus("GPRS ULANG"); - - modem.gprsDisconnect(); - delay(1000); - - if (!modem.gprsConnect(apn, user, pass)) - { - Serial.println("[GSM] GPRS reconnect failed!"); - return false; - } - - Serial.println("[GSM] GPRS reconnected"); - } - - return true; + delay(1000); } +// ===================================================== +// LOOP // ===================================================== void loop() { - if (!ensureGPRS()) - { - Serial.println("[GSM] Recover failed, restarting modem..."); - oledGSMStatus("RESTART MODEM"); + // =================================================== + // CHECK WIFI + // =================================================== + + if (!ensureWiFi()) + { + Serial.println("[WiFi] Recover failed!"); + + oledWiFiStatus("WIFI ERROR"); - modem.restart(); delay(5000); - return; // skip this loop + + return; } // =============== MQ135 ================= + MQ135.setA(110.47); MQ135.setB(-2.862); + float co2 = readAverage(MQ135); + if (co2 < 0) co2 = 0; + // ================================================= + MQ135.setA(605.18); MQ135.setB(-3.937); + float benzene = readAverage(MQ135); + if (benzene < 0) benzene = 0; // =============== MQ7 =================== + MQ7.setA(99.042); MQ7.setB(-1.518); + float co = readAverage(MQ7); + if (co < 0) co = 0; // ========== AIR QUALITY ESTIMATION ===== + int aq = 100; if (co2 > 700) aq -= map(co2, 700, 2000, 0, 50); + if (co2 > 2000) aq -= map(co2, 2000, 5000, 50, 80); if (co > 10) aq -= map(co, 10, 50, 0, 30); + if (co > 50) aq -= 30; @@ -285,7 +350,10 @@ void loop() aq = constrain(aq, 0, 100); + // ================= STATUS ================= + String status; + if (aq >= 90) status = "Sangat Baik"; else if (aq >= 70) @@ -298,97 +366,112 @@ void loop() status = "Sangat Buruk"; // =============== OLED DISPLAY ========== - oledMQStatus("CO2 : " + String(co2) + " ppm", "CO : " + String(co) + " ppm", "BZ : " + String(benzene) + " ppm", "AQ : " + String(aq) + " % ", status); + + oledMQStatus( + "CO2 : " + String(co2) + " ppm", + "CO : " + String(co) + " ppm", + "BZ : " + String(benzene) + " ppm", + "AQ : " + String(aq) + " % ", + status); // =============== SERIAL ================= + Serial.println("===== STATUS UDARA ====="); + Serial.print("CO2 : "); Serial.print(co2); Serial.println(" ppm"); + Serial.print("CO : "); Serial.print(co); Serial.println(" ppm"); + Serial.print("BZ : "); Serial.print(benzene); Serial.println(" ppm"); + Serial.print("AQ : "); Serial.print(aq); Serial.print("% "); + Serial.println(status); + Serial.println("========================\n"); delay(5000); - client.stop(); - delay(1000); + // ================================================= + // HTTP REQUEST + // ================================================= - if (client.connect(server, port)) + if (WiFi.status() == WL_CONNECTED) { - String url = "/api/update?"; + HTTPClient http; + + String url = String(server) + "/api/update?"; + url += "co2=" + String(co2); url += "&co=" + String(co); url += "&bz=" + String(benzene); url += "&aq=" + String(aq); + url += "&id=2"; Serial.print("[HTTP] GET "); Serial.println(url); - // Send request - client.print(String("GET ") + url + " HTTP/1.1\r\n"); - client.print("Host: k-dummy.my.id\r\n"); - client.print("Connection: close\r\n\r\n"); + oledWiFiStatus("MENGIRIM DATA..."); - oledGSMStatus("MENUNGGU RESP"); + http.begin(url); - // ------------------------------- - // READ RESPONSE - // ------------------------------- - String response = ""; - unsigned long timeout = millis(); + int httpCode = http.GET(); - while (client.connected() && millis() - timeout < 8000) + if (httpCode > 0) { - while (client.available()) + Serial.print("[HTTP] Response code: "); + Serial.println(httpCode); + + String response = http.getString(); + + Serial.println("----- HTTP RESPONSE -----"); + Serial.println(response); + Serial.println("-------------------------"); + + int jsonStart = response.indexOf('{'); + + if (jsonStart >= 0) { - char c = client.read(); - response += c; - timeout = millis(); // reset timeout when data arrives + String json = response.substring(jsonStart); + + Serial.print("[JSON] "); + Serial.println(json); + + oledWiFiStatus("RESP OK"); } - } + else + { + Serial.println("[ERROR] No JSON found!"); - client.stop(); - - Serial.println("----- HTTP RESPONSE -----"); - Serial.println(response); - Serial.println("-------------------------"); - - // ------------------------------- - // EXTRACT JSON BODY - // ------------------------------- - int jsonStart = response.indexOf('{'); - if (jsonStart >= 0) - { - String json = response.substring(jsonStart); - - Serial.print("[JSON] "); - Serial.println(json); - - oledGSMStatus("RESP OK"); + oledWiFiStatus("RESP ERROR"); + } } else { - Serial.println("[ERROR] No JSON found!"); - oledGSMStatus("RESP ERROR"); + Serial.print("[ERROR] HTTP failed: "); + Serial.println(http.errorToString(httpCode)); + + oledWiFiStatus("GAGAL KIRIM"); } + + http.end(); } else { - Serial.println("[ERROR] Server connection failed!"); - oledGSMStatus("GAGAL KIRIM"); + Serial.println("[ERROR] WiFi disconnected!"); + + oledWiFiStatus("WIFI PUTUS"); } - client.stop(); Serial.println("===== LOOP END ====="); delay(10000); -} +} \ No newline at end of file diff --git a/src/main.cpp.error b/src/main.cpp.error new file mode 100644 index 0000000..3d67ee9 --- /dev/null +++ b/src/main.cpp.error @@ -0,0 +1,396 @@ +#include +// ===================================================== +// ESP32 + MQ-135 + MQ-7 + OLED SSD1306 (0.96" 128x64) +// Bahasa Indonesia | Stabil | Client-ready +// ===================================================== + +#define TINY_GSM_MODEM_SIM800 +#define TINY_GSM_RX_BUFFER 650 + +#include +#include +#include +#include +#include + +// ================== SIM800L ================= +#define MODEM_RX 16 // ESP32 GPIO16 ← SIM800L TX +#define MODEM_TX 17 // ESP32 GPIO17 → SIM800L RX (via resistor) + +HardwareSerial SerialAT(2); +TinyGsm modem(SerialAT); +TinyGsmClient client(modem); + +// APN Indonesia (change if needed) +const char apn[] = "internet"; +const char user[] = ""; +const char pass[] = ""; + +// Server +// const char server[] = "k-dummy.my.id"; +const char server[] = "13.54.104.247"; +const int port = 8080; + +// ================= OLED CONFIG ================= +#define SCREEN_WIDTH 128 +#define SCREEN_HEIGHT 64 +#define OLED_RESET -1 +#define OLED_ADDR 0x3C + +Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); + +// ================= MQ CONFIG =================== +#define BOARD "ESP-32" +#define VOLTAGE 3.3 +#define ADC_BITS 12 + +#define PIN_MQ135 34 +#define PIN_MQ7 35 + +#define RATIO_CLEAN_MQ135 3.6 +#define RATIO_CLEAN_MQ7 27.5 + +MQUnifiedsensor MQ135(BOARD, VOLTAGE, ADC_BITS, PIN_MQ135, "MQ-135"); +MQUnifiedsensor MQ7(BOARD, VOLTAGE, ADC_BITS, PIN_MQ7, "MQ-7"); + +// ================== HELPER ================== +void oledGSMStatus(const String &msg) +{ + display.clearDisplay(); + display.setTextSize(1); + display.setTextColor(SSD1306_WHITE); + display.setCursor(0, 0); + display.println("STATUS GSM:"); + display.println(msg); + display.display(); +} + +void oledMQStatus(const String &msg1, const String &msg2, const String &msg3, const String &msg4, String msg5 = "") +{ + display.clearDisplay(); + display.setTextSize(1); + display.setTextColor(SSD1306_WHITE); + display.setCursor(0, 0); + display.println("MQ STATUS:"); + display.println(msg1); + display.println(msg2); + display.println(msg3); + display.println(msg4); + display.println(msg5); + display.display(); +} + +// ================= HELPER ====================== +float readAverage(MQUnifiedsensor &sensor, int samples = 5) +{ + float sum = 0; + for (int i = 0; i < samples; i++) + { + sensor.update(); + sum += sensor.readSensor(); + delay(50); + } + return sum / samples; +} + +// ===================================================== +void setup() +{ + Serial.begin(115200); + delay(500); + + // ================= OLED INIT ================= + Wire.begin(21, 22); + if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) + { + Serial.println("❌ OLED tidak ditemukan!"); + while (true) + delay(1000); + } + + // SIM800L UART + Serial.println("[GSM] Init UART..."); + oledGSMStatus("Init GSM..."); + + SerialAT.begin(9600, SERIAL_8N1, MODEM_RX, MODEM_TX); + delay(3000); + + Serial.println("[GSM] Hidupkan modem..."); + oledGSMStatus("Hidupkan modem..."); + if (!modem.restart()) + { + Serial.println("[ERROR] Modem restart failed!"); + oledGSMStatus("MODEM GAGAL"); + oledGSMStatus("RESTART ESP32..."); + ESP.restart(); // Restart ESP32 + } + + Serial.println("[GSM] Waiting for network..."); + oledGSMStatus("Menunggu jaringan..."); + delay(2000); + if (!modem.waitForNetwork()) + { + Serial.println("[ERROR] No network!"); + oledGSMStatus("GAGAL JARINGAN"); + oledGSMStatus("RESTART ESP32..."); + ESP.restart(); // Restart ESP32 + } + + Serial.println("[GSM] Network OK"); + oledGSMStatus("JARINGAN OK"); + delay(2000); + + Serial.println("[GSM] Connecting GPRS..."); + oledGSMStatus("Menghubungkan GPRS..."); + if (!modem.gprsConnect(apn, user, pass)) + { + Serial.println("[ERROR] GPRS failed!"); + oledGSMStatus("GAGAL GPRS"); + oledGSMStatus("RESTART ESP32..."); + ESP.restart(); // Restart ESP32 + } + + Serial.println("[GSM] GPRS CONNECTED"); + oledGSMStatus("GPRS OK"); + delay(2000); + + // MQ init + Serial.println("[MQ] Init MQ135 & MQ7"); + + oledMQStatus("Init MQ135 & MQ7", "Mulai kalibrasi sensor...", "Pastikan udara bersih", "(±1-2 menit)"); + + // ================= KALIBRASI ================= + Serial.println("Mulai kalibrasi sensor..."); + Serial.println("Pastikan udara bersih (±1-2 menit)"); + + // MQ135 + MQ135.setRegressionMethod(1); + MQ135.init(); + float r0_135 = 0; + for (int i = 0; i < 10; i++) + { + MQ135.update(); + r0_135 += MQ135.calibrate(RATIO_CLEAN_MQ135); + delay(600); + } + r0_135 /= 10; + MQ135.setR0(r0_135); + + // MQ7 + MQ7.setRegressionMethod(1); + MQ7.init(); + float r0_7 = 0; + for (int i = 0; i < 10; i++) + { + MQ7.update(); + r0_7 += MQ7.calibrate(RATIO_CLEAN_MQ7); + delay(600); + } + r0_7 /= 10; + MQ7.setR0(r0_7); + + if (r0_135 <= 0 || r0_7 <= 0) + { + Serial.println("❌ Kalibrasi gagal!"); + oledMQStatus("KALIBRASI GAGAL", "", "", "RESTART ESP32..."); + ESP.restart(); + } + + Serial.println("Kalibrasi selesai!"); + + oledMQStatus("KALIBRASI OK", "...", "Mulai Monitoring", "..."); +} + +bool ensureGPRS() +{ + if (!modem.isNetworkConnected()) + { + Serial.println("[GSM] Network lost, waiting..."); + oledGSMStatus("NET PUTUS"); + + if (!modem.waitForNetwork(60000L)) + { + Serial.println("[GSM] Network still down!"); + return false; + } + } + + if (!modem.isGprsConnected()) + { + Serial.println("[GSM] GPRS lost, reconnecting..."); + oledGSMStatus("GPRS ULANG"); + + modem.gprsDisconnect(); + delay(1000); + + if (!modem.gprsConnect(apn, user, pass)) + { + Serial.println("[GSM] GPRS reconnect failed!"); + return false; + } + + Serial.println("[GSM] GPRS reconnected"); + } + + return true; +} + +// ===================================================== +void loop() +{ + if (!ensureGPRS()) + { + Serial.println("[GSM] Recover failed, restarting modem..."); + oledGSMStatus("RESTART MODEM"); + + modem.restart(); + delay(5000); + return; // skip this loop + } + + // =============== MQ135 ================= + MQ135.setA(110.47); + MQ135.setB(-2.862); + float co2 = readAverage(MQ135); + if (co2 < 0) + co2 = 0; + + MQ135.setA(605.18); + MQ135.setB(-3.937); + float benzene = readAverage(MQ135); + if (benzene < 0) + benzene = 0; + + // =============== MQ7 =================== + MQ7.setA(99.042); + MQ7.setB(-1.518); + float co = readAverage(MQ7); + if (co < 0) + co = 0; + + // ========== AIR QUALITY ESTIMATION ===== + int aq = 100; + + if (co2 > 700) + aq -= map(co2, 700, 2000, 0, 50); + if (co2 > 2000) + aq -= map(co2, 2000, 5000, 50, 80); + + if (co > 10) + aq -= map(co, 10, 50, 0, 30); + if (co > 50) + aq -= 30; + + if (benzene > 5) + aq -= map(benzene, 5, 50, 0, 40); + + aq = constrain(aq, 0, 100); + + String status; + if (aq >= 90) + status = "Sangat Baik"; + else if (aq >= 70) + status = "Baik"; + else if (aq >= 50) + status = "Sedang"; + else if (aq >= 30) + status = "Buruk"; + else + status = "Sangat Buruk"; + + // =============== OLED DISPLAY ========== + oledMQStatus("CO2 : " + String(co2) + " ppm", "CO : " + String(co) + " ppm", "BZ : " + String(benzene) + " ppm", "AQ : " + String(aq) + " % ", status); + + // =============== SERIAL ================= + Serial.println("===== STATUS UDARA ====="); + Serial.print("CO2 : "); + Serial.print(co2); + Serial.println(" ppm"); + Serial.print("CO : "); + Serial.print(co); + Serial.println(" ppm"); + Serial.print("BZ : "); + Serial.print(benzene); + Serial.println(" ppm"); + Serial.print("AQ : "); + Serial.print(aq); + Serial.print("% "); + Serial.println(status); + Serial.println("========================\n"); + + delay(5000); + + client.stop(); + delay(1000); + + if (client.connect(server, port)) + { + String url = "/api/update?"; + url += "co2=" + String(co2); + url += "&co=" + String(co); + url += "&bz=" + String(benzene); + url += "&aq=" + String(aq); + url += "&id=1"; + + Serial.print("[HTTP] GET "); + Serial.println(url); + + // Send request + client.print(String("GET ") + url + " HTTP/1.1\r\n"); + client.print("Host: k-dummy.my.id\r\n"); + client.print("Connection: close\r\n\r\n"); + + oledGSMStatus("MENUNGGU RESP"); + + // ------------------------------- + // READ RESPONSE + // ------------------------------- + String response = ""; + unsigned long timeout = millis(); + + while (client.connected() && millis() - timeout < 8000) + { + while (client.available()) + { + char c = client.read(); + response += c; + timeout = millis(); // reset timeout when data arrives + } + } + + client.stop(); + + Serial.println("----- HTTP RESPONSE -----"); + Serial.println(response); + Serial.println("-------------------------"); + + // ------------------------------- + // EXTRACT JSON BODY + // ------------------------------- + int jsonStart = response.indexOf('{'); + if (jsonStart >= 0) + { + String json = response.substring(jsonStart); + + Serial.print("[JSON] "); + Serial.println(json); + + oledGSMStatus("RESP OK"); + } + else + { + Serial.println("[ERROR] No JSON found!"); + oledGSMStatus("RESP ERROR"); + } + } + else + { + Serial.println("[ERROR] Server connection failed!"); + oledGSMStatus("GAGAL KIRIM"); + } + + client.stop(); + Serial.println("===== LOOP END ====="); + + delay(10000); +} diff --git a/src/main.cpp.no1 b/src/main.cpp.no1 new file mode 100644 index 0000000..ffe061c --- /dev/null +++ b/src/main.cpp.no1 @@ -0,0 +1,18 @@ +#include +#define MQ135_PIN 34 + +void setup() { + Serial.begin(115200); + delay(1000); + + Serial.println("MQ135 Test"); +} + +void loop() { + int sensorValue = analogRead(MQ135_PIN); + + Serial.print("MQ135 Value: "); + Serial.println(sensorValue); + + delay(1000); +} \ No newline at end of file diff --git a/src/main.cpp.bck-no-edit b/src/main.cpp.onlysebsor similarity index 100% rename from src/main.cpp.bck-no-edit rename to src/main.cpp.onlysebsor diff --git a/src/main.cpp.sim b/src/main.cpp.sim new file mode 100644 index 0000000..5976ae5 --- /dev/null +++ b/src/main.cpp.sim @@ -0,0 +1,400 @@ +#include +// ===================================================== +// ESP32 + MQ-135 + MQ-7 + OLED SSD1306 (0.96" 128x64) +// Bahasa Indonesia | Stabil | Client-ready +// ===================================================== + +#define TINY_GSM_MODEM_SIM800 +#define TINY_GSM_RX_BUFFER 650 + +#include +#include +#include +#include +#include +#include +#include + +// ================== SIM800L ================= +#define MODEM_RX 16 // ESP32 GPIO16 ← SIM800L TX +#define MODEM_TX 17 // ESP32 GPIO17 → SIM800L RX (via resistor) + +HardwareSerial SerialAT(2); +TinyGsm modem(SerialAT); +TinyGsmClient client(modem); + +// APN Indonesia (change if needed) +const char apn[] = "internet"; +const char user[] = ""; +const char pass[] = ""; + +// Server +const char server[] = "leman.k-dummy.my.id"; +// const char server[] = "13.54.104.247"; +const int port = 80; + +// ================= OLED CONFIG ================= +#define SCREEN_WIDTH 128 +#define SCREEN_HEIGHT 64 +#define OLED_RESET -1 +#define OLED_ADDR 0x3C + +Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); + +// ================= MQ CONFIG =================== +#define BOARD "ESP-32" +#define VOLTAGE 3.3 +#define ADC_BITS 12 + +#define PIN_MQ135 34 +#define PIN_MQ7 35 + +#define RATIO_CLEAN_MQ135 3.6 +#define RATIO_CLEAN_MQ7 27.5 + +MQUnifiedsensor MQ135(BOARD, VOLTAGE, ADC_BITS, PIN_MQ135, "MQ-135"); +MQUnifiedsensor MQ7(BOARD, VOLTAGE, ADC_BITS, PIN_MQ7, "MQ-7"); + +// ================== HELPER ================== +void oledGSMStatus(const String &msg) +{ + display.clearDisplay(); + display.setTextSize(1); + display.setTextColor(SSD1306_WHITE); + display.setCursor(0, 0); + display.println("STATUS GSM:"); + display.println(msg); + display.display(); + delay(500); +} + +void oledMQStatus(const String &msg1, const String &msg2, const String &msg3, const String &msg4, String msg5 = "") +{ + display.clearDisplay(); + display.setTextSize(1); + display.setTextColor(SSD1306_WHITE); + display.setCursor(0, 0); + display.println("MQ STATUS:"); + display.println(msg1); + display.println(msg2); + display.println(msg3); + display.println(msg4); + display.println(msg5); + display.display(); + delay(500); +} + +// ================= HELPER ====================== +float readAverage(MQUnifiedsensor &sensor, int samples = 5) +{ + float sum = 0; + for (int i = 0; i < samples; i++) + { + sensor.update(); + sum += sensor.readSensor(); + delay(50); + } + return sum / samples; +} + +// ===================================================== +void setup() +{ + Serial.begin(115200); + delay(500); + + // ================= OLED INIT ================= + Wire.begin(21, 22); + if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) + { + Serial.println("❌ OLED tidak ditemukan!"); + while (true) + delay(1000); + } + + // SIM800L UART + Serial.println("[GSM] Init UART..."); + oledGSMStatus("Init GSM..."); + + SerialAT.begin(9600, SERIAL_8N1, MODEM_RX, MODEM_TX); + delay(3000); + + Serial.println("[GSM] Hidupkan modem..."); + oledGSMStatus("Hidupkan modem..."); + if (!modem.restart()) + { + Serial.println("[ERROR] Modem restart failed!"); + oledGSMStatus("MODEM GAGAL"); + oledGSMStatus("RESTART ESP32..."); + ESP.restart(); // Restart ESP32 + } + + Serial.println("[GSM] Waiting for network..."); + oledGSMStatus("Menunggu jaringan..."); + delay(2000); + if (!modem.waitForNetwork()) + { + Serial.println("[ERROR] No network!"); + oledGSMStatus("GAGAL JARINGAN"); + oledGSMStatus("RESTART ESP32..."); + ESP.restart(); // Restart ESP32 + } + + Serial.println("[GSM] Network OK"); + oledGSMStatus("JARINGAN OK"); + delay(2000); + + Serial.println("[GSM] Connecting GPRS..."); + oledGSMStatus("Menghubungkan GPRS..."); + if (!modem.gprsConnect(apn, user, pass)) + { + Serial.println("[ERROR] GPRS failed!"); + oledGSMStatus("GAGAL GPRS"); + oledGSMStatus("RESTART ESP32..."); + ESP.restart(); // Restart ESP32 + } + + Serial.println("[GSM] GPRS CONNECTED"); + oledGSMStatus("GPRS OK"); + delay(2000); + + // MQ init + Serial.println("[MQ] Init MQ135 & MQ7"); + + oledMQStatus("Init MQ135 & MQ7", "Mulai kalibrasi sensor...", "Pastikan udara bersih", "(±1-2 menit)"); + + // ================= KALIBRASI ================= + Serial.println("Mulai kalibrasi sensor..."); + Serial.println("Pastikan udara bersih (±1-2 menit)"); + + // MQ135 + MQ135.setRegressionMethod(1); + MQ135.init(); + float r0_135 = 0; + for (int i = 0; i < 10; i++) + { + MQ135.update(); + r0_135 += MQ135.calibrate(RATIO_CLEAN_MQ135); + delay(600); + } + r0_135 /= 10; + MQ135.setR0(r0_135); + + // MQ7 + MQ7.setRegressionMethod(1); + MQ7.init(); + float r0_7 = 0; + for (int i = 0; i < 10; i++) + { + MQ7.update(); + r0_7 += MQ7.calibrate(RATIO_CLEAN_MQ7); + delay(600); + } + r0_7 /= 10; + MQ7.setR0(r0_7); + + if (r0_135 <= 0 || r0_7 <= 0) + { + Serial.println("❌ Kalibrasi gagal!"); + oledMQStatus("KALIBRASI GAGAL", "", "", "RESTART ESP32..."); + ESP.restart(); + } + + Serial.println("Kalibrasi selesai!"); + + oledMQStatus("KALIBRASI OK", "...", "Mulai Monitoring", "..."); +} + +bool ensureGPRS() +{ + if (!modem.isNetworkConnected()) + { + Serial.println("[GSM] Network lost, waiting..."); + oledGSMStatus("NET PUTUS"); + + if (!modem.waitForNetwork(60000L)) + { + Serial.println("[GSM] Network still down!"); + return false; + } + } + + if (!modem.isGprsConnected()) + { + Serial.println("[GSM] GPRS lost, reconnecting..."); + oledGSMStatus("GPRS ULANG"); + + modem.gprsDisconnect(); + delay(1000); + + if (!modem.gprsConnect(apn, user, pass)) + { + Serial.println("[GSM] GPRS reconnect failed!"); + return false; + } + + Serial.println("[GSM] GPRS reconnected"); + } + + return true; +} + +// ===================================================== +void loop() +{ + if (!ensureGPRS()) + { + Serial.println("[GSM] Recover failed, restarting modem..."); + oledGSMStatus("RESTART MODEM"); + + modem.restart(); + delay(5000); + return; // skip this loop + } + + // =============== MQ135 ================= + MQ135.setA(110.47); + MQ135.setB(-2.862); + float co2 = readAverage(MQ135); + if (co2 < 0) + co2 = 0; + + MQ135.setA(605.18); + MQ135.setB(-3.937); + float benzene = readAverage(MQ135); + if (benzene < 0) + benzene = 0; + + // =============== MQ7 =================== + MQ7.setA(99.042); + MQ7.setB(-1.518); + float co = readAverage(MQ7); + if (co < 0) + co = 0; + + // ========== AIR QUALITY ESTIMATION ===== + int aq = 100; + + if (co2 > 700) + aq -= map(co2, 700, 2000, 0, 50); + if (co2 > 2000) + aq -= map(co2, 2000, 5000, 50, 80); + + if (co > 10) + aq -= map(co, 10, 50, 0, 30); + if (co > 50) + aq -= 30; + + if (benzene > 5) + aq -= map(benzene, 5, 50, 0, 40); + + aq = constrain(aq, 0, 100); + + String status; + if (aq >= 90) + status = "Sangat Baik"; + else if (aq >= 70) + status = "Baik"; + else if (aq >= 50) + status = "Sedang"; + else if (aq >= 30) + status = "Buruk"; + else + status = "Sangat Buruk"; + + // =============== OLED DISPLAY ========== + oledMQStatus("CO2 : " + String(co2) + " ppm", "CO : " + String(co) + " ppm", "BZ : " + String(benzene) + " ppm", "AQ : " + String(aq) + " % ", status); + + // =============== SERIAL ================= + Serial.println("===== STATUS UDARA ====="); + Serial.print("CO2 : "); + Serial.print(co2); + Serial.println(" ppm"); + Serial.print("CO : "); + Serial.print(co); + Serial.println(" ppm"); + Serial.print("BZ : "); + Serial.print(benzene); + Serial.println(" ppm"); + Serial.print("AQ : "); + Serial.print(aq); + Serial.print("% "); + Serial.println(status); + Serial.println("========================\n"); + + delay(5000); + + client.stop(); + delay(1000); + + if (client.connect(server, port)) + { + String url = "/api/update?"; + url += "co2=" + String(co2); + url += "&co=" + String(co); + url += "&bz=" + String(benzene); + url += "&aq=" + String(aq); + url += "&id=1"; + + Serial.print("[HTTP] GET "); + Serial.println(url); + + // Send request + client.print(String("GET ") + url + " HTTP/1.1\r\n"); + client.print("Host: leman.k-dummy.my.id\r\n"); + client.print("Connection: close\r\n\r\n"); + + oledGSMStatus("MENUNGGU RESP"); + + // ------------------------------- + // READ RESPONSE + // ------------------------------- + String response = ""; + unsigned long timeout = millis(); + + while (client.connected() && millis() - timeout < 8000) + { + while (client.available()) + { + char c = client.read(); + response += c; + timeout = millis(); // reset timeout when data arrives + } + } + + client.stop(); + + Serial.println("----- HTTP RESPONSE -----"); + Serial.println(response); + Serial.println("-------------------------"); + + // ------------------------------- + // EXTRACT JSON BODY + // ------------------------------- + int jsonStart = response.indexOf('{'); + if (jsonStart >= 0) + { + String json = response.substring(jsonStart); + + Serial.print("[JSON] "); + Serial.println(json); + + oledGSMStatus("RESP OK"); + } + else + { + Serial.println("[ERROR] No JSON found!"); + oledGSMStatus("RESP ERROR"); + } + } + else + { + Serial.println("[ERROR] Server connection failed!"); + oledGSMStatus("GAGAL KIRIM"); + } + + client.stop(); + Serial.println("===== LOOP END ====="); + + delay(10000); +} diff --git a/src/main.cpp.gprs-ok b/src/main.cpp.this similarity index 98% rename from src/main.cpp.gprs-ok rename to src/main.cpp.this index 0a17884..a863ad1 100644 --- a/src/main.cpp.gprs-ok +++ b/src/main.cpp.this @@ -110,7 +110,8 @@ void setup() { SerialMon.println("[ERROR] Modem restart failed!"); oledStatus("MODEM FAIL"); - while (1); + // ESP.restart(); + ESP.restart(); } SerialMon.println("[GSM] Waiting for network..."); @@ -119,7 +120,7 @@ void setup() { SerialMon.println("[ERROR] No network!"); oledStatus("NO SIGNAL"); - while (1); + ESP.restart(); } SerialMon.println("[GSM] Network OK"); @@ -130,7 +131,7 @@ void setup() { SerialMon.println("[ERROR] GPRS failed!"); oledStatus("GPRS FAIL"); - while (1); + ESP.restart(); } SerialMon.println("[GSM] GPRS CONNECTED");