#define BLYNK_TEMPLATE_ID "TMPL39sshMipF"
#define BLYNK_TEMPLATE_NAME "heat controller"
#define BLYNK_AUTH_TOKEN "e8Xm8OQs4QUUITtZawrQiBA-k2H5zdc_"
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <BlynkSimpleEsp32.h>
#include <WiFi.h>
// Temperature state ranges
#define TEMP_IDLE_MAX 20
#define TEMP_HEATING_MAX 30
#define TEMP_STABILIZING_MAX 35
#define TEMP_TARGET_MAX 37
// Blynk virtual pins
#define VPIN_TEMP V0
#define VPIN_STATE V1
#define SYSTEM V2
// Pin definitions
#define SWITCH_PIN 14
#define RELAY_PIN 27
#define BUZZER_PIN 25
#define ONE_WIRE_BUS 15
#define BLYNK_PRINT Serial
const char* ssid = "Wokwi-GUEST";
const char* password = "";
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
Adafruit_SSD1306 display(128, 64, &Wire, -1);
float temperature = 0;
volatile bool flag = false;
esp_timer_handle_t periodic_timer;
bool systemEnabled = true;
void periodicTimerCallback(void* arg) {
flag = true;
}
void setup() {
Serial.begin(115200);
pinMode(RELAY_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(SWITCH_PIN, INPUT_PULLUP);
digitalWrite(RELAY_PIN, LOW);
digitalWrite(BUZZER_PIN, LOW);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
while (true);
}
Serial.print("Connecting to WiFi...");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected!");
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Starting...");
display.display();
delay(1000);
sensors.begin();
const esp_timer_create_args_t periodic_timer_args = {
.callback = &periodicTimerCallback,
.arg = nullptr,
.dispatch_method = ESP_TIMER_TASK,
.name = "periodic_timer"
};
esp_timer_create(&periodic_timer_args, &periodic_timer);
esp_timer_start_periodic(periodic_timer, 1000000); // 1 second
}
const char* mqttServer = "38.242.251.245";
BLYNK_WRITE(V2) {
systemEnabled = (param.asInt() == 1);
}
void loop() {
Blynk.run();
bool switchState = (digitalRead(SWITCH_PIN) == LOW);
bool systemOn = systemEnabled && switchState;
if (flag) {
flag = false;
if (systemOn) {
readAndHandleTemperature();
} else {
displaySystemOff();
digitalWrite(RELAY_PIN, LOW);
Blynk.virtualWrite(VPIN_TEMP, 0);
Blynk.virtualWrite(VPIN_STATE, "System OFF");
}
}
Blynk.virtualWrite(SYSTEM, systemOn ? 1 : 0);
}
void readAndHandleTemperature() {
sensors.requestTemperatures();
temperature = sensors.getTempCByIndex(0);
if (temperature == DEVICE_DISCONNECTED_C) {
Serial.println("Error: Could not read temperature");
return;
}
String state;
if (temperature < TEMP_IDLE_MAX) {
state = "Idle";
digitalWrite(RELAY_PIN, LOW);
} else if (temperature < TEMP_HEATING_MAX) {
state = "Heating";
digitalWrite(RELAY_PIN, HIGH);
} else if (temperature < TEMP_STABILIZING_MAX) {
state = "Stabilizing";
digitalWrite(RELAY_PIN, HIGH);
} else if (temperature < TEMP_TARGET_MAX) {
state = "Target Reached";
digitalWrite(RELAY_PIN, LOW);
} else {
state = "Overheat";
digitalWrite(RELAY_PIN, LOW);
tone(BUZZER_PIN, 2000, 1000); // Buzzer alert
}
Blynk.virtualWrite(VPIN_TEMP, temperature);
Blynk.virtualWrite(VPIN_STATE, state);
updateOLED(temperature, state);
Serial.printf("Temp: %.2f °C | State: %s\n", temperature, state.c_str());
}
void updateOLED(float temp, String state) {
display.clearDisplay();
display.setCursor(0, 0);
display.printf("Temp: %.1f C\n", temp);
display.printf("State: %s\n", state.c_str());
display.printf("WiFi: %s\n", WiFi.isConnected() ? "OK" : "FAIL");
display.display();
}
void displaySystemOff() {
display.clearDisplay();
display.setCursor(0, 0);
display.println("System OFF");
display.printf("WiFi: %s\n", WiFi.isConnected() ? "OK" : "FAIL");
display.display();
}