Don't like ads? PRO users don't see any ads ;-)
Guest

wizdum

By: a guest on Apr 27th, 2009  |  syntax: None  |  size: 15.94 KB  |  hits: 2,881  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /******************************************************************************************
  2. * Airsoft C4 Prop by Joshua Burgess                                                       *
  3. * www.nightscapeairsoft.com                                                               *
  4. * joshuaburgess@gmail.com                                                                 *
  5. *******************************************************************************************/
  6.   #include <keypad.h>
  7.  
  8.     #define ROWS 4
  9.     #define COLS 3
  10.  
  11.   //Define all the bomb states  
  12. #define ON 0
  13. #define READY 1
  14. #define ARMED 2
  15. #define DISARMED 3
  16. #define DETONATED 4
  17.  
  18. keypad kpd = keypad(ROWS, COLS);//create a new keypad
  19.  
  20. int second=30, minute=2, hour=0; // declare time variables
  21. int bombState=0; //1 = Ready, 2 = Armed, 3 = Disarmed, 4 = detonated
  22. int repeat=0;//flag to prevent repeat of getArmCode();
  23. int repeatDisarm=0;//flag to prevent repeat of getDisarmCode();
  24. int repeatBuzzer=0;//flag to prevent buzzer from running multiple times.
  25. int tether = 2;//pin that contains the tether.
  26. int disarmPin = 3;//pin that the red pushbutton is plugged into.
  27. int speakerPin = 5;//pin that the piezo buzzer is connected to.
  28. int pinStatus = 0;//stores value of the tether pin.
  29. int disarmPinStatus = 0;//stores value of the disarm pin.
  30.  
  31. char ArmCode[] = "7355608";//code to arm the bomb
  32. char disarmCode[] = "1234567";//code to disarm the bomb
  33. char CANCEL_KEY = '*';//stores the cancel key variable.
  34.  
  35.  
  36. char notes[] = "A c A c A c E "; // a space represents a rest
  37. const byte length = sizeof(notes); // the number of notes
  38. byte beats[length] = { 1, 1, 1, 1, 1, 1, 1, 4};
  39. char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C', 'D', 'E', 'F', 'G', 'A', 'B' };
  40. unsigned int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956, 587, 659, 698, 784, 880, 988 };
  41.  
  42. //Above is the beats the note plays for
  43. byte tempo = 1000;
  44.  
  45. void setup()
  46. {
  47.   Serial.begin(9600);
  48.   kpd.init();
  49.   clearLCD();
  50.   backlightOn();
  51.   pinMode(disarmPin, INPUT);//sets the input pin for the pushbutton.
  52.   pinMode(speakerPin, OUTPUT);//sets the output pin for the piezo buzzer
  53. }
  54.  
  55. void loop(){
  56.   switch (bombState) {
  57. /*****************************************************
  58. *Initial bomb state, waiting for teather.
  59. *
  60. *******************************************************/
  61.   case ON:
  62.    
  63.   pinStatus = digitalRead(tether);
  64.   if (pinStatus == HIGH) {
  65.       selectLineOne();
  66.       delay(100);
  67.       Serial.print("Attach Tether");
  68.   }
  69.   else {
  70.       bombState = READY;
  71.       delay(500);
  72.   }
  73.     break;
  74.    
  75. /***********************************************************
  76. *Ready state prepares bomb, waits for arm code to be input
  77. *
  78. ************************************************************/
  79.   case READY:
  80.  
  81.   clearLCD();
  82.   selectLineOne();
  83.   delay(100);
  84.   Serial.print("Enter Code"); //Notify user of status.
  85.  
  86.    if (getArmCode() == true) {
  87.      
  88.        //Make sure tether hasn't been removed
  89.        pinStatus = digitalRead(tether);
  90.        if (pinStatus == HIGH) { //if the tether has been removed,
  91.             selectLineOne();
  92.             delay(100);
  93.             Serial.print("Tether Removed"); //make it known
  94.             delay(1000);
  95.             clearLCD();
  96.             bombState = DETONATED; //and set off bomb.
  97.        }
  98.        
  99.        else { //if the tether is still connected, print "correct".
  100.            clearLCD();
  101.            selectLineOne();
  102.            delay(100);
  103.            Serial.print("Correct");
  104.            delay(500);
  105.            clearLCD();
  106.            bombState = ARMED; //Start countdown
  107.        }
  108.   }//Close getArmCode(); = true
  109.  
  110.  if (getArmCode() == false) {
  111.    
  112.        //Make sure tether hasn't been removed
  113.        pinStatus = digitalRead(tether);
  114.        if (pinStatus == HIGH) { //if the tether has been removed,
  115.            selectLineOne();
  116.            delay(100);
  117.            Serial.print("Tether Removed"); //make it known
  118.            delay(1000);
  119.            clearLCD();
  120.            bombState = DETONATED; //and set off bomb.
  121.        }
  122.    
  123.        else {
  124.            clearLCD();
  125.            selectLineOne();
  126.            delay(100);
  127.            Serial.print("Incorrect");//if code fails, and tether is connected, print "Incorrect"
  128.        }
  129.  }// Close getArmCode(); = false.
  130.  
  131.   break;
  132.    
  133. /**************************************************
  134. *Armed state. Countdown starts, waits for pushbutton to be pressed.
  135. *If button is pressed, wait for code from keypad.
  136. ***************************************************/
  137.  
  138.   case ARMED:
  139.  
  140.   disarmPinStatus = digitalRead(disarmPin);
  141.   if (disarmPinStatus == LOW) {
  142.        selectLineOne();
  143.        delay(100);
  144.        Serial.print("Enter Code:"); //if disarm button is pressed, ask user to input code.
  145.    
  146.        if (getDisarmCode() == true) {
  147.    
  148.             //Make sure tether hasn't been removed
  149.             pinStatus = digitalRead(tether);
  150.            
  151.             if (pinStatus == HIGH) { //if the tether has been removed,
  152.                 selectLineOne();
  153.                 delay(100);
  154.                 Serial.print("Tether Removed"); //make it known
  155.                 delay(1000);
  156.                 clearLCD();
  157.                 bombState = DETONATED; //and set off bomb.
  158.             }
  159.  
  160.             else {    
  161.                 clearLCD();
  162.                 selectLineOne();
  163.                 delay(100);
  164.                 Serial.print("Correct"); //if code is correct, and tether is connected, print "Correct".
  165.                 delay(500);
  166.                 clearLCD();
  167.                 bombState = DISARMED; //and set bombState to disarmed.
  168.                 break;
  169.             }
  170.       } //close getDisarmCode(); = True
  171.  
  172.       if (getDisarmCode() == false) {
  173.    
  174.       //Make sure tether hasn't been removed
  175.       pinStatus = digitalRead(tether);
  176.          
  177.           if (pinStatus == HIGH) { //if the tether has been removed,
  178.               selectLineOne();
  179.               delay(100);
  180.               Serial.print("Tether Removed"); //make it known
  181.               delay(1000);
  182.               clearLCD();
  183.               bombState = DETONATED; //and set off bomb.
  184.           }
  185.    
  186.           else {
  187.               clearLCD();
  188.               selectLineOne();
  189.               delay(100);
  190.               Serial.print("Try Again");//if code fails, notify user
  191.               //second = 1; //and remove all the remaining seconds.
  192.          
  193.               if (second > 15) {
  194.                 second = second - 15;
  195.               }
  196.          
  197.               else {
  198.                   second=1;// erase seconds from count after button press.
  199.               }
  200.           }    
  201.    } //close getDisarmCode(); = false
  202.      
  203.      
  204.   } //close disarmPinStatus(); = true
  205.  
  206.   else {
  207.       countdown(); //if disarmpin has not been pressed, continue countdown.
  208.   }
  209.  
  210.   break;
  211.  
  212. /**************************************************************
  213. *DISARMED. Counter stopped, displays "bomb disarmed"
  214. *
  215. **************************************************************/
  216.  
  217. case DISARMED:
  218.  
  219.     selectLineOne();
  220.     delay(100);
  221.     Serial.print("Bomb Disarmed"); //bomb has been disarmed, inform user.
  222.     break;
  223.  
  224. /*******************************************************
  225. *Detonated. activate buzzer for 8 beeps, then 1 long.
  226. *Print "Have A Nice Day. to LCD.
  227. ********************************************************/
  228.  
  229. case DETONATED:
  230.  
  231.   if (repeatBuzzer == 0) { //make sure buzzer for loop has not already been run.
  232.  
  233.        for (int i = 0; i < length; i++) {
  234.            if (notes[i] == ' ') {
  235.                delay(beats[i] * tempo); // rest
  236.            }
  237.        
  238.            else {
  239.                 playNote(notes[i], beats[i] * tempo);
  240.            }
  241.      
  242.            // pause between notes
  243.            delay(tempo / 2);
  244.            repeatBuzzer = 1; //set flag to prevent code from looping again.
  245.         }//clos for loop
  246.   }//close repeatBuzzer.
  247.  
  248.   else {
  249.       selectLineOne();
  250.       delay(100);
  251.       Serial.print("Have A Nice Day"); //loop message informing user of bomb detonation.
  252.   }
  253.  
  254.   }//closes switch
  255. }//closes loop
  256.  
  257.  
  258. /***********************************************************
  259. * Main countdown timer                                     *
  260. *                 countdown()                              *
  261. ************************************************************/
  262. void countdown(){
  263.  
  264.     //Make sure tether hasn't been removed
  265.     pinStatus = digitalRead(tether);
  266.    
  267.        if (pinStatus == HIGH) { //if the tether has been removed,
  268.            selectLineOne();
  269.            delay(100);
  270.            Serial.print("Tether Removed"); //make it known
  271.            delay(1000);
  272.            clearLCD();
  273.            bombState = DETONATED; //and set off bomb.
  274.        }
  275.  
  276.   static unsigned long lastTick = 0; // set up a local variable to hold the last time we decremented one second
  277. // (static variables are initialized once and keep their values between function calls)
  278.  
  279. // decrement one second every 1000 milliseconds
  280.   if (second > 0) {
  281.       if (millis() - lastTick >= 1000) {
  282.           lastTick = millis();
  283.           second--;
  284.           serialOutput();
  285.       }
  286.   }
  287.  
  288.  // decrement one minute every 60 seconds
  289.   if (minute > 0) {
  290.       if (second <= 0) {
  291.           minute--;
  292.           second = 60; // reset seconds to 60
  293.       }
  294.   }
  295.  
  296. // decrement one hour every 60 minutes
  297.   if (hour > 0) {
  298.       if (minute <= 0) {
  299.           hour--;
  300.           minute = 60; // reset minutes to 60
  301.       }//closes if
  302.   }//closes if
  303.  
  304. } //close countdown();
  305.  
  306.  
  307. /***********************************************************************
  308. *                          getArmCode();                               *
  309. *  Grabs the code to arm the bomb from the keypad.                     *
  310. *                                                                      *
  311. ************************************************************************/
  312. boolean getArmCode(){
  313.   // returns true when all PW keys are pressed in sequence
  314.   // returns false when number of keys in pW pressed but don't exactly match the PW
  315.   // CANCEL_KEY erases all previous digits input
  316.   int count=0;  // how many keys we have
  317.   int matchCount=0;  // how many keys match
  318.  
  319.   if(repeat == 0){
  320.  
  321.       for(count=0, matchCount=0; count < sizeof(ArmCode)-1; count++){
  322.           char key;
  323.          
  324.           do{
  325.               key = kpd.get_key();
  326.           }
  327.           while(key == '\0');
  328.          
  329.           if(key == ArmCode[count]) {
  330.               matchCount++;
  331.           }
  332.          
  333.           else if(key == CANCEL_KEY){
  334.               count=0;
  335.               matchCount=0;
  336.               loop();
  337.           }
  338.       }//close for loop
  339.   }//close repeat flag check
  340.  
  341. // here when the same number of keys pressed as characters in the PW
  342.   if(matchCount == count) {
  343.       repeat=1;
  344.       return true;
  345.   }
  346.  
  347.   else {
  348.       return false;
  349.  
  350.   }
  351. }//close getArmCode();
  352.  
  353.  
  354. /**********************************************************************
  355. *                   getDisarmCode();                                  *
  356. *    Gets disarm code from keypad.                                    *
  357. *                                                                     *
  358. ***********************************************************************/
  359. boolean getDisarmCode(){
  360.  
  361. // returns true when all PW keys are pressed in sequence
  362. // returns false when number of keys in pW pressed but don't exactly match the PW
  363. // CANCEL_KEY erases all previous digits input
  364.  
  365.   int count=0;  // how many keys we have
  366.   int matchCount=0;  // how many keys match
  367.   long disarmTime = millis()+7000L;//7000 instead of 15000 b/c of added delays making total 30s
  368.  
  369.   if(repeatDisarm == 0){
  370.  
  371.       for(count=0, matchCount=0; count < sizeof(disarmCode)-1; count++){
  372.           char key;
  373.           do{
  374.                if(disarmTime < millis()){ //if 15 seconds have passed, bail out
  375.               //count=sizeof(disarmCode)+1;
  376.               break;
  377.               }
  378.              
  379.             key = kpd.get_key();        
  380.           }
  381.           while(key == '\0');
  382.    
  383.           if(key == disarmCode[count]) {
  384.               matchCount++;
  385.           }
  386.    
  387.           else if(key == CANCEL_KEY){
  388.               count=0;
  389.               matchCount=0;
  390.               //loop();
  391.           }
  392.  
  393.           if(disarmTime < millis()) {
  394.               //count = 9999; //ensure count != matchcount.
  395.               return false;
  396.               break;
  397.           }
  398.  
  399.      }// close for loop
  400.   } //close repeat flag check
  401.  
  402. // here when the same number of keys pressed as characters in the PW
  403.   if(matchCount == count) {
  404.       repeatDisarm=1;
  405.       return true;
  406.   }
  407.   else {
  408.       return false;
  409.  
  410.   }
  411. }//close getDisarmCode();
  412.  
  413. /**************************************************
  414. *PIEZO BUZZER STUFF                               *
  415. *                                                 *
  416. ***************************************************/
  417.  
  418. void playTone(int tone, int duration) {
  419.   for (long i = 0; i < duration * 1000L; i += tone * 2) {
  420.     digitalWrite(speakerPin, HIGH);
  421.     delayMicroseconds(tone);
  422.     digitalWrite(speakerPin, LOW);
  423.     delayMicroseconds(tone);
  424.   }
  425. }
  426.  
  427. void playNote(char note, int duration) {
  428.  
  429.   // play the tone corresponding to the note name
  430.   for (int i = 0; i < 14; i++) {
  431.     if (names[i] == note) {
  432.         playTone(tones[i], duration);
  433.     }
  434.   }
  435. }
  436.  
  437.  
  438. /****************************************************************
  439. *                     serialOutput();                           *
  440. *    prints the values of the timer over the serial connection  *
  441. *         and onto the LCD                                      *
  442. *****************************************************************/
  443. void serialOutput() {
  444. //clearLCD();
  445.   backlightOn();
  446. //Print time on each line
  447.   selectLineTwo();
  448.   delay(100);
  449.   Serial.print("ARMED : ");
  450.   Serial.print(hour, DEC); // the hour, sent to the screen in decimal format
  451.   Serial.print(":"); // a colon between the hour and the minute
  452.   Serial.print(minute, DEC); // the minute, sent to the screen in decimal format
  453.   Serial.print(":"); // a colon between the minute and the second
  454.   Serial.println(second, DEC); // the second, sent to the screen in decimal format
  455. //termination condition
  456.   if (second == 0 && minute == 0 && hour == 0) {
  457.       clearLCD();
  458.       backlightOn();
  459.       bombState = DETONATED; //clear LCD and set bomb state to "detonated" when timer runs out
  460.   }
  461. }//close serialOutput();
  462.  
  463.  
  464. /*********************************************************************
  465. *       Serial LCD disagnostic and general use tools                 *
  466. *   selectLineOne(); | selectLineTwo(); | goTo(); | clearLCD();      *
  467. *      backlightOn(); | backlightOff(); | serCommand();             *
  468. **********************************************************************/
  469. void selectLineOne(){  //puts the cursor at line 0 char 0.
  470.    Serial.print(0xFE, BYTE);   //command flag
  471.    Serial.print(128, BYTE);    //position
  472. }
  473. void selectLineTwo(){  //puts the cursor at line 0 char 0.
  474.    Serial.print(0xFE, BYTE);   //command flag
  475.    Serial.print(192, BYTE);    //position
  476. }
  477. void goTo(int position) { //position = line 1: 0-15, line 2: 16-31, 31+ defaults back to 0
  478. if (position<16){ Serial.print(0xFE, BYTE);   //command flag
  479.               Serial.print((position+128), BYTE);    //position
  480. }else if (position<32){Serial.print(0xFE, BYTE);   //command flag
  481.               Serial.print((position+48+128), BYTE);    //position
  482. } else { goTo(0); }
  483. }
  484.  
  485. void clearLCD(){
  486.    Serial.print(0xFE, BYTE);   //command flag
  487.    Serial.print(0x01, BYTE);   //clear command.
  488. }
  489. void backlightOn(){  //turns on the backlight
  490.     Serial.print(0x7C, BYTE);   //command flag for backlight stuff
  491.     Serial.print(157, BYTE);    //light level.
  492. }
  493. void backlightOff(){  //turns off the backlight
  494.     Serial.print(0x7C, BYTE);   //command flag for backlight stuff
  495.     Serial.print(128, BYTE);     //light level for off.
  496. }
  497. void serCommand(){   //a general function to call the command flag for issuing all other commands  
  498.   Serial.print(0xFE, BYTE);
  499. }
  500.  
  501. //END of bomb program.