#include <OneWire.h>
#include <DallasTemperature.h>
#include <Ticker.h> // Built-in ESP32/ESP8266 timer library
#define ONE_WIRE_BUS 21
#define HEATER_PIN 2
// Temperature thresholds
const float TARGET_TEMP = 30.0;
const float STABILIZE_MARGIN = 1.0;
const float OVERHEAT_TEMP = 40.0;
const float IDLE_TEMP = 20.0;
enum State { IDLE, HEATING, STABILIZING, TARGET_REACHED, OVERHEAT };
State currentState = IDLE;
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
volatile bool tempCheckFlag = false; // Set by timer ISR
Ticker tempTimer; // Timer object
const char* stateToStr(State s) {
switch (s) {
case IDLE: return "Idle";
case HEATING: return "Heating";
case STABILIZING: return "Stabilizing";
case TARGET_REACHED: return "Target Reached";
case OVERHEAT: return "Overheat";
default: return "Unknown";
}
}
// Timer ISR runs every second
void IRAM_ATTR onTempTimer() {
tempCheckFlag = true; // Set flag for main loop
}
void setup() {
Serial.begin(115200);
sensors.begin();
pinMode(HEATER_PIN, OUTPUT);
digitalWrite(HEATER_PIN, LOW);
// Start timer interrupt every 1 second
tempTimer.attach_ms(1000, onTempTimer);
}
void loop() {
if (tempCheckFlag) {
tempCheckFlag = false; // Reset flag
sensors.requestTemperatures();
float lastTempC = sensors.getTempCByIndex(0);
if (lastTempC >= OVERHEAT_TEMP) {
currentState = OVERHEAT;
digitalWrite(HEATER_PIN, LOW);
} else {
// State machine logic
switch (currentState) {
case IDLE:
if (lastTempC < IDLE_TEMP) {
currentState = HEATING;
digitalWrite(HEATER_PIN, HIGH);
}
break;
case HEATING:
if (lastTempC >= TARGET_TEMP - STABILIZE_MARGIN) {
currentState = STABILIZING;
}
break;
case STABILIZING:
if (lastTempC >= TARGET_TEMP) {
currentState = TARGET_REACHED;
digitalWrite(HEATER_PIN, LOW);
}
break;
case TARGET_REACHED:
if (lastTempC < TARGET_TEMP - STABILIZE_MARGIN) {
currentState = HEATING;
digitalWrite(HEATER_PIN, HIGH);
}
break;
case OVERHEAT:
if (lastTempC < IDLE_TEMP) {
currentState = HEATING;
digitalWrite(HEATER_PIN, HIGH);
}
break;
}
}
// Serial log
Serial.printf("Temp: %.2f°C | State: %s | Heater: %s\n",
lastTempC, stateToStr(currentState),
digitalRead(HEATER_PIN) ? "ON" : "OFF");
}
}