// ⚡ BLYNK CONFIGURATION
#define BLYNK_TEMPLATE_ID "TMPL5qe_2q274"
#define BLYNK_TEMPLATE_NAME "Quickstart Template"
#define BLYNK_AUTH_TOKEN "YPTDpB6eZ3VIW_GX6gcM9goVXnQNKg-I"
#define BLYNK_PRINT Serial
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
// ⚡ VIRTUAL PINS
#define VPIN_POWER V0
#define VPIN_HEAT_LEVEL V1
#define VPIN_TEMPERATURE V2
#define VPIN_STATUS_LED V3
#define VPIN_ALARM_LED V4
#define VPIN_SMALL_BTN V5
#define VPIN_MEDIUM_BTN V6
#define VPIN_BIG_BTN V7
#define VPIN_TERMINAL V8
#define VPIN_TEMP_GAUGE V9
LiquidCrystal_I2C lcd(0x27, 16, 2);
OneWire oneWire(4);
DallasTemperature sensors(&oneWire);
// ⚡ Pin definitions (grouped)
const uint8_t powerLED = 12, smallLED = 13, mediumLED = 14, bigLED = 15,
alarmLED = 16, buzzerPin = 17, servoControl = 18;
const uint8_t btnPower = 32, btnSmall = 33, btnMedium = 25, btnBig = 26;
// ⚡ State variables
bool stoveStatus = false, alarmStatus = false;
uint8_t heatLevel = 0;
float currentTemp = 25.0;
uint32_t lastTempRead = 0, lastBlynkUpdate = 0, lastDisplayUpdate = 0;
uint32_t btnDebounce[4] = {0, 0, 0, 0}; // Power, Small, Medium, Big
// 🚨 Constants
const float CRITICAL_TEMP = 100.0;
const uint8_t AUTO_SHUTDOWN_TEMP = 110;
const uint16_t DEBOUNCE_MS = 300;
// ⚡ BLYNK Handlers (optimized)
BLYNK_WRITE(VPIN_POWER) {
stoveStatus = param.asInt();
heatLevel = stoveStatus ? 2 : 0;
beep(1);
}
BLYNK_WRITE(VPIN_SMALL_BTN) { if (param.asInt() && stoveStatus) { heatLevel = 1; beep(1); }}
BLYNK_WRITE(VPIN_MEDIUM_BTN) { if (param.asInt() && stoveStatus) { heatLevel = 2; beep(1); }}
BLYNK_WRITE(VPIN_BIG_BTN) { if (param.asInt() && stoveStatus) { heatLevel = 3; beep(1); }}
BLYNK_CONNECTED() {
Blynk.virtualWrite(VPIN_POWER, stoveStatus);
Blynk.virtualWrite(VPIN_HEAT_LEVEL, heatLevel);
Blynk.virtualWrite(VPIN_TEMPERATURE, currentTemp);
Blynk.virtualWrite(VPIN_STATUS_LED, stoveStatus ? 255 : 0);
}
void setup() {
Serial.begin(115200);
// ⚡ Pin modes (optimized loops)
uint8_t outputs[] = {powerLED, smallLED, mediumLED, bigLED, alarmLED, buzzerPin, servoControl};
for (uint8_t pin : outputs) pinMode(pin, OUTPUT);
uint8_t inputs[] = {btnPower, btnSmall, btnMedium, btnBig};
for (uint8_t pin : inputs) pinMode(pin, INPUT_PULLUP);
sensors.begin();
Wire.begin();
lcd.init();
lcd.backlight();
lcd.clear();
lcd.print("INITIALIZING...");
// ⚡ WiFi (faster connection)
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, pass);
uint8_t attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts++ < 20) {
delay(500);
Serial.print(".");
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\n✅ WiFi OK");
lcd.clear();
lcd.print("WiFi OK");
Blynk.config(BLYNK_AUTH_TOKEN);
Blynk.connect(3000);
delay(1000);
} else {
Serial.println("\n⚠️ EDGE MODE");
lcd.clear();
lcd.print("EDGE MODE");
delay(1000);
}
lcd.clear();
lcd.print("READY TO USE");
delay(1500);
updateDisplay();
}
void loop() {
uint32_t now = millis();
Blynk.run();
// ⚡ Temperature (every 2s)
if (now - lastTempRead >= 2000) {
readTemperature();
lastTempRead = now;
}
// ⚡ Buttons (checked every cycle for responsiveness)
checkButtons();
// ⚡ LED updates
updateLEDs();
// 🚨 Safety
checkAlarm();
// ⚡ Display (every 500ms)
if (now - lastDisplayUpdate >= 500) {
updateDisplay();
lastDisplayUpdate = now;
}
// ⚡ Blynk update (every 3s)
if (now - lastBlynkUpdate >= 3000) {
sendBlynkUpdate();
lastBlynkUpdate = now;
}
}
void sendBlynkUpdate() {
if (!Blynk.connected()) return;
Blynk.virtualWrite(VPIN_POWER, stoveStatus);
Blynk.virtualWrite(VPIN_HEAT_LEVEL, heatLevel);
Blynk.virtualWrite(VPIN_TEMPERATURE, currentTemp);
Blynk.virtualWrite(VPIN_TEMP_GAUGE, currentTemp);
Blynk.virtualWrite(VPIN_STATUS_LED, stoveStatus ? 255 : 0);
Blynk.virtualWrite(VPIN_ALARM_LED, alarmStatus ? 255 : 0);
}
void readTemperature() {
sensors.requestTemperatures();
float temp = sensors.getTempCByIndex(0);
if (temp != DEVICE_DISCONNECTED_C && temp > -50 && temp < 200) {
currentTemp = temp;
} else {
// Simulate based on heat
if (stoveStatus && heatLevel > 0) {
float increase[] = {0, 2.0, 3.5, 6.0};
currentTemp += increase[heatLevel];
if (currentTemp > 120) currentTemp = 120;
} else if (currentTemp > 25) {
currentTemp -= 2.0;
if (currentTemp < 25) currentTemp = 25;
}
}
}
void checkAlarm() {
// Emergency shutdown
if (currentTemp >= AUTO_SHUTDOWN_TEMP) {
stoveStatus = false;
heatLevel = 0;
alarmStatus = true;
for (uint8_t i = 0; i < 3; i++) {
digitalWrite(buzzerPin, HIGH);
digitalWrite(alarmLED, HIGH);
delay(200);
digitalWrite(buzzerPin, LOW);
digitalWrite(alarmLED, LOW);
delay(100);
}
lcd.clear();
lcd.print("! AUTO SHUTDOWN!");
lcd.setCursor(0, 1);
lcd.print("TEMP:");
lcd.print((int)currentTemp);
lcd.print("C DANGER");
if (Blynk.connected()) {
Blynk.virtualWrite(VPIN_TERMINAL, "🚨 EMERGENCY! Temp: " + String((int)currentTemp) + "°C\n");
}
delay(3000);
return;
}
// Critical temp alarm
if (currentTemp > CRITICAL_TEMP) {
alarmStatus = true;
digitalWrite(buzzerPin, millis() % 1000 < 100);
} else {
alarmStatus = false;
digitalWrite(buzzerPin, LOW);
}
}
void checkButtons() {
uint32_t now = millis();
// Power
if (digitalRead(btnPower) == LOW && (now - btnDebounce[0] > DEBOUNCE_MS)) {
stoveStatus = !stoveStatus;
heatLevel = stoveStatus ? 2 : 0;
beep(1);
btnDebounce[0] = now;
}
if (!stoveStatus) return; // Skip heat buttons if off
// Small
if (digitalRead(btnSmall) == LOW && (now - btnDebounce[1] > DEBOUNCE_MS)) {
heatLevel = 1;
beep(1);
btnDebounce[1] = now;
}
// Medium
if (digitalRead(btnMedium) == LOW && (now - btnDebounce[2] > DEBOUNCE_MS)) {
heatLevel = 2;
beep(1);
btnDebounce[2] = now;
}
// Big
if (digitalRead(btnBig) == LOW && (now - btnDebounce[3] > DEBOUNCE_MS)) {
heatLevel = 3;
beep(1);
btnDebounce[3] = now;
}
}
void updateLEDs() {
digitalWrite(powerLED, stoveStatus);
digitalWrite(smallLED, stoveStatus && heatLevel == 1);
digitalWrite(mediumLED, stoveStatus && heatLevel == 2);
digitalWrite(bigLED, stoveStatus && heatLevel == 3);
digitalWrite(alarmLED, alarmStatus && (millis() % 500 < 250));
}
void updateDisplay() {
static String prev0 = "", prev1 = "";
String line0 = "KOMPOR: ";
line0 += stoveStatus ? "NYALA " : "MATI ";
line0 += Blynk.connected() ? " @" : (WiFi.status() == WL_CONNECTED ? " ~" : "");
String line1 = "T:" + String((int)currentTemp) + "C H:";
const char* levels[] = {"OFF ", "LOW ", "MED ", "HIGH"};
line1 += levels[heatLevel];
if (alarmStatus) line1 += "!";
if (line0 != prev0) {
lcd.setCursor(0, 0);
lcd.print(line0);
prev0 = line0;
}
if (line1 != prev1) {
lcd.setCursor(0, 1);
lcd.print(line1);
prev1 = line1;
}
}
void beep(uint8_t count) {
for (uint8_t i = 0; i < count; i++) {
digitalWrite(buzzerPin, HIGH);
delay(50);
digitalWrite(buzzerPin, LOW);
if (i < count - 1) delay(50);
}
}