Are you bored? Might as well build a laser turret. You know - one that goes pew pew, shoots a red beam in lots of different directions, and maybe even throw in a smoke machine? Yep, one of them.

What You Will Need

  • Arduino
  • 2 servos
  • Laser module, such as one from this sensor kit [Broken URL Removed]
  • Piezo buzzer or other small output device
  • Metal wire and cable ties for fixing
  • Long female->male jump cables, plus regular jump cables

Optionally, a smoke machine is needed - the laser is pretty low wattage, so you won't be able to see the beam without smoke even in a dark room.

components

Build Plan

The basic idea of the turret is to put the laser module on top of one servo to provide horizontal rotation; then mount that package onto another servo placed at a 90 degree angle to provide vertical movement. We've got a piezo to provide the pew pew sound effects, and I'm throwing in a smoke machine for good measure.

Servo Testing

Depending on your servo, the wires may be coloured differently, but in general:

  • Red is the positive wire, and on both my servos it was the centre of three - to be connected to +5v rail.
  • Brown or black is the negative, to be connected to GND on the Arduino.
  • White or orange is the signal wire, to be connected to a PWM capable digital I/O pin (9 and 10 in the demo below).

Once you've wired up your two servos, upload the following sample code. I've named one servo "hori" to control the horizontal movement, and the other "vert". Each should perform a full range of motion sweep (about 60 degrees, in my case).

        #include <servo.h>
Servo vert,hori; // create servo object to control a servo
                // a maximum of eight servo objects can be created
int pos = 0; // variable to store the servo position
void setup()
{
  hori.attach(9);
  vert.attach(10); // attaches the servo on pin 9,10 to the servo objects
  vert.write(0);
  hori.write(0);
}

void loop()
{
  for(pos = 0; pos < 180; pos += 10) // goes from 0 degrees to 180 degrees
  { // in steps of 10 degrees
    vert.write(pos);
    hori.write(pos); // tell servo to go to position in variable 'pos'
    delay(100); // waits 100ms for the servo to reach the position
  }
  for(pos = 180; pos>=1; pos-=10) // goes back from 180 degrees to 0 degrees
  {
    vert.write(pos); // tell servo to go to position in variable 'pos'
    hori.write(pos);
    delay(100); // waits 100ms for the servo to reach the position
  }
}

All good? Moving on then.

Testing the Laser and Pew Pew Sound

The laser module is just like an LED, but it has a resistor built into the module so we can hook it up directly to a digital I/O - very simple. If you're using the same laser module as me, the "-" goes to GND, the S goes to pin 12. Modify the sample code above to make pin 12 an output:

        int laser = 12;
pinMode(laser,OUTPUT);

Then blink the pin on and off each loop using standard digitalWrite() method.

We'll just use PWM to drive the piezo buzzer at a comfortable sound level - you could experiment with using the tone library if you wanted, but a simple noise is all I need. Connect the black wire to ground and the red wire to pin 11. Define your buzzer on the relevant pin, set to output mode, and activate using analogWrite(buzzer, 100) (or any number you want up to 254); and analogWrite(buzzer,0) to turn off.

The full sample code modified to sweep two servo, activate a laser, and play the annoying sound, can be found here.

All your components should be working - now we need to tie it all together.

Creating the Turret

Using cable ties, attach one servo to the other; it doesn't really matter which, just make sure one will move on the horizontal and the other will move the vertical. You can pull off the rotor blade and re-seat during testing if the angle isn't right.

servos

Use some stiff modelling wire to fix the laser module to the blade of the other servo, like so:

wire-for-laser-module

Finally, I attached the whole thing to a desk leg with yet more cable-ties and a bit of scrap wood.

attach-turret-to-table

Programming the Turret

I don't know about you, but my idea of a laser turret comes from countless numbers of sci-fi films and star trek episodes. Invariably someone will fly past a turret and little pew-pew shots will come flying out in a sweeping pattern, always milliseconds too slow so our protagonist doesn't actually get hit. That's what I'm trying to replicate, though feel free to tweak the main routine to suit your idea of what a turret should do.

Here's the pseudo code I ended up using for the main loop:

  • Randomize time between bursts, and time between each individual shot.
  • Randomize the start and end position for each servo, vert and hori.
  • Randomize the number of shots to take.
  • Work out the number of degrees of change after each shot as the difference between start and end positions divided by number of shots.
  • Move the servos to the starting positions, and wait a little for them to get there (100ms)
  • Loop until all shots have been taken, each time moving the servos a little as previously calculated; move and shoot, move and shoot.
  • Repeat.

I also added a separate fire() method to structure the code a little better. Adjust the ranges of all random() functions to speed up or slow down each parameter; or increase the number of shots for a more dance club vibe. Scroll down for a video of the code in action!

        #include <servo.h>

Servo vert,hori; // create servo object to control a servo

int pos = 0; // variable to store the servo position
int laser = 12;
int buzzer = 11;

void setup()
{
     hori.attach(9);
     vert.attach(10); // attaches the servo on pin 9 to the servo object
     pinMode(laser,OUTPUT);
     pinMode(buzzer,OUTPUT);
}

void loop()
{
     int timeBetweenBursts = random(200,1000);
     int timeBetweenShots = random(50,200);
     int vertStart = random(1,180);
     int vertEnd = random(1,180);
     int horiStart = random(1,180);
     int horiEnd = random(1,180);
     int numShots = random(5,20);

     int vertChange = (vertEnd - vertStart) / numShots; //how much to move vertical axis by each shot
     int horiChange = (horiEnd - horiStart) / numShots;

     vert.write(vertStart);//let it get to start position first, wait a little
     hori.write(horiStart);
     delay(100);

     for(int shot = 0; shot<numShots; shot++){
          vert.write(vertStart);
          hori.write(horiStart);

          vertStart += vertChange;//increment the vert value for next time
          horiStart += horiChange;

          fire();
          delay(timeBetweenShots); //add a bit of variety to the speed of shots
     }
     delay(timeBetweenBursts);
}

void fire(){
     digitalWrite(laser,HIGH);
     analogWrite(buzzer,100);
     delay(20);//adjust this to change length of turret shot
     digitalWrite(laser,LOW);
     analogWrite(buzzer, 0);
}

In Action

http://www.youtube.com/watch?v=LmpqJ961qtM

I don't think there's a practical use for this little toy, but it's an awful lot of fun and there are a lot of variables you can tweak to get the desired effect. Perhaps it'll come in handy for a homemade LEGO movie?