// ---------------- PIN DEFINITIONS ----------------
#define PIR_PIN 14
#define BUTTON_PIN 27
#define SERVO_PIN 16
// ---------------- SERVO SETTINGS ----------------
#define SERVO_FREQ 50
#define SERVO_RES 16
#define OPEN_ANGLE 90
#define CLOSE_ANGLE 0
// ---------------- TIMING ----------------
const unsigned long OPEN_TIME = 5000; // 5 seconds
const unsigned long DEBOUNCE_TIME = 50;
// ---------------- STATE ----------------
enum GateState { CLOSED, OPEN };
GateState gateState = CLOSED;
unsigned long gateOpenTimestamp = 0;
unsigned long lastButtonChangeTime = 0;
bool lastButtonState = HIGH;
bool stableButtonState = HIGH;
// ---------------- SERVO FUNCTION ----------------
void setServoAngle(int angle) {
uint32_t duty = map(angle, 0, 180, 1638, 8192);
ledcWrite(SERVO_PIN, duty); // ESP32 core v3.x style
}
// ---------------- SETUP ----------------
void setup() {
Serial.begin(115200);
pinMode(PIR_PIN, INPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
ledcAttach(SERVO_PIN, SERVO_FREQ, SERVO_RES);
setServoAngle(CLOSE_ANGLE);
Serial.println("System ready. Gate CLOSED.");
}
// ---------------- LOOP ----------------
void loop() {
unsigned long now = millis();
// ---------------- AUTO CLOSE ----------------
if (gateState == OPEN && (now - gateOpenTimestamp >= OPEN_TIME)) {
closeGate();
}
// ---------------- PIR (ONLY WHEN CLOSED) ----------------
if (gateState == CLOSED && digitalRead(PIR_PIN) == HIGH) {
triggerGate("PIR motion detected", now);
}
// ---------------- BUTTON DEBOUNCE (ONLY WHEN CLOSED) ----------------
bool reading = digitalRead(BUTTON_PIN);
if (reading != lastButtonState) {
lastButtonChangeTime = now;
}
if ((now - lastButtonChangeTime) > DEBOUNCE_TIME) {
if (reading != stableButtonState) {
stableButtonState = reading;
if (gateState == CLOSED && stableButtonState == LOW) {
triggerGate("Button pressed", now);
}
}
}
lastButtonState = reading;
}
// ---------------- TRIGGER ----------------
void triggerGate(const char* source, unsigned long now) {
if (gateState == OPEN) return;
Serial.print("[TRIGGER] ");
Serial.println(source);
openGate();
gateOpenTimestamp = now;
}
// ---------------- OPEN ----------------
void openGate() {
setServoAngle(OPEN_ANGLE);
gateState = OPEN;
gateOpenTimestamp = millis();
Serial.println("Gate OPENED");
}
// ---------------- CLOSE ----------------
void closeGate() {
setServoAngle(CLOSE_ANGLE);
gateState = CLOSED;
Serial.println("Gate CLOSED");
}