#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
// Pinos
#define NTC_PIN A0
#define RELAY_PIN 8
#define BTN_SET 3
#define BTN_UP 4
#define BTN_DOWN 5
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Constantes NTC
const float BETA = 3950.0;
const float R_SERIE = 100000.0;
const float T0 = 298.15;
const float R0 = 100000.0;
// EEPROM endereços
#define ADDR_SETTEMP 0
#define ADDR_MINTEMP 10
#define ADDR_MAXTEMP 20
#define ADDR_HIST 30
#define ADDR_MODE 40
// Variáveis de configuração
float setTemp = 30.0;
float minTemp = 10.0;
float maxTemp = 60.0;
float histerese = 1.0;
bool coolingMode = false; // false = HEAT, true = COOL
// Estados
float currentTemp = 0.0;
bool configMode = false;
int configStep = 0;
bool relayState = false;
unsigned long lastButtonTime = 0;
const int debounceDelay = 200;
void setup() {
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, LOW);
pinMode(BTN_SET, INPUT_PULLUP);
pinMode(BTN_UP, INPUT_PULLUP);
pinMode(BTN_DOWN, INPUT_PULLUP);
lcd.init();
lcd.backlight();
EEPROM.get(ADDR_SETTEMP, setTemp);
EEPROM.get(ADDR_MINTEMP, minTemp);
EEPROM.get(ADDR_MAXTEMP, maxTemp);
EEPROM.get(ADDR_HIST, histerese);
EEPROM.get(ADDR_MODE, coolingMode);
if (isnan(setTemp) || setTemp < 5 || setTemp > 100) setTemp = 30.0;
if (isnan(minTemp) || minTemp < 0 || minTemp > 100) minTemp = 10.0;
if (isnan(maxTemp) || maxTemp < 5 || maxTemp > 120) maxTemp = 60.0;
if (isnan(histerese) || histerese < 0.1 || histerese > 10.0) histerese = 1.0;
lcd.setCursor(0, 0);
lcd.print("Termostato NTC");
delay(2000);
lcd.clear();
}
void loop() {
handleButtons();
currentTemp = readNTC();
if (!configMode) {
lcd.setCursor(0, 0);
lcd.print("Temp: ");
lcd.print(currentTemp, 1);
lcd.print((char)223);
lcd.print("C ");
lcd.setCursor(0, 1);
lcd.print("Set:");
lcd.print(setTemp, 1);
lcd.print((char)223);
lcd.print("C ");
lcd.print("R:");
lcd.print(relayState ? "ON " : "OFF");
// Controle de saída
if (currentTemp < minTemp) {
setRelay(false);
} else if (currentTemp > maxTemp) {
setRelay(true);
} else {
if (!coolingMode) { // HEAT
if (currentTemp < setTemp - histerese / 2) setRelay(true);
else if (currentTemp > setTemp + histerese / 2) setRelay(false);
} else { // COOL
if (currentTemp > setTemp + histerese / 2) setRelay(true);
else if (currentTemp < setTemp - histerese / 2) setRelay(false);
}
}
}
delay(10);
}
void handleButtons() {
if (millis() - lastButtonTime < debounceDelay) return;
if (!digitalRead(BTN_SET)) {
lastButtonTime = millis();
if (!configMode) {
configMode = true;
configStep = 0;
lcd.clear();
} else {
configStep++;
if (configStep > 5) {
configMode = false;
lcd.clear();
// saveSettings();
} else {
lcd.clear();
}
}
}
if (configMode) {
lcd.setCursor(0, 0);
switch (configStep) {
case 0:
lcd.print("Ajuste SetTemp:");
changeValue(setTemp, 5.0, 100.0, 0.5);
lcd.setCursor(0, 1);
lcd.print(setTemp, 1); lcd.print((char)223); lcd.print("C ");
break;
case 1:
lcd.print("Ajuste MinTemp:");
changeValue(minTemp, 0.0, 100.0, 0.5);
lcd.setCursor(0, 1);
lcd.print(minTemp, 1); lcd.print((char)223); lcd.print("C ");
break;
case 2:
lcd.print("Ajuste MaxTemp:");
changeValue(maxTemp, 5.0, 120.0, 0.5);
lcd.setCursor(0, 1);
lcd.print(maxTemp, 1); lcd.print((char)223); lcd.print("C ");
break;
case 3:
lcd.print("Ajuste Histerese:");
changeValue(histerese, 0.1, 10.0, 0.1);
lcd.setCursor(0, 1);
lcd.print(histerese, 1); lcd.print((char)223); lcd.print("C ");
break;
case 4:
lcd.print("Modo:");
if (!digitalRead(BTN_UP) || !digitalRead(BTN_DOWN)) {
coolingMode = !coolingMode;
lastButtonTime = millis();
delay(50);
}
lcd.setCursor(0, 1);
lcd.print(coolingMode ? "COOL (Resfr.) " : "HEAT (Aquec.)");
break;
case 5:
lcd.print("Salvando...");
delay(100);
break;
default:
configStep = 0;
break;
}
}
}
void changeValue(float &value, float minV, float maxV, float step) {
if (!digitalRead(BTN_UP)) {
value += step;
if (value > maxV) value = maxV;
lastButtonTime = millis();
delay(50);
}
if (!digitalRead(BTN_DOWN)) {
value -= step;
if (value < minV) value = minV;
lastButtonTime = millis();
delay(50);
}
}
void saveSettings() {
EEPROM.put(ADDR_SETTEMP, setTemp);
EEPROM.put(ADDR_MINTEMP, minTemp);
EEPROM.put(ADDR_MAXTEMP, maxTemp);
EEPROM.put(ADDR_HIST, histerese);
EEPROM.put(ADDR_MODE, coolingMode);
}
float readNTC() {
int analogValue = analogRead(NTC_PIN);
float voltage = analogValue * 5.0 / 1023.0;
float resistance = R_SERIE * (5.0 / voltage - 1.0);
float tempK = 1.0 / (1.0 / T0 + (1.0 / BETA) * log(resistance / R0));
float tempC = tempK - 273.15;
return tempC;
}
void setRelay(bool state) {
relayState = state;
digitalWrite(RELAY_PIN, state ? HIGH : LOW);
}