#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <esp_sleep.h> // Include ESP32 sleep library
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C // I2C address for the SSD1306 OLED display
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const int ldrPin = 34;
const int tempPin = 35;
const int soilMoisturePin = 32;
const int ldrThresholdHigh = 500; // Adjust as needed
const int ldrThresholdLow = 1000; // Adjust as needed
const float tempThresholdHigh = 200.0; // Adjust as needed
const float tempThresholdLow = 10.0; // Adjust as needed
const int soilMoistureThresholdHigh = 3000; // Adjust as needed
const int soilMoistureThresholdLow = 1000; // Adjust as needed
const int ldrTargetValue = 2048; // Define a target value for LDR
const int soilMoistureTargetValue = 2048; // Define a target value for soil moisture
unsigned long displayStartTime = 0;
const unsigned long displayDuration = 30000; // 30 seconds
const char* lightHighWarnings[] = {
"I need some sunglasses",
"It's too bright!",
"Too much light here!"
};
const char* lightLowWarnings[] = {
"Can we put the big light on?",
"It's too dark!",
"Need more light!"
};
const char* tempHighWarnings[] = {
"Its too hot in here :(",
"Temperature too high!",
"I'm overheating!"
};
const char* tempLowWarnings[] = {
"Is it cold in here?",
"Temperature too low!",
"I'm freezing!"
};
const char* soilMoistureHighWarnings[] = {
"I'm full!",
"Too much water!",
"Soil too wet!"
};
const char* soilMoistureLowWarnings[] = {
"I'm thirsty :(",
"Need more water!",
"Soil too dry!"
};
void setup() {
Serial.begin(115200);
pinMode(ldrPin, INPUT);
pinMode(tempPin, INPUT);
pinMode(soilMoisturePin, INPUT);
// Initialize OLED display with I2C address
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.display();
delay(2000);
display.clearDisplay();
// Show initial message "Hi Becks :)" for 5 seconds
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 16);
display.println("Hi Becks:)");
display.display();
delay(5000);
// Record the start time of the display
displayStartTime = millis();
}
void displayWarnings(const char* warnings[], int count, int values[], const char* units[], const char* direction[]) {
for (int i = 0; i < count; i++) {
display.clearDisplay();
display.setCursor(0, 0);
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.println(warnings[i]);
display.print("(");
display.print(values[i]);
display.print(units[i]);
display.print(" ");
display.print(direction[i]);
display.println(")");
display.display();
delay(5000);
}
}
void loop() {
unsigned long currentTime = millis();
unsigned long elapsedTime = currentTime - displayStartTime;
int ldrValue = analogRead(ldrPin);
int tempValue = analogRead(tempPin);
int soilMoistureValue = analogRead(soilMoisturePin);
float voltage = tempValue * (3.3 / 4095.0);
float temperatureC = voltage * 100.0;
float ldrPercentage = ((float)ldrValue / ldrTargetValue) * 100;
float soilMoisturePercentage = ((float)soilMoistureValue / soilMoistureTargetValue) * 100;
bool warning = false;
int messageCount = 0;
const char* currentWarnings[9]; // Maximum of 9 warnings (3 per type)
int warningValues[9];
const char* warningUnits[9];
const char* warningDirections[9];
if (ldrValue > ldrThresholdHigh) {
int messageIndex = random(0, 3);
currentWarnings[messageCount] = lightHighWarnings[messageIndex];
warningValues[messageCount] = ldrPercentage - ((float)ldrThresholdHigh / ldrTargetValue) * 100;
warningUnits[messageCount] = "%";
warningDirections[messageCount] = "over";
messageCount++;
warning = true;
} else if (ldrValue < ldrThresholdLow) {
int messageIndex = random(0, 3);
currentWarnings[messageCount] = lightLowWarnings[messageIndex];
warningValues[messageCount] = ((float)ldrThresholdLow / ldrTargetValue) * 100 - ldrPercentage;
warningUnits[messageCount] = "%";
warningDirections[messageCount] = "under";
messageCount++;
warning = true;
}
if (temperatureC > tempThresholdHigh) {
int messageIndex = random(0, 3);
currentWarnings[messageCount] = tempHighWarnings[messageIndex];
warningValues[messageCount] = temperatureC - tempThresholdHigh;
warningUnits[messageCount] = "C";
warningDirections[messageCount] = "over";
messageCount++;
warning = true;
} else if (temperatureC < tempThresholdLow) {
int messageIndex = random(0, 3);
currentWarnings[messageCount] = tempLowWarnings[messageIndex];
warningValues[messageCount] = tempThresholdLow - temperatureC;
warningUnits[messageCount] = "C";
warningDirections[messageCount] = "under";
messageCount++;
warning = true;
}
if (soilMoistureValue > soilMoistureThresholdHigh) {
int messageIndex = random(0, 3);
currentWarnings[messageCount] = soilMoistureHighWarnings[messageIndex];
warningValues[messageCount] = soilMoisturePercentage - ((float)soilMoistureThresholdHigh / soilMoistureTargetValue) * 100;
warningUnits[messageCount] = "%";
warningDirections[messageCount] = "over";
messageCount++;
warning = true;
} else if (soilMoistureValue < soilMoistureThresholdLow) {
int messageIndex = random(0, 3);
currentWarnings[messageCount] = soilMoistureLowWarnings[messageIndex];
warningValues[messageCount] = ((float)soilMoistureThresholdLow / soilMoistureTargetValue) * 100 - soilMoisturePercentage;
warningUnits[messageCount] = "%";
warningDirections[messageCount] = "under";
messageCount++;
warning = true;
}
if (warning) {
displayWarnings(currentWarnings, messageCount, warningValues, warningUnits, warningDirections);
} else {
// Show "Plant is all good!" message for 5 seconds
display.clearDisplay();
display.setCursor(0, 0);
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.println("Plant is");
display.println("all good!");
display.display();
delay(5000);
}
displayStartTime = millis(); // Reset display start time for measurement display
while ((millis() - displayStartTime) < displayDuration) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("Brightness: ");
display.print(ldrPercentage, 1);
display.println("%");
display.setCursor(0, 16);
display.print("Temp (C): ");
display.println(temperatureC);
display.setCursor(0, 32);
display.print("Soil Moisture: ");
display.print(soilMoisturePercentage, 1);
display.println("%");
display.display();
delay(1000);
}
// Clear the display and go to low power mode
display.clearDisplay();
display.display();
Serial.println("Entering deep sleep mode");
esp_deep_sleep_start();
}