/* Circuit: PIR module on pin 2, +5V and GND supplied by Arduino.
LED just uses the built in LED. It's just intended to
show the timing of the output device, which would have to
be replaced by a motor of some kind to actually open and close
a door.
PIR sensor module set to LOW jumper mode (non retriggering)
and time and sensitivity pots on the module left as they were
for mine, out of the box.
Set Serial monitor to 115200 baud, no line ending.
More info on PIR sensor courtesy of Adafruit Industries:
https://learn.adafruit.com/pir-passive-infrared-proximity-motion-sensor/testing-a-pir
Timing/sensor explanation:
This is intended for a motivated cat. That is, kitty is gonna have
to work a little so the door doesn't just open if the cat is merely
detected once. What if Mr. Whiskers decides to sleep in front of
the kitty door? You want him to catch a cold from an open door?
So this presumes Mr. Whiskers perhaps paws at something of circles
or paces or looks back at his pet human indicating a desire to cross
the threshold of the door. My two cats certainly do.
Then, once the cat has been moving for three seconds, he is considered
present and wanting the door to open. It will open (led will light up
for this demo).
If Mr Kitty decides to waffle about before crossing the threshold, he
will continue to be detected and the door will stay open as long as he's
purposefully wasting his day away as cats are known to do.
It will stay open for another five seconds once he has passed through
the door.
by Hallowed31, July 03, 2024.
Countdown timer technique courtesy of cattledog from the Arduino Forum.
*/
int ledPin = LED_BUILTIN;
int pirPin = 2;
int ledState;
int lastLedState;
int pirState;
int lastPirState;
int eventCounter = 0;
unsigned long stopwatchRuntime = 0;
unsigned long lastStopwatchCheck = 0; // keep track of time that no detection changed to detction
unsigned long stopwatchTimer = 0; // keep track of time at every new detection event
unsigned long holdDoorOpenTimer = 0;
const long interval = 1000; // how often to reprint door open timer on Serial monitor
int timer = 5;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(pirPin, INPUT);
Serial.begin(115200);
Serial.println("pirCatDoorTimerDemo");
Serial.println();
pirState = 0; // set initial states
lastPirState = 0;
ledState = 0;
lastLedState = 0;
}
void loop() {
stopwatchRuntime = millis(); // start free running timer that never actually stops
pirState = digitalRead(pirPin);
switch (pirState) {
case 0:
/* cat got door open by moving, time for device to obey cat */
theCatsOutOftheBag();
break;
case 1:
/* cat moving to open door, ie not just sleeping there */
ledState = pirState;
theCatsInTheBag();
break;
}
}
void theCatsInTheBag() {
stopwatchTimer = stopwatchRuntime - lastStopwatchCheck;
if (lastPirState == 0) {
lastPirState = 1;
eventCounter += 1;
}
catDetectING(); // print Serial debugging data for events and timer
if (stopwatchTimer > 3000) { // if cat keeps moving over timeframe of three seconds...
digitalWrite(ledPin, ledState); // do the thing (turn led on in this test)
lastLedState = ledState; // and set state to act upon so as soon as cat through door, it holds
}
}
void theCatsOutOftheBag() {
lastPirState = pirState;
lastStopwatchCheck = stopwatchRuntime;
if (lastLedState == 1) {
if (stopwatchRuntime - holdDoorOpenTimer >= interval) {
holdDoorOpenTimer = stopwatchRuntime;
catDetectED(); // print Serial debugging data for events, timer and door countdown
timer--;//decrease timer count
if (timer == -1)// less than 0
{
doorClosingMessage();
timer = 5; // reset timer variable for next door opening event
lastLedState = lastPirState;
}
}
digitalWrite(ledPin, lastLedState);
}
else {
lastLedState = 0;
digitalWrite(ledPin, lastLedState);
}
}
void catDetectED() {
Serial.print("Event Counter: ");
Serial.print(eventCounter);
Serial.print("\tTime since detection: ");
Serial.print(stopwatchTimer);
Serial.print("\tDoor open timer: ");
Serial.println(timer);
}
void catDetectING() {
Serial.print("Event Counter: ");
Serial.print(eventCounter);
Serial.print("\tTime since detection: ");
Serial.println(stopwatchTimer);
}
void doorClosingMessage() {
Serial.println();
Serial.println("Closing Door - watch your tail!");
Serial.println();
}