#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>
// Pin definitions
#define ONE_WIRE_BUS 2 // DS18B20 data pin
#define RELAY_PIN 6 // Relay control pin
#define CLK_PIN 3 // Rotary encoder CLK
#define DT_PIN 4 // Rotary encoder DT
#define SW_PIN 5 // Rotary encoder switch (optional)
// Temperature limits
#define MIN_TEMP 0.0
#define MAX_TEMP 85.0
#define TEMP_STEP 0.5 // Temperature adjustment step
// Initialize components
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
LiquidCrystal_I2C lcd(0x27, 16, 2); // Adjust I2C address if needed
// Variables
float setTemp = 75.0; // Default set temperature
float currentTemp = 0.0;
int encoderPos = 0;
int lastClkState = HIGH;
unsigned long lastUpdate = 0;
void setup() {
Serial.begin(9600);
sensors.begin();
// Initialize LCD
lcd.init();
lcd.backlight();
lcd.print("Temp Controller");
delay(2000);
lcd.clear();
// Set pin modes in arduino
pinMode(RELAY_PIN, OUTPUT);
pinMode(CLK_PIN, INPUT);
pinMode(DT_PIN, INPUT);
pinMode(SW_PIN, INPUT_PULLUP);
digitalWrite(RELAY_PIN, LOW); // Start with relay off
}
void loop() {
unsigned long currentMillis = millis();
// Read temperature every second
if (currentMillis - lastUpdate >= 1000) {
lastUpdate = currentMillis;
readTemperature();
controlRelay();
updateDisplay();
}
// Handle rotary encoder input
handleEncoder();
}
void readTemperature() {
sensors.requestTemperatures();
currentTemp = sensors.getTempCByIndex(0);
// Check for sensor errors
if (currentTemp == DEVICE_DISCONNECTED_C) {
Serial.println("Error: Sensor disconnected");
lcd.setCursor(0, 1);
lcd.print("Sensor Error! ");
return;
}
Serial.print("Current Temp: ");
Serial.print(currentTemp);
Serial.print("°C | Set Temp: ");
Serial.print(setTemp);
Serial.println("°C");
}
void controlRelay() {
// Hysteresis of ±0.1°C to prevent rapid cycling
if (currentTemp < (setTemp - 0.1)) { // Heat if below 82.9°C
digitalWrite(RELAY_PIN, HIGH);
}
else if (currentTemp > (setTemp + 0.1)) { // Stop if above 83.1°C
digitalWrite(RELAY_PIN, LOW);
}
}
void updateDisplay() {
lcd.setCursor(0, 0);
lcd.print("Set:");
lcd.print(setTemp, 1);
lcd.print((char)223); // Degree symbol
lcd.print("C ");
lcd.setCursor(0, 1);
lcd.print("Cur:");
lcd.print(currentTemp, 1);
lcd.print((char)223); // Degree symbol
lcd.print("C ");
}
void handleEncoder() {
int clkState = digitalRead(CLK_PIN);
if (clkState != lastClkState && clkState == HIGH) {
// Encoder was turned
if (digitalRead(DT_PIN) != clkState) {
setTemp += TEMP_STEP; // Clockwise turn
} else {
setTemp -= TEMP_STEP; // Counter-clockwise turn
}
// Constrain temperature to limits
setTemp = constrain(setTemp, MIN_TEMP, MAX_TEMP);
// Update display immediately when changing set temp
updateDisplay();
}
lastClkState = clkState;
// Optional: Handle encoder button press
if (digitalRead(SW_PIN) == LOW) {
delay(50); // Simple debounce
while (digitalRead(SW_PIN) == LOW); // Wait for release
// Could add button functionality here
}
}