This is a schoolproject with arduino, this was my first time

working with an Arduino. As a teenager I was always fascinated by military simulation games and airsoft. So when the oppurtunity came to build something awesome with Arduino, I decided to make my own laser gun something easier said than done.

This tutorial is made for intermediate Arduino project creators.

Step 1: Requirments


· A plastic toy gun (bigger the better, it will be easier to wire it and fit it all in)

· 2 Vibration Motors (can be found in an old game controller or 2 old cellphones)

· 2x Button

· 3x Led

· 4x 220Ω resistor

· 3x 10kΩ resistor

· IR receiver TSOP 48 series (needs to be compatible with IR-led)

· Laser (optional)

· IR Led (940nm), blue ones have the ability to be checked (debugged)

· Piezo Buzzer

· Potentiometer

· Masking tape, and any paint you prefer. (primer optional)

Step 2: Testing Hardware

Put all the hardware in the breadboard and test all your hardware.

The code will also clarify which pins correspond to your hardware.

Step 3: Planning and Projecting

Take your gun and draw in the inside where your hardware parts are going to be, make sure there is enough room. Keep in mind that you need to close the gun, and calculate the other side of the gun in your concept.

Step 4: Adjusting Frame

Adjust the frame if needed, this includes drilling holes

Step 5: ​Make Sure It Fits

Fit in all your hardware parts but don’t solder them, if everything fits remove your hardware to go to the next step.

Step 6: Preparing to Paint

Take your plastic toy gun and sand it on places with 400 grit sandpaper on places where the plastic is smooth. This will help the primer stick better to the plastic, don’t use any lower grit sand paper unless you are going for a scratched look.

Step 7: Primer Time!

Go outside or use a ventilated room to spray your primer

on the plastic parts of your gun, keep in mind to spray 25-30 cm away from your gun and spray in short bursts.

If a part doesn’t take the primer well enough, let it dry and add another layer when it is dry.

Step 8: Waiting

Wait min 3 hours, to let the primer dry.

Step 9: Multiple Colors ?

YAAY the primer dried, take a roll of masking tape and mask the parts you want to color a different color. Use your fingernails or a pencil to get the tape into the cavities (lines) of your gun.
Cut away excess masking tape with a sharp knife or scalper.

if not spray it with the color you like, same techniques apply as the primer.

Step 10: Constructing

For construction there is not a definite way you do

this, because it depends on your gun

Big Gun:

Take your painted gun and solder your parts on your solderboard, try to create different islands of solderboard which are going to the same location in your gun. Connect the boards grounds together, do the same with your 5 Volts. Make a connection from your ground to the Arduino likewise with the 5 volts. (we do this because we only have 1 5v port and 3 ground ports.

Tips for Small Gun:

Because your gun is small, it will be harder to use a solderboard you will probably connect wires direct to each other. In this case you will need isolation tape or shrinking plastic covers for your exposed wire to prevent short circuiting your laser gun.

IR receiver:

Mount your ir-receiver on a visible position for your enemy, do NOT put your IR receiver inside a barrel or tube.


The code of this gun has a mode where you can turn off the laser, this is because lasers can seriously harm your eyes, if playing in this mode ALWAYS PLAY WITH GLASSES.

Step 11: Lesson IR

So how does IR work?

Well IR is a electromagnetic radiation, like light in led but then with a longer wavelength. The wavelength is so high that we humans can’t see it.

we use this (ir-led) to sign to a receiver which can only read IR light, we flash our ir-light according to a set of rules.

In this example:

We tell our receiver after 16 pulses, that it needs to check for a start signal from the ir-led after a minimum of 4.5 Ms. When it detects the amount of pulses needed to start it will read your code in 0 and 1, you can do here what ever you want to share with your receiver according to your read function. After you shared your info you can close your reading with in this example a 562.5µs wavelength pulse.

The code we use is more simplified and only uses 3 bits which allows us to play with max 6 players (3 digits *2 possibilities 0 or 1) , the reason we did this is to minimize the amount of time your IR-led is pulsing, which means smoother gameplay

Instead of using an end pulse we have a timer which tells when it should stop reading and resets the receiver.

But ehh if we can’t see ir-light, how can I check if my ir-led is working.

Well if you have blue colored ir-led you can see the ir led trough your camera of your mobile phone.

Step 12: The Code.

All right enough technical explanations.
Here comes the code: feel free to add your own tones and vibrate functions, in the upper part. There are already voids made for error sound and shoot sound where you can experiment in.

And enjoy your Lasergames

// Infrared protocol communication part written by Tim Peeters,
// Laser game Luger Sharp, this code is meant to get the laser gun up and running, it features alot of aditional hardware, only the buttons and ir-led and receiver are critical.\ // Made by Hicham Ouchan

//Game Setup variables.

int maxPlayers = 10; //max players in game.

int playerID = 2; //player number of this instance.

bool useSound = true;


int triggerButton = 9; // in

int reloadButton = 8; // in

int sendPin = 12; // in

int magazineLed = 6; // not

int LifePin = 4; // not

int buzzer = 11; // in

int receiverPin = 2; // nog niet

int LowVibratePin = 5; // in

int HighVibratePin = 7; //

int SwitchPin = A0;

int LaserDot = 13;

int serviceLight =3;

//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

int ret[2];

//Variables Settings

int ammoCap = 12;

int maxLives = 3;


int ammo = 12;

int lives = 3;

bool fireEnabled = true;

bool soundEnabled = true;

void setup() {


pinMode(magazineLed, OUTPUT);

pinMode(LifePin, OUTPUT);

pinMode(buzzer, OUTPUT);

pinMode(receiverPin, INPUT);

pinMode(triggerButton, INPUT);

pinMode(reloadButton, INPUT);

pinMode(sendPin, OUTPUT);

pinMode(LowVibratePin, OUTPUT);

pinMode(HighVibratePin, OUTPUT);

pinMode(SwitchPin, INPUT);

pinMode(LaserDot, OUTPUT);



void loop() {




if (ret[0] != -1) {

Serial.print("Player: ");


Serial.print(" Message: ");




void triggerCheck() { // check if a trigger is activated

int triggerStatus = digitalRead(triggerButton);

int ReloadStatus = digitalRead(reloadButton);

/// tone(buzzer, 500); // Send 1KHz sound signal...

if (triggerStatus == 1) {



if (ReloadStatus == 1) {




void Fire() { // enable firing a pulse and vibrate function, this function is to have a nice overview on what happens when you fire

if (ammo != 0 and fireEnabled == true) {

encodeIRpulse(playerID, 1);

ammo -= 1;

Vibrate(HighVibratePin, 300);

HitSound(50, 200);

char snum[2];

Serial.println( itoa(ammo, snum, 10));



else {

if (ammo = 0){

Serial.println("Out of Ammo");

for (int i = 0; i < 5; i++) {

digitalWrite(magazineLed, HIGH);



digitalWrite(magazineLed, LOW);




Serial.println("Gun is locked");




void Reload() { // reload function

if (ammo < ammoCap) {

for (int i = 0; i < 10; i++) {

int flashtime = 200 / (i + 1);


digitalWrite(magazineLed, HIGH);

Vibrate(LowVibratePin, 200);

tone(buzzer, 80);



digitalWrite(magazineLed, LOW);



Vibrate(LowVibratePin, 1500);


ammo = ammoCap;


else {

Serial.println("Magazine is already full");




void HitSound(int low, int high) { // hitsound says it in the title plays a random sound when shooting

unsigned long time = millis();

while (millis() - time <= 500) {

tone(buzzer, random(low, high));



tone(buzzer, 50);





void Vibrate(int vibrateModule, int delayTime) { // a function to make the vibrating motors operate easier

digitalWrite(vibrateModule, HIGH);


digitalWrite(vibrateModule, LOW);


void WeaponSwitch() { // a switch to control different modes on the gun, normal, with laser and lock

int potentionVal = map((analogRead(SwitchPin)), 0, 1023, 0, 360);

//MM Serial.println(potentionVal);

fireEnabled = true;

soundEnabled = true;

digitalWrite(serviceLight, LOW);

if (potentionVal > 140 and potentionVal < 210) {

digitalWrite(LaserDot, HIGH);


if (potentionVal < 140 and potentionVal >= 0) {

digitalWrite(LaserDot, LOW);


if (potentionVal > 230 and potentionVal < 310) {

soundEnabled = false;

return soundEnabled;


if (potentionVal > 340 and potentionVal <= 360) {

fireEnabled = false;

digitalWrite(serviceLight, HIGH);

digitalWrite(LaserDot, LOW);

return fireEnabled;


return fireEnabled;


void ErrorSound() { // the error sound gets created here

tone(buzzer, 15);


tone(buzzer, 30);


tone(buzzer, 40);




// IR PROTOCOL STARTS HERE, don’t touch this if you are not comfortable with programming

//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;

if (pulseIn(receiverPin, LOW, 10000) < startBit) {

digitalWrite(LifePin, LOW);

//Serial.println(pulseIn(receiverPin, LOW));

ret[0] = -1;



digitalWrite(LifePin, HIGH);

//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);

//message bits

//message[0] = pulseIn(receiverPin, LOW);

//message[1] = pulseIn(receiverPin, LOW);

//message[2] = pulseIn(receiverPin, LOW);

//message[3] = pulseIn(receiverPin, LOW);

endPulse = pulseIn(receiverPin, LOW);


for (int i = 0; i <= 3; i++) {




//sender bit (player ID) decoding

for (int i = 0; i <= 3; i++) {


if (sender[i] > one && sender[i] < startBit) {

sender[i] = 1;


else if (sender[i] > zero && sender[i]) {

sender[i] = 0;




//When the data is not a one or a zero, it is an unknown signal.

ret[0] = -1;




ret[0] = convert(sender);



//message bit decoding

for(int i=0;i<=3;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;









void encodeIRpulse(int player, int message) {

int encoded[4];

for (int i = 0; i < 4; i++) {

encoded[i] = player >> i & B1; //encode data as '1' or '0'



for (int i=4; i<8; i++) {

encoded[i] = player>>i & B1;



//Start of data stream.

dataPulse(sendPin, startBit);

digitalWrite(sendPin, HIGH);


//Sending of data.

for (int i = 3; i >= 0; i--) {

if (encoded[i] == 0) {

dataPulse(sendPin, zero);

} else {

dataPulse(sendPin, one);


digitalWrite(sendPin, HIGH);



//End of data stream.

dataPulse(sendPin, endBit);

digitalWrite(LifePin, LOW);


void dataPulse(int pin, int pulseTime) {

for (int i = 0; i <= pulseTime / 26; i++) {

digitalWrite(pin, HIGH);


digitalWrite(pin, LOW);




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;