#include <ESP32Servo.h>
#define SERVO_PIN 21
Servo myServo;
#define BUTTON_PIN 14 // data line for the feature button
#define SENSOR_PIN 12
byte buttonState = LOW; //button starts at low
byte motionState = LOW;
byte newButtonState; //initialising 'new' detection states
byte newMotionState;
boolean isOpen = false; //boolean value used for checking if the door is open
int position = 0;
unsigned long maxOpenDuration = 5000;
unsigned long timeSinceDetect = millis();
unsigned long timePreviousButtonChange = millis();
unsigned long debounceDelay = 100;
//defining a set number of time that the button can't change for
unsigned long timeNow = millis(); //getting the current time
unsigned long timeSinceMotion = millis();
void close(){
isOpen = false; //boolean changed to mark closing
position = 0; //modify the position to the closed position
myServo.write(position); //return the servo to the closed position
Serial.println("Close door"); //output showing that the door has been closed
}
void open(){
isOpen = true; //boolean changed to mark opening
timeSinceDetect = millis(); //get the time so that the door will stay open for a while
position = 180; //modify the position to the open position
myServo.write(position); //move the servo to the open position
Serial.println("Open door"); //output showing that the door has been opened
}
void IRAM_ATTR buttonPressedInterrupt(){
timeNow = millis(); //getting the time of the button being pressed
if ((timeNow - timePreviousButtonChange) > debounceDelay) {
// this code is only reached if bounceDelay interval since last change has passed
newButtonState = digitalRead(BUTTON_PIN); // read the button state
// button state has changed
if (newButtonState != buttonState) { //check for a change in button state
buttonState = newButtonState; // update button state
timePreviousButtonChange = timeNow;//update time of last button state change
if (buttonState == HIGH) { //if the button is being pressed
if (isOpen == false){ //if the door is closed
Serial.println("button pressed");
open(); //open the door
}else{ //if the door is open
timeSinceDetect = millis(); //extend the open time by resetting the detection timer
Serial.println("Open time extended from press");
}
}
else { //if the button is being released
if (isOpen == true){ //if the door is already open
timeSinceDetect = millis(); //get the time now to extend the time it will be open
Serial.println("Open time extended from release");
} else{ //if the door is not already open
Serial.println("button released");
open(); //open the door
}
}
}
}
}
void IRAM_ATTR motionInterrupt(){
newMotionState = digitalRead(SENSOR_PIN); // read the sensor state
timeSinceMotion = millis();
motionState = newMotionState; // update sensor state
if (motionState == HIGH) { //if there is motion detected
if (isOpen == false){ //if the door is closed
Serial.println("motion detected");
open(); //open the door
motionState = LOW;
}
else if (isOpen == true) { //if it is open
timeSinceDetect = millis(); //reset the time since last detection
Serial.println("Open time extended from motion");
motionState = LOW;
}
}
}
void setup() {
Serial.begin(115200); //assign the serial so the outputs can be put in the serial monitor
myServo.attach(SERVO_PIN); //attatching the object myServo to the pin the servo is connected to
pinMode(SENSOR_PIN, INPUT); //assigning the sensor's pin as an input pin
pinMode(BUTTON_PIN, INPUT); //assigning the button pin as an input pin
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), buttonPressedInterrupt, RISING);
//attatching the button's interrupt to the button's pin
attachInterrupt(digitalPinToInterrupt(SENSOR_PIN), motionInterrupt, RISING);
//attaching the motion sensor's interrupt to the sensor's pin
isOpen = false; //making sure that the door starts closed
}
void loop() {
timeNow = millis(); //getting the current time
motionState = digitalRead(SENSOR_PIN); //check for motion
if (isOpen == true){ //if the door is open
if ((timeNow - timeSinceDetect) > maxOpenDuration) { //check it has been open longer than the time it should be
close(); //close the door
}
if (motionState == HIGH){
if (timeNow - timeSinceMotion > 1000){
Serial.println("Open time extended from motion");
timeSinceMotion = millis();
timeSinceDetect = millis();
}
}
}
}