#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include "loadingAnimation.h"
#define DHTPIN 4 // DHT sensor pin
#define DHTTYPE DHT11
#define BUTTON_PIN 2 // Button pin
#define DEBOUNCE_DELAY 50 // Short delay for debounce
#define HOLD_DELAY 1000 // Hold delay to enter submenu (1 second)
LiquidCrystal_I2C lcd(0x27, 16, 2);
DHT dht(DHTPIN, DHTTYPE);
byte customChar[] = {
B01010,
B10101,
B01010,
B10101,
B01010,
B10101,
B01010,
B10101
};
enum MenuState { MENU, SUBMENU };
MenuState currentState = MENU;
const char* menuItems[] = {"Temperature", "Humidity", "Option 1", "Message"};
int selectedItem = 0;
unsigned long buttonPressStart = 0; // Tracks the start time of a button press
bool buttonHeld = false;
void clearSerialBuffer();
void setup() {
lcd.begin(16, 2);
lcd.backlight();
Serial.begin(9600); // Start serial communication at 9600 baud
lcd.createChar(0, customChar);
dht.begin();
pinMode(BUTTON_PIN, INPUT_PULLUP); // Button with internal pull-up resistor
loadingAnimation(lcd);
lcd.clear();
displayMenu();
}
void loop() {
int buttonState = digitalRead(BUTTON_PIN);
if (buttonState == LOW) {
// Button is pressed; check for long hold
if (buttonPressStart == 0) {
buttonPressStart = millis(); // Record the time the button was first pressed
}
// Check if button is held
if (!buttonHeld && millis() - buttonPressStart > HOLD_DELAY) {
buttonHeld = true;
handleButtonHold();
}
} else {
// Button released
if (buttonHeld) {
// Reset hold state on release
buttonHeld = false;
} else if (buttonPressStart != 0 && millis() - buttonPressStart < HOLD_DELAY) {
// If it was a short press, handle as a normal press
handleButtonPress();
}
// Reset button press start time
buttonPressStart = 0;
}
// Check for real-time updates in specific submenus
if (currentState == SUBMENU) {
switch (selectedItem) {
case 0: // Temperature submenu
displayTemperature();
break;
case 1: // Humidity submenu
displayHumidity();
break;
case 3: // Message submenu
readFromLCD(); // Continuously read data while in "Message" submenu
break;
}
}
delay(DEBOUNCE_DELAY);
}
void handleButtonPress() {
if (currentState == MENU) {
// Move the ">" indicator down to the next item
selectedItem = (selectedItem + 1) % (sizeof(menuItems) / sizeof(menuItems[0]));
displayMenu();
}
}
void handleButtonHold() {
if (currentState == MENU) {
// Enter the selected submenu
currentState = SUBMENU;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("< Main Menu");
// Show specific information for Temperature, Humidity, or read message
switch (selectedItem) {
case 0:
displayTemperature();
break;
case 1:
displayHumidity();
break;
case 2:
displayHumidity(); // Assuming this is intentional; adjust as needed
break;
case 3:
readFromLCD();
break;
}
} else {
// Return to main menu
currentState = MENU;
displayMenu();
}
}
void displayMenu() {
lcd.clear();
for (int i = 0; i < 2; i++) { // Display 2 lines at a time
int index = (selectedItem + i) % (sizeof(menuItems) / sizeof(menuItems[0]));
lcd.setCursor(0, i);
lcd.print((i == 0) ? "> " : " ");
lcd.print(menuItems[index]);
}
}
void displayTemperature() {
lcd.setCursor(0, 1);
float temperature = dht.readTemperature();
if (isnan(temperature)) {
lcd.print("Sensor error! ");
} else {
lcd.print("Temp: ");
lcd.print(temperature);
lcd.print("\xDF""C "); // Clear any leftover characters
}
}
void displayHumidity() {
lcd.setCursor(0, 1);
float humidity = dht.readHumidity();
if (isnan(humidity)) {
lcd.print("Sensor error! ");
} else {
lcd.print("Hum: ");
lcd.print(humidity);
lcd.print("% "); // Clear any leftover characters
}
}
void readFromLCD() {
if (Serial.available() > 0) {
lcd.setCursor(0, 1);
lcd.print(" "); // Clear the previous message
// Read new input
String input = Serial.readStringUntil('\n'); // Read until newline character
lcd.setCursor(0, 1); // Set cursor back to the second line
lcd.print(input); // Print the new input
}
}
void serialFlush(){
while(Serial.available() > 0) {
char t = Serial.read();
}
}