Laser cat entertainer


My first project with Arduino and servo motors. The idea came after seeing online several electronic projects where tired humans found a way to entertain their cats. They tried with a solution with two requirements: a energy level comparable with the cats (close to infinity), and the ability to retain the cat attention. A laser moved by two little servo motors is a solution perfect for the human, and irresistible for the cat!

Most of online projects describing that circuit are built with an Arduino UNO, or Arduino Nano. At the time of realizing such project I had available only a Teensy++ 2.0. Fortunately the Teensy family was adopted by Arduino and it can be possible to program such devce via Arduino IDE very easily. So, start with build directions.

The very first step to program a Teensy device with Arduino IDE is to download Teensyduino, available at www.pjrc.com/teensy/teensyduino.html. Such page explains to the most curious some requirements/compatibilities; to download and install Teensy support for Arduino click www.pjrc.com/teensy/td_download.html. Following last link directions is very straightforward, so at this point you have a running environment to program the Teensy board.

On the PJRC website it is possible to find the pinout of Teensy++ 2.0 with pin numbers to be used in Arduino IDE. From following image I chosen to use the pin number 0 for vertical servo, and pin number 25 for horizontal one.

Teensyduino pinout

Below the code of present project. It is a little more complicated than other projects, because I desired to move the two motors seamlessy together, so a step performed by one motor is followed by a step of the other motor.

// Laser cat entertainer code for Teensy++ 2.0
// Teensy++ 2.0 onboard led pin = 6

#include <Servo.h>

#define SERVO_H_PIN 0
#define SERVO_V_PIN 25
#define LED_PIN 6

Servo verticalServo; 
Servo horizontalServo;
bool vAxysDirection;
bool hAxysDirection;

//////////////////////////////////////////////////////////////////////////////
// Main setup routine
void setup()
{
  //pinMode(LED_PIN, OUTPUT);
  verticalServo.attach(SERVO_V_PIN);
  horizontalServo.attach(SERVO_H_PIN); 
}

//////////////////////////////////////////////////////////////////////////////
// Main loop routine
void loop()
{
  // Horizontal angle between 40 and 120 degrees
  // Vertical angle between 90 and 135 degrees
  MoveServos(horizontalServo, random(40,120), verticalServo, random(90,135));

  // Wait some time
  delay(random(1000, 2000));

  // Servo testing instructions
  //digitalWrite(LED_PIN, 1);
  //horizontalServo.write(0);
  //delay(1000);
  //horizontalServo.write(180);
  //digitalWrite(LED_PIN, 0);
  //delay(5000);
}

//////////////////////////////////////////////////////////////////////////////
// Servos control routine. The two servos seem to move simultaneously
void MoveServos(Servo & hServo, int newHAngle, Servo & vServo, int newVAngle)
{
  // Random speed for every shift
  int waitBeforeNextStep = random(0, 60);
  
  // Read current servo angles
  int currentHAngle = hServo.read();
  int currentVAngle = vServo.read();

  // Evaluate direction on horizontal axys
  hAxysDirection = currentHAngle < newHAngle;

  // Evaluate direction on vertical axys
  vAxysDirection = currentVAngle < newVAngle;

  // Move both servos
  bool vContinue;
  bool hContinue;
  
  while(true)
  {
    vContinue = hContinue = false;
    
    // Horizontal step
    if(ContinueLoop(false, currentHAngle, newHAngle))
    {
      hServo.write(currentHAngle);
      delay(waitBeforeNextStep);
      hAxysDirection ? currentHAngle++ : currentHAngle--;
      hContinue = true;
    }

    // Vertical step
    if(ContinueLoop(true, currentVAngle, newVAngle))
    {
      vServo.write(currentVAngle);
      delay(waitBeforeNextStep);
      vAxysDirection ? currentVAngle++ : currentVAngle--;
      vContinue = true;
    }

    if(!hContinue && !vContinue) break;
  }
}

bool ContinueLoop(bool vertical, int i, int target)
{
  bool currentAxysDirection;
  
  // Select current axys direction
  if (vertical) { currentAxysDirection = vAxysDirection; }
  else { currentAxysDirection = hAxysDirection; }

  // Evaluate condition
  if (currentAxysDirection) { return i < target; }
  else { return i > target; }
}

Next step is designing the power supply circuit. I managed to use a 9V battery, so a 7805 linear voltage regulator is needed. Next image is the schematic of the entire circuit.

Teensyduino pinout

Teensyduino pinout

Teensyduino pinout

Teensyduino pinout

The bill of materials:

  • Teensy++ 2.0 board [buy here] but you can use every arduino compatible board you like, simply adapt output pin numbers;
  • laser module [buy here];
  • 2x micro servo [buy here];
  • 7805 linear voltage regulator [buy here];
  • 2x 100nF capacitors [buy here];
  • breadboard [buy here] or any prototyping board you like;
  • wood/plastic/metal to build the vertical servo holding structure;
  • a little case for the circuit.

Comments