F.O.C – arduino Fuck Off Cat project

By | May 2, 2016

Probably some of the cat owners relate to my problem, so here it goes!

There are nights in which my cat is probably possessed by demons (plural here). While he does not climb walls, it does sound so. Another ability of his is to lick plastics, he will find them even if you thought there was none.

Demon Cat

Demon Cat

All of this is ok if you are an heavy sleeper, which is not the case. So if you resemble my grandpa or a goddamn menhir… just move along. Here we will discuss the awesome and yet simple, F.O.C… the Fuck Off Cat.

Concept

  1. Cat approaches
  2. F.O.C detects cat
  3. F.O.C mind controls cats to go to the furthest away point in the house

Obviously the last point cannot involve cucumbers as I haven’t figure out the process of replicating them on the fly, but lasers! Yes, LASERS! (Dunno why caps, LASERS just sound awesome and I am not even a big fan of meme culture)

Ingredients

So the F.O.C mind control ingredients:

  • any variant of Arduino (or perhaps just one ATmega microcontroller)
  • PIR (Passive InfraRed) sensor
  • Laser
  • 2x 9V batteries (or a powerbank…)
  • Servo

I will leave you a schematic later, for now a pic will do:

13072719_1132085856813475_2458566533163978862_o

F.O.C full system

If you remove the PIR sensor cover you can see the polarity of each connection. Most of the connections I achieved looking at each component separately in the Arduino tutorials.You need a dedicated battery for the servo otherwise it won’t move and don’t forget to connect the servo ground to the arduino and to the battery.

A quick demo

Code

#include <Servo.h>

Servo myservo;  // create servo object to control a servo (up to 12)

/////////////////////////////
//VARS
//the time we give the sensor to calibrate (10-60 secs according to the datasheet)
int calibrationTime = 30;        

//the time when the sensor outputs a low impulse
long unsigned int lowIn;         

//the amount of milliseconds the sensor has to be low 
//before we assume all motion has stopped
long unsigned int pause = 5000;  

boolean lockLow = true;
boolean takeLowTime;  
int val = 0;
int pos = 0;                   // variable to store the servo position
int pirState = LOW;            // we start, assuming no motion detected
int blinkState = 0;

int LASERDELAY = 50;

//BOARD PINS
int LEDPIN = 13;               // Blinks until calibration done
int SERVOPIN = 7;              // Outputs commands to the Servo
int PIRPIN = 12;               // Following are explicit...
int LASERPIN = 8;
/////////////////////////////

void setup() {
  myservo.attach(SERVOPIN);    // attaches the servo on pin SERVOPIN to the servo object

  pinMode(LEDPIN, OUTPUT);     
  pinMode(LASERPIN, OUTPUT);   
  pinMode(PIRPIN, INPUT);     

  Serial.begin(9600);
  Serial.println("Starting...");

  digitalWrite(LEDPIN, LOW);

  //give the sensor some time to calibrate
  Serial.print("calibrating sensor ");
  for(int i = 0; i < calibrationTime; i++){
      Serial.print(".");
      delay(1000);
      blinkState = !blinkState;
      digitalWrite(LEDPIN, blinkState); //blink led to notify of calibration phase
   }
   Serial.println(" done");
   Serial.println("SENSOR ACTIVE");
   delay(30);

   digitalWrite(LEDPIN, LOW);
}


void move_servo() {
  digitalWrite(LASERPIN, HIGH);   //Turn on laser for rotation

  for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(LASERDELAY);                       // waits 15ms for the servo to reach the position
  }

  digitalWrite(LASERPIN, LOW);   //We dont want the cat back, disable laser!

  for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
    myservo.write(pos);              
    delay(LASERDELAY);    
  }

}

void loop() {
  
    if(digitalRead(PIRPIN) == HIGH){
       digitalWrite(LEDPIN, HIGH); 
       if(lockLow){  
         //makes sure we wait for a transition to LOW before any further output is made:
         lockLow = false;            
         Serial.println("---");
         Serial.print("motion detected at ");
         Serial.print(millis()/1000);
         Serial.println(" sec"); 
         delay(50);
         }         
         takeLowTime = true;
         move_servo();
       }

     if(digitalRead(PIRPIN) == LOW){       
       digitalWrite(LEDPIN, LOW); 

       if(takeLowTime){
        lowIn = millis();          //save the time of the transition from high to LOW
        takeLowTime = false;       //make sure this is only done at the start of a LOW phase
        }

       //if the sensor is low for more than the given pause, 
       //we assume that no more motion is going to happen
       if(!lockLow && millis() - lowIn > pause){  
           //makes sure this block of code is only executed again after 
           //a new motion sequence has been detected
           lockLow = true;                        
           Serial.print("motion ended at ");      
           Serial.print((millis() - pause)/1000);
           Serial.println(" sec");
           delay(50);
           }
       }
}

 

Now I just need to place it over the door and make some nice videos during night!! 😀

Cheers!

Leave a Reply