#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <DHT.h>
#include <Wire.h>
#include <RTClib.h>
#define TFT_CS 10
#define TFT_RST 9
#define TFT_DC 8
#define DHT_PIN_1 7
#define DHT_PIN_2 6
#define DHT_TYPE DHT22
#define ROTARY_CLK 3
#define ROTARY_DT 4
#define ROTARY_SW 5
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
DHT dht1(DHT_PIN_1, DHT_TYPE);
DHT dht2(DHT_PIN_2, DHT_TYPE);
RTC_DS3231 rtc;
volatile int rotaryPosition = 0;
bool isCelsius = true;
bool showSettings = false;
DateTime lastDisplayUpdate;
void setup() {
Serial.begin(9600);
tft.begin();
dht1.begin();
dht2.begin();
if (!rtc.begin()) {
tft.setTextSize(2);
tft.setTextColor(ILI9341_WHITE);
tft.setCursor(0, 0);
tft.println("Clock is lost");
tft.setTextSize(1);
tft.println("Do you want to continue?");
tft.println("Rotate encoder to select");
tft.println("Press to confirm");
pinMode(ROTARY_CLK, INPUT_PULLUP);
pinMode(ROTARY_DT, INPUT_PULLUP);
pinMode(ROTARY_SW, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(ROTARY_CLK), handleEncoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(ROTARY_DT), handleEncoder, CHANGE);
while (digitalRead(ROTARY_SW) == HIGH) {
delay(50);
}
if (rotaryPosition == 0) {
while (rtc.lostPower()) {
delay(500);
}
}
}
lastDisplayUpdate = rtc.now();
}
void loop() {
DateTime now = rtc.now();
if (showSettings) {
handleSettings();
return;
}
// Update display every 5 seconds
if (now.second() % 5 == 0 && now != lastDisplayUpdate) {
lastDisplayUpdate = now;
float temperature1, temperature2;
float humidity1, humidity2;
// Read temperature and humidity from first DHT22
humidity1 = dht1.readHumidity();
temperature1 = dht1.readTemperature();
// Read temperature and humidity from second DHT22
humidity2 = dht2.readHumidity();
temperature2 = dht2.readTemperature();
// If temperature or humidity reading failed, display an error message
if (isnan(humidity1) || isnan(temperature1) || isnan(humidity2) || isnan(temperature2)) {
tft.fillScreen(ILI9341_BLACK);
tft.setTextSize(2);
tft.setTextColor(ILI9341_RED);
tft.setCursor(0, 0);
if (isnan(humidity1) || isnan(temperature1)) {
tft.println("Error reading sensor 1!");
} else {
tft.println("Error reading sensor 2!");
}
return;
}
// Convert temperature to Fahrenheit if needed
if (!isCelsius) {
temperature1 = temperature1 * 9.0 / 5.0 + 32.0;
temperature2 = temperature2 * 9.0 / 5.0 + 32.0;
}
// Display date and time
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(0, 0);
tft.setTextSize(1);
tft.setTextColor(ILI9341_WHITE);
tft.print(now.year(), DEC);
tft.print('/');
tft.print(now.month(), DEC);
tft.print('/');
tft.print(now.day(), DEC);
tft.print(" ");
int hour = now.hour();
bool isPM = false;
if (hour > 12) {
hour -= 12;
isPM = true;
}
tft.print(hour);
tft.print(":");
if (now.minute() < 10) tft.print("0");
tft.print(now.minute(), DEC);
if (isPM) {
tft.print(" PM");
} else {
tft.print(" AM");
}
// Display temperature and humidity on TFT display
tft.setCursor(0, 20);
tft.print("Temp 1: ");
tft.println(temperature1, 1);
tft.print("Humidity 1: ");
tft.println(humidity1, 1);
tft.print("Temp 2: ");
tft.println(temperature2, 1);
tft.print("Humidity 2: ");
tft.println(humidity2, 1);
// Display unit indication
tft.setCursor(0, 220);
tft.setTextSize(1);
tft.setTextColor(ILI9341_WHITE);
if (isCelsius) {
tft.println("Unit: Celsius");
} else {
tft.println("Unit: Fahrenheit");
}
}
// If the RTC is lost, keep taking readings every 20 seconds
if (rtc.lostPower()) {
delay(20000);
return;
}
delay(1000); // Delay before next iteration
}
void handleEncoder() {
static unsigned long lastRotaryTime = 0;
unsigned long currentRotaryTime = millis();
if (currentRotaryTime - lastRotaryTime > 4) {
int CLK = digitalRead(ROTARY_CLK);
int DT = digitalRead(ROTARY_DT);
if (CLK == HIGH) {
if (DT == LOW) {
rotaryPosition++;
} else {
rotaryPosition--;
}
} else {
if (DT == HIGH) {
rotaryPosition++;
} else {
rotaryPosition--;
}
}
if (rotaryPosition > 3) {
rotaryPosition = 3;
} else if (rotaryPosition < 0) {
rotaryPosition = 0;
}
lastRotaryTime = currentRotaryTime;
}
}
void handleSettings() {
tft.fillScreen(ILI9341_BLACK);
tft.setTextSize(2);
tft.setTextColor(ILI9341_WHITE);
tft.setCursor(0, 0);
tft.println("Settings");
tft.setTextSize(1);
tft.setTextColor(ILI9341_YELLOW);
tft.println("Use encoder to scroll options:");
tft.setTextColor(ILI9341_WHITE);
tft.println("1. Show all readings");
tft.println("2. Convert to Celsius/Fahrenheit");
tft.println("3. Calculate average");
tft.println("4. Back to main screen");
switch (rotaryPosition) {
case 0:
tft.fillRect(0, 88, 320, 12, ILI9341_GREEN); // Highlight selected option
break;
case 1:
tft.fillRect(0, 100, 320, 12, ILI9341_GREEN);
break;
case 2:
tft.fillRect(0, 112, 320, 12, ILI9341_GREEN);
break;
case 3:
tft.fillRect(0, 124, 320, 12, ILI9341_GREEN);
break;
}
if (digitalRead(ROTARY_SW) == LOW) {
delay(200); // debounce
switch (rotaryPosition) {
case 0:
showSettings = false;
break;
case 1:
showAllReadings();
break;
case 2:
toggleTemperatureUnit();
break;
case 3:
showAverage();
break;
}
}
}
void showAllReadings() {
showSettings = false; // Exit settings
}
void toggleTemperatureUnit() {
isCelsius = !isCelsius;
}
void showAverage() {
float temperature1 = dht1.readTemperature();
float temperature2 = dht2.readTemperature();
float humidity1 = dht1.readHumidity();
float humidity2 = dht2.readHumidity();
float averageTemperature = (temperature1 + temperature2) / 2;
float averageHumidity = (humidity1 + humidity2) / 2;
tft.fillScreen(ILI9341_BLACK);
tft.setTextSize(2);
tft.setTextColor(ILI9341_WHITE);
tft.setCursor(0, 0);
tft.println("Average:");
tft.setTextSize(1);
tft.setTextColor(ILI9341_YELLOW);
tft.println("Temperature: ");
tft.setTextColor(ILI9341_WHITE);
tft.print(averageTemperature);
tft.println(isCelsius ? "°C" : "°F");
tft.setTextColor(ILI9341_YELLOW);
tft.println("Humidity: ");
tft.setTextColor(ILI9341_WHITE);
tft.print(averageHumidity);
tft.println("%");
delay(5000);
}