#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
// LCD setup: I2C address 0x27, 16 columns and 2 rows
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Pin Definitions
const int sensorPin = A0; // RT1000 temperature sensor
const int relay1Pin = 7; // Relay 1
const int relay2Pin = 8; // Relay 2
const int modeButtonPin = 2;
const int upButtonPin = 3;
const int downButtonPin = 4;
// Variables
float temperature = 0.0;
float setpoint = 20.0; // Default setpoint
int mode = 0;
unsigned long lastSwitchTime = 0;
const unsigned long switchInterval = 5000; // Toggle screen every 5 seconds
unsigned long lastInteractionTime = 0;
const unsigned long returnToDefaultInterval = 5000; // 5 seconds return to default
bool screenToggle = true; // Toggle between screens
int currentUnit = 1; // Unit 1 or Unit 2 (starting with unit 1)
bool isBelowSetpoint = false; // Flag to indicate temperature below setpoint
// Function to read RT1000 temperature sensor
float readTemperature() {
int sensorValue = analogRead(sensorPin);
return map(sensorValue, 0, 1023, 0, 50); // Assuming the sensor range is 0-50°C
}
// Function to display welcome message
void displayWelcomeMessage() {
lcd.clear();
lcd.setCursor(4, 0);
lcd.print("Welcome");
lcd.setCursor(5, 1);
lcd.print("Syncro");
delay(5000); // Show for 5 seconds
}
// Function to show temperature and setpoint
void displayTempSetpointScreen() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Temp: ");
lcd.print(temperature);
lcd.setCursor(0, 1);
lcd.print("Set P: ");
lcd.print(setpoint, 1); // Show setpoint with 1 decimal
}
// Function to show unit statuses
void displayUnitStatusScreen() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("UNIT-1: ");
lcd.print(digitalRead(relay1Pin) == HIGH ? "ON" : "OFF");
lcd.setCursor(0, 1);
lcd.print("UNIT-2: ");
lcd.print(digitalRead(relay2Pin) == HIGH ? "ON" : "OFF");
}
// Function to show device info
void displayDeviceInfo() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("ID: 1 Baud:9600");
lcd.setCursor(0, 1);
lcd.print("Parity: 8N1");
delay(1000); // Show for 2 seconds
}
// Function to show vendor info
void displayVendorInfo() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Make: Syncro");
delay(1000); // Show for 2 seconds
}
// Function to check button press
void checkButtons() {
if (digitalRead(modeButtonPin) == LOW) {
mode++;
if (mode > 2) mode = 0;
screenToggle = false; // Stop screen toggling
lastInteractionTime = millis();
delay(100); // Debounce delay
}
if (digitalRead(upButtonPin) == LOW) {
if (mode == 0) { // Adjust setpoint only in temperature mode
setpoint += 0.5;
if (setpoint > 30) setpoint = 30; // Max setpoint is 30
}
screenToggle = false; // Stop screen toggling
lastInteractionTime = millis();
delay(200); // Debounce delay
}
if (digitalRead(downButtonPin) == LOW) {
if (mode == 0) { // Adjust setpoint only in temperature mode
setpoint -= 0.5;
if (setpoint < 15) setpoint = 15; // Min setpoint is 15
}
screenToggle = false; // Stop screen toggling
lastInteractionTime = millis();
delay(200); // Debounce delay
}
}
// Function to manage relay control
void manageRelay() {
unsigned long thirtyMinutes = 5000; // 30 minutes in milliseconds
if (temperature > setpoint) {
// Turn ON both units if above setpoint
digitalWrite(relay1Pin, HIGH);
digitalWrite(relay2Pin, HIGH);
isBelowSetpoint = false; // Reset flag
}
// If below setpoint, turn on one unit and auto-sequence every 30 minutes
else if (temperature <= setpoint - 0.5) {
if (!isBelowSetpoint) {
// If first time below setpoint, turn on only one unit
digitalWrite(relay1Pin, HIGH); // Relay 1 ON
digitalWrite(relay2Pin, LOW); // Relay 2 OFF
currentUnit = 1; // Start with unit 1
lastSwitchTime = millis(); // Reset the switch timer
isBelowSetpoint = true; // Set flag to indicate temperature is below setpoint
}
if (millis() - lastSwitchTime > thirtyMinutes) {
// Auto-sequence switching
if (currentUnit == 1) {
digitalWrite(relay1Pin, LOW); // Relay 1 OFF
digitalWrite(relay2Pin, HIGH); // Relay 2 ON
currentUnit = 2;
} else {
digitalWrite(relay1Pin, HIGH); // Relay 1 ON
digitalWrite(relay2Pin, LOW); // Relay 2 OFF
currentUnit = 1;
}
lastSwitchTime = millis(); // Reset the timer for the next 30-minute cycle
}
}
}
// Setup function
void setup() {
lcd.begin(16, 2); // Initialize with 16 columns and 2 rows
lcd.backlight();
displayWelcomeMessage();
// Pin modes
pinMode(sensorPin, INPUT);
pinMode(relay1Pin, OUTPUT);
pinMode(relay2Pin, OUTPUT);
pinMode(modeButtonPin, INPUT_PULLUP);
pinMode(upButtonPin, INPUT_PULLUP);
pinMode(downButtonPin, INPUT_PULLUP);
// Initialize relays: Ensure one relay is on
digitalWrite(relay1Pin, HIGH); // Relay 1 ON at startup
digitalWrite(relay2Pin, LOW); // Relay 2 OFF
// Read setpoint from EEPROM
EEPROM.get(0, setpoint);
if (isnan(setpoint) || setpoint < 15 || setpoint > 30) {
setpoint = 20.0; // Set default setpoint if EEPROM value is invalid
}
}
// Main loop function
void loop() {
// Read temperature
temperature = readTemperature();
// Check button presses
checkButtons();
// Return to default screen after inactivity
if (millis() - lastInteractionTime > returnToDefaultInterval) {
screenToggle = true;
mode = 0; // Reset to temperature screen mode
}
// Display temperature or unit status based on time interval
if (screenToggle) {
if (millis() - lastSwitchTime >= switchInterval) {
displayTempSetpointScreen();
lastSwitchTime = millis();
} else {
displayUnitStatusScreen();
}
}
// Display the mode screen if button pressed
if (!screenToggle) {
switch (mode) {
case 0:
displayTempSetpointScreen();
break;
case 1:
displayDeviceInfo();
break;
case 2:
displayVendorInfo();
break;
}
}
// Manage relay based on temperature and setpoint
manageRelay();
// Save the setpoint to EEPROM if it has changed
static float lastSetpoint = -1;
if (setpoint != lastSetpoint) {
EEPROM.put(0, setpoint);
lastSetpoint = setpoint;
}
delay(1000);
}