Arduino Lasertag Project

134

3

1

Hello there! Today I'll be explaining how I made a Arduino lasertag gun for a project at the HKU School of Arts at Utrecht, The Netherlands.

Step 1: Get Yourself an Arduino and Some Infrared Leds and Sensors (plus Some More Stuff).

Step 1.

I started this project by buying some Infrared LED's and and Infrared Sensor that function at 33khz (you can use 38khz aswell). Most lasertag guns use infrared to send data, as it is much more reliable to send data with. With infrared you won't have any interference from other lightsources such as the sun.

For this project I used:

  • a Piezo buzzer.
  • a simple button component..
  • a 128x64 adafruit lcd screen.
  • a red led light for visual feedback.
  • a laser diode module (laserpointer).
  • a infrared led (33khz).
  • a infrared receiver (33khz).
  • some transistors and gauge wires.
  • a soldering iron and some lead.
  • sticky tape.
  • a glue gun.
  • a Arduino Uno and a Usb B cable.

The first thing I did was to make a basic setup for my lightgun (see pictures).

Step 2: Use This Code for the Gun.

After I setup my electronics on a breadboard I used this code to get it to work (make sure you have 2 arduino's to test the device).

The code:

<p>/* IR Lightgun Arduino code by Tim Peeters 2018-19<br> *  
 * Made with the 'Building an Arduino-based laser game tutorial'
 * by Duane O'Brien at https://www.ibm.com/developerworks/opensource/tutorials/os-arduino1/
 * 
 * V3.0 
 */
 
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h></p><p>// OLED display TWI address
#define OLED_ADDR   0x3C</p><p>// reset pin not used on 4-pin OLED module
Adafruit_SSD1306 display(-1);  // -1 = no reset pin</p><p>//Game Setup variables.
int maxPlayers = 10; //max players in game.
const int playerID = 1; //player number of this instance. (MUST BE BETWEEN 1 and 10!)
bool useSound = true;</p><p>int maxLives = 3;
int currentLives;</p><p>//Gun variables-------------|
bool isShooting = false;
int shotDelayTime = 100;</p><p>//Bullet Count
int currentBullets = 0;
int maxBullets = 100;</p><p>//Hardware variables
const int buttonPin = 6;
const int ledPin = 9;</p><p>const int speakerPin = 8;
const int laserPin = 2;
const int lcdClockPin = A5;
const int lcdSerialPin = A4;</p><p>const int sendPin = 3;
const int receiverPin = 5;</p><p>//The following variables declare the pulse lengths of the IR Code being send.
const int startBit   = 2000;   // This pulse sets the threshold for a transmission start bit
const int endBit     = 3000;   // This pulse sets the threshold for an end bit
const int one        = 1000;   // This pulse sets the threshold for a transmission that 
                               // represents a 1
const int zero       = 400;    // This pulse sets the threshold for a transmission that 
                               // represents a 0
                               
const int waitTime = 300;      // The amount of time to wait between pulses</p><p>//The following array holds the decoded IR data.
int ret[2];</p><p>bool hasDied = false;</p><p>void setup() {
  
  //Input Sensors
  pinMode(buttonPin, INPUT);</p><p>  //Output Sensors
  pinMode(ledPin, OUTPUT);
  pinMode(speakerPin, OUTPUT);
  pinMode(laserPin, OUTPUT);</p><p>  pinMode(lcdClockPin, OUTPUT);
  pinMode(lcdSerialPin, OUTPUT);
  
  //IR Sensors
  pinMode(sendPin, OUTPUT);
  pinMode(receiverPin, INPUT);
  
  //Serial Debug (for feedback)
  Serial.begin(9600);</p><p>  
  //Startup Sound
  for (int i = 1;i < 4;i++) {
    digitalWrite(ledPin, HIGH);
    playTone(1000/i, 100);
    digitalWrite(ledPin, LOW);
  }
  
  Serial.println("Gun Setup");
  
  //Game Setup
  currentLives = maxLives;
  currentBullets = maxBullets;
  Serial.println(currentBullets);</p><p>  display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
  display.clearDisplay();
  display.display();</p><p>  display.setTextSize(1);
  display.setTextColor(WHITE);  
  display.setCursor(10,10);
  display.print("Player: " + String(playerID));
  display.setCursor(10,40);
  display.print("Lives: " + String(currentLives) + " / " + String(maxLives));
  display.setCursor(10,55);
  display.print("Bullets: " + String(currentBullets) + " / " + String(maxBullets));
  display.display();</p><p>  digitalWrite(laserPin, HIGH);
}</p><p>void loop() {</p><p>  if(hasDied == false){
    SenseIR();
    Trigger();
  }</p><p>  if(ret[0] != -1 && ret[0] != 0){
    playTone(1000, 50);
    Serial.print("Player: ");
    Serial.print(ret[0]);
    Serial.print(" Message: ");
    Serial.println(ret[1]);</p><p>    DoDamage();
  }</p><p>  
  if(ret[0] == -1){
    //Serial.println("ERROR: Unknown Signal");
    //playTone(3000, 300);
  }
}</p><p>void DoDamage(){
  if(ret[0] != playerID|| ret[0] != -1){
    if(currentLives > 1){
      currentLives--;</p><p>      digitalWrite(ledPin, HIGH);
      delay(100);
      digitalWrite(ledPin, LOW);
      
      for(int i = 0; i < 4; i++){
        playTone(10000 - i*100, 100/i);
      }  </p><p>      display.clearDisplay();
    
      display.setTextSize(1);
      display.setTextColor(WHITE);  
      display.setCursor(10,10);
      display.print("Player: " + String(playerID));
      display.setCursor(10,40);
      display.print("Lives: " + String(currentLives) + " / " + String(maxLives));
      display.setCursor(10,55);
      display.print("Bullets: " + String(currentBullets) + " / " + String(maxBullets));
      display.display();
    }
    else{
      GameOver();
      hasDied = true;
    }
  }
}</p><p>void GameOver(){
  if(hasDied == false){
      display.clearDisplay();
    
      display.setTextSize(2);
      display.setTextColor(WHITE);  
      display.setCursor(10,20);
      display.print("GAME OVER");
      display.display();</p><p>      digitalWrite(ledPin, HIGH);
      digitalWrite(laserPin, LOW);
      playTone(10000, 2500);
  }
}</p><p>void Trigger(){
  int buttonState = digitalRead(buttonPin);
  
  if(buttonState == 1 && isShooting == false){
    isShooting = true;
    
    if(currentBullets > 0){
      fireShot();
      Serial.println(currentBullets);
      
    }
    else{
      Serial.println("Out of bullets.");
    }
  }
  if(buttonState == LOW){
    isShooting = false;
  }
}</p><p>void fireShot(){
    currentBullets--;
    
    
    
    //Send IR data
    encodeIRpulse(playerID, 1);</p><p>    
    //enable the laser and led.
    digitalWrite(ledPin, HIGH);
    digitalWrite(laserPin, LOW);
    delay(200);
    digitalWrite(ledPin, LOW);
    digitalWrite(laserPin, HIGH);</p><p>    //Shooting sound
    playTone(4500, 300);
    playTone(4000, 200);
    
    //Update LCD Display
    display.clearDisplay();
    
    display.setTextSize(1);
    display.setTextColor(WHITE);  
    display.setCursor(10,10);
    display.print("Player: " + String(playerID));
    display.setCursor(10,40);
    display.print("Lives: " + String(currentLives) + " / " + String(maxLives));
    display.setCursor(10,55);
    display.print("Bullets: " + String(currentBullets) + " / " + String(maxBullets));
    display.display();</p><p>    
}</p><p>//The function for playing a single tone with a certain duration.
void playTone(int tone, int duration) {
  if(useSound == true){
  for (long i = 0; i < duration * 1000L; i += tone * 2) {
    digitalWrite(speakerPin, HIGH);
    delayMicroseconds(tone);
    digitalWrite(speakerPin, LOW);
    delayMicroseconds(tone);
  }
 }
}</p><p>//IR Led receiver function.
void SenseIR(){
  
  //We will be sending a 8bit signal with IR, the first 4 bits define the sender of the signal. 
  //The other 4 bits define the message of the signal.
  int sender[4];
  //int message[4];
  int endPulse;</p><p>  
  if (pulseIn(receiverPin, LOW, 10000) < startBit) {
    ret[0] = -1;
    return;
  }</p><p>  //Assignment of pulses to bit array------||
  
  //sender bits
  sender[0]   = pulseIn(receiverPin, LOW);
  sender[1]   = pulseIn(receiverPin, LOW);
  sender[2]   = pulseIn(receiverPin, LOW);
  sender[3]   = pulseIn(receiverPin, LOW);</p><p>  //message bits
  //message[0]  = pulseIn(receiverPin, LOW);
  //message[1]  = pulseIn(receiverPin, LOW);
  //message[2]  = pulseIn(receiverPin, LOW);
  //message[3]  = pulseIn(receiverPin, LOW);</p><p>  endPulse = pulseIn(receiverPin, LOW);
  //---------------------------------------||</p><p>  
  for(int i = 0; i <= 3; i++){
    Serial.println(sender[i]);
    //Serial.println(message[i]);
  }
  </p><p>  //sender bit (player ID) decoding
  for(int i = 0; i <= 3; i++){
    //Serial.println(sender[i]);
    if(sender[i] > one && sender[i] < startBit) {
      sender[i] = 1;
    } 
    else if (sender[i] > zero && sender[i]) {
      sender[i] = 0;
    } 
    else 
    {
      //When the data is not a one or a zero, it is an unknown signal.
      ret[0] = -1;
      return;
    }
  }</p><p>  ret[0]=convert(sender);
  //Serial.println(ret[0]);</p><p>  /*
  //message bit decoding
  for(int i=0;i<=3;i++) {
    //Serial.println(message[i]);
    if(message[i] > one) {
      message[i] = 1;
    } else if (message[i] > zero) {
      message[i] = 0;
    } else {
      // Since the data is neither zero or one, we have an error
      Serial.println("unknown action");
      ret[0] = -1;
      return;
    }
  }
  ret[1]=convert(message);
  //Serial.println(ret[1]);
  */
  
  return;
  </p><p>}</p><p>void encodeIRpulse(int player, int message){
  int encoded[4];</p><p>  for (int i=0; i<4; i++) {
    encoded[i] = player>>i & B1;   //encode data as '1' or '0'
    
  }</p><p>  /*
  for (int i=4; i<8; i++) {
    encoded[i] = player>>i & B1;
  }
  */
  
  //Start of data stream.
  dataPulse(sendPin, startBit);
  digitalWrite(sendPin, HIGH);
  delayMicroseconds(waitTime);
   
  //Sending of data.
  for (int i=3; i>=0; i--) {
    if (encoded[i] == 0) {
     dataPulse(sendPin, zero);
    } else {
     dataPulse(sendPin, one);
    }
    
    digitalWrite(sendPin, HIGH);
    delayMicroseconds(waitTime);
  } </p><p>  //End of data stream.
  dataPulse(sendPin, endBit);
}</p><p>void dataPulse(int pin, int pulseTime){
  for(int i = 0; i <= pulseTime/26; i++) {
    digitalWrite(pin, HIGH);
    delayMicroseconds(13);
    digitalWrite(pin, LOW);
    delayMicroseconds(13);
  }
}</p><p>int convert(int bits[]) {
  int result = 0;
  int seed   = 1;
  for(int i=3;i>=0;i--) {
    if(bits[i] == 1) {
      result += seed;
    }
    seed = seed * 2;
  }
  
  return result;
}</p>

Step 3: Take That Dusty Old Nerf Gun Out of Your Drawer (or Buy One).

After I got my software and hardware to work I used old Nerf gun I had lying around to function as the housing of the Arduino and it's hardware.

Step 4: Modify the Nerf Gun.

After I dusted of the gun, I took it apart and had a look inside. I planned out where the different parts of the gun would come and where I would place the Arduino Uno.

I took out all the lose parts and the old firing mechanism and painted the gun. After this I made some modifications on the inside so I could fit the arduino inside the old magazine chamber of the gun.

Step 5: Solder Your Components and Glue Them Into the Gun.

After I modified and painted the gun it was time for me to solder all my components to seperate breadboards. Shortly after that, I glued them into the gun and I was ready to go test it!

Step 6: Tadaa!

Eventually the lasertag gun turned out like this. You can shoot, receive and decode IR messages with the code. Whilst everything is connected in a neatly modified nerf gun. Just connect the powerbank to the arduino and you are ready to go :)

Share

    Recommendations

    • Build a Tool Contest

      Build a Tool Contest
    • Faux-Real Contest

      Faux-Real Contest
    • Warm and Fuzzy Contest

      Warm and Fuzzy Contest

    Discussions

    1
    None

    This awesome! With the Arduino you can make all kinds of interactive systems to go along with the game.