top of page

Automated Cat Laser Pointer (Lasercat) - Initial Design

Writer's picture: Sophia SchulzSophia Schulz

Updated: Dec 7, 2023

Personal Project (ongoing since April 2023)


Background

At the end of 2022, I adopted two sister kittens — Suki and Koko — and as much as I love playing with them, I can't always be available to interact with them at any given moment. My cats especially love chasing laser dots from pointers such as the one pictured below, but these obviously require constant user input through holding the button — a button that is frequently unresponsive and unreliable. I thus set out to create an automated cat laser pointer that would require little-to-no user input so my cats could be entertained even if I was out of the house.



Initial Design

I broke the initial planning and design of the system down into three aspects:

  1. Mechanical design

  2. Components and circuitry

  3. Programming

Mechanical design: The basis for my initial design was a pan-and-tilt system with two degrees of freedom (two axes of rotation and no translation). I wanted the system to be fixed to a wall (out of the cats' reach) and from this vantage point I could then select the limits of rotation for each axis to give full coverage of the floor for the laser dot to travel on. Thus, in order to provide two independent axes of rotation, I chose to design the system with two motors attached at 90° angles to each other. I designed attachment parts in Autodesk Inventor to then be 3D printed (see Hardware Design section below).


Components and circuitry: For components, I selected:

  • A laser-emitting diode rated at 5V,

  • Two 9g servo motors each rated at 4.8-6V (each to provide a separate axis of rotation),

  • Microcontroller (I started with Arduino Uno for prototyping),

  • Micro-USB to DIP adapter,

  • AC to DC 5V 1A wall adapter,

  • Breadboard and wires (for prototyping).

The initial circuit used for prototyping can be seen in the Hardware Design section below.


Programming: As I was simultaneously learning microcontroller programming in low-level C in a university course, I decided to implement the initial software using this language and directly driving the motors using Pulse Width Modulation (PWM). This was achieved by directly manipulating the Arduino Uno's registers to implement a PWM timer and Interrupt Service Routine (ISR) to send the required duty cycle signal to each motor. I also wanted the motion of the laser dot to be randomised to an extent for more variety of play for my cats, which meant periodically randomising the duty cycle driven to each motor. My initial code for prototyping can be found in the Software Design section below.


Hardware Design

CAD Design: To design the attachment parts for the servo motors and laser diode, I first took measurements of these parts and sketched out potential designs, ensuring that moving parts wouldn't interfere with each other once printed and attached.

I then modelled the attachment pieces for the second motor to the first and for the laser diode to the second motor using Autodesk Inventor. I used part of a servo horn model to with the intention of using mounting screws to attach each piece securely to each motor. These models, which will likely be 3D printed using ABS plastic, are shown below:

Circuit Design: While designing the attachment parts in CAD, I also started implementing the physical circuitry required for initial prototyping. I soldered pins onto a micro-USB to DIP adapter and used this along with an AC to DC 5V 1A wall adapter in order to draw 5V externally, rather than from the Arduino Uno, to power the servo motors and laser diode. For prototyping, I powered the Arduino using my laptop, but intend to set the 5V pin on the board as input so that the Uno can also be powered externally via the micro-USB cable for the finished product.


Since each motor and the laser diode were rated at around 5V, I connected these in parallel on the breadboard and also connected the two motors' signal pins to two of the PWM pins on the Arduino. I also used rubber bands to attach the motors and laser diode to each other as a temporary solution while designing the final attachment parts in Inventor. The completed prototyping circuit can be seen below.



Software Design

For initial prototyping, I focused on using low-level C to directly drive a randomised PWM signal to each motor using the timer ISR. I also used datasheets for the 9g servo motors and the ATmega328P, the microcontroller used for the Arduino Uno, to determine the necessary PWM signal and the registers needed to implement it.


Although the rated PWM signal for the 9g servo motors is a 1-2ms "on" signal over a 20ms period (where 1ms corresponds to a -90° position and 2ms corresponds to a +90° position), the actual signal and positioning varies per motor. Hence, determining the exact values to use for the OCRA and TOP values (set by OCR1A/OCR1B and ICR1 respectively) took some trial and error with the motors to visually determine which values utilised the full 180° range for each. The 20ms period was implemented using the 16-bit timer with a prescaler of 64 and a TOP value of 5000, while OCRA values ranging from 200-800 were used to implement the "on" portion of the duty cycle to vary the position of the motors.


To randomise the motion of the servo motors, I created a simple pseudo-random number generator function based on the length of time since the microcontroller's been turned on (using the randomSeed() and millis() functions). I used this function to 1. randomise the OCRA value and thus the duty cycle being sent to each motor, thereby randomising the target position of each, and 2. randomise the time intervals (from 0.4s to 1s) between updating the OCRA value to randomise the motion further and allow the motors to reach their target positions. For prototyping purposes, I chose to have each motor update their positions at the same time, but I also experimented with offsetting them which produced more fluid motion. The code used for initial prototyping can be seen below.


#include <Arduino.h> #include <stdio.h> #include <avr/io.h> #include <avr/interrupt.h> #include <stdlib.h> // initialise counter variables: volatile int counter = 0; volatile int counterMatch = 100; // random number generator function: int randomNumber(int min, int max) { int randomNum = 0; randomSeed(millis()); randomNum = random(max - min + 1) + min; return randomNum; } // timer ISR: ISR(TIMER1_OVF_vect) { counter++; if (counter == counterMatch) { OCR1A = randomNumber(200, 800); // randomise position of Servo 1 OCR1B = randomNumber(200, 800); // randomise position of Servo 2 counterMatch = randomNumber(20, 50); // randomise time interval counter = 0; } TCNT1 = 0; // reset timer } int main(void) { cli(); // disable interrupts // Timer 1 (16-bit): TCCR1A |= (1<<WGM11); // fast PWM mode with ICR1 to set TOP TCCR1B |= (1<<WGM12) | (1<<WGM13); // fast PWM mode with ICR1 to set TOP TCCR1A |= (1<<COM1A1) | (1<<COM1B1); // clear OC1A and OC1B on compare match TCCR1B |= (1<<CS11) | (1<<CS10); // setting prescalar of 64; see page 110 OCR1A = 400; // starting duty cycle (~1.5ms) for servo 1 OCR1B = 400; // starting duty cycle (~1.5ms) for servo 2 ICR1 = 5000; // TOP value to set 50Hz TIMSK1 |= (1 << TOIE1); // Enable Timer1 overflow interrupt // Servo 1: OC1A (PB1) and Servo 2: OC1B (PB2) controlled by PWM output from Timer 1 DDRB |= (1<<DDB1); // set PB1 as output DDRB |= (1<<DDB2); // set PB2 as output sei(); // enable interrupts while(1) { // superloop // no operation } }


Initial Testing

Initial tests with the prototyping setup and code proved successful in randomising the motion of the laser and achieving two degrees of freedom in its movement. However, I had programmed the motors to operate at their maximum speed and range of motion, meaning the laser dot travelled across the floor and walls at a speed far too fast for my cats to properly chase (although they were thoroughly entertained by the dot shooting across my walls). The rubber bands did not hold well either, making further refinement of the motion difficult. Hence, I decided to refine and develop the programming after completing the 3D printing of the attachment parts.


Next Steps

Other than getting my designed 3D parts printed and iterating upon them to ensure they work for this application, most of my next steps have to do with programming the system to perform different functions and fine-tune the motion:

  1. Field-testing with cats to fine-tune the randomised pathfinding of the laser dot by iterating on two factors: a) the best range of motion for the motors to rotate within in order to ensure full floor coverage without going "out of reach" of my cats (eg. based on furniture and wall placement), and b) the ideal speed at which the motors should rotate at so that my cats can properly chase the laser dot.

  2. Implementing a "manual" mode in hardware through the use of the Arduino's Analog-to-Digital converter and two potentiometers, one for each of the motors, thus allowing user-input to control the motors. The varying voltage signals from the potentiometers can be mapped to the PWM duty cycle values to vary the motor positioning based on a user turning each potentiometer.

  3. Implementing a finite state machine using button ISRs in software to allow a user to transition from "automatic" mode (using the random number generator) to "manual" mode (using the potentiometers) at any given moment. I will also potentially implement different sub-states within the "automatic" mode for different timer lengths (eg. turning on the system for 10 min, 15 min or 20 min and then turning off automatically). "Manual" mode can also be used to help reset and calibrate the system if the dot starts going "out of bounds". At this point, I may also implement the software in C++ in order to create more compact code using object-oriented programming concepts.

  4. Finalising the design to be more compact and hang on my wall, acting as a finished stand-alone product. This will involve designing and 3D printing the holding case (as sketched out in the Hardware Design section) and soldering the final circuit onto a PCB for more secure connections. I will also potentially down-size to a smaller microcontroller such as an ESP32 for the final model, thus opening doors for WiFi implementation and creating a GUI to digitally control the laser.

25 views0 comments

Recent Posts

See All

Commentaires


© 2025 by Sophia Schulz.

bottom of page