#include <Arduino.h>
#include <TM1637Display.h>
#include "DHT.h"
// Pin Definitions
#define DHTPIN 2 // DHT22 Data Pin
#define DHTTYPE DHT22 // Using high-precision DHT22 sensor
#define CLK_PIN 3 // TM1637 Clock Pin
#define DIO_PIN 8 // TM1637 Data Pin
#define RELAY_PIN 4 // Relay/LED Control Pin (Active-LOW Configuration)
#define BTN_SET 5 // Menu Mode Toggle Button
#define BTN_UP 6 // Target Temperature Increment Button
#define BTN_DOWN 7 // Target Temperature Decrement Button
// Thermostat Control System Variables (Celsius)
float targetTemp = 5.0; // Default baseline cooling target
const float HYSTERESIS = 1.5; // Preventing short-cycling buffer window
bool isCooling = false;
bool inSettingMode = false;
// Initialize Electronic Hardware Profiles
DHT dht(DHTPIN, DHTTYPE);
TM1637Display display(CLK_PIN, DIO_PIN);
// Custom 7-Segment structural bits mapping out the "°C" symbol layout
const uint8_t CELSIUS_SUFFIX[] = {
SEG_A | SEG_B | SEG_G | SEG_F, // Degree circle symbol (°)
SEG_A | SEG_D | SEG_E | SEG_F // Alpha character capital 'C'
};
void setup() {
Serial.begin(9600); // Initializing tracking data window
dht.begin();
display.setBrightness(0x0f); // Fire up segments to maximum brightness level
// Define Output Controls
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, HIGH); // Safety Rule: Force relay loop OFF at system initialization
// Set up button ports using the internal Pull-Up network loops
pinMode(BTN_SET, INPUT_PULLUP);
pinMode(BTN_UP, INPUT_PULLUP);
pinMode(BTN_DOWN, INPUT_PULLUP);
// Initialization flash display confirmation sequence "8888"
display.showNumberDec(8888, false);
delay(600);
display.clear();
Serial.println("System Initialized Successfully.");
}
void loop() {
// Read User Input Profile: Detect if SET switch breaks ground
if (digitalRead(BTN_SET) == LOW) {
delay(200); // Debounce delay path to ignore physical switch bounce noise
inSettingMode = !inSettingMode; // Swap working application state matrix
display.clear();
while(digitalRead(BTN_SET) == LOW); // Wait for user to completely let go of the button
}
if (inSettingMode) {
adjustSettingsMode();
} else {
runThermostatMode();
}
}
void adjustSettingsMode() {
// Read Increment Input Channel
if (digitalRead(BTN_UP) == LOW) {
delay(150); // Fast debounce track
targetTemp += 0.5; // Increment target value by halves
if (targetTemp > 30.0) targetTemp = 30.0; // Enforce maximum safe hot threshold limit
}
// Read Decrement Input Channel
if (digitalRead(BTN_DOWN) == LOW) {
delay(150); // Fast debounce track
targetTemp -= 0.5; // Decrement target value by halves
if (targetTemp < -5.0) targetTemp = -5.0; // Enforce minimum safe sub-zero structural freezing floor
}
// Active UI Display Rendering during adjustment
int displayTargetInt = (int)targetTemp;
display.showNumberDec(displayTargetInt, false, 2, 0); // Plot numeric value on the first 2 digits
display.setSegments(CELSIUS_SUFFIX, 2, 2); // Anchor the "°C" graphics to the remaining 2 digits
}
void runThermostatMode() {
static unsigned long lastReadingTimestamp = 0;
static float monitoredTemp = 0.0;
// Query sensor node non-blockingly every 2000 milliseconds to avoid blocking logic loops
if (millis() - lastReadingTimestamp >= 2000) {
monitoredTemp = dht.readTemperature();
lastReadingTimestamp = millis();
// Print data outputs continuously to the Serial Monitor stream log
Serial.print("Internal Temp: ");
Serial.print(monitoredTemp, 1);
Serial.print(" C | Current Cooling Target Set Point: ");
Serial.print(targetTemp, 1);
Serial.println(" C");
}
// Handle Unexpected Sensor Outages Safely
if (isnan(monitoredTemp)) {
// Generate an immediate "Err" alphabetic readout sequence across 7-segment pins
uint8_t errorMask[] = { SEG_A|SEG_D|SEG_E|SEG_F|SEG_G, SEG_E|SEG_G, SEG_E|SEG_G }; // E r r
display.setSegments(errorMask, 3, 0);
digitalWrite(RELAY_PIN, HIGH); // SYSTEM CRITICAL TRIP OVERRIDE: Kill heavy power to the Peltier element immediately
return;
}
// Standard Operation Mode Display Output
int roundTemp = (int)monitoredTemp;
display.showNumberDec(roundTemp, false, 2, 0); // Output live value to display left side digits
display.setSegments(CELSIUS_SUFFIX, 2, 2); // Draw "°C" suffix to right side digits
// --- Automated Thermostat Temperature Control Calculations ---
if (!isCooling && monitoredTemp > (targetTemp + HYSTERESIS)) {
isCooling = true;
digitalWrite(RELAY_PIN, LOW); // Active-LOW Profile: Drive low to snap relay closed and activate cooling
Serial.println("[!] Fridge Status Shift: TARGET BREACHED. COOLING MODE ACTIVATED.");
}
else if (isCooling && monitoredTemp <= (targetTemp - HYSTERESIS)) {
isCooling = false;
digitalWrite(RELAY_PIN, HIGH); // Active-LOW Profile: Drive high to drop relay contact open and deactivate cooling
Serial.println("[!] Fridge Status Shift: SATIATED COLD ENVIRONMENT. RELAY SHUTDOWN IDLE STAGE.");
}
}