#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include <Servo.h> // For servo control
// Pin configuration
#define DHTPIN 2
#define MQ2PIN A1 // Analog pin for MQ2 sensor
#define BUZZERPIN 3
#define ROTARY_A_PIN 4 // Rotary Encoder A pin
#define ROTARY_B_PIN 5 // Rotary Encoder B pin
#define ROTARY_BTN_PIN 6 // Rotary Encoder button pin
#define BUTTON_2_PIN 7 // Second button for opening/closing the menu
// DHT setup
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
// LCD setup (20x40 LCD)
#define I2C_ADDR 0x27
#define LCD_COLUMNS 20
#define LCD_LINES 4
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
// Servo setup
#define SERVOPIN 11 // Define the pin for the servo motor
Servo myServo; // Create a Servo object
// Variables
int currentPage = 1;
bool tempControlOn = false; // Temp Control toggle
bool buzzerOn = false; // Buzzer toggle
bool motorOn = false; // Motor toggle
bool fanOn = false; // Fan toggle
int rotaryPosition = 0; // Rotary encoder position
int previousRotaryPosition = 0; // To track position changes
bool menuOpen = false; // Track if menu is open
// Thresholds for controlling temp and MQ2
const int temperatureThresholds[] = {85, 95, 90}; // Example thresholds
// Function declarations
void updateDisplay(float temperature = NAN, float humidity = NAN, int mq2Value = -1);
void openMenu();
void closeMenu();
void manageBuzzer(float temperature, int mq2Value);
void manageServo(float temperature, int mq2Value);
void readRotaryEncoder();
// Initialize setup()
void setup() {
// Initialize the LCD
lcd.init();
lcd.backlight();
// Initialize the DHT sensor
dht.begin();
// Set pin modes
pinMode(MQ2PIN, INPUT);
pinMode(BUZZERPIN, OUTPUT);
pinMode(ROTARY_A_PIN, INPUT);
pinMode(ROTARY_B_PIN, INPUT);
pinMode(ROTARY_BTN_PIN, INPUT_PULLUP); // Button on rotary encoder
pinMode(BUTTON_2_PIN, INPUT_PULLUP); // Second button for menu
// Attach interrupt for rotary encoder
attachInterrupt(digitalPinToInterrupt(ROTARY_A_PIN), readRotaryEncoder, CHANGE);
myServo.attach(SERVOPIN); // Attach the servo to pin
// Display welcome message
lcd.setCursor(0, 0);
lcd.print("Welcome to your");
lcd.setCursor(0, 1);
lcd.print("Smart Enclosure");
lcd.setCursor(0, 2);
lcd.print("Version 3.0.0");
delay(5000); // Display for 5 seconds
lcd.clear();
// Display initial page
updateDisplay();
}
void loop() {
unsigned long currentMillis = millis();
static unsigned long lastDHTRead = 0;
// Read DHT sensor only if interval passed
if (currentMillis - lastDHTRead >= 1000) {
lastDHTRead = currentMillis;
float temperature = dht.readTemperature(true); // Temperature in Fahrenheit
float humidity = dht.readHumidity();
int mq2Value = analogRead(MQ2PIN);
// Update display based on rotary encoder position
updateDisplay(temperature, humidity, mq2Value);
// Check and manage buzzer & servo motor
manageBuzzer(temperature, mq2Value);
manageServo(temperature, mq2Value);
}
// Check if the second button (BUTTON_2) is pressed to open/close the menu
if (digitalRead(BUTTON_2_PIN) == LOW) {
delay(200); // Debounce delay
if (menuOpen) {
closeMenu(); // Close the menu
} else {
openMenu(); // Open the menu
}
}
// Check if the rotary button is pressed to enter selected option
if (digitalRead(ROTARY_BTN_PIN) == LOW) {
delay(200); // Debounce delay
// If menu is open, process the selection
if (menuOpen) {
if (rotaryPosition == 0) {
openTempControlPage(); // Open Temp Control settings
} else if (rotaryPosition == 1) {
buzzerOn = !buzzerOn; // Toggle Buzzer
} else if (rotaryPosition == 2) {
motorOn = !motorOn; // Toggle Motor
} else if (rotaryPosition == 3) {
fanOn = !fanOn; // Toggle Fan
}
while (digitalRead(ROTARY_BTN_PIN) == LOW) { // Wait for button release
delay(10);
}
rotaryPosition = 0; // Reset rotary position after selection
}
}
delay(100); // Short delay for stability
}
void openMenu() {
menuOpen = true; // Mark menu as open
// Update display for menu
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Menu");
// Show menu options (scroll through with rotary encoder)
lcd.setCursor(0, 1);
lcd.print("1. Temp Control");
lcd.setCursor(0, 2);
lcd.print("2. Buzzer");
lcd.setCursor(0, 3);
lcd.print("3. Motor");
lcd.setCursor(0, 4);
lcd.print("4. Fan");
// Scroll through menu options using rotary encoder
if (rotaryPosition == 0) {
lcd.setCursor(0, 1);
lcd.print("> Temp Control");
} else if (rotaryPosition == 1) {
lcd.setCursor(0, 2);
lcd.print("> Buzzer");
} else if (rotaryPosition == 2) {
lcd.setCursor(0, 3);
lcd.print("> Motor");
} else if (rotaryPosition == 3) {
lcd.setCursor(0, 4);
lcd.print("> Fan");
}
}
void closeMenu() {
menuOpen = false; // Mark menu as closed
updateDisplay(); // Return to main page
}
void openTempControlPage() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Temp Control");
lcd.setCursor(0, 1);
lcd.print("Thresholds:");
// Display the current temperature thresholds
for (int i = 0; i < 3; i++) {
lcd.setCursor(0, i + 2);
lcd.print("T" + String(i + 1) + ": " + String(temperatureThresholds[i]));
}
// Wait for user input to change or exit
while (digitalRead(ROTARY_BTN_PIN) == LOW) {
delay(10);
}
closeMenu(); // Close the menu after adjusting settings
}
void updateDisplay(float temperature, float humidity, int mq2Value) {
if (!menuOpen) {
if (currentPage == 1) {
lcd.setCursor(0, 0);
lcd.print("Temp: ");
if (isnan(temperature)) {
lcd.print("NA");
} else {
lcd.print(temperature);
lcd.print(" F");
}
lcd.setCursor(0, 1);
lcd.print("Hum: ");
if (isnan(humidity)) {
lcd.print("NA");
} else {
lcd.print(humidity);
lcd.print(" %");
}
lcd.setCursor(0, 2);
lcd.print("MQ2: ");
if (mq2Value == -1) {
lcd.print("NA");
} else {
lcd.print(mq2Value);
}
lcd.setCursor(0, 3);
lcd.print("Page: 1");
}
}
}
void manageBuzzer(float temperature, int mq2Value) {
// Add buzzer logic based on temperature and MQ2 value
}
void manageServo(float temperature, int mq2Value) {
// Add servo control logic based on temperature
}
void readRotaryEncoder() {
int A = digitalRead(ROTARY_A_PIN);
int B = digitalRead(ROTARY_B_PIN);
if (A == B) {
rotaryPosition++;
} else {
rotaryPosition--;
}
if (rotaryPosition > 3) rotaryPosition = 0;
if (rotaryPosition < 0) rotaryPosition = 3;
}