Introduction: The Laser Cat Toy. "The AutoMazer"

Here is an updated video of the working product above:

Step 1: The Idea

Why spend useless money on multiple different cat toys when there is one screaming your name. The "AutoMazer" is an automated and randomized laser pointer that scans the room with its high power laser pointer. It is perfect for owners that are busy at work but also want to make their cats happy while they are away from home. Here are the steps that us here at Cathletes inc. took to create the perfect cat toy.

Step 2: Testing Stage

Our second stage of this project was to check if all of our hardware was operating.

Materials used:

  • 1 UNO Arduino board
  • 1 breadboard
  • 2 servos
  • 1 laser pointer
  • 1 pan and tilt housing system
  • 1 ultrasonic sensor
  • 1 Ziploc container
  • 1 infrared sensor
  • 1 infrared remote
  • multiple connecting wires

The bread boards main use was to connect all of the components to the power and ground rails. The servos were connected to the pan and tilt housing system, and on top of that, the laser is connected to the pan and tilt housing unit as well. Lastly the ultrasonic sensor was alone. All together, these components create the perfect cat toy.

Pan and tilt housing unit link:

https://www.amazon.com/Camera-Platform-Anti-Vibrat...

Infrared sensor + controller link:

https://www.amazon.com/CTYRZCH-Infrared-Control-Re...

Step 3: The Servo's

The main method behind all of this madness is the two servos at work. They are connected to a pan and tilt housing system that allows the two servos to cover a whole plane of area (left to right 180 degrees, up to down 180 degrees). From there we ran some basic code to make sure that they both worked. Then finally, we implemented code that made the two servos cover a specific area, all the while being randomized.

Code:

randmov = random(180); //states the amount of degrees that the servo will move within randomly

randmov = random(0,180); // states the max and min that the servo can randomly move within

randmov2 = random(180);

randmov2 = random(0,180);

Step 4: The Ultrasonic Sensor

The next step in this project is to implement the ultrasonic sensor. It allows the AutoMazer to turn on when the cat is near, and turn off when the cat has left.

Ultrasonic sensor code:

const int trigPin = 12;
const int echoPin = 11;

long duration; int distance;

pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT); Serial.begin(9600);

if (distance < 40)
{

if (digitalRead(btnPin) ==HIGH ) { for (int x = 0; x < 10; x++) {

servo2.write(randmov);

servo1.write(randmov2); delay (75);

} }

Step 5: The Laser

Like any other light source in Arduino, this is fairly basic to understand and control. You can turn the laser on and off with commands such as digitalWrite, etc...

Step 6: The Infrared Sensor

Hooking up the infrared sensor demanded a little extra work. However, the link below will show how you how to set the sensor up to the Arduino, as well as the code. The code, in brief, sets up the sensor and then provides you with the code that corresponds with the button that you have pressed.

https://www.sunfounder.com/learn/RFID_kit_V1_for_A...

Furthermore, the Infrared sensor and remote in the "Automazer" works as an activator. When the power button is pressed, the ultrasonic sensor is activated, which then activates the rest of the circuit. Or in other words... it is just a power button.

Also, the library for the infrared sensor was downloaded already. However, if you do not know how to download a library to your Arduino, here is a link to show you how: https://www.arduino.cc/en/Guide/Libraries

Step 7: The Circuit

The circuit was a basic part of this project. The biggest significance of the breadboard is just connecting components such as the laser and the ultrasonic sensor to the power rails. However, if you have more time and you are skilled with a soldering iron, you may not even need the breadboard. This would make the circuit cleaner and easier to put into the box.

Step 8: Creating the Box

Originally, the box was made out of cardboard and it was shaped into the form of a rectangular prism. After the main shape was made, we cut a rectangular hole in the top of the box in order for the servos to come through, along with the pan and tilt housing unit. When the pan and tilt housing unit was securely glued on, the Arduino and breadboard was placed inside carefully and enclosed with two cardboard squares. Two additional holes were also made for the ultrasonic sensor to come through. However, if you are looking to make the prototype more appealing, you can buy a ziploc container instead of cardboard. It does look more appealing and it is easier to access the circuit if anything happens. If you choose the Ziploc container, there are some holes that you will need to cut. The major hole is the hole supporting the pan and tilt housing system. When I made it, I used a sharpie and just drew an outline around the pan and tilt housing system and then proceeded to cut it out with an Exacto knife. The next holes that needed to be cut were the holes for the ultrasonic sensor and the infrared sensor (see in first picture of instructable). Lastly, I cut a hole for the breadboard so the circuit fit more comfortably.

Step 9: Plug in the Arduino

This is the final step. Along with a complete circuit, all that is left is code. Once the Arduino is plugged in, the whole project will work! Enjoy!

CODE:

#include //servo library

#include //infrared library

Servo servo1; //instantiates the first servo as “servo1”

Servo servo2; //instantiates the second servo as “servo2”

int xpos; //variable for x axis position of servo

int ypos; //variable for y axis position of servo

int randmov = 0;//creates variable for random movements of servo 1

int randmov2 = 0;//creates variable for random movements of servo 2

int servo1_pin = 10; //assigns servo 1 to pin 10

int servo2_pin = 9; //assigns servo 2 to pin 9

int initial_position = 90; //sets the initial position of servo 1 to 90 degrees

int initial_position1 = 90; //sets the initial position of servo 2 to 90 degrees

int laserPin = 6; //assigns the laser pointer to pin 6

const int btnPin = 13; //assigns the button to pin 13

int buttonState = 0; //sets the button state to OFF

const int trigPin = 12; //trigger pin on ultrasonic to pin 12

const int echoPin = 11; //echo pin on ultrasonic to pin 11

long duration; //makes “duration” a long type variable (meaning that the number can approach infinite)

int distance; //makes distance an integer variable

const int irReceiverPin = 2; //assigns the infrared sensor to pin 2

int flagg = 1; // makes the integer "flagg" = 1

IRrecv irrecv(irReceiverPin); //Creates a variable of type IRrecv

decode_results results; //creates a variable of type decode

//////////////////////////////////////////////////////////////////////////////////////

void setup() {// put your setup code here, to run once:

pinMode(6, OUTPUT); //makes pin 6 an output

servo1.attach (servo1_pin ) ; //Attach the Servo variable to pin 10

servo2.attach (servo2_pin ) ; //Attach the Servo variable to pin 9

servo1.write (initial_position); //sets the servo to 90 degrees

servo2.write (initial_position1); //sets the servo to 90 degrees

pinMode (btnPin, INPUT); //makes the variable "btnPin" an input

Serial.begin(180); //Sets the data rate to 180 bits per second for serial data transmission

randomSeed(analogRead(0)); //pseudo random number generator. Creates random degree for servo to turn to.

pinMode(trigPin, OUTPUT); //makes trigPin an output

pinMode(echoPin, INPUT); //makes echoPin an input

Serial.begin(9600); //Sets the data rate to 9600 bits per second for serial data transmission

Serial.begin(9600); //initialize serial monitor

irrecv.enableIRIn(); //enable ir receiver module

}

//////////////////////////////////////////////////////////////////////////////////////

void loop() {// put your main code here, to run repeatedly:

{

if (irrecv.decode(&results)) //if the ir receiver module receiver data, run code below

{

Serial.println("irCode: "); //print"irCode:"

Serial.print(results.value, HEX); //print the value in hexdecimal

Serial.print(", bits: "); //print" , bits: "

Serial.println(results.bits); //print the bits

irrecv.resume(); // Receive the next value

}

if(results.value == 0xFFFFFFFF) //if the power button on the infrared controller is pressed, run code below

{ mainCode (); //runs the sub-rountine named "mainCode"

results.value = 0; //resets the value to 0

}

}

}

void mainCode ()//sub-routine named "mainCode"

{

while (true) { //while true, run code below

if (irrecv.decode(&results)) //if the ir receiver module receiver data

{

break; //break out of while loop

}

buttonState = digitalRead(btnPin); //reads the state of the button

Serial.println(buttonState); //prints the state of button

digitalWrite(trigPin, LOW); //turns trigPin OFF

delayMicroseconds(2); //delays the program for 2 microseconds

digitalWrite(trigPin, HIGH); //turns trigPin ON

delayMicroseconds(10); //delay program for ten milliseconds

digitalWrite(trigPin, LOW); //turns off the trigPin

duration = pulseIn(echoPin, HIGH); /*when echoPin is on, the pulseIn command starts a timer. When it turns off, the timer stops. Since duration is a long variable, duration can run forever. pulseIn is the timer command for the ultrasonic sensor. */

distance= duration*0.034/2; // distance is determined by duration of timer, multiplied by 0.034and divided by 2.

Serial.print("Distance: "); //puts the word "distance:" in front of distance in serial monitor Serial.println(distance); //prints out distance in serial monitor

randmov = random(180); //generates pseudo-random numbers with a max number of 180 for servo 1

randmov = random(0,180); //generates pseudo-random numbers between 0-180 for servo 1

randmov2 = random(180); //generates pseudo-random numbers with a max number of 180 for servo 2

randmov2 = random(0,180); //generates pseudo-random numbers between 0-180 for servo 2

Serial.println(randmov); //prints the random number

if (distance < 10) //if the distance in front of the ultrasonic sensor is 10 or less, run code below

{

if (digitalRead(btnPin) ==HIGH ) //if the button is on, run code below

{

for (int x = 0; x < 10; x++) // if the distance was 40 or less, run the code 10 times

{

servo2.write(randmov); //makes servo2 turn to the random number that was generated servo1.write(randmov2); //makes servo1 turn to the random number that was generated

delay (75); //delays program for 75 milliseconds

laserPointer (); //runs the laserpointer sub-rountine

}

}

}

}

}

void laserPointer ()//laser pointer sub-routine

{

digitalWrite (laserPin, HIGH); // Turn Laser On

}

/////////////////////////////////////////////////////////////////////////////////////