#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define PIR_PIN 33
#define BUZZER_PIN 32
#define FAN_RELAY_PIN 25
#define LIGHT_RELAY_PIN 26
#define BUTTON_UP_PIN 14
#define BUTTON_DOWN_PIN 12
LiquidCrystal_I2C lcd(0x27, 16, 2); // Set the LCD address to 0x27 for a 16x2 display
int peopleCount = 0;
int maxPeople = 10; // Default maximum people allowed
unsigned long buzzerStartTime = 0;
bool buzzerOn = false;
bool buzzerTriggered = false; // New flag to track if the buzzer has already been triggered
// States for input transition detection
bool pirState = LOW;
bool lastPirState = LOW;
// Button states
bool buttonUpState = HIGH;
bool lastButtonUpState = HIGH;
bool buttonDownState = HIGH;
bool lastButtonDownState = HIGH;
// Timer for PIR state
unsigned long pirLowStartTime = 0;
bool pirWasLow = false; // Track if PIR was previously low
bool exitout = false;
void setup() {
Serial.begin(115200); // Start serial communication for debugging
pinMode(PIR_PIN, INPUT);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(FAN_RELAY_PIN, OUTPUT);
pinMode(LIGHT_RELAY_PIN, OUTPUT);
pinMode(BUTTON_UP_PIN, INPUT_PULLUP);
pinMode(BUTTON_DOWN_PIN, INPUT_PULLUP);
digitalWrite(FAN_RELAY_PIN, LOW); // Initially fan is off
digitalWrite(LIGHT_RELAY_PIN, LOW); // Initially light is off
digitalWrite(BUZZER_PIN, LOW); // Initially buzzer is off
lcd.init();
lcd.backlight();
updateDisplay();
Serial.println("Setup complete. Initial state:");
Serial.print("People Count: "); Serial.println(peopleCount);
Serial.print("Max People: "); Serial.println(maxPeople);
}
void loop() {
handlePeopleCounting();
handleMaxPeopleAdjustment();
handleUtilitiesControl();
handleBuzzer();
}
void handlePeopleCounting() {
pirState = digitalRead(PIR_PIN); // Read PIR sensor state
// Detect transition from LOW to HIGH (person entering)
if (pirState != lastPirState) {
if (pirState == HIGH) {
Serial.println("PIR detected motion (HIGH).");
if (peopleCount < maxPeople && !exitout) {
peopleCount++;
Serial.print("People count increased: "); Serial.println(peopleCount);
updateDisplay();
}
if (peopleCount > 0 && exitout) {
peopleCount--; // Decrease count after 10 seconds of being LOW
Serial.print("People count decreased (exitout): "); Serial.println(peopleCount);
updateDisplay();
if (peopleCount == 0) {
exitout = false;
}
}
// Reset the low timer since we detected motion
pirWasLow = false;
} else { // pirState is LOW
Serial.println("PIR detected no motion (LOW), starting timer.");
pirLowStartTime = millis(); // Start the timer for low state
pirWasLow = true;
for(int ii = 0; ii < 2; ii++) {
tone(BUZZER_PIN, 1000);
delay(100);
noTone(BUZZER_PIN);
delay(100);
}
}
lastPirState = pirState; // Update last PIR state
}
// Check if PIR has been LOW for 10 seconds
if (pirWasLow && (millis() - pirLowStartTime >= 10000)) {
Serial.println("PIR has been LOW for 10 seconds, enabling exitout.");
exitout = true;
pirWasLow = false; // Reset low state tracking
}
}
void handleMaxPeopleAdjustment() {
buttonUpState = digitalRead(BUTTON_UP_PIN);
buttonDownState = digitalRead(BUTTON_DOWN_PIN);
// Detect button press (transition from HIGH to LOW)
if (buttonUpState != lastButtonUpState && buttonUpState == LOW) {
maxPeople++;
Serial.print("Max people increased: "); Serial.println(maxPeople);
updateDisplay();
lastButtonUpState = buttonUpState; // Update last button up state
}
if (buttonDownState != lastButtonDownState && buttonDownState == LOW && maxPeople > 1) {
maxPeople--;
Serial.print("Max people decreased: "); Serial.println(maxPeople);
updateDisplay();
lastButtonDownState = buttonDownState; // Update last button down state
}
// Update states for debouncing purposes
lastButtonUpState = buttonUpState;
lastButtonDownState = buttonDownState;
}
void handleUtilitiesControl() {
if (peopleCount > 0) {
digitalWrite(FAN_RELAY_PIN, HIGH); // Turn on fan
digitalWrite(LIGHT_RELAY_PIN, HIGH); // Turn on light
} else {
digitalWrite(FAN_RELAY_PIN, LOW); // Turn off fan
digitalWrite(LIGHT_RELAY_PIN, LOW); // Turn off light
}
}
void handleBuzzer() {
if (peopleCount >= maxPeople && !buzzerTriggered) {
buzzerOn = true;
buzzerTriggered = true; // Set buzzerTriggered to true to avoid re-triggering
buzzerStartTime = millis();
tone(BUZZER_PIN, 1000);
Serial.println("Buzzer ON (room full).");
}
if (buzzerOn && millis() - buzzerStartTime >= 2000) {
buzzerOn = false;
noTone(BUZZER_PIN);
Serial.println("Buzzer OFF (2 seconds passed).");
}
// Reset the buzzer trigger if people count goes below maxPeople
if (peopleCount < maxPeople) {
buzzerTriggered = false;
}
}
void updateDisplay() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("People: ");
lcd.print(peopleCount);
lcd.setCursor(0, 1);
lcd.print("Max: ");
lcd.print(maxPeople);
// Debug output for the display
Serial.print("LCD Update - People: "); Serial.print(peopleCount);
Serial.print(", Max People: "); Serial.println(maxPeople);
}