Dress your dog up for Halloween! This project mods a pair of Doggles brand dog goggles with a swiveling laser diode for targeting all those ghouls and goblins lurking near ground level.

While this is a fairly simple electronics project suitable for intrepid novices, there are a few common sense safety considerations to keep in mind throughout:

  • Any battery-powered circuit is capable of burning your pet, but you can mitigate the risk of injury (but never completely eliminate it).
  • Protect batteries from a scratching paw with adhesive, fabric tape, or both. Mount batteries on the exterior components, never in direct contact with your pet's face. Do not allow lipoly batteries to be abused and remove/discontinue use immediately if your battery is damaged.
  • Adhesives can give off fumes an should be completely dry (sometimes 24 hours or more) before going anywhere near your pet's face, especially its eyes.
  • Never leave your pet unattended while wearing any costume. Observe for signs of discomfort.
  • While positive reinforcement with treats can help some pets aclimate to any costume, other pets may not tolerate wearing your project at all. Be ready to accept this fact, and don't push the issue or abuse your pet!
  • Do not shine lasers directly into anyone's eyes. The laser used in this project is relatively safe but could still cause eye damage if stared at for more than ~30 seconds. 

"Pfft, of course, I've thought of all these things and have a few more safety pointers, Becky!"

"That all makes sense to me and I would never put my pet in danger by forgetting to follow proper safety measures!"

Ok then, I think you're ready to proceed.

This guide was written for the Trinket Mini board, but can also be done with the Trinket M0. We recommend the Trinket M0 as it is easier to use and is more compatible with modern computers!

Tools & Supplies:

After building these, your dog can be Terminator, Robo Cop, or, in my case, Tank Girl's kangaroo boyfriend.

Portaits by Andrew Baker

This diagram uses the original Trinket but you can also use the Trinket M0 with the exact same wiring!

For testing:

Laser red wire and servo red wire to USB+ on Trinket

Laser black wire and servo brown wire to Gnd on Trinket

Servo orange wire to #0 on Trinket

For battery power:

Laser red wire and servo red wire to BAT+ on Trinket

Laser black wire and servo brown wire to Gnd on Trinket

Servo orange wire to #0 on Trinket

It's a good idea to protype your circuit user a solderless breadboard before soldering it up. On Trinket, the positive red wires should go to USB+ for testing over USB power, then moved to BAT+ later for battery power.

Wire up your breadboard or soldered circuit according to the circuit diagram noting the above.

Use black gaffer tape to secure your laser to the flat paddle servo attachment and stick it on the servo gear. Do not screw it on yet, we'll adjust the position after testing the servo rotation.

You may need to solder longer wires on your laser diode for testing purposes.

Prepare the side of your dog goggles by making sure they're clean and dry.

Use hot glue to temporarily mount the servo to the goggles. This is a weak connection that we will use for testing/fitting purposes only, and is to be replaced with a more heavy duty adhesive in a later step.

The Arduino code presented below works well on Trinket Mini boards. But if you have a Trinket M0 board you must use the CircuitPython code on the next page of this guide, no Arduino IDE required!

You will need the Adafruit_SoftServo library to run this sketch.

Plug your Trinket into your computer's USB port, press the reset button and upload the following sketch:

  SoftServo sketch for Adafruit Trinket. Increments values to change position on the servo 
  (0 = zero degrees, full = 180 degrees)
  Required library is the Adafruit_SoftServo library
  available at https://github.com/adafruit/Adafruit_SoftServo
  The standard Arduino IDE servo library will not work with 8 bit
  AVR microcontrollers like Trinket and Gemma due to differences
  in available timer hardware and programming. We simply refresh
  by piggy-backing on the timer0 millis() counter
  Required hardware includes an Adafruit Trinket microcontroller
  a servo motor, and a potentiometer (nominally 1Kohm to 100Kohm
  As written, this is specifically for the Trinket although it should
  be Gemma or other boards (Arduino Uno, etc.) with proper pin mappings
  Trinket:        USB+   Gnd   Pin #0  
  Connection:     Servo+  -    Servo1

#include <Adafruit_SoftServo.h>  // SoftwareServo (works on non PWM pins)

#define SERVO1PIN 0   // Servo control line (orange) on Trinket Pin #0
int moveAmount = 1;  // change this value to change speed of servo
int servoPos = 0;  // variable for servo position

Adafruit_SoftServo myServo1;  //create servo object
void setup() {
  // Set up the interrupt that will refresh the servo for us automagically
  OCR0A = 0xAF;            // any number is OK
  TIMSK |= _BV(OCIE0A);    // Turn on the compare interrupt (below!)
  myServo1.attach(SERVO1PIN);   // Attach the servo to pin 0 on Trinket
  myServo1.write(90);           // Tell servo to go to position per quirk
  delay(15);                    // Wait 15ms for the servo to reach the position

void loop()  {
    myServo1.write(servoPos);                    // tell servo to go to position
  servoPos = servoPos + moveAmount;  // increment servo position (value between 0 and 180) 
  if (servoPos == 0 || servoPos == 180){
    moveAmount = -moveAmount; //reverse incrementer at bounds
  delay(15);                              // waits 15ms for the servo to reach the position

// We'll take advantage of the built in millis() timer that goes off
// to keep track of time, and refresh the servo every 20 milliseconds
// The SIGNAL(TIMER0_COMPA_vect) function is the interrupt that will be
// Called by the microcontroller every 2 milliseconds
volatile uint8_t counter = 0;
  // this gets called every 2 milliseconds
  counter += 2;
  // every 20 milliseconds, refresh the servos!
  if (counter >= 20) {
    counter = 0;

When the variable moveAmount is increased, the motor moves faster and makes more noise. A squeaking motor next to your dog's ear is not nice, so keep it slow and quiet!

Adjust the position of the flat paddle servo attachment on the servo's toothed shaft until you're happy with the alignment.

Without removing the flat paddle from the servo, untape the laser and use one of the included screws to secure the paddle to the servo. Retape the laser to the paddle.

Trinket M0 boards can run CircuitPython — a different approach to programming compared to Arduino sketches. In fact, CircuitPython comes factory pre-loaded on Trinket M0. If you’ve overwritten it with an Arduino sketch, or just want to learn the basics of setting up and using CircuitPython, this is explained in the Adafruit Trinket M0 guide.

These directions are specific to the "M0” boards. The original Trinket Mini with an 8-bit AVR microcontroller doesn’t run CircuitPython…for those boards, use the Arduino sketch on the “Arduino code” page of this guide.

Below is CircuitPython code that works similarly (though not exactly the same) as the Arduino sketch shown on a prior page. To use this, plug the Trinket M0 into USB…it should show up on your computer as a small flash drive…then edit the file “main.py” with your text editor of choice. Select and copy the code below and paste it into that file, entirely replacing its contents (don’t mix it in with lingering bits of old code). When you save the file, the code should start running almost immediately (if not, see notes at the bottom of this page).

If Trinket M0 doesn’t show up as a drive, follow the Trinket M0 guide link above to prepare the board for CircuitPython.

# Laser Dog Goggles
# https://learn.adafruit.com/laser-dog-goggles

import time
import board
import pwmio
from adafruit_motor import servo

# servo pin for the M0 boards:
pwm = pwmio.PWMOut(board.A2, duty_cycle=2 ** 15, frequency=50)
my_servo = servo.Servo(pwm)
speed = .04     # 40ms lower value means faster movement
max_turn = 180  # rotation range 180 degree, half a circle

while True:
    # move stepper max_turn degrees clockwise
    for angle in range(0, max_turn, 1):
        my_servo.angle = angle

    # move stepper max_turn degrees counter clockwise
    for angle in range(max_turn, 0, -1):
        my_servo.angle = angle

This code requires an additional library be installed:

  1. adafruit_motor

If you’ve just reloaded the board with CircuitPython, create the “lib” directory and then download the Adafruit CircuitPython Bundle. You can copy 'adafruit_motor' folder into the lib directory.

$ mkdir /Volumes/CIRCUITPY/lib 
$ cp -pr adafruit_motor /Volumes/CIRCUITPY/lib

Solder up the wires to your trinket according to the circuit diagram, shortening them considerably.

Solder a JST battery connector to the back of your Trinket.

Now when you program the circuit over USB, you'll notice that the motor and laser don't power on. That's because they are wired to the battery power, so any changes in your code will only be visible after you disconnect USB and reconnect a battery.

You can either solder the switch directly to your battery or use a JST extension cable to make a switch adapter to go between the battery and Trinket.

Stick the Trinket to the bottom side of the servo and gaff tape the battery to the outside flat side of the servo. Try your new laser dog goggles on and notice the angle of the assembly and how it affects where the laser points. Make any desired adjustments by removing the motor-laser assembly and re-hot-glueing it on at a different angle.

After you've found your ideal laser angle, use E6000 adhesive to permanently attach the assembly to the side of the dog goggles, tape or prop up in place if necessary, and let dry for at least 24 hours. Remember adhesive give off fumes and shouldn't be placed near your pet's face until completely dry.

This guide was first published on Oct 08, 2014. It was last updated on Oct 08, 2014.