#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include "DHT.h"
#include <LiquidCrystal.h>
#include <Keypad.h>
#include <SimpleDHT.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
const int rows = 4;
const int cols = 4;
int keyconv=0;
String MODE ;
char keys [rows][cols] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte colpins[cols] = {27,13,22,34};
byte rowpins[rows] = {33,25,26,16};
Keypad keypad = Keypad(makeKeymap(keys), rowpins, colpins, rows, cols);
// WiFi parameters
#define WLAN_SSID "Wokwi-GUEST"
#define WLAN_PASS ""
#define AIO_SERVER "io.adafruit.com"
#define AIO_SERVERPORT 1883
#define AIO_USERNAME "khizersharief20202"
#define AIO_KEY "aio_NBbv38Iy15p1TFw1PJdTt3BaQQWq"
WiFiClient client;
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
Adafruit_MQTT_Publish Temperature1 = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Temperature1");
Adafruit_MQTT_Publish Humidity1 = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Humidity1");
#define TFT_DC 2
#define TFT_CS 15
#define TFT_MOSI 23
#define TFT_CLK 18
#define TFT_RST 4
#define TFT_MISO 19
#define DHTPIN 14
#define DHTTYPE DHT22
#define MAX_READINGS 1440 // Maximum number of readings to store (assuming one reading per minute for 24 hours)
struct Reading {
float temperature;
float humidity;
unsigned long timestamp;
};
Reading readings[MAX_READINGS];
int numReadings = 0; // Number of readings stored
int nextIndex = 0;
float minTemperature = 0.0;
float maxTemperature = 0.0;
float minHumidity = 0.0;
float maxHumidity = 0.0;
byte hum=0;
byte temp=0;
const int rpin = 21;
const int bpin = 17;
const int gpin = 5;
int Wbuttonstate = 0;
int Gbuttonstate = 0;
int Vbuttonstate = 0;
int Fbuttonstate = 0;
int lightval = 0;
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);
DHT dht(DHTPIN, DHTTYPE);
unsigned long lastLogTime = 0;
unsigned long lastDebugTime = 0;
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
void Start() {
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(0,0);
tft.setTextColor(ILI9341_WHITE);
tft.println("\nSelect Mode");
tft.setTextColor(ILI9341_GREEN);
tft.println("1. Winter");
tft.println("2. Germinating");
tft.println("3. Vegetative");
tft.println("4. Fruiting");
tft.println("5. Editable Mode");
tft.println("6. Advanced WIFI Mode");
}
void setup() {
pinMode(rpin, OUTPUT);
pinMode(gpin, OUTPUT);
pinMode(bpin, OUTPUT);
pinMode(32, INPUT);
tft.begin();
tft.setRotation(1);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("GETTING THE READINGS");
delay(1000);
Serial.begin(9600);
dht.begin();
Start();
}
void loop() {
float h = dht.readHumidity();
float t = dht.readTemperature();
char key = keypad.getKey();
if (key){
delay(2000);
tft.fillScreen(ILI9341_BLACK);
Serial.println(analogRead(32));
float h = dht.readHumidity();
float t = dht.readTemperature();
lightval = analogRead(32);
if (isnan(h) || isnan(t)) {
Serial.println(F("Failed to read from DHT sensor!"));
return;
}
Serial.println(key);
keyconv = key-'0';
Serial.println(keyconv);
if (lightval < 3500) {
triggernightmode();
} else if (keyconv==1) {
float minTemp=0;
float maxTemp=1000;
float minhumidity=-1000;
float maxhumidity=1000;
if (t < 0) {
turnonred();
MODE= "WINTER";
refreshDisplayMode(MODE, t, h,minTemp,maxTemp,minhumidity,maxhumidity);
} else {
turnongreen();
MODE= "WINTER";
refreshDisplayMode(MODE, t, h,minTemp,maxTemp,minhumidity,maxhumidity);
}
} else if (keyconv==2) {
float minTemp=18;
float maxTemp=32;
float minhumidity=70;
float maxhumidity=95;
if (t < 18 || t > 32 || h < 70 || h > 95) {
turnonred();
MODE= "GERMINATING";
refreshDisplayMode(MODE, t, h,minTemp,maxTemp,minhumidity,maxhumidity);
} else {
turnongreen();
MODE= "GERMINATING";
refreshDisplayMode(MODE, t, h,minTemp,maxTemp,minhumidity,maxhumidity);
}
} else if (keyconv==3) {
float minTemp=20;
float maxTemp=25;
float minhumidity=60;
float maxhumidity=70;
if (t < 20 || t > 25 || h < 60 || h > 70) {
turnonred();
MODE= "VEGITATIVE";
refreshDisplayMode(MODE, t, h,minTemp,maxTemp,minhumidity,maxhumidity);
} else {
turnongreen();
MODE= "VEGITATIVE";
refreshDisplayMode(MODE, t, h,minTemp,maxTemp,minhumidity,maxhumidity);
}
} else if (keyconv==4) {
float minTemp=-1000;
float maxTemp=28;
float minhumidity=40;
float maxhumidity=50;
if (t > 28 || h < 40 || h > 50) {
turnonred();
MODE= "FRUITING";
refreshDisplayMode(MODE, t, h,minTemp,maxTemp,minhumidity,maxhumidity);
} else {
turnongreen();
MODE= "FRUITING";
refreshDisplayMode(MODE, t, h,minTemp,maxTemp,minhumidity,maxhumidity);
}
} else if (keyconv==5) {
handleEditableMode();
}else if (keyconv==6){
advancedfeaturewifi();
}
}
LogData(t, h);
OutputDebugString(t, h);
}
void DisplayMode(String mode, float temperature, float humidity) {
calculateMinMaxValues(); // Calculate min/max values before displaying
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(0, 0);
tft.println(mode + " MODE");
tft.print("Temp= ");
tft.print(temperature);
tft.println(" C ");
tft.print("Humidity= ");
tft.print(humidity);
tft.println("% ");
tft.println();
tft.println("Last 24h Stats:");
tft.print("Min Temp= ");
tft.print(minTemperature);
tft.println(" C ");
tft.print("Max Temp= ");
tft.print(maxTemperature);
tft.println(" C ");
tft.print("Min Humidity= ");
tft.print(minHumidity);
tft.println("% ");
tft.print("Max Humidity= ");
tft.print(maxHumidity);
tft.println("% ");
delay(1000);
}
void refreshDisplayMode(String mode, float temperature, float humidity,float minTemp, float maxTemp, float minhumidity, float maxhumidity) {
bool shouldExit = false;
while (!shouldExit) {
float h = dht.readHumidity();
float t = dht.readTemperature();
lightval = analogRead(32);
if (lightval < 3500) {
triggernightmode();
} else{
char key = keypad.getKey();
if (key){
shouldExit=true;
Start();
} else {
if (t < minTemp || t>maxTemp || h < minhumidity || h > maxhumidity){
turnonred();
}else{
turnongreen();
}
DisplayMode(mode, t, h);
LogData(t, h);
OutputDebugString(t, h);
}
}
}
}
void LogData(float temperature, float humidity) {
unsigned long currentTime = millis();
// Log temperature and humidity readings every minute
if (currentTime - lastLogTime >= 60000) {
// Store the reading in the array
readings[nextIndex].temperature = temperature;
readings[nextIndex].humidity = humidity;
readings[nextIndex].timestamp = currentTime;
// Increment the index for the next reading
nextIndex = (nextIndex + 1) % MAX_READINGS;
// Increment the number of readings if it hasn't reached the maximum
if (numReadings < MAX_READINGS) {
numReadings++;
}
lastLogTime = currentTime;
}
}
void OutputDebugString(float temperature, float humidity) {
unsigned long currentTime = millis();
// Output debug string containing latest values for temperature and humidity every 5 seconds
if (currentTime - lastDebugTime >= 5000) {
// Output debug string containing latest values for temperature and humidity
Serial.println("REALTIME VALUE DEBUG SRTING");
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println("°C ");
Serial.print("Humidity: ");
Serial.print(humidity);
Serial.println("% ");
Serial.println(" ");
Serial.println("STORED Debug String:");
for (int i = 0; i < numReadings; i++) {
Serial.print("Reading ");
Serial.print(i + 1);
Serial.print(": Temp = ");
Serial.print(readings[i].temperature);
Serial.print("°C, Humidity = ");
Serial.print(readings[i].humidity);
Serial.println("%");
}
Serial.println();
lastDebugTime = currentTime;
}
}
void triggernightmode(){
float h = dht.readHumidity();
float t = dht.readTemperature();
float minTemp=10;
float maxTemp=15;
float minhumidity=30;
float maxhumidity=80;
if (t < 10 || t > 15 || h < 30 || h > 80) {
turnonred();
MODE= "NIGHT";
refreshnightDisplayMode(MODE, t, h,minTemp,maxTemp,minhumidity,maxhumidity);
} else {
turnongreen();
MODE= "NIGHT";
refreshnightDisplayMode(MODE, t, h,minTemp,maxTemp,minhumidity,maxhumidity);
}
}
void refreshnightDisplayMode(String mode, float temperature, float humidity,float minTemp,float maxTemp,float minhumidity,float maxhumidity) {
bool shouldExit = false;
while (!shouldExit) {
float h = dht.readHumidity();
float t = dht.readTemperature();
lightval = analogRead(32);
if (lightval > 3500) {
shouldExit=true;
} else{
if (t < minTemp || t>maxTemp || h < minhumidity || h > maxhumidity){
turnonred();
}else{
turnongreen();
}
DisplayMode(mode, t, h);
LogData(t, h);
OutputDebugString(t, h);}
}
}
void calculateMinMaxValues() {
minTemperature = 100.0; // Reset to a high value
maxTemperature = -100.0; // Reset to a low value
minHumidity = 100.0; // Reset to a high value
maxHumidity = -100.0; // Reset to a low value
unsigned long currentTime = millis();
unsigned long twentyFourHoursAgo = currentTime - 24 * 60 * 60 * 1000; // 24 hours ago in milliseconds
// Iterate over the stored readings to find minimum and maximum values within the last 24 hours
for (int i = 0; i < numReadings; i++) {
if (currentTime - readings[i].timestamp <= 24 * 60 * 60 * 1000) {
minTemperature = min(minTemperature, readings[i].temperature);
maxTemperature = max(maxTemperature, readings[i].temperature);
minHumidity = min(minHumidity, readings[i].humidity);
maxHumidity = max(maxHumidity, readings[i].humidity);
}
}
}
void handleEditableMode() {
String mode = "Editable Mode";
float minTemp = 0.0;
float maxTemp = 0.0;
float minhumidity = 0.0;
float maxhumidity = 0.0;
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(0, 0);
tft.println(mode);
tft.println("Enter minimum temperature (0-40 C):");
minTemp = getUserInputTemperature();
tft.println("Enter maximum temperature (0-40 C):");
maxTemp = getUserInputTemperature();
while (minTemp >= maxTemp) {
tft.println("Minimum temperature must be less than maximum temperature. Please re-enter.");
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(0, 0);
tft.println(mode);
tft.println("Minimum temperature must be less than maximum temperature. Please re-enter.");
minTemp = getUserInputTemperature();
tft.println("Enter maximum temperature (0-40 C):");
maxTemp = getUserInputTemperature();
}
tft.println("Enter minimum humidity (0-100%):");
minhumidity = getUserInputHumidity();
tft.println("Enter maximum humidity (0-100%):");
maxhumidity = getUserInputHumidity();
while (minhumidity >= maxhumidity) {
tft.println("Minimum humidity must be less than maximum humidity. Please re-enter.");
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(0, 0);
tft.println(mode);
tft.println("Minimum humidity must be less than maximum humidity. Please re-enter.");
minhumidity = getUserInputHumidity();
tft.println("Enter maximum humidity (0-100%):");
maxhumidity = getUserInputHumidity();
}
// Display the entered values
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(0, 0);
tft.println(mode);
tft.println();
tft.print("Entered Minimum Temperature: ");
tft.print(minTemp);
tft.println(" C");
tft.print("Entered Maximum Temperature: ");
tft.print(maxTemp);
tft.println(" C");
tft.print("Entered Minimum Humidity: ");
tft.print(minhumidity);
tft.println("%");
tft.print("Entered Maximum Humidity: ");
tft.print(maxhumidity);
tft.println("%");
float h = dht.readHumidity();
float t = dht.readTemperature();
if (t < minTemp || t>maxTemp || h < minhumidity || h > maxhumidity) {
turnonred();
MODE= "USER EDITABLE";
refreshDisplayMode(MODE, t, h,minTemp,maxTemp,minhumidity,maxhumidity);
} else {
turnongreen();
MODE= "USER EDITABLE";
refreshDisplayMode(MODE, t, h,minTemp,maxTemp,minhumidity,maxhumidity);
}
}
float getUserInputTemperature() {
float temperature = 0.0;
String input = "";
char key;
while (true) {
key = keypad.getKey();
if (key >= '0' && key <= '9') {
input += key;
tft.print(key);
} else if (key == '*') {
temperature = input.toFloat();
if (temperature >= 0 && temperature <= 40) {
break;
} else {
tft.println("Temperature must be between 0-40 C. Please re-enter.");
input = "";
delay(1000);
tft.setCursor(0, tft.getCursorY());
tft.println("Enter temperature (0-40 C):");
}
}
}
return temperature;
}
float getUserInputHumidity() {
float humidity = 0.0;
String input = "";
char key;
while (true) {
key = keypad.getKey();
if (key >= '0' && key <= '9') {
input += key;
tft.print(key);
} else if (key == '*') {
humidity = input.toFloat();
if (humidity >= 0 && humidity <= 100) {
break;
} else {
tft.println("Humidity must be between 0-100%. Please re-enter.");
input = "";
delay(1000);
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(0, 4);
tft.println("Enter humidity (0-100%):");
}
}
}
return humidity;
}
void turnonred(){
digitalWrite(bpin, HIGH);
digitalWrite(gpin, HIGH);
digitalWrite(rpin, LOW);
}
void turnongreen(){
digitalWrite(bpin, HIGH);
digitalWrite(gpin, LOW);
digitalWrite(rpin, HIGH);
}
void advancedfeaturewifi(){
// Connect to WiFi access point.
Serial.println(); Serial.println();
delay(10);
Serial.print(F("Connecting to "));
Serial.println(WLAN_SSID);
WiFi.begin(WLAN_SSID, WLAN_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(F("."));
}
Serial.println();
Serial.println(F("WiFi connected"));
Serial.println(F("IP address: "));
Serial.println(WiFi.localIP());
// connect to adafruit io
connect();
bool shouldExit = false;
while (!shouldExit) {
float h = dht.readHumidity();
float t = dht.readTemperature();
lightval = analogRead(32);
if (lightval < 3500) {
triggernightmode();
} else{
char key = keypad.getKey();
if (key){
shouldExit=true;
Start();
} else {
if(! mqtt.ping(3)) {
// reconnect to adafruit io
if(! mqtt.connected())
connect();
}
byte hum = dht.readHumidity();
byte temp= dht.readTemperature();
Serial.print((int)temp); Serial.print(" *C, ");
Serial.print((int)hum); Serial.println(" H");
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(0, 0);
tft.print((int)temp); tft.print(" *C, ");
tft.print((int)hum); tft.println(" H");
delay(5000);
if (! Temperature1.publish(temp)) { //Publish to Adafruit
Serial.println(F("Failed"));
}
if (! Humidity1.publish(hum)) { //Publish to Adafruit
Serial.println(F("Failed"));
}
else {
Serial.println(F("Sent!"));
}
}
}
}
}
void connect() {
Serial.print(F("Connecting to Adafruit IO... "));
int8_t ret;
while ((ret = mqtt.connect()) != 0) {
switch (ret) {
case 1: Serial.println(F("Wrong protocol")); break;
case 2: Serial.println(F("ID rejected")); break;
case 3: Serial.println(F("Server unavail")); break;
case 4: Serial.println(F("Bad user/pass")); break;
case 5: Serial.println(F("Not authed")); break;
case 6: Serial.println(F("Failed to subscribe")); break;
default: Serial.println(F("Connection failed")); break;
}
if(ret >= 0)
mqtt.disconnect();
Serial.println(F("Retrying connection..."));
delay(10000);
}
Serial.println(F("Adafruit IO Connected!"));
}