#include <WiFi.h>
#include <HTTPClient.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
#define DHTPIN 15
#define DHTTYPE DHT22
#define MQ2_GAS_PIN 34
#define BUZZER_PIN 27
#define LED_HIJAU 25
#define LED_KUNING 19
#define LED_MERAH 26
DHT dht(DHTPIN, DHTTYPE);
const char* ssid = "Wokwi-GUEST";
const char* password = "";
String apiKey = "KJ4WOEVXO7A8E7S3";
String serverName = "http://api.thingspeak.com/update";
unsigned long lastCloudTime = 0;
unsigned long lastDisplayTime = 0;
const long cloudInterval = 15000;
const long displayInterval = 1000;
void setup() {
Serial.begin(115200);
pinMode(MQ2_GAS_PIN, INPUT);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LED_HIJAU, OUTPUT);
pinMode(LED_KUNING, OUTPUT);
pinMode(LED_MERAH, OUTPUT);
dht.begin();
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("Gagal inisialisasi OLED SSD1306"));
for (;;);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(10, 20);
display.println("SAFETY SYSTEM");
display.setCursor(10, 35);
display.println("Connecting WiFi...");
display.display();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
display.clearDisplay();
display.setCursor(10, 25);
display.println("WiFi Terhubung!");
display.display();
delay(1000);
}
void loop() {
unsigned long currentMillis = millis();
// Update sensors and display every 1 second without blocking
if (currentMillis - lastDisplayTime >= displayInterval) {
lastDisplayTime = currentMillis;
float suhu = dht.readTemperature();
float kelembapan = dht.readHumidity();
int rawGas = analogRead(MQ2_GAS_PIN);
int gasPercent = map(rawGas, 0, 4095, 0, 100);
if (isnan(suhu) || isnan(kelembapan)) {
Serial.println("Gagal membaca dari sensor DHT22!");
return;
}
int hazardLevel = 0;
if (suhu > 50.0 || gasPercent > 60) {
hazardLevel = 2;
} else if ((suhu >= 40.0 && suhu <= 50.0) || (gasPercent >= 30 && gasPercent <= 60)) {
hazardLevel = 1;
} else {
hazardLevel = 0;
}
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.print("Suhu : "); display.print(suhu, 1); display.println(" C");
display.print("Gas : "); display.print(gasPercent); display.println(" %");
display.println("---------------------");
if (hazardLevel == 2) {
digitalWrite(LED_MERAH, HIGH); digitalWrite(LED_KUNING, LOW); digitalWrite(LED_HIJAU, LOW);
tone(BUZZER_PIN, 2000);
display.setTextSize(2); display.setCursor(0, 35); display.println("DANGER!!!");
display.setTextSize(1); display.setCursor(0, 55); display.println("EVAKUASI SEGERA!");
} else if (hazardLevel == 1) {
digitalWrite(LED_MERAH, LOW); digitalWrite(LED_KUNING, HIGH); digitalWrite(LED_HIJAU, LOW);
tone(BUZZER_PIN, 1000, 200);
display.setTextSize(2); display.setCursor(0, 35); display.println("WARNING!");
display.setTextSize(1); display.setCursor(0, 55); display.println("Cek Area Kerja");
} else {
digitalWrite(LED_MERAH, LOW); digitalWrite(LED_KUNING, LOW); digitalWrite(LED_HIJAU, HIGH);
noTone(BUZZER_PIN);
display.setTextSize(2); display.setCursor(0, 35); display.println("NORMAL");
display.setTextSize(1); display.setCursor(0, 55); display.println("Kondisi Aman");
}
display.display();
}
// Cloud telemetry update every 15 seconds
if (currentMillis - lastCloudTime >= cloudInterval) {
lastCloudTime = currentMillis;
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
float suhu = dht.readTemperature();
int rawGas = analogRead(MQ2_GAS_PIN);
int gasPercent = map(rawGas, 0, 4095, 0, 100);
int hazardLevel = (suhu > 50.0 || gasPercent > 60) ? 2 : ((suhu >= 40.0 && suhu <= 50.0) || (gasPercent >= 30 && gasPercent <= 60)) ? 1 : 0;
String url = serverName + "?api_key=" + apiKey + "&field1=" + String(suhu) + "&field2=" + String(gasPercent) + "&field3=" + String(hazardLevel);
http.begin(url);
int httpCode = http.GET();
if (httpCode > 0) {
Serial.print("Data Terkirim! HTTP Response: ");
Serial.println(httpCode);
} else {
Serial.println("Gagal mengirim data");
}
http.end();
}
}
}