#include <ESP32Servo.h>
const int buttonPin = 25;
const int pirPin = 26;
const int servoPin = 27;
Servo gateServo;
bool isGateOpen = false;
unsigned long gateOpenedAt = 0;
const unsigned long gateOpenDuration = 10000; // 10 seconds (10,000 ms)
volatile bool buttonFlag = false;
volatile bool pirFlag = false;
// --- Debounce Variables ---
volatile unsigned long lastButtonPress = 0;
const unsigned long debounceDelay = 250; // 250 milliseconds debounce
void IRAM_ATTR buttonISR() {
unsigned long currentTime = millis();
// Software debounce check
if ((currentTime - lastButtonPress) > debounceDelay) {
buttonFlag = true;
lastButtonPress = currentTime;
}
}
void IRAM_ATTR pirISR() {
pirFlag = true;
}
// --- Main Setup ---
void setup() {
Serial.begin(115200);
pinMode(buttonPin, INPUT_PULLUP);
pinMode(pirPin, INPUT_PULLDOWN);
// Configure Servo
gateServo.attach(servoPin);
gateServo.write(0); // 0 degrees = CLOSED position
attachInterrupt(digitalPinToInterrupt(buttonPin), buttonISR, FALLING);
// Rising edge because PIR goes LOW -> HIGH on motion
attachInterrupt(digitalPinToInterrupt(pirPin), pirISR, RISING);
Serial.println("System Ready. Gate is CLOSED.");
}
// --- Main Loop ---
void loop() {
// 1. Check for Triggers
if (buttonFlag || pirFlag) {
if (!isGateOpen) {
// Gate was closed, so open it
gateServo.write(90);
isGateOpen = true;
Serial.print("Triggered by: ");
Serial.println(buttonFlag ? "Manual Button" : "PIR Motion Sensor");
Serial.println("Gate OPENED.");
} else {
// Gate is already open (Repeated Trigger Handling)
Serial.print("Trigger detected while open. Extending time by 10s. Trigger: ");
Serial.println(buttonFlag ? "Manual Button" : "PIR Motion Sensor");
}
gateOpenedAt = millis();
buttonFlag = false;
pirFlag = false;
}
if (isGateOpen && (millis() - gateOpenedAt >= gateOpenDuration)) {
gateServo.write(0); // Move back to CLOSED position
isGateOpen = false;
Serial.println("Time elapsed. Gate CLOSED.");
}
}