Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /******************************************************************************************
- * Airsoft C4 Prop by Joshua Burgess *
- * www.nightscapeairsoft.com *
- * joshuaburgess@gmail.com *
- *******************************************************************************************/
- #include <keypad.h>
- #define ROWS 4
- #define COLS 3
- //Define all the bomb states
- #define ON 0
- #define READY 1
- #define ARMED 2
- #define DISARMED 3
- #define DETONATED 4
- keypad kpd = keypad(ROWS, COLS);//create a new keypad
- int second=30, minute=2, hour=0; // declare time variables
- int bombState=0; //1 = Ready, 2 = Armed, 3 = Disarmed, 4 = detonated
- int repeat=0;//flag to prevent repeat of getArmCode();
- int repeatDisarm=0;//flag to prevent repeat of getDisarmCode();
- int repeatBuzzer=0;//flag to prevent buzzer from running multiple times.
- int tether = 2;//pin that contains the tether.
- int disarmPin = 3;//pin that the red pushbutton is plugged into.
- int speakerPin = 5;//pin that the piezo buzzer is connected to.
- int pinStatus = 0;//stores value of the tether pin.
- int disarmPinStatus = 0;//stores value of the disarm pin.
- char ArmCode[] = "7355608";//code to arm the bomb
- char disarmCode[] = "1234567";//code to disarm the bomb
- char CANCEL_KEY = '*';//stores the cancel key variable.
- char notes[] = "A c A c A c E "; // a space represents a rest
- const byte length = sizeof(notes); // the number of notes
- byte beats[length] = { 1, 1, 1, 1, 1, 1, 1, 4};
- char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C', 'D', 'E', 'F', 'G', 'A', 'B' };
- unsigned int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956, 587, 659, 698, 784, 880, 988 };
- //Above is the beats the note plays for
- byte tempo = 1000;
- void setup()
- {
- Serial.begin(9600);
- kpd.init();
- clearLCD();
- backlightOn();
- pinMode(disarmPin, INPUT);//sets the input pin for the pushbutton.
- pinMode(speakerPin, OUTPUT);//sets the output pin for the piezo buzzer
- }
- void loop(){
- switch (bombState) {
- /*****************************************************
- *Initial bomb state, waiting for teather.
- *
- *******************************************************/
- case ON:
- pinStatus = digitalRead(tether);
- if (pinStatus == HIGH) {
- selectLineOne();
- delay(100);
- Serial.print("Attach Tether");
- }
- else {
- bombState = READY;
- delay(500);
- }
- break;
- /***********************************************************
- *Ready state prepares bomb, waits for arm code to be input
- *
- ************************************************************/
- case READY:
- clearLCD();
- selectLineOne();
- delay(100);
- Serial.print("Enter Code"); //Notify user of status.
- if (getArmCode() == true) {
- //Make sure tether hasn't been removed
- pinStatus = digitalRead(tether);
- if (pinStatus == HIGH) { //if the tether has been removed,
- selectLineOne();
- delay(100);
- Serial.print("Tether Removed"); //make it known
- delay(1000);
- clearLCD();
- bombState = DETONATED; //and set off bomb.
- }
- else { //if the tether is still connected, print "correct".
- clearLCD();
- selectLineOne();
- delay(100);
- Serial.print("Correct");
- delay(500);
- clearLCD();
- bombState = ARMED; //Start countdown
- }
- }//Close getArmCode(); = true
- if (getArmCode() == false) {
- //Make sure tether hasn't been removed
- pinStatus = digitalRead(tether);
- if (pinStatus == HIGH) { //if the tether has been removed,
- selectLineOne();
- delay(100);
- Serial.print("Tether Removed"); //make it known
- delay(1000);
- clearLCD();
- bombState = DETONATED; //and set off bomb.
- }
- else {
- clearLCD();
- selectLineOne();
- delay(100);
- Serial.print("Incorrect");//if code fails, and tether is connected, print "Incorrect"
- }
- }// Close getArmCode(); = false.
- break;
- /**************************************************
- *Armed state. Countdown starts, waits for pushbutton to be pressed.
- *If button is pressed, wait for code from keypad.
- ***************************************************/
- case ARMED:
- disarmPinStatus = digitalRead(disarmPin);
- if (disarmPinStatus == LOW) {
- selectLineOne();
- delay(100);
- Serial.print("Enter Code:"); //if disarm button is pressed, ask user to input code.
- if (getDisarmCode() == true) {
- //Make sure tether hasn't been removed
- pinStatus = digitalRead(tether);
- if (pinStatus == HIGH) { //if the tether has been removed,
- selectLineOne();
- delay(100);
- Serial.print("Tether Removed"); //make it known
- delay(1000);
- clearLCD();
- bombState = DETONATED; //and set off bomb.
- }
- else {
- clearLCD();
- selectLineOne();
- delay(100);
- Serial.print("Correct"); //if code is correct, and tether is connected, print "Correct".
- delay(500);
- clearLCD();
- bombState = DISARMED; //and set bombState to disarmed.
- break;
- }
- } //close getDisarmCode(); = True
- if (getDisarmCode() == false) {
- //Make sure tether hasn't been removed
- pinStatus = digitalRead(tether);
- if (pinStatus == HIGH) { //if the tether has been removed,
- selectLineOne();
- delay(100);
- Serial.print("Tether Removed"); //make it known
- delay(1000);
- clearLCD();
- bombState = DETONATED; //and set off bomb.
- }
- else {
- clearLCD();
- selectLineOne();
- delay(100);
- Serial.print("Try Again");//if code fails, notify user
- //second = 1; //and remove all the remaining seconds.
- if (second > 15) {
- second = second - 15;
- }
- else {
- second=1;// erase seconds from count after button press.
- }
- }
- } //close getDisarmCode(); = false
- } //close disarmPinStatus(); = true
- else {
- countdown(); //if disarmpin has not been pressed, continue countdown.
- }
- break;
- /**************************************************************
- *DISARMED. Counter stopped, displays "bomb disarmed"
- *
- **************************************************************/
- case DISARMED:
- selectLineOne();
- delay(100);
- Serial.print("Bomb Disarmed"); //bomb has been disarmed, inform user.
- break;
- /*******************************************************
- *Detonated. activate buzzer for 8 beeps, then 1 long.
- *Print "Have A Nice Day. to LCD.
- ********************************************************/
- case DETONATED:
- if (repeatBuzzer == 0) { //make sure buzzer for loop has not already been run.
- for (int i = 0; i < length; i++) {
- if (notes[i] == ' ') {
- delay(beats[i] * tempo); // rest
- }
- else {
- playNote(notes[i], beats[i] * tempo);
- }
- // pause between notes
- delay(tempo / 2);
- repeatBuzzer = 1; //set flag to prevent code from looping again.
- }//clos for loop
- }//close repeatBuzzer.
- else {
- selectLineOne();
- delay(100);
- Serial.print("Have A Nice Day"); //loop message informing user of bomb detonation.
- }
- }//closes switch
- }//closes loop
- /***********************************************************
- * Main countdown timer *
- * countdown() *
- ************************************************************/
- void countdown(){
- //Make sure tether hasn't been removed
- pinStatus = digitalRead(tether);
- if (pinStatus == HIGH) { //if the tether has been removed,
- selectLineOne();
- delay(100);
- Serial.print("Tether Removed"); //make it known
- delay(1000);
- clearLCD();
- bombState = DETONATED; //and set off bomb.
- }
- static unsigned long lastTick = 0; // set up a local variable to hold the last time we decremented one second
- // (static variables are initialized once and keep their values between function calls)
- // decrement one second every 1000 milliseconds
- if (second > 0) {
- if (millis() - lastTick >= 1000) {
- lastTick = millis();
- second--;
- serialOutput();
- }
- }
- // decrement one minute every 60 seconds
- if (minute > 0) {
- if (second <= 0) {
- minute--;
- second = 60; // reset seconds to 60
- }
- }
- // decrement one hour every 60 minutes
- if (hour > 0) {
- if (minute <= 0) {
- hour--;
- minute = 60; // reset minutes to 60
- }//closes if
- }//closes if
- } //close countdown();
- /***********************************************************************
- * getArmCode(); *
- * Grabs the code to arm the bomb from the keypad. *
- * *
- ************************************************************************/
- boolean getArmCode(){
- // returns true when all PW keys are pressed in sequence
- // returns false when number of keys in pW pressed but don't exactly match the PW
- // CANCEL_KEY erases all previous digits input
- int count=0; // how many keys we have
- int matchCount=0; // how many keys match
- if(repeat == 0){
- for(count=0, matchCount=0; count < sizeof(ArmCode)-1; count++){
- char key;
- do{
- key = kpd.get_key();
- }
- while(key == '\0');
- if(key == ArmCode[count]) {
- matchCount++;
- }
- else if(key == CANCEL_KEY){
- count=0;
- matchCount=0;
- loop();
- }
- }//close for loop
- }//close repeat flag check
- // here when the same number of keys pressed as characters in the PW
- if(matchCount == count) {
- repeat=1;
- return true;
- }
- else {
- return false;
- }
- }//close getArmCode();
- /**********************************************************************
- * getDisarmCode(); *
- * Gets disarm code from keypad. *
- * *
- ***********************************************************************/
- boolean getDisarmCode(){
- // returns true when all PW keys are pressed in sequence
- // returns false when number of keys in pW pressed but don't exactly match the PW
- // CANCEL_KEY erases all previous digits input
- int count=0; // how many keys we have
- int matchCount=0; // how many keys match
- long disarmTime = millis()+7000L;//7000 instead of 15000 b/c of added delays making total 30s
- if(repeatDisarm == 0){
- for(count=0, matchCount=0; count < sizeof(disarmCode)-1; count++){
- char key;
- do{
- if(disarmTime < millis()){ //if 15 seconds have passed, bail out
- //count=sizeof(disarmCode)+1;
- break;
- }
- key = kpd.get_key();
- }
- while(key == '\0');
- if(key == disarmCode[count]) {
- matchCount++;
- }
- else if(key == CANCEL_KEY){
- count=0;
- matchCount=0;
- //loop();
- }
- if(disarmTime < millis()) {
- //count = 9999; //ensure count != matchcount.
- return false;
- break;
- }
- }// close for loop
- } //close repeat flag check
- // here when the same number of keys pressed as characters in the PW
- if(matchCount == count) {
- repeatDisarm=1;
- return true;
- }
- else {
- return false;
- }
- }//close getDisarmCode();
- /**************************************************
- *PIEZO BUZZER STUFF *
- * *
- ***************************************************/
- void playTone(int tone, int duration) {
- for (long i = 0; i < duration * 1000L; i += tone * 2) {
- digitalWrite(speakerPin, HIGH);
- delayMicroseconds(tone);
- digitalWrite(speakerPin, LOW);
- delayMicroseconds(tone);
- }
- }
- void playNote(char note, int duration) {
- // play the tone corresponding to the note name
- for (int i = 0; i < 14; i++) {
- if (names[i] == note) {
- playTone(tones[i], duration);
- }
- }
- }
- /****************************************************************
- * serialOutput(); *
- * prints the values of the timer over the serial connection *
- * and onto the LCD *
- *****************************************************************/
- void serialOutput() {
- //clearLCD();
- backlightOn();
- //Print time on each line
- selectLineTwo();
- delay(100);
- Serial.print("ARMED : ");
- Serial.print(hour, DEC); // the hour, sent to the screen in decimal format
- Serial.print(":"); // a colon between the hour and the minute
- Serial.print(minute, DEC); // the minute, sent to the screen in decimal format
- Serial.print(":"); // a colon between the minute and the second
- Serial.println(second, DEC); // the second, sent to the screen in decimal format
- //termination condition
- if (second == 0 && minute == 0 && hour == 0) {
- clearLCD();
- backlightOn();
- bombState = DETONATED; //clear LCD and set bomb state to "detonated" when timer runs out
- }
- }//close serialOutput();
- /*********************************************************************
- * Serial LCD disagnostic and general use tools *
- * selectLineOne(); | selectLineTwo(); | goTo(); | clearLCD(); *
- * backlightOn(); | backlightOff(); | serCommand(); *
- **********************************************************************/
- void selectLineOne(){ //puts the cursor at line 0 char 0.
- Serial.print(0xFE, BYTE); //command flag
- Serial.print(128, BYTE); //position
- }
- void selectLineTwo(){ //puts the cursor at line 0 char 0.
- Serial.print(0xFE, BYTE); //command flag
- Serial.print(192, BYTE); //position
- }
- void goTo(int position) { //position = line 1: 0-15, line 2: 16-31, 31+ defaults back to 0
- if (position<16){ Serial.print(0xFE, BYTE); //command flag
- Serial.print((position+128), BYTE); //position
- }else if (position<32){Serial.print(0xFE, BYTE); //command flag
- Serial.print((position+48+128), BYTE); //position
- } else { goTo(0); }
- }
- void clearLCD(){
- Serial.print(0xFE, BYTE); //command flag
- Serial.print(0x01, BYTE); //clear command.
- }
- void backlightOn(){ //turns on the backlight
- Serial.print(0x7C, BYTE); //command flag for backlight stuff
- Serial.print(157, BYTE); //light level.
- }
- void backlightOff(){ //turns off the backlight
- Serial.print(0x7C, BYTE); //command flag for backlight stuff
- Serial.print(128, BYTE); //light level for off.
- }
- void serCommand(){ //a general function to call the command flag for issuing all other commands
- Serial.print(0xFE, BYTE);
- }
- //END of bomb program.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement