added wifi connection

This commit is contained in:
kicap
2026-08-25 19:00:50 +08:00
parent f40aa81a35
commit e3df89f417
6 changed files with 1053 additions and 155 deletions

View File

@ -1,34 +1,23 @@
#include <Arduino.h> #include <Arduino.h>
// ===================================================== // =====================================================
// ESP32 + MQ-135 + MQ-7 + OLED SSD1306 (0.96" 128x64) // ESP32 + MQ-135 + MQ-7 + OLED SSD1306 (0.96" 128x64)
// Bahasa Indonesia | Stabil | Client-ready // WiFi Version
// ===================================================== // =====================================================
#define TINY_GSM_MODEM_SIM800 #include <WiFi.h>
#define TINY_GSM_RX_BUFFER 650 #include <HTTPClient.h>
#include <Wire.h> #include <Wire.h>
#include <TinyGsmClient.h>
#include <MQUnifiedsensor.h> #include <MQUnifiedsensor.h>
#include <Adafruit_GFX.h> #include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h> #include <Adafruit_SSD1306.h>
// ================== SIM800L ================= // ================== WIFI ==================
#define MODEM_RX 16 // ESP32 GPIO16 ← SIM800L TX const char* ssid = "KARAN";
#define MODEM_TX 17 // ESP32 GPIO17 → SIM800L RX (via resistor) const char* password = "12345679";
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 // Server
const char server[] = "k-dummy.my.id"; const char server[] = "http://leman.k-dummy.my.id";
const int port = 8080; const int port = 80;
// ================= OLED CONFIG ================= // ================= OLED CONFIG =================
#define SCREEN_WIDTH 128 #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"); MQUnifiedsensor MQ7(BOARD, VOLTAGE, ADC_BITS, PIN_MQ7, "MQ-7");
// ================== HELPER ================== // ================== HELPER ==================
void oledGSMStatus(const String &msg) void oledWiFiStatus(const String &msg)
{ {
display.clearDisplay(); display.clearDisplay();
display.setTextSize(1); display.setTextSize(1);
display.setTextColor(SSD1306_WHITE); display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0); display.setCursor(0, 0);
display.println("STATUS GSM:");
display.println("STATUS WIFI:");
display.println(msg); display.println(msg);
display.display(); 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.clearDisplay();
display.setTextSize(1); display.setTextSize(1);
display.setTextColor(SSD1306_WHITE); display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0); display.setCursor(0, 0);
display.println("MQ STATUS:"); display.println("MQ STATUS:");
display.println(msg1); display.println(msg1);
display.println(msg2); display.println(msg2);
display.println(msg3); display.println(msg3);
display.println(msg4); display.println(msg4);
display.println(msg5); display.println(msg5);
display.display(); display.display();
delay(500);
} }
// ================= HELPER ====================== // ================= HELPER ======================
float readAverage(MQUnifiedsensor &sensor, int samples = 5) float readAverage(MQUnifiedsensor &sensor, int samples = 5)
{ {
float sum = 0; float sum = 0;
for (int i = 0; i < samples; i++) for (int i = 0; i < samples; i++)
{ {
sensor.update(); sensor.update();
sum += sensor.readSensor(); sum += sensor.readSensor();
delay(50); delay(50);
} }
return sum / samples; 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() void setup()
{ {
@ -99,184 +164,184 @@ void setup()
delay(500); delay(500);
// ================= OLED INIT ================= // ================= OLED INIT =================
Wire.begin(21, 22); Wire.begin(21, 22);
if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR))
{ {
Serial.println("OLED tidak ditemukan!"); Serial.println("OLED tidak ditemukan!");
while (true) while (true)
delay(1000); delay(1000);
} }
// SIM800L UART // ================= WIFI INIT =================
Serial.println("[GSM] Init UART...");
oledGSMStatus("Init GSM...");
SerialAT.begin(9600, SERIAL_8N1, MODEM_RX, MODEM_TX); Serial.println("[WiFi] Init WiFi...");
delay(3000);
Serial.println("[GSM] Hidupkan modem..."); if (!connectWiFi())
oledGSMStatus("Hidupkan modem...");
if (!modem.restart())
{ {
Serial.println("[ERROR] Modem restart failed!"); Serial.println("[ERROR] WiFi gagal!");
oledGSMStatus("MODEM GAGAL");
oledGSMStatus("RESTART ESP32..."); oledWiFiStatus("RESTART ESP32");
ESP.restart(); // Restart ESP32
delay(2000);
ESP.restart();
} }
Serial.println("[GSM] Waiting for network..."); // ================= MQ INIT =================
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"); 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 ================= // ================= KALIBRASI =================
Serial.println("Mulai kalibrasi sensor..."); Serial.println("Mulai kalibrasi sensor...");
Serial.println("Pastikan udara bersih (±1-2 menit)"); Serial.println("Pastikan udara bersih (±1-2 menit)");
// MQ135 // ================= MQ135 =================
MQ135.setRegressionMethod(1); MQ135.setRegressionMethod(1);
MQ135.init(); MQ135.init();
float r0_135 = 0; float r0_135 = 0;
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
MQ135.update(); MQ135.update();
r0_135 += MQ135.calibrate(RATIO_CLEAN_MQ135); r0_135 += MQ135.calibrate(RATIO_CLEAN_MQ135);
delay(600); delay(600);
} }
r0_135 /= 10; r0_135 /= 10;
MQ135.setR0(r0_135); MQ135.setR0(r0_135);
// MQ7 // ================= MQ7 =================
MQ7.setRegressionMethod(1); MQ7.setRegressionMethod(1);
MQ7.init(); MQ7.init();
float r0_7 = 0; float r0_7 = 0;
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
MQ7.update(); MQ7.update();
r0_7 += MQ7.calibrate(RATIO_CLEAN_MQ7); r0_7 += MQ7.calibrate(RATIO_CLEAN_MQ7);
delay(600); delay(600);
} }
r0_7 /= 10; r0_7 /= 10;
MQ7.setR0(r0_7); MQ7.setR0(r0_7);
// ================= CHECK CALIBRATION =================
if (r0_135 <= 0 || r0_7 <= 0) if (r0_135 <= 0 || r0_7 <= 0)
{ {
Serial.println("Kalibrasi gagal!"); Serial.println("Kalibrasi gagal!");
oledMQStatus("KALIBRASI GAGAL", "", "", "RESTART ESP32...");
oledMQStatus(
"KALIBRASI GAGAL",
"",
"",
"RESTART ESP32...");
delay(2000);
ESP.restart(); ESP.restart();
} }
Serial.println("Kalibrasi selesai!"); Serial.println("Kalibrasi selesai!");
oledMQStatus("KALIBRASI OK", "...", "Mulai Monitoring", "..."); Serial.print("MQ135 R0 = ");
} Serial.println(r0_135);
bool ensureGPRS() Serial.print("MQ7 R0 = ");
{ Serial.println(r0_7);
if (!modem.isNetworkConnected())
{
Serial.println("[GSM] Network lost, waiting...");
oledGSMStatus("NET PUTUS");
if (!modem.waitForNetwork(60000L)) oledMQStatus(
{ "KALIBRASI OK",
Serial.println("[GSM] Network still down!"); "...",
return false; "Mulai Monitoring",
} "...");
}
if (!modem.isGprsConnected()) delay(1000);
{
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;
} }
// =====================================================
// LOOP
// ===================================================== // =====================================================
void loop() void loop()
{ {
if (!ensureGPRS()) // ===================================================
{ // CHECK WIFI
Serial.println("[GSM] Recover failed, restarting modem..."); // ===================================================
oledGSMStatus("RESTART MODEM");
if (!ensureWiFi())
{
Serial.println("[WiFi] Recover failed!");
oledWiFiStatus("WIFI ERROR");
modem.restart();
delay(5000); delay(5000);
return; // skip this loop
return;
} }
// =============== MQ135 ================= // =============== MQ135 =================
MQ135.setA(110.47); MQ135.setA(110.47);
MQ135.setB(-2.862); MQ135.setB(-2.862);
float co2 = readAverage(MQ135); float co2 = readAverage(MQ135);
if (co2 < 0) if (co2 < 0)
co2 = 0; co2 = 0;
// =================================================
MQ135.setA(605.18); MQ135.setA(605.18);
MQ135.setB(-3.937); MQ135.setB(-3.937);
float benzene = readAverage(MQ135); float benzene = readAverage(MQ135);
if (benzene < 0) if (benzene < 0)
benzene = 0; benzene = 0;
// =============== MQ7 =================== // =============== MQ7 ===================
MQ7.setA(99.042); MQ7.setA(99.042);
MQ7.setB(-1.518); MQ7.setB(-1.518);
float co = readAverage(MQ7); float co = readAverage(MQ7);
if (co < 0) if (co < 0)
co = 0; co = 0;
// ========== AIR QUALITY ESTIMATION ===== // ========== AIR QUALITY ESTIMATION =====
int aq = 100; int aq = 100;
if (co2 > 700) if (co2 > 700)
aq -= map(co2, 700, 2000, 0, 50); aq -= map(co2, 700, 2000, 0, 50);
if (co2 > 2000) if (co2 > 2000)
aq -= map(co2, 2000, 5000, 50, 80); aq -= map(co2, 2000, 5000, 50, 80);
if (co > 10) if (co > 10)
aq -= map(co, 10, 50, 0, 30); aq -= map(co, 10, 50, 0, 30);
if (co > 50) if (co > 50)
aq -= 30; aq -= 30;
@ -285,7 +350,10 @@ void loop()
aq = constrain(aq, 0, 100); aq = constrain(aq, 0, 100);
// ================= STATUS =================
String status; String status;
if (aq >= 90) if (aq >= 90)
status = "Sangat Baik"; status = "Sangat Baik";
else if (aq >= 70) else if (aq >= 70)
@ -298,97 +366,112 @@ void loop()
status = "Sangat Buruk"; status = "Sangat Buruk";
// =============== OLED DISPLAY ========== // =============== 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 =================
Serial.println("===== STATUS UDARA ====="); Serial.println("===== STATUS UDARA =====");
Serial.print("CO2 : "); Serial.print("CO2 : ");
Serial.print(co2); Serial.print(co2);
Serial.println(" ppm"); Serial.println(" ppm");
Serial.print("CO : "); Serial.print("CO : ");
Serial.print(co); Serial.print(co);
Serial.println(" ppm"); Serial.println(" ppm");
Serial.print("BZ : "); Serial.print("BZ : ");
Serial.print(benzene); Serial.print(benzene);
Serial.println(" ppm"); Serial.println(" ppm");
Serial.print("AQ : "); Serial.print("AQ : ");
Serial.print(aq); Serial.print(aq);
Serial.print("% "); Serial.print("% ");
Serial.println(status); Serial.println(status);
Serial.println("========================\n"); Serial.println("========================\n");
delay(5000); 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 += "co2=" + String(co2);
url += "&co=" + String(co); url += "&co=" + String(co);
url += "&bz=" + String(benzene); url += "&bz=" + String(benzene);
url += "&aq=" + String(aq); url += "&aq=" + String(aq);
url += "&id=2";
Serial.print("[HTTP] GET "); Serial.print("[HTTP] GET ");
Serial.println(url); Serial.println(url);
// Send request oledWiFiStatus("MENGIRIM DATA...");
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"); http.begin(url);
// ------------------------------- int httpCode = http.GET();
// READ RESPONSE
// -------------------------------
String response = "";
unsigned long timeout = millis();
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(); String json = response.substring(jsonStart);
response += c;
timeout = millis(); // reset timeout when data arrives Serial.print("[JSON] ");
Serial.println(json);
oledWiFiStatus("RESP OK");
} }
} else
{
Serial.println("[ERROR] No JSON found!");
client.stop(); oledWiFiStatus("RESP ERROR");
}
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 else
{ {
Serial.println("[ERROR] No JSON found!"); Serial.print("[ERROR] HTTP failed: ");
oledGSMStatus("RESP ERROR"); Serial.println(http.errorToString(httpCode));
oledWiFiStatus("GAGAL KIRIM");
} }
http.end();
} }
else else
{ {
Serial.println("[ERROR] Server connection failed!"); Serial.println("[ERROR] WiFi disconnected!");
oledGSMStatus("GAGAL KIRIM");
oledWiFiStatus("WIFI PUTUS");
} }
client.stop();
Serial.println("===== LOOP END ====="); Serial.println("===== LOOP END =====");
delay(10000); delay(10000);
} }

396
src/main.cpp.error Normal file
View File

@ -0,0 +1,396 @@
#include <Arduino.h>
// =====================================================
// 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 <Wire.h>
#include <TinyGsmClient.h>
#include <MQUnifiedsensor.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// ================== 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);
}

18
src/main.cpp.no1 Normal file
View File

@ -0,0 +1,18 @@
#include <Arduino.h>
#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);
}

400
src/main.cpp.sim Normal file
View File

@ -0,0 +1,400 @@
#include <Arduino.h>
// =====================================================
// 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 <Wire.h>
#include <TinyGsmClient.h>
#include <MQUnifiedsensor.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <HTTPClient.h>
#include <Wire.h>
// ================== 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);
}

View File

@ -110,7 +110,8 @@ void setup()
{ {
SerialMon.println("[ERROR] Modem restart failed!"); SerialMon.println("[ERROR] Modem restart failed!");
oledStatus("MODEM FAIL"); oledStatus("MODEM FAIL");
while (1); // ESP.restart();
ESP.restart();
} }
SerialMon.println("[GSM] Waiting for network..."); SerialMon.println("[GSM] Waiting for network...");
@ -119,7 +120,7 @@ void setup()
{ {
SerialMon.println("[ERROR] No network!"); SerialMon.println("[ERROR] No network!");
oledStatus("NO SIGNAL"); oledStatus("NO SIGNAL");
while (1); ESP.restart();
} }
SerialMon.println("[GSM] Network OK"); SerialMon.println("[GSM] Network OK");
@ -130,7 +131,7 @@ void setup()
{ {
SerialMon.println("[ERROR] GPRS failed!"); SerialMon.println("[ERROR] GPRS failed!");
oledStatus("GPRS FAIL"); oledStatus("GPRS FAIL");
while (1); ESP.restart();
} }
SerialMon.println("[GSM] GPRS CONNECTED"); SerialMon.println("[GSM] GPRS CONNECTED");