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.
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.
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.
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
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
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; }