#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <Wire.h>
#include "RTClib.h"
#include "DHT.h"
#include <Adafruit_FT6206.h>
// Pins for the TFT display (SPI)
#define TFT_CS 4
#define TFT_RST 7
#define TFT_DC 8
//Pins for PWM Outputs
#define airInPin 3
#define airOutPin 5
#define lowerFansPin 6
#define upperFansPin 9
//Pins for Relais Output
#define lightPin A0
#define filterPin A1
// Initialize the TFT display
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
// Initialize the touchscreen
Adafruit_FT6206 ts = Adafruit_FT6206();
// Initialize the RTC
RTC_DS1307 rtc;
// Initialize the DHT22 sensor
#define DHTPIN 2
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
// Variables for storing time intervals
unsigned long lastUpdate = 0;
const unsigned long updateInterval = 60000; // 1 minute
// Variables for storing previous sensor values
float lastTemperature = NAN;
float lastHumidity = NAN;
DateTime lastTime;
unsigned int lightOnHour = 0;
unsigned int lightOffHour = 0;
unsigned int lightOnMinute = 6;
unsigned int lightOffMinute = 0;
unsigned int tempMin = 20;
unsigned int tempMax = 28;
unsigned int humidMin = 40;
unsigned int humidMax = 70;
bool airInOutManually = false;
bool lightManually = false;
bool filterManually = false;
bool lowerFansManually = false;
bool upperFansManually = false;
bool fansInterval = false;
bool fansIntervalStatus = false;
byte airInPercentage = 100;
byte airOutPercentage = 100;
byte lowerFansPercentage = 100;
byte upperFansPercentage = 100;
unsigned long fanLastToggleTime = 0;
unsigned int fanOnInterval = 10 *60* 1000; // 15 Minuten in Millisekunden
unsigned int fanOffInterval = 5 *60* 1000; // 5 Minuten in Millisekunden
unsigned int touchX;
unsigned int touchY;
// Variables for touch handling
bool wasTouched = false;
unsigned long touchStartTime = 0;
const unsigned long touchThreshold = 10; // 20 milliseconds
unsigned long lastActivityTime = 0;
const unsigned long inactivityInterval = 10 * 60 * 1000;
// Enum for screen state
enum ScreenState {
HOME_SCREEN,
SETTINGS_SCREEN,
LIGHTCYCLE_SCREEN,
AIRINOUT_SCREEN,
AIRINOUT_SCREEN2,
FILTER_SCREEN,
FANS_SCREEN
};
ScreenState currentScreen = HOME_SCREEN;
ScreenState previousScreen = HOME_SCREEN;
// Function prototypes to avoid implicit declaration warnings
void drawHomeScreen();
void updateHomeScreen();
void drawSettingsScreen();
void updateSettingsScreen();
void drawLightcycleScreen();
void updateLightcycleScreen();
void drawAirInOutScreen();
void updateAirInOutScreen();
void drawFilterScreen();
void updateFilterScreen();
void drawFansScreen();
void updateFansScreen();
void drawBackspaceButton();
void updateTime();
void updateDisplay();
void onOffButtonAirInOutManually();
void onOffButtonLightManually();
void onOffButtonFilterManually();
void onOffButtonFansManually();
void airInPercentageStrip();
void airOutPercentageStrip();
void setup() {
// Initialize serial communication
Serial.begin(9600);
// Initialize the TFT display
tft.begin();
tft.setRotation(0); // Set rotation for portrait mode
tft.fillScreen(ILI9341_BLACK);
// Initialize the touchscreen
if (!ts.begin()) {
Serial.println("Couldn't start touchscreen controller");
while (1);
}
// Initialize the RTC
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
// Check if the RTC lost power and if so, set the time
if (!rtc.isrunning()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
// Initialize the DHT22 sensor
dht.begin();
pinMode(lightPin, OUTPUT);
pinMode(filterPin, OUTPUT);
pinMode(airInPin, OUTPUT);
pinMode(airOutPin, OUTPUT);
pinMode(lowerFansPin, OUTPUT);
pinMode(upperFansPin, OUTPUT);
// Ensure the relays are off initially
digitalWrite(lightPin, LOW);
digitalWrite(filterPin, LOW);
// Set initial MOSFET states
analogWrite(airInPin, 0); // Set Initial Percentage Value
analogWrite(airOutPin, 0); // Set Initial Percentage Value
analogWrite(lowerFansPin, 0); // Set Initial Percentage Value
analogWrite(upperFansPin, 0); // Set Initial Percentage Value
// Draw the initial screen
checkLightTimer();
drawHomeScreen();
}
void loop() {
updateTime();
// Check if it's time to update the display
unsigned long currentMillis = millis();
//Update Display every 1 Minute
/*if (currentMillis - lastUpdate >= updateInterval) {
lastUpdate = currentMillis;
updateDisplay();
}*/
if (currentMillis - lastActivityTime >= inactivityInterval) {
if (currentScreen != HOME_SCREEN) {
currentScreen = HOME_SCREEN;
drawHomeScreen();
}
}
// Check if Disply was touched
if (ts.touched()) {
TS_Point p = ts.getPoint();
// map the point to screen coordinates
p.x = map(p.x, 0, 240, 240, 0);
p.y = map(p.y, 0, 320, 320, 0);
touchX = p.x;
touchY = p.y;
wasTouched = true;
touchStartTime = millis();
} else if (wasTouched && millis() - touchStartTime >= touchThreshold) {
wasTouched = false;
handleTouch();
}
}
void handleTouch() {
lastActivityTime = millis(); // Update last activity time on touch
if (currentScreen == HOME_SCREEN) {
if (touchX > 120 && touchX < 230 && touchY > 288 && touchY < 310) {
previousScreen = currentScreen;
currentScreen = SETTINGS_SCREEN;
drawSettingsScreen();
}
} else if (currentScreen == SETTINGS_SCREEN) {
// Handle settings screen touch events
if (touchX > 200 && touchX < 230 && touchY > 280 && touchY < 310) {
previousScreen = currentScreen;
currentScreen = HOME_SCREEN;
drawHomeScreen();
} else if (touchX > 10 && touchX < 230 && touchY > 60 && touchY < 90) {
previousScreen = currentScreen;
currentScreen = LIGHTCYCLE_SCREEN;
drawLightcycleScreen();
} else if (touchX > 10 && touchX < 230 && touchY > 100 && touchY < 130) {
previousScreen = currentScreen;
currentScreen = AIRINOUT_SCREEN;
drawAirInOutScreen();
} else if (touchX > 10 && touchX < 230 && touchY > 140 && touchY < 170) {
previousScreen = currentScreen;
currentScreen = FILTER_SCREEN;
drawFilterScreen();
} else if (touchX > 10 && touchX < 230 && touchY > 180 && touchY < 210) {
previousScreen = currentScreen;
currentScreen = FANS_SCREEN;
drawFansScreen();
}
} else if (currentScreen == LIGHTCYCLE_SCREEN) {
// Handle light cycle screen touch events
if (touchX > 200 && touchX < 230 && touchY > 280 && touchY < 310) {
previousScreen = currentScreen;
currentScreen = SETTINGS_SCREEN;
drawSettingsScreen();
} else if (touchX > 173 && touchX < 193 && touchY > 60 && touchY < 80) {
adjustLightOnHour(1);
} else if (touchX > 173 && touchX < 193 && touchY > 100 && touchY < 120) {
adjustLightOnHour(-1);
} else if (touchX > 210 && touchX < 230 && touchY > 60 && touchY < 80) {
adjustLightOnMinute(15);
} else if (touchX > 210 && touchX < 230 && touchY > 100 && touchY < 120) {
adjustLightOnMinute(-15);
} else if (touchX > 173 && touchX < 193 && touchY > 130 && touchY < 150) {
adjustLightOffHour(1);
} else if (touchX > 173 && touchX < 193 && touchY > 170 && touchY < 190) {
adjustLightOffHour(-1);
} else if (touchX > 210 && touchX < 230 && touchY > 130 && touchY < 150) {
adjustLightOffMinute(15);
} else if (touchX > 210 && touchX < 230 && touchY > 170 && touchY < 190) {
adjustLightOffMinute(-15);
} else if (touchX > 10 && touchX < 120 && touchY > 230 && touchY < 265) {
lightManually = true;
onOffButtonLightManually();
} else if (touchX > 120 && touchX < 230 && touchY > 230 && touchY < 265) {
lightManually = false;
onOffButtonLightManually();
}
setRelaisOutputs();
} else if (currentScreen == AIRINOUT_SCREEN) {
// Handle light cycle screen touch events
if (touchX > 200 && touchX < 230 && touchY > 280 && touchY < 310) {
previousScreen = currentScreen;
currentScreen = SETTINGS_SCREEN;
drawSettingsScreen();
} else if (touchX > 173 && touchX < 193 && touchY > 60 && touchY < 80) {
adjustTempMin(1);
} else if (touchX > 173 && touchX < 193 && touchY > 100 && touchY < 120) {
adjustTempMin(-1);
} else if (touchX > 210 && touchX < 230 && touchY > 60 && touchY < 80) {
adjustTempMax(1);
} else if (touchX > 210 && touchX < 230 && touchY > 100 && touchY < 120) {
adjustTempMax(-1);
} else if (touchX > 173 && touchX < 193 && touchY > 130 && touchY < 150) {
adjustHumidMin(1);
} else if (touchX > 173 && touchX < 193 && touchY > 170 && touchY < 190) {
adjustHumidMin(-1);
} else if (touchX > 210 && touchX < 230 && touchY > 130 && touchY < 150) {
adjustHumidMax(5);
} else if (touchX > 210 && touchX < 230 && touchY > 170 && touchY < 190) {
adjustHumidMax(-5);
} else if (touchX > 50 && touchX < 80 && touchY > 280 && touchY < 310) {
previousScreen = currentScreen;
currentScreen = AIRINOUT_SCREEN2;
drawAirInOutScreen2();
} else if (touchX > 10 && touchX < 120 && touchY > 230 && touchY < 265) {
airInOutManually = true;
onOffButtonAirInOutManually();
} else if (touchX > 120 && touchX < 230 && touchY > 230 && touchY < 265) {
airInOutManually = false;
onOffButtonAirInOutManually();
}
setMosfetOutputs();
} else if (currentScreen == AIRINOUT_SCREEN2) {
// Handle air in/out screen touch events
if (touchX > 200 && touchX < 230 && touchY > 280 && touchY < 310) {
previousScreen = currentScreen;
currentScreen = SETTINGS_SCREEN;
drawSettingsScreen();
}
else if (touchX > 10 && touchX < 54 && touchY > 85 && touchY < 105) {
airInPercentage = 20;
airInPercentageStrip();
} else if (touchX > 54 && touchX < 98 && touchY > 85 && touchY < 105) {
airInPercentage = 40;
airInPercentageStrip();
} else if (touchX > 98 && touchX < 142 && touchY > 85 && touchY < 105) {
airInPercentage = 60;
airInPercentageStrip();
} else if (touchX > 142 && touchX < 186 && touchY > 85 && touchY < 105) {
airInPercentage = 80;
airInPercentageStrip();
} else if (touchX > 186 && touchX < 230 && touchY > 85 && touchY < 105) {
airInPercentage = 100;
airInPercentageStrip();
} else if (touchX > 10 && touchX < 54 && touchY > 145 && touchY < 165) {
airOutPercentage = 20;
airOutPercentageStrip();
} else if (touchX > 54 && touchX < 98 && touchY > 145 && touchY < 165) {
airOutPercentage = 40;
airOutPercentageStrip();
} else if (touchX > 98 && touchX < 142 && touchY > 145 && touchY < 165) {
airOutPercentage = 60;
airOutPercentageStrip();
} else if (touchX > 142 && touchX < 186 && touchY > 145 && touchY < 165) {
airOutPercentage = 80;
airOutPercentageStrip();
} else if (touchX > 186 && touchX < 230 && touchY > 145 && touchY < 165) {
airOutPercentage = 100;
airOutPercentageStrip();
} else if (touchX > 10 && touchX < 40 && touchY > 280 && touchY < 310) {
previousScreen = currentScreen;
currentScreen = AIRINOUT_SCREEN;
drawAirInOutScreen();
}
setMosfetOutputs();
} else if (currentScreen == FILTER_SCREEN) {
// Handle filter screen touch events
if (touchX > 200 && touchX < 230 && touchY > 280 && touchY < 310) {
previousScreen = currentScreen;
currentScreen = SETTINGS_SCREEN;
drawSettingsScreen();
} else if (touchX > 10 && touchX < 120 && touchY > 230 && touchY < 265) {
filterManually = true;
onOffButtonFilterManually();
} else if (touchX > 120 && touchX < 230 && touchY > 230 && touchY < 265) {
filterManually = false;
onOffButtonFilterManually();
}
setRelaisOutputs();
} else if (currentScreen == FANS_SCREEN) {
// Handle fans screen touch events
if (touchX > 200 && touchX < 230 && touchY > 280 && touchY < 310) {
previousScreen = currentScreen;
currentScreen = SETTINGS_SCREEN;
drawSettingsScreen();
} else if (touchX > 10 && touchX < 120 && touchY > 230 && touchY < 265) {
lowerFansManually = true;
upperFansManually = true;
onOffButtonFansManually();
} else if (touchX > 120 && touchX < 230 && touchY > 230 && touchY < 265) {
lowerFansManually = false;
upperFansManually = false;
onOffButtonFansManually();
setMosfetOutputs();
} else if (touchX > 10 && touchX < 54 && touchY > 85 && touchY < 105) {
upperFansPercentage = 20;
upperFansPercentageStrip();
} else if (touchX > 54 && touchX < 98 && touchY > 85 && touchY < 105) {
upperFansPercentage = 40;
upperFansPercentageStrip();
} else if (touchX > 98 && touchX < 142 && touchY > 85 && touchY < 105) {
upperFansPercentage = 60;
upperFansPercentageStrip();
} else if (touchX > 142 && touchX < 186 && touchY > 85 && touchY < 105) {
upperFansPercentage = 80;
upperFansPercentageStrip();
} else if (touchX > 186 && touchX < 230 && touchY > 85 && touchY < 105) {
upperFansPercentage = 100;
upperFansPercentageStrip();
} else if (touchX > 10 && touchX < 54 && touchY > 145 && touchY < 165) {
lowerFansPercentage = 20;
lowerFansPercentageStrip();
} else if (touchX > 54 && touchX < 98 && touchY > 145 && touchY < 165) {
lowerFansPercentage = 40;
lowerFansPercentageStrip();
} else if (touchX > 98 && touchX < 142 && touchY > 145 && touchY < 165) {
lowerFansPercentage = 60;
lowerFansPercentageStrip();
} else if (touchX > 142 && touchX < 186 && touchY > 145 && touchY < 165) {
lowerFansPercentage = 80;
lowerFansPercentageStrip();
} else if (touchX > 186 && touchX < 230 && touchY > 145 && touchY < 165) {
lowerFansPercentage = 100;
lowerFansPercentageStrip();
} else if (touchX > 150 && touchX < 190 && touchY > 182 && touchY < 202) {
fansIntervalStatus = true;
intervalButtonFans();
} else if (touchX > 190 && touchX < 230 && touchY > 182 && touchY < 202) {
fansIntervalStatus = false;
intervalButtonFans();
}
setMosfetOutputs();
}
}
void checkLightTimer() {
DateTime now = rtc.now();
int currentTime = now.hour() * 60 + now.minute();
int lightOnTime = lightOnHour * 60 + lightOnMinute;
int lightOffTime = lightOffHour * 60 + lightOffMinute;
if (lightOffTime == 0) {
lightOffTime = 1440;
}
// Lichtsteuerung
if (currentTime >= lightOnTime && currentTime < lightOffTime) {
lightManually = true;
} else {
lightManually = false;
}
}
void setRelaisOutputs() { //Relais Lights
if (lightManually == true) {
digitalWrite(lightPin, HIGH);
} else if (lightManually == false) {
digitalWrite(lightPin, LOW);
}
//Relais Filter
if (filterManually == true) {
digitalWrite(filterPin, HIGH);
} else if (filterManually == false) {
digitalWrite(filterPin, LOW);
}
}
void setMosfetOutputs() {
int mapAirIn = map(airInPercentage, 0, 100, 0, 255);
int mapAirOut = map(airOutPercentage, 0, 100, 0, 255);
int mapLowerFans = map(lowerFansPercentage, 0, 100, 0, 255);
int mapUpperFans = map(upperFansPercentage, 0, 100, 0, 255);
//Air In/Out
if (airInOutManually == true) {
analogWrite(airInPin, mapAirIn);
analogWrite(airOutPin, mapAirOut);
} else if (airInOutManually == false) {
analogWrite(airInPin, 0);
analogWrite(airOutPin, 0);
}
//Lower Fans
if (lowerFansManually == true) {
if (fansIntervalStatus == false) {
analogWrite(lowerFansPin, mapLowerFans);
} else if (fansIntervalStatus == true) {
checkFansInterval();
if (fansInterval == true) {
analogWrite(lowerFansPin, mapLowerFans);
} else if (fansInterval == false) {
analogWrite(lowerFansPin, 0);
}
}
} else if (lowerFansManually == false) {
analogWrite(lowerFansPin, 0);
}
//Upper Fans
if (upperFansManually == true) {
if (fansIntervalStatus == false) {
analogWrite(upperFansPin, mapUpperFans);
} else if (fansIntervalStatus == true) {
checkFansInterval();
if (fansInterval == true) {
analogWrite(upperFansPin, mapUpperFans);
} else if (fansInterval == false) {
analogWrite(upperFansPin, 0);
}
}
} else if (upperFansManually == false) {
analogWrite(upperFansPin, 0);
}
}
void drawHomeScreen() {
tft.fillRect(0, 30, 240, 320, ILI9341_BLACK);
updateHomeScreen();
// Draw settings button
tft.drawRect(120, 280, 110, 30, ILI9341_GREEN); // Adjusted for portrait mode
tft.setCursor(128, 288);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("Settings");
}
void updateHomeScreen() {
checkLightTimer();
if (lightManually == true) {
drawSun(161, 210, 25, 0xfe60);
} else if (lightManually == false) {
tft.fillRect(111, 149, 110, 110, ILI9341_BLACK);
drawCrescentMoon(161, 210, 25, 0xc618);
}
// Read temperature and humidity
float t = dht.readTemperature();
float h = dht.readHumidity();
if (t > tempMax || h > humidMax) {
airInOutManually = true;
lowerFansManually = true;
upperFansManually = true;
} else if (t < tempMin || h < humidMin) {
airInOutManually = false;
if (lowerFansManually == true || upperFansManually == true) {
checkFansInterval();
}
} else if (lowerFansManually == true || upperFansManually == true) {
checkFansInterval();
}
// Update the display only if values have changed
if (t != lastTemperature || h != lastHumidity) {
lastTemperature = t;
lastHumidity = h;
// Clear previous temperature and humidity
tft.fillRect(10, 65, 220, 21, ILI9341_BLACK);
tft.fillRect(10, 115, 220, 21, ILI9341_BLACK);
// Display temperature
//tft.drawRect(10, 60, 220, 41, ILI9341_GREEN);
tft.setCursor(30, 65);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(3);
tft.print(" T= ");
tft.print(t, 1);
tft.print(" C");
// Display humidity
//tft.drawRect(10, 130, 220, 41, ILI9341_GREEN);
tft.setCursor(30, 115);
tft.print("rF= ");
tft.print(h, 1);
tft.print(" %");
} else { //Display old values
//tft.drawRect(10, 60, 220, 41, ILI9341_GREEN);
tft.setCursor(30, 65);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(3);
tft.print(" T= ");
tft.print(lastTemperature, 1);
tft.print(" C");
// tft.drawRect(10, 130, 220, 41, ILI9341_GREEN);
tft.setCursor(30, 115);
tft.print("rF= ");
tft.print(lastHumidity, 1);
tft.print(" %");
}
drawOverview(10, 223, 10);
setRelaisOutputs();
setMosfetOutputs();
}
void drawSettingsScreen() {
tft.fillRect(0, 30, 240, 320, ILI9341_BLACK);
updateTime();
tft.setCursor(10, 30);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(3);
tft.print("Settings");
drawBackspaceButton();
//Draw Llightcycle button
tft.drawRect(10, 60, 220, 30, ILI9341_GREEN); // Adjusted for portrait mode
tft.setCursor(18, 68);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("Lightcycle");
//Draw Air In/Out button
tft.drawRect(10, 100, 220, 30, ILI9341_GREEN); // Adjusted for portrait mode
tft.setCursor(18, 108);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("Air In/Out");
//Draw Filter button
tft.drawRect(10, 140, 220, 30, ILI9341_GREEN); // Adjusted for portrait mode
tft.setCursor(18, 148);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("Filter");
//Draw Fans button
tft.drawRect(10, 180, 220, 30, ILI9341_GREEN); // Adjusted for portrait mode
tft.setCursor(18, 188);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("Fans");
}
void updateSettingsScreen() {
updateTime();
}
void drawLightcycleScreen() {
tft.fillRect(0, 30, 240, 320, ILI9341_BLACK);
updateTime();
drawBackspaceButton();
tft.setCursor(10, 30);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(3);
tft.print("Lightcycle");
//Daily On buttons and text
tft.drawRect(210, 60, 20, 20, ILI9341_GREEN); // Adjusted for portrait mode
tft.setCursor(215, 63);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("+");
tft.drawRect(210, 100, 20, 20, ILI9341_GREEN);
tft.setCursor(215, 103);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("-");
tft.drawRect(174, 60, 20, 20, ILI9341_GREEN); // Adjusted for portrait mode
tft.setCursor(179, 63);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("+");
tft.drawRect(174, 100, 20, 20, ILI9341_GREEN);
tft.setCursor(179, 103);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("-");
tft.setCursor(10, 83);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("Daily ON");
tft.setCursor(173, 83);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
if (lightOnHour < 10) {
tft.print("0");
}
tft.print(lightOnHour);
tft.print(":");
if (lightOnMinute < 10) {
tft.print("0");
}
tft.print(lightOnMinute);
//Daily off buttons and text
tft.drawRect(210, 130, 20, 20, ILI9341_GREEN); // Adjusted for portrait mode
tft.setCursor(215, 133);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("+");
tft.drawRect(210, 170, 20, 20, ILI9341_GREEN);
tft.setCursor(215, 173);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("-");
tft.drawRect(174, 130, 20, 20, ILI9341_GREEN); // Adjusted for portrait mode
tft.setCursor(179, 133);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("+");
tft.drawRect(174, 170, 20, 20, ILI9341_GREEN);
tft.setCursor(179, 173);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("-");
tft.setCursor(10, 153);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("Daily OFF");
tft.setCursor(173, 153);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
if (lightOffHour < 10) {
tft.print("0");
}
tft.print(lightOffHour);
tft.print(":");
if (lightOffMinute < 10) {
tft.print("0");
}
tft.print(lightOffMinute);
onOffButtonLightManually();
}
void updateLightcycleScreen() {
updateTime();
}
void drawAirInOutScreen() {
tft.fillRect(0, 30, 240, 320, ILI9341_BLACK);
updateTime();
drawBackspaceButton();
drawScrollRightButton();
tft.setCursor(10, 30);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(3);
tft.print("Air In/Out");
tft.drawRect(210, 60, 20, 20, ILI9341_GREEN); // Adjusted for portrait mode
tft.setCursor(215, 63);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("+");
tft.drawRect(210, 100, 20, 20, ILI9341_GREEN);
tft.setCursor(215, 103);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("-");
tft.drawRect(174, 60, 20, 20, ILI9341_GREEN); // Adjusted for portrait mode
tft.setCursor(179, 63);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("+");
tft.drawRect(174, 100, 20, 20, ILI9341_GREEN);
tft.setCursor(179, 103);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("-");
tft.setCursor(10, 83);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("Temp Range C");
tft.setCursor(173, 83);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
if (tempMin < 10) {
tft.print("0");
}
tft.print(tempMin);
tft.print("-");
if (tempMax < 10) {
tft.print("0");
}
tft.print(tempMax);
//Daily off buttons and text
tft.drawRect(210, 130, 20, 20, ILI9341_GREEN); // Adjusted for portrait mode
tft.setCursor(215, 133);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("+");
tft.drawRect(210, 170, 20, 20, ILI9341_GREEN);
tft.setCursor(215, 173);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("-");
tft.drawRect(174, 130, 20, 20, ILI9341_GREEN); // Adjusted for portrait mode
tft.setCursor(179, 133);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("+");
tft.drawRect(174, 170, 20, 20, ILI9341_GREEN);
tft.setCursor(179, 173);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("-");
tft.setCursor(10, 153);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("Humid Range %");
tft.setCursor(173, 153);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
if (humidMin < 10) {
tft.print("0");
}
tft.print(humidMin);
tft.print("-");
if (humidMax < 10) {
tft.print("0");
}
tft.print(humidMax);
onOffButtonAirInOutManually();
}
void updateAirInOutScreen() {
updateTime();
}
void drawAirInOutScreen2() {
tft.fillRect(0, 59, 240, 320, ILI9341_BLACK);
updateTime();
drawBackspaceButton();
drawScrollLeftButton();
tft.setCursor(10, 30);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(3);
tft.print("Air In/Out");
tft.setCursor(10, 65);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("Air In %");
airInPercentageStrip();
tft.setCursor(10, 125);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("Air Out %");
airOutPercentageStrip();
}
void updateAirInOutScreen2() {
updateTime();
}
void drawFilterScreen() {
tft.fillRect(0, 30, 240, 320, ILI9341_BLACK);
updateTime();
drawBackspaceButton();
tft.setCursor(10, 30);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(3);
tft.print("Filter");
onOffButtonFilterManually();
}
void updateFilterScreen() {
updateTime();
}
void drawFansScreen() {
tft.fillRect(0, 30, 240, 320, ILI9341_BLACK);
updateTime();
drawBackspaceButton();
tft.setCursor(10, 30);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(3);
tft.print("Fans");
tft.setCursor(10, 65);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("Upper Fans %");
upperFansPercentageStrip();
tft.setCursor(10, 125);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("Lower Fans %");
lowerFansPercentageStrip();
tft.setCursor(10, 185);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("Interval");
intervalButtonFans();
onOffButtonFansManually();
}
void updateFansScreen() {
updateTime();
}
void drawBackspaceButton() {
//Draw backspace button
tft.drawRect(200, 280, 30, 30, ILI9341_GREEN); // Adjusted for portrait mode
tft.setCursor(203, 288);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("<-");
}
void drawScrollLeftButton() {
//Draw backspace button
tft.drawRect(10, 280, 30, 30, ILI9341_GREEN); // Adjusted for portrait mode
tft.setCursor(18, 288);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("<");
}
void drawScrollRightButton() {
//Draw backspace button
tft.drawRect(50, 280, 30, 30, ILI9341_GREEN); // Adjusted for portrait mode
tft.setCursor(58, 288);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print(">");
}
void updateTime() {
DateTime now = rtc.now();
// Update the date and time if it has changed
if (now.minute() != lastTime.minute()) {
lastTime = now;
char buf1[11];
char buf2[6];
snprintf(buf1, sizeof(buf1), "%02d/%02d/%04d", now.month(), now.day(), now.year());
snprintf(buf2, sizeof(buf2), "%02d:%02d", now.hour(), now.minute());
// Clear previous date and time
tft.fillRect(0, 0, 240, 29, ILI9341_BLACK);
tft.setCursor(10, 10);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1);
tft.print(buf1);
tft.setCursor(200, 10);
tft.print(buf2);
checkLightTimer();
updateDisplay();
setRelaisOutputs();
setMosfetOutputs();
}
}
void updateDisplay() {
if (currentScreen == HOME_SCREEN) {
updateHomeScreen();
} else if (currentScreen == SETTINGS_SCREEN) {
updateSettingsScreen();
} else if (currentScreen == LIGHTCYCLE_SCREEN) {
updateLightcycleScreen();
} else if (currentScreen == AIRINOUT_SCREEN) {
updateAirInOutScreen();
} else if (currentScreen == FILTER_SCREEN) {
updateFilterScreen();
} else if (currentScreen == FANS_SCREEN) {
updateFansScreen();
}
}
void onOffButtonAirInOutManually() {
tft.fillRect(10, 230, 220, 35, ILI9341_BLACK);
if (airInOutManually) {
drawOnOffButton(10, 230, "ON", true);
drawOnOffButton(120, 230, "OFF", false);
} else {
drawOnOffButton(10, 230, "ON", false);
drawOnOffButton(120, 230, "OFF", true);
}
}
void onOffButtonLightManually() {
tft.fillRect(10, 230, 220, 35, ILI9341_BLACK);
if (lightManually == true) {
drawOnOffButton(10, 230, "ON", true);
drawOnOffButton(120, 230, "OFF", false);
} else if (lightManually == false) {
drawOnOffButton(10, 230, "ON", false);
drawOnOffButton(120, 230, "OFF", true);
}
}
void onOffButtonFilterManually() {
tft.fillRect(10, 230, 220, 35, ILI9341_BLACK);
if (filterManually) {
drawOnOffButton(10, 230, "ON", true);
drawOnOffButton(120, 230, "OFF", false);
} else {
drawOnOffButton(10, 230, "ON", false);
drawOnOffButton(120, 230, "OFF", true);
}
}
void onOffButtonFansManually() {
tft.fillRect(10, 230, 220, 35, ILI9341_BLACK);
if (lowerFansManually == true && upperFansManually == true) {
drawOnOffButton(10, 230, "ON", true);
drawOnOffButton(120, 230, "OFF", false);
} else {
drawOnOffButton(10, 230, "ON", false);
drawOnOffButton(120, 230, "OFF", true);
}
}
void drawOnOffButton(int x, int y, const char* label, bool isActive) {
if (isActive) {
tft.fillRect(x + 1, y + 1, 108, 33, ILI9341_GREEN);
} else {
tft.drawRect(x, y, 110, 35, ILI9341_GREEN);
}
tft.setCursor(x + 37, y + 7);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(3);
tft.print(label);
}
void airInPercentageStrip() {
drawPercentageStrip(10, 85, airInPercentage);
}
void airOutPercentageStrip() {
drawPercentageStrip(10, 145, airOutPercentage);
}
void upperFansPercentageStrip() {
drawPercentageStrip(10, 85, upperFansPercentage);
}
void lowerFansPercentageStrip() {
drawPercentageStrip(10, 145, lowerFansPercentage);
}
void drawPercentageStrip(int x, int y, byte percentage) {
tft.fillRect(x + 1, y + 1, 218, 18, ILI9341_BLACK);
for (int i = 20; i <= 100; i += 20) {
if (i <= percentage) {
tft.fillRect(x, y, 44, 20, ILI9341_GREEN);
} else {
tft.drawRect(x, y, 44, 20, ILI9341_GREEN);
}
if (i == 100) {
tft.setCursor(x + 8, y + 3);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print(i);
x += 44;
} else {
tft.setCursor(x + 20, y + 3);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print(i);
x += 44;
}
}
}
void intervalButtonFans() {
tft.fillRect(150, 182, 80, 20, ILI9341_BLACK);
if (fansIntervalStatus == true) {
drawIntervalButton(150, 182, "ON", true);
drawIntervalButton(190, 182, "OFF", false);
} else {
drawIntervalButton(150, 182, "ON", false);
drawIntervalButton(190, 182, "OFF", true);
}
}
void drawIntervalButton(int x, int y, const char* label, bool isActive) {
if (isActive) {
tft.fillRect(x + 1, y + 1, 38, 18, ILI9341_GREEN);
} else {
tft.drawRect(x, y, 40, 20, ILI9341_GREEN);
}
tft.setCursor(x + 2, y + 3);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print(label);
}
void adjustLightOnHour(int delta) {
lightOnHour = (lightOnHour + delta + 24) % 24;
tft.fillRect(172, 83, 24, 14, ILI9341_BLACK);
tft.setCursor(173, 83);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
if (lightOnHour < 10) {
tft.print("0");
}
tft.print(lightOnHour);
}
void adjustLightOnMinute(int delta) {
lightOnMinute = (lightOnMinute + delta + 60) % 60;
tft.fillRect(209, 83, 22, 14, ILI9341_BLACK);
tft.setCursor(209, 83);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
if (lightOnMinute < 10) {
tft.print("0");
}
tft.print(lightOnMinute);
}
void adjustLightOffHour(int delta) {
lightOffHour = (lightOffHour + delta + 24) % 24;
tft.fillRect(172, 153, 24, 14, ILI9341_BLACK);
tft.setCursor(173, 153);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
if (lightOffHour < 10) {
tft.print("0");
}
tft.print(lightOffHour);
}
void adjustLightOffMinute(int delta) {
lightOffMinute = (lightOffMinute + delta + 60) % 60;
tft.fillRect(209, 153, 22, 14, ILI9341_BLACK);
tft.setCursor(209, 153);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
if (lightOffMinute < 10) {
tft.print("0");
}
tft.print(lightOffMinute);
}
void adjustTempMin(int delta) {
tempMin = (tempMin + delta);
tft.fillRect(172, 83, 24, 14, ILI9341_BLACK);
tft.setCursor(173, 83);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
if (tempMin < 10) {
tft.print("0");
}
tft.print(tempMin);
}
void adjustTempMax(int delta) {
tempMax = (tempMax + delta );
tft.fillRect(209, 83, 22, 14, ILI9341_BLACK);
tft.setCursor(209, 83);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
if (tempMax < 10) {
tft.print("0");
}
tft.print(tempMax);
}
void adjustHumidMin(int delta) {
humidMin = (humidMin + delta);
tft.fillRect(172, 153, 24, 14, ILI9341_BLACK);
tft.setCursor(173, 153);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
if (humidMin < 10) {
tft.print("0");
}
tft.print(humidMin);
}
void adjustHumidMax(int delta) {
humidMax = (humidMax + delta );
tft.fillRect(209, 153, 22, 14, ILI9341_BLACK);
tft.setCursor(209, 153);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
if (humidMax < 10) {
tft.print("0");
}
tft.print(humidMax);
}
void drawSun(int x, int y, int radius, uint16_t color) {
// Zeichne die Sonne (Kreis)
tft.fillCircle(x, y, radius, color);
// Zeichne Sonnenstrahlen
for (int i = 0; i < 360; i += 30) {
float angle = i * PI / 180;
int x1 = x + (radius + 10) * cos(angle);
int y1 = y + (radius + 10) * sin(angle);
int x2 = x + (radius + 20) * cos(angle);
int y2 = y + (radius + 20) * sin(angle);
tft.drawLine(x1, y1, x2, y2, color);
}
}
void drawCrescentMoon(int x, int y, int radius, uint16_t color) {
// Zeichne den Vollmond
tft.fillCircle(x, y, radius, color);
// Zeichne einen kleineren, schwarzen Kreis, um die Sichel zu erzeugen
tft.fillCircle(x + radius / 2, y, radius, ILI9341_BLACK);
}
void drawOverview(int x, int y, int d) {
tft.setCursor(x, y);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1);
tft.print("Air In: ");
if (airInOutManually == true && airInPercentage == 100) {
tft.print(airInPercentage);
tft.print("%");
} else if (airInOutManually == true) {
tft.print(" ");
tft.print(airInPercentage);
tft.print("%");
} else {
tft.print(" OFF");
}
tft.setCursor(x, y + d);
tft.setTextColor(ILI9341_WHITE);
tft.print("Air Out:");
if (airInOutManually == true && airOutPercentage == 100) {
tft.print(airOutPercentage);
tft.print("%");
} else if (airInOutManually == true) {
tft.print(" ");
tft.print(airOutPercentage);
tft.print("%");
} else {
tft.print(" OFF");
}
tft.setCursor(x, y + (2 * d));
tft.setTextColor(ILI9341_WHITE);
tft.print("Fans L: ");
if (lowerFansManually == true && lowerFansPercentage == 100) {
tft.print(lowerFansPercentage);
tft.print("%");
} else if (lowerFansManually == true) {
tft.print(" ");
tft.print(lowerFansPercentage);
tft.print("%");
} else {
tft.print(" OFF");
}
tft.setCursor(x, y + (3 * d));
tft.setTextColor(ILI9341_WHITE);
tft.print("Fans U: ");
if (upperFansManually == true && lowerFansPercentage == 100) {
tft.print(upperFansPercentage);
tft.print("%");
} else if (upperFansManually == true) {
tft.print(" ");
tft.print(upperFansPercentage);
tft.print("%");
} else {
tft.print(" OFF");
}
tft.setCursor(x, y + (4 * d));
tft.setTextColor(ILI9341_WHITE);
tft.print("Filter: ");
if (filterManually == true ) {
tft.print(" ON");
} else if (filterManually == false) {
tft.print("OFF");
}
tft.setCursor(x, y + (5 * d));
tft.setTextColor(ILI9341_WHITE);
tft.print("T Min: ");
tft.print(tempMin);
tft.print("C");
tft.setCursor(x, y + (6 * d));
tft.setTextColor(ILI9341_WHITE);
tft.print("T Max: ");
tft.print(tempMax);
tft.print("C");
tft.setCursor(x, y + (7 * d));
tft.setTextColor(ILI9341_WHITE);
tft.print("rF Min: ");
tft.print(humidMin);
tft.print("%");
tft.setCursor(x, y + (8 * d));
tft.setTextColor(ILI9341_WHITE);
tft.print("rF Max: ");
tft.print(humidMax);
tft.print("%");
}
void checkFansInterval() {
unsigned long currentMillis = millis();
// Wenn die Lüfter derzeit eingeschaltet sind und die ON-Periode abgelaufen ist
if (fansInterval == true && currentMillis - fanLastToggleTime >= fanOnInterval) {
fansInterval = false;
fanLastToggleTime = currentMillis;
}
// Wenn die Lüfter derzeit ausgeschaltet sind und die OFF-Periode abgelaufen ist
else if (fansInterval == false && currentMillis - fanLastToggleTime >= fanOffInterval) {
fansInterval = true;
fanLastToggleTime = currentMillis;
}
}