Laser Tag - University of Oxford CWM 2015


This project was completed by a group of 8 second year engineering students during a one-week long Course Work Module.

Armour

Introduction

This module functions as the wearable armour target. There are three main components to the armour module. One board houses the microcontroller which is the heart of the system. This board is mounted on the right shoulder of the vest. The second component is the IR target which is mounted on the chest of the vest. The third major component is the wireless communications module.

Components

  • FRDM - KL25Z mbed board
  • nRF24L01 wireless communication module
  • tsmp1138 IR receiver module
  • 3 white LEDs
  • solid core wires
  • standard core wires
  • 410 kOhm resistor
  • 3.3 nF capacitor

Functionality

The IR Module

The IR module is designed to both record shots that hit the player and to provide indication of the state of the player to other players. This board contains three white LEDs which indicate the state of the player. If the player is 'alive' the LEDs are on. The LEDs turned off indicate a 'dead' player. The board has 5 connections between it and the microcontroller. Black and red wires are for the power lines, representing ground and high respectively. The orange and yellow wires are for controlling the LEDs. These are connected to Digital Outputs from the board. The orange wire controls the toggling of the LEDs while the yellow wire provides a virtual ground. The green wire is for the Serial connection between the IR receiver and the microcontroller.

/media/uploads/Huqi/20150612_105034.jpg

The Wireless Communication

The wireless communication module both receives and sends data from/to the scoreboard. It receives game state commands such as start, pause, continue, and end. It sends back to the scoreboard data about the game such as hits that this armour has received and from which player and the shots fired by the connected gun. Again, the black and red are power lines, while the remaining wires (blue, yellow, green. white, pink, brown) are for transferring data.

/media/uploads/Huqi/20150612_105118.jpg

The Microcontroller Board

This board contains all the logic for the armour. It contains a method to check for hits to the armour and to decode which player had hit it. It also contains all of the logic for decoding signals from the scoreboard and for sending data back. It also communicates with the gun via Serial connection to send game states or requests for data.

/media/uploads/Huqi/img_20150612_140658123_hdr-2.jpg

Tips for Assembly

Wireless Communications

  • Look at the pins name for the nRF24L01P as listed below
  • Connect the pins as follows: mosi - PTD2 , miso - PTD3, sclk - PTD1, csn - PTA13, ce - PTD0
  • Connect V to the 3v3 pin and GND as normal

http://3.bp.blogspot.com/-BAvB_8SHs9Y/UrbqD5cCNQI/AAAAAAAAFLw/vuSLb10qCHg/s1600/riyas_RF_2.4G_RFM.jpg

IR Receiver Circuit

  • Look at pin diagram listed below
  • Connect the pins as listed: Pin 1 - GND, Pin 2 - Output, Pin 3 - 3v3
  • Make sure to put a 3.3 nF capacitor between the output and ground to smooth the output
  • For the wirless LEDs, you can connect them in parallel between your Digital Out powerlines. You will need a 410 kOhm resistor in series to reduce current drawn

http://www.vishay.com/images/product-images/pt-medium/82484-pt-medium.jpg

Code

Armour Program for the Board

/* Armour Program 

Authors: Jamieson Brynes and Qi Hu

This program is designed for use with the gun and scoreboard program from the Laser Tag - University of Oxford CWM 2015 project.

A few notes: 

For sending data to the gun
'a' ==> Enable gun
'z' ==> Send back bullet count data
'B' ==> Disable gun

For data received from the IR
'a' ==> Player 1
'z' ==> Player 2
'B' ==> Player 3
52 ==> Static target ( does not contribute to score)

*/

#include "mbed.h"
#include "comm.h"

DigitalOut myled(LED1);
Serial RX(NC,PTE1);              //Set up serial for IR sensor
DigitalOut LEDHigh(PTE30);       //Pin for LED high value
DigitalOut LEDLow(PTE29);        //Pin for LED low value
Serial gun(PTE22,PTE23);         //Serial communication between the armour and the gun
Serial pc(USBTX, USBRX);         //Pc serial for debugging
DigitalOut gunEnableFlag(PTE21); //Flag for gunEnable

//Initialize functions
void checkHit();
void checkScoreboard();
void gameStart();
void gameEnd();
void gamePause();
void gameContinue();
void powerDown();
void sendGunInfo(char code);
void powerUp();

//Initialize communication buffers
char* rxBuffer = new char[4];
char* txBuffer = new char[4];


char gameOn;            //Initialize boolean for game state

Timer t;


int main()
{
    
    //Initialize txBuffer
    for (int i = 0; i < 4; i++) {
        txBuffer[i] = 0;
    }

    RX.baud(1000);          //Set baud rate for the receiver

    //Set default values for the LEDs and game state
    LEDLow = 0;
    LEDHigh = 0;
    gameOn = 0;

    
    commInit(1);             //Initialize communications

while(true)
{


    while(gameOn) {
       
        //Game loop
        checkHit();
        checkScoreboard();
    }

    while(!gameOn) {
        
        //Loop to run when game is off
        checkScoreboard();
        if(t.read() >  5)
        {
            powerUp();
            t.stop();
            t.reset();
        }
    }
    
    }

}

void checkHit()
{
    char identifier = 0;


    //Logic to see if we have been hit
    if(RX.readable()) {
        //Read until we find a value we recognize
        while(identifier != 'a' && identifier != 'z' && identifier != 'B' && identifier != 52) {
            identifier = RX.getc();
        }
    }

    if(identifier != 0) {
        //Store data

        if(identifier == 'a') {
            txBuffer[0]++;
        }
        if(identifier == 'z') {
            txBuffer[1]++;
        }
        if(identifier == 'B') {
            txBuffer[2]++;
        }


        powerDown();


    }
    

    //If not hit, continue as normal


}

void checkScoreboard()
{
// comm check, needs to be done regularly
    if(commRead(rxBuffer)) {

        //Get gun shots and load it in
        /*sendGunInfo('z');
        wait(0.5);
        if(gun.readable())
        {
            char shots;
            shots = gun.getc();
            txBuffer[3] += shots;
            
            while(gun.readable())
            {
                char trash;
                trash = gun.getc();
            }
        }
        */
        commSetAck(txBuffer);
        pc.printf("Refreshing acknowledge buffer \n\r");
        switch(rxBuffer[0]) 
        {
            case 0: //code to be executed on start signal
                pc.printf("Starting\n\r");
                gameStart();
                //wait(2);

                break;
            case 1: // code to be executed on a get hits request
                 pc.printf("Received get request.\n\r");   
                txBuffer[3] = 0;
                
                break;
            case 2: // code to be executed on end signal 
                pc.printf("Ending game");
                gameEnd();

                break;
            case 3: // code to be executed on pause signal 

                gamePause();

                break;
            case 4: // code to be executed on resume signal 

                gameContinue();

                break;
            default:
                commSetAck(txBuffer);
                
                break;

        }
    }

}

void powerDown()
{

    sendGunInfo('B');
    LEDHigh = 0;
    gameOn = 0;
    
    //Time delay for the armour to be down
    t.start();

}

void powerUp()
{
    //Switch LEDs on
    LEDHigh = 1;
    //Enable gun
    sendGunInfo('a');
    
    gameOn = 1;
 
    

    while(RX.readable()) 
    {
        //Loop to wipe buffer of the receiver
        //Need to ignore any shots received during the power down phase
        char trash;
        trash = RX.getc();
    }
}

void gameStart()
{
    pc.printf("Starting game\n\r");
    //Enable gun
    sendGunInfo('a');

    //Switch LEDs on
    LEDHigh = 1;
    
    //Enable game loop
    gameOn = 1;
    
    //Reset scoring buffer
    for (int i = 0; i < 4; i++) {
        txBuffer[i] = 0;
    }
    
    pc.printf("Ending start game routine\n\r");
    
    

}


void gameEnd()
{
    //Set flag and send data to gun
    gameOn = 0;
    sendGunInfo('B');

    //Turn off LED
    LEDHigh = 0;
    
    while(RX.readable()) 
    {
        //Loop to wipe buffer of the receiver
        //Need to ignore any shots received during the power down phase
        char trash;
        trash = RX.getc();
    }
}

void gamePause()
{
    //Set flag and send data to gun
    gameOn = 0;
    sendGunInfo('B');
    t.stop();


}

void gameContinue()
{
    //Set flag and send data to gun
    gameOn = 1;
    sendGunInfo('a');
    
    while(RX.readable()) 
    {
        //Loop to wipe buffer of the receiver
        //Need to ignore any shots received during the power down phase
        char trash;
        trash = RX.getc();
    }
    
    if(t.read() > 0)
    {
        t.start();
    }

}

void sendGunInfo(char code)
{
    //Send flag to gun and push a code to them
    gunEnableFlag = 1;
    gun.putc(code);
    gunEnableFlag = 0;
}

All wikipages