Advertisement
Guest User

wizdum

a guest
Apr 27th, 2009
8,346
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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.
  502.  
Advertisement
RAW Paste Data Copied
Advertisement