Airsoft Prop - Can it be done? Advice please

Hi all,

I am a absolute noob to arduino programming and although I have read through verious topics on the type of project I am trying to achieve it is all over my head. The one thing I have noticed however is everyone seems to go for the same setup of a 16x2 led display with a 4x4 matrix keyboard for this type of project. Maybe there is a limitation that only allows this.

Allow me to explain what I am trying to achieve.
I run an Airsoft Combat Game site and one of the services we offer is a combat experience that we regularly get memebers of the armed forces attending. I want to step up the types of things we offer and thought a excellent idea would be a prop bomb.

We would like the prop to operate like so but need to know is it achievable? your help is much apprieciated. If any one would like the challenge of coding it for us we would be more than happy :smiley:

Airsoft Bomb Project V1.0 - 07/10/2013

COMPONENTS

  • 8.4V 1500mah battery - power supply
    4x4 Matrix Keypad for activation/deactivation codes
    Key switch to turn on/off power
    16x2 LED display screen - display activation messages/time remaining and setup instructions
    RFID activation switch - RFID card needs to be swiped to start countdown and RFID needs to be swiped before deactivation code can be entered
    Relay to RF transmitter - sends signal when timer runs out
    green led (steady) to signal bomb safe
    amber led (steady) to signal bomb awaiting rfid activation (armed)
    red led (flashing) to signal bomb is in countdown
    red led (steady) to signal bomb is ready to start countdown
    speaker 1 - chirps on button press, chirps on every minute, chirps every second within remaining 60 seconds, chirps three times per second in last ten seconds
    Speaker 2 - if possible to play robotic voice instructions

ACTIVATION SEQUENCE

  1. Key is turned to on position turning device on
    1.1 - Green LED illuminates
    1.2 - Speaker 2 Voice plays "Please swipe ID card"
    1.3 - screen displays same message "Please swipe ID card"

  2. RFID card is swiped
    2.1 - Green LED stays Illuminated
    2.2 - Speaker 1 chirps to confirm swipe
    2.3 - Voice plays "Welcome Commander, Please enter activation code"
    2.4 - Screen displays message "Welcome Commander, enter code"

  3. 4 Digit activation code is entered on 4x4 matrix keyboard confirmed with pound key.
    3.1 LED screen displays code entered when first key pressed
    3.2 Speaker 1 chirps on each key stroke after 4 keystokes go to 3.3
    3.3 Message diplayed "hit # to confirm code 1234"
    3.4 Voice Plays "Hit # to confirm code"

  4. pressed to confirm code entry

4.1 Speaker chirps twice to confirm
4.2 Message displays "Code Confirmed"
4.3 Voice plays "Code Confirmed"
4.4 Green Led goes out
4.5 Amber light comes on

  1. Enter Time
    5.1 Message displays "Enter Countdown Time"
    5.2 Voice plays "Enter Countdown Time"

  2. Enter time in hh:mm:ss on 4x4 matrix keyboard confirmed with pound key.
    6.1 Speaker chips on each keystroke
    6.2 key entry displays on led screen hh:mm:ss eg 01:59:59
    6.3 On sixth keystroke show message "Confirm Countdown 01:59:59"
    6.4 Voice plays "Hit # to confirm Countdown 1 hour 59 minutes 59 seconds"

  3. pressed to confirm countdown

7.1 Speaker chirps twice to confirm
7.2 Message displays "Countdown Confirmed - Bomb Armed"
7.3 Voice plays "Countdown Confirmed - Bomb Armed"
7.4 Amber Led goes out
7.5 Red Led comes on steady
7.6 After 3 seconds - message displays on screen "Hit # to start countdown"

8.Hit # to start countdown
8.1 Screen displays time counting down
8.2 voice says "Countdown begun"
8.3 Red LED flashes until detonation

DETENATION SEQUENCE

  1. When countdown reaches 1 minute remaining
    1.1 Voice plays "1 Minute until detenation"
    1.2 Screen Flashes
    1.3 speaker chirps every second

  2. When countdown reaches 10 seconds
    2.1 Voice plays "10 Seconds until Detenation"
    2.2 Speaker chirps 3 times every second

  3. When countdown reaches zero
    3.1 Speaker sounds continuous tone for 5 seconds
    3.2 Message displays "Detonated"
    3.3 Signal sent to relay and transmitter sends signal

DE-ACTIVATION SEQUENCE

  1. RFID Card swiped to initiate deactivation - countdown continues
    1.1 Voice Plays "Welcome Commader, Enter Deactivation Code"

  2. Activation code entered to deactivate on 4x4 matrix
    2.1 when code is entered correctly
    2.1.1 Countdown stops
    2.1.2 Message displays "Bomb Disarmed"
    2.1.3 Speaker double beeps
    2.1.4 Red LED goes out
    2.1.5 Green LED comes on

2.2 When code is incorrect
2.2.1 Message displays "Incorrect Code Try Again"
2.2.2 Sequence restarts at DE-ACTIVATION SEQUENCE point 2

LCD?

Shouldn't it by convention have a red seven-segment LED display?

And four wires?

:smiley:

If it helps I am looking to do something similar to this but with a RFID reader intergrated.

(Note to admin: Now this has changed to programming errors please feel free to move this thread to the relevant area.)

Right I have had a go at getting started on the code myself.
I found a similar project on these forums with the code posted and used that as a base.
I have proto typed it with the hardware from the project found here: http://www.instructables.com/id/Prop-bomb/ as the code I found on this forum seems to have originated from this page also.
But....
Although the hardware is wired and operates correctly (nano with ATMega328 and protoshield), confirmed using small scale test of 'hello world' to test LCD and blink tests to test the LED's and Relay there seems to be some issues in the code itself:

1.When running the code the text on LCD screen garbles after a few seconds:
https://docs.google.com/file/d/0BwF78mk3vejaRE5vck5xVjdveFE/edit?usp=sharing
https://docs.google.com/file/d/0BwF78mk3vejadk9ndzM4Z0lmQ00/edit?usp=sharing

  1. the LED's do not light up when required

I am sure this is an issue in the code but as this is my first project and first time trying C++ coding need a little guidance.

Code is below:

/*Airsoft TIMER
 Version 1.5
 Creators:
 Chase Cooley
 Joey Meyer
 Turned into usable code, 6/16/2011:
 Matt Falcon
 Edited by Combat 11/10/2013
 */
//LCD Reference positions
//lcd.setCursor(0, 0); // top left
//lcd.setCursor(15, 0); // top right
//lcd.setCursor(0, 1); // bottom left
//lcd.setCursor(15, 1); // bottom right

#include <Keypad.h>
#include <LiquidCrystal.h>
#define pound 2
#define KP_ROWS 4
#define KP_COLS 4
int LED_RED = 7;
int LED_GREEN = 6;
int RELAY = 5;
unsigned int timerSeconds = 1800; // start with 30 minutes on the clock
byte password[4];
byte entered[4];
unsigned int currentLength = 0;
byte i = 0;
const byte ROWS = 4; // Four rows
const byte COLS = 4; // Four columns
//Animation
byte skull[8] = {
  B01110,
  B11111,
  B10101,
  B11111,
  B01110,
  B01010,
  B00000,
};
//LCD Pins
LiquidCrystal lcd(7,8,9,10,11,12);
//Keypad
char keys[KP_ROWS][KP_COLS] = {
  {
    '1','2','3','A'        }
  ,
  {
    '4','5','6','B'        }
  ,
  {
    '7','8','9','C'        }
  ,
  {
    '*','0','#','D'        }
};
byte rowPins[KP_ROWS] = {
  0, 1, A0, A2}; //connect to the row pinouts of the keypad {8, 7, 6, 5}
byte colPins[KP_COLS] = { 
  A1, A3, A4, A5 }; //connect to the column pinouts of the keypad {4, 3, 2, 1}
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, KP_ROWS, KP_COLS);
char key;

void setup() {
  pinMode(LED_RED, OUTPUT); // sets digital pin 7 as output
  pinMode(LED_GREEN, OUTPUT); // sets digital pin 6 as output
  pinMode(RELAY, OUTPUT); //sets digital pin 5 as output
  lcd.begin(16, 2); //setup LCD column count 16 and row count 2
  lcd.print(" COMBAT AIRSOFT "); //displays text on LCD top row
  delay(2500); //Keeps text on LCD for 2.5 seconds
  digitalWrite(LED_GREEN, HIGH); // sets LED_GREEN on
  delay(1000); //Keeps LED_GREEN on for 1 second
  digitalWrite(LED_GREEN, LOW); //sets LED_GREEN off
  lcd.clear(); //clears lcd display
  lcd.print(" ENTER ARM CODE "); //displays text on LCD top row
  lcd.setCursor(6, 1); //sets cursor to poition 7th column 2nd row for code entry
  while (currentLength < 4) { //if user input through keypad is less than 4 characters continue to wait for key inputs
    key = keypad.getKey();
    if (key != NO_KEY) {
      lcd.print(key); //displays users entry on lcd
      password[currentLength] = key; 
      currentLength++;
      lcd.setCursor(currentLength + 6, 1);
    } 
    else delay(100); // only sample it every 1/10 sec
  }
  lcd.noCursor();
  lcd.clear(); //clears lcd display
  lcd.print(" CODE CONFIRMED "); //displays text on LCD top row
  lcd.setCursor(6, 1); // sets cursor to poition 7th column 2nd row
  lcd.print(entered[1] & password[1], DEC); //displays first digit of code entered
  lcd.print(entered[2] & password[2], DEC); //displays second digit of code entered
  lcd.print(entered[3] & password[3], DEC); //displays third digit of code entered
  lcd.print(entered[4] & password[4], DEC); //displays forth digit of code entered
  delay(2500); //Keeps text on LCD for 2.5 seconds
  lcd.clear(); //clears lcd display
  currentLength = 0; //not sure what this does?????
}


void loop() {
  lcd.clear(); //clears lcd display
  lcd.print("ENTER CODE:"); //displays text on LCD starting at position 0,0 (top left)
  lcd.setCursor(12,0); //sets input cursor to 13th column top row
      while (currentLength < 4) { //if user input through keypad is less than 4 characters continue to wait for key inputs
        key = keypad.getKey();
        if (key != NO_KEY) {
        lcd.print(key); //displays users entry on lcd
        password[currentLength] = key; 
        currentLength++;
        lcd.setCursor(currentLength + 12, 0);
        } 
        else delay(100); // only sample it every 1/10 sec
      } 
    if (memcmp(entered,password,4) == 0) { // compares code entered to code entered in void setup() returns 0 if matched and triggers following comands
      lcd.noCursor();//clears cursor from LCD
      lcd.clear();//clears LCD
      lcd.print("DEFUSED");//displays text on LCD
      lcd.setCursor(0, 1);//Sets cursor on LCD to 1st coloumn second row
      lcd.print("BOMB RESETING");//displays text on second row
      digitalWrite(LED_GREEN, HIGH);//turns LED_GREEN on
      delay(25000); // hold that on screen for 2.5 seconds
      currentLength = 0;//not sure what this is for?????
    } 
    else { //If code does not match code entered in void setup() carry out following command
      lcd.noCursor();//clears cursor form LCD
      lcd.clear();//clears LCD
      lcd.print(" CODE INCORRECT ");//Displays text on LCD position 0,0 top left
      lcd.setCursor(0, 1);//sets cursor to bootom left of LCD
      lcd.print("  TIME  -00:30  "); // Display time penalty message
      digitalWrite(LED_RED, HIGH);// turns LED_RED on
        if (timerSeconds > 30) {timerSeconds - 30;} //deducts 30 seconds from rmaining time
      else timerSeconds = 1; // will trigger bomboom() next cycle
      currentLength = 0;//not sure what this is for???????
      delay(2500); // hold that on screen for 2.5 seconds
    }
  
  timer(); // prints current time on screen, checks for "go off" time, holds loop for 1 second
}

void timer() {
  lcd.setCursor(0,1); //sets cursor to bottom left of LCD
  lcd.print("TIME LEFT: ");//displays text on second row
  lcd.print(timerSeconds / 60); // integer number of minutes on clock
  lcd.print(":");
  lcd.print(timerSeconds % 60); //mod 60; //gives us number of seconds outside of 60sec/min
  delay(950); // hold us here for 0.950 seconds
    {
    digitalWrite(LED_RED, HIGH);// toggle LED_RED once a second
    delay(1000);
    digitalWrite(LED_RED, LOW);
    delay(1000);
    tone(9,784, 200); // play bleep for 50ms
    }
  delay(50); // and there's the rest of that 1 second (not counting LCD delay)
  //timerSeconds--;//not sure what this is for????
  if (timerSeconds = 0) bombomb();
}
void bombomb() {
  // routine for making ze BOMB GOEZ OFF!!!1 :D
  lcd.noCursor();
  lcd.clear();
  lcd.print("DETONATED");
  lcd.setCursor(7,1);
  lcd.createChar(0,skull);
  lcd.write(byte(0));
  tone(9,110,200);
  {
    digitalWrite(RELAY, HIGH); //turns relay on which activates transmitter
    delay(1000); //WAITS ONE SECOND
    digitalWrite(RELAY, LOW); //switches relay off
  }
    {
      digitalWrite(LED_GREEN, HIGH); // sets the green LED on
      tone(9,110, 200);
      delay(500); // waits half a second
      digitalWrite(LED_RED, HIGH); // sets the red LED on
      digitalWrite(LED_GREEN, LOW); // sets the green LED off
      tone(9,110, 200);
      delay(500); // waits half a second
      digitalWrite(LED_RED, LOW); // sets the red LED off
      digitalWrite(LED_GREEN, HIGH); // sets the green LED on
      tone(9,110, 200);
      delay(500); // waits half a second
      digitalWrite(LED_GREEN, LOW);// sets the green LED off
     } 
  {
  while (key = NO_KEY) {
    key = keypad.getKey();
    if (key = '#') {
      lcd.clear();
      lcd.print("RESET THE BOMB");
      delay(2500); // 2.5 sec delay
      timerSeconds = 1800; // put 5 minutes on the clock
      // and we break the loop and go back to timer.
    } 
    else key = NO_KEY; // continue looking for pound key
  }
}
}

The code in bombomb() looks highly dubious - at the very least, there are quite a lot of misplaced braces there.

I suggest you simplify your sketch as far as possible and start with a test that just displays a message and responds to button presses in some trivial way. See if this does what you expect and is stable. If so, gradually add in the other functionality. Trying to go from nothing to a complex working sketch in one go is not the way to do it - make lots of tiny incremental steps, testing as you go to make sure what you have works before you add in anything else.

Trying to go from nothing to a complex working sketch in one go is not the way to do it - make lots of tiny incremental steps, testing as you go to make sure what you have works before you add in anything else.

I'll second that. It is rare for me to add more than a dozen lines of code without running a test, or at least compiling to make sure I haven't screwed something up.

Doing the code development incrementally, seeing something happen at each step, no matter how trivial, is much more motivating than spending days writing code that was wrong 30 seconds into the process.

I mad a similar project, but it is much simpler than you originally wanted.

when you turn on the switch the screen displays "bomb on", "enter code". you then set a 4 digit disarm code. at which point it will display "you've entered XXXX" .

it will then say, "press # to arm".

when you press # a 10min countdown starts.

to disarm you must press * then the 4 digit code.
you have 3 chances,
the first 2 times you enter a code wrong it cuts the time in half, the third time detonates.

a speaker beeps every second while counting down and a amber LED flashes.

if you disarm it a green LED comes on steady.

if the bomb detonates for any reason a green, amber and red led chase, and a speaker beeps 3 times a second and the screen displays "bomb detonated".

here is my code

#include <Keypad.h>
#include <LiquidCrystal.h>
#define pound 14

int Scount = 00; // count seconds
int Mcount = 10; // count minutes
int Hcount = 0; // count hours
int DefuseTimer = 0; // set timer to 0
int trycount = 0;

long secMillis = 0; // store last time for second add
long interval = 1000; // interval for seconds

char password[4]; // number of characters in our password
int currentLength = 0; //defines which number we are currently writing
int i = 0;
char entered[4];

int ledPin = A4; //red led
int ledPin2 = A5; //yellow led
int ledPin3 = A3; //green led

LiquidCrystal lcd(8, 9, 10, 11, 12, 13); // the pins we use on the LCD
// pin 8 to RS, pin 9 to E, pin 10 to D4, pin 11 to D5, pin 12 to D6, pin 13 to D7.
// Ground to pins VSS,RW,K.
//+5vdc to pin VDD.
//220 ohm resistor between pins A and VDD.
//Potentiometer center pin to V0, positive pin to VDD, Negative pin to VSS.

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};
byte rowPins[ROWS] = {5, 4, 3, 2}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {A0, A1, A2}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );


void setup() {
  pinMode(ledPin, OUTPUT); // sets the digital pin as output
  pinMode(ledPin2, OUTPUT); // sets the digital pin as output
  pinMode(ledPin3, OUTPUT); // sets the digital pin as output
  lcd.begin(16, 2);
  Serial.begin(9600);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Bomb on!");
  lcd.setCursor(0, 1);
  lcd.print("Enter Code:");
  while (currentLength < 4)
  {
    lcd.setCursor(currentLength + 12, 1);
    lcd.cursor();
    char key = keypad.getKey();
    key == NO_KEY;
    if (key != NO_KEY)
    {
      if ((key != '*') && (key != '#'))
      {
        lcd.print(key);
        tone(7, 5000, 100);
        password[currentLength] = key;
        currentLength++;
      }
    }
  }

  if (currentLength == 4)
  {
    delay(500);
    lcd.noCursor();
    lcd.clear();
    lcd.home();
    lcd.print("You've Entered: ");
    lcd.setCursor(6, 1);
    lcd.print(password[0]);
    lcd.print(password[1]);
    lcd.print(password[2]);
    lcd.print(password[3]);

    delay(3000);
    lcd.clear();
    lcd.print ("Press # to arm");
    delay(50);
    currentLength = 5;

    while (currentLength == 5)
    {

      char key3 = keypad.getKey();

      if (key3 == '#')
      {
        lcd.clear();
        lcd.print ("Bomb Armed!");
        delay(3000);
        lcd.clear();
        currentLength = 0;
      }
    }
  }
}
void loop()
{
  timer();
  char key2 = keypad.getKey(); // get the key

  if (key2 == '*')
  {
    tone(7, 5000, 100);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Code: ");

    while (currentLength < 4)
    {

      timer();

      char key2 = keypad.getKey();
      if (key2 == '#')
      {
        tone(7, 5000, 100);
        currentLength = 0;
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Code: ");
      }
      else if (key2 != NO_KEY)
      {

        lcd.setCursor(currentLength + 7, 0);
        lcd.cursor();

        lcd.print(key2);
        entered[currentLength] = key2;
        currentLength++;
        tone(7, 5000, 100);
        delay(100);
        lcd.noCursor();
        lcd.setCursor(currentLength + 6, 0);
        lcd.print("*");
        lcd.setCursor(currentLength + 7, 0);
        lcd.cursor();
      }
    }

    if (currentLength == 4)
    {
      if (entered[0] == password[0] && entered[1] == password[1] && entered[2] == password[2] && entered[3] == password[3])
      {
        lcd.noCursor();
        lcd.clear();
        lcd.home();
        lcd.print("Bomb Defused");
        currentLength = 0;
        digitalWrite(ledPin3, HIGH);
        delay(2500);
        lcd.setCursor(0, 1);
        lcd.print("Reset the Bomb");
        delay(1000000);
      }
      else
      {
        lcd.noCursor();
        lcd.clear();
        lcd.home();
        lcd.print("Wrong Password!");
        trycount++;

        if (Hcount > 0)
        {
          Hcount = Hcount / 2;
        }

        if (Mcount > 0)
        {
          Mcount = Mcount / 2;
        }
        if (Scount > 0)
        {
          Scount = Scount / 2;
        }
        if (trycount == 3)
        {
          Mcount = Mcount - 59;
          Hcount = Hcount - 59;
          Scount = Scount - 59;
        }
        delay(1000);
        currentLength = 0;

      }
    }
  }
}

void timer()
{
  Serial.print(Scount);
  Serial.println();

  if (Hcount <= 0)
  {
    if ( Mcount < 0 )
    {
      lcd.noCursor();
      lcd.clear();
      lcd.home();
      lcd.print("The Bomb Has ");
      lcd.setCursor (0, 1);
      lcd.print("Exploded!");

      while (Mcount < 0)
      {
        digitalWrite(ledPin, HIGH); // sets the LED on
        tone(7, 7000, 100);
        delay(100);
        digitalWrite(ledPin, LOW); // sets the LED off
        tone(7, 7000, 100);
        delay(100);
        digitalWrite(ledPin2, HIGH); // sets the LED on
        tone(7, 7000, 100);
        delay(100);
        digitalWrite(ledPin2, LOW); // sets the LED off
        tone(7, 7000, 100);
        delay(100);
        digitalWrite(ledPin3, HIGH); // sets the LED on
        tone(7, 7000, 100);
        delay(100);
        digitalWrite(ledPin3, LOW); // sets the LED off
        tone(7, 7000, 100);
        delay(100);
      }
    }
  }

  lcd.setCursor (0, 1); // sets cursor to 2nd line
  lcd.print ("Timer:");

  if (Hcount >= 10)
  {
    lcd.setCursor (7, 1);
    lcd.print (Hcount);
  }
  if (Hcount < 10)
  {
    lcd.setCursor (7, 1);
    lcd.write ("0");
    lcd.setCursor (8, 1);
    lcd.print (Hcount);
  }

  lcd.print (":");

  if (Mcount >= 10)
  {
    lcd.setCursor (10, 1);
    lcd.print (Mcount);
  }
  if (Mcount < 10)
  {
    lcd.setCursor (10, 1);
    lcd.write ("0");
    lcd.setCursor (11, 1);
    lcd.print (Mcount);
  }

  lcd.print (":");

  if (Scount >= 10)
  {
    lcd.setCursor (13, 1);
    lcd.print (Scount);
  }
  if (Scount < 10)
  {
    lcd.setCursor (13, 1);
    lcd.write ("0");
    lcd.setCursor (14, 1);
    lcd.print (Scount);
  }

  if (Hcount < 0)
  {
    Hcount = 0;
  }

  if (Mcount < 0)
  {
    Hcount --;
    Mcount = 59;
  }

  if (Scount < 1) // if 60 do this operation
  {
    Mcount --; // add 1 to Mcount
    Scount = 59; // reset Scount
  }

  if (Scount > 0) // do this oper. 59 times
  {
    unsigned long currentMillis = millis();

    if (currentMillis - secMillis > interval)
    {
      tone(7, 7000, 50);
      secMillis = currentMillis;
      Scount --; // add 1 to Scount
      digitalWrite(ledPin2, HIGH); // sets the LED on
      delay(10); // waits for a second
      digitalWrite(ledPin2, LOW); // sets the LED off
      delay(10); // waits for a second
      //lcd.clear();
    }
  }
}

20171214_141521.jpg