#define BLYNK_TEMPLATE_ID "TMPL6w5pglPFv"
#define BLYNK_TEMPLATE_NAME "Monitor Kelembaban Suhu"
#define BLYNK_AUTH_TOKEN "wHZy6Up4x4d37rV-yjmZUeNhvCfTMpza"
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <RTClib.h>
#include <DHT.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
// WiFi Credentials
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
// OLED Config
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
TwoWire I2C_OLED = TwoWire(1);
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &I2C_OLED, OLED_RESET);
// RTC
RTC_DS1307 rtc;
// DHT Config
#define DHTPIN 21
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
// Pin Aktuator
#define EXHAUSTPIN 2
#define BUZZERPIN 19
// RGB LED (digital only)
#define REDPIN 23
#define GREENPIN 22
#define BLUEPIN 15
// Manual control
bool manualFanControl = false;
bool fanManualState = false;
// Blynk components
BlynkTimer timer;
WidgetTerminal terminal(V5);
void setup() {
Serial.begin(9600);
// Inisialisasi I2C & perangkat
I2C_OLED.begin(16, 17); // OLED
Wire.begin(4, 5); // RTC
dht.begin();
if (!rtc.begin()) {
Serial.println("RTC tidak terdeteksi");
while (true);
}
if (!rtc.isrunning()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("Gagal inisialisasi OLED");
while (true);
}
display.clearDisplay();
display.display();
pinMode(BUZZERPIN, OUTPUT);
pinMode(EXHAUSTPIN, OUTPUT);
pinMode(REDPIN, OUTPUT);
pinMode(GREENPIN, OUTPUT);
pinMode(BLUEPIN, OUTPUT);
digitalWrite(BUZZERPIN, LOW);
digitalWrite(EXHAUSTPIN, HIGH);
setRGB(0, 0, 0);
// Blynk
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
timer.setInterval(2000L, sendSensorData);
}
BLYNK_WRITE(V6) {
fanManualState = param.asInt();
manualFanControl = true;
}
void loop() {
Blynk.run();
timer.run();
}
void sendSensorData() {
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
DateTime now = rtc.now();
String currentTime = formatTime(now);
if (isnan(temperature) || isnan(humidity)) {
Serial.println("Sensor error");
terminal.println("Sensor DHT22 gagal dibaca.");
terminal.flush();
return;
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("Waktu: ");
display.print(currentTime);
Blynk.virtualWrite(V3, currentTime);
display.setCursor(0, 16);
display.print("Suhu: ");
display.print(temperature);
display.println(" C");
Blynk.virtualWrite(V0, temperature);
display.setCursor(0, 32);
display.print("Lembab: ");
display.print(humidity);
display.println(" %");
Blynk.virtualWrite(V1, humidity);
bool fanStatus = false;
String fanMode = "Auto";
if (manualFanControl) {
digitalWrite(EXHAUSTPIN, fanManualState ? LOW : HIGH);
fanStatus = fanManualState;
fanMode = "Manual";
display.setCursor(0, 48);
display.print(fanStatus ? "Exhaust ON (M)" : "Exhaust OFF (M)");
} else {
if (temperature > 30 || humidity > 70) {
fanStatus = true;
digitalWrite(EXHAUSTPIN, LOW);
tone(BUZZERPIN, 1000, 200);
display.setCursor(0, 48);
display.print("Exhaust ON (Auto)");
} else {
fanStatus = false;
digitalWrite(EXHAUSTPIN, HIGH);
digitalWrite(BUZZERPIN, LOW);
display.setCursor(0, 48);
display.print("Exhaust OFF");
}
}
Blynk.virtualWrite(V2, fanStatus ? 255 : 0);
// RGB status
int statusLevel = 0;
String statusLabel = "Normal";
if (temperature > 35 || humidity > 70) {
statusLevel = 2;
statusLabel = "Bahaya";
} else if (temperature > 30 || humidity > 60) {
statusLevel = 1;
statusLabel = "Waspada";
}
switch (statusLevel) {
case 0: setRGB(0, 1, 0); break; // Hijau
case 1: setRGB(1, 1, 0); break; // Kuning
case 2: setRGB(1, 0, 0); break; // Merah
}
display.display();
// Log ke terminal
terminal.println("[" + currentTime + "]");
terminal.print("Suhu: ");
terminal.print(temperature);
terminal.println(" C");
terminal.print("Kelembaban: ");
terminal.print(humidity);
terminal.println(" %");
terminal.print("Exhaust: ");
terminal.print(fanStatus ? "ON" : "OFF");
terminal.print(" (");
terminal.print(fanMode);
terminal.println(")");
terminal.print("Status: ");
terminal.println(statusLabel);
terminal.println();
terminal.flush();
// Log ke serial
Serial.print("[" + currentTime + "] ");
Serial.print("Suhu: " + String(temperature) + " C | ");
Serial.println("Kelembaban: " + String(humidity) + " %");
}
String formatTime(DateTime now) {
char buf[20];
sprintf(buf, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
return String(buf);
}
void setRGB(bool r, bool g, bool b) {
digitalWrite(REDPIN, r);
digitalWrite(GREENPIN, g);
digitalWrite(BLUEPIN, b);
}