Advertisement
doktorinjh

Briefcase Bomb Defusal Game Code

Nov 11th, 2019
1,836
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Arduino 20.92 KB | None | 0 0
  1. /* Latest Build: 11/11/19
  2.  *  Includes: Keypad puzzle, 7-segment countdown, Morse Code puzzle, Rotary Puzzle,
  3.  *  MP3 sounds, Missile Toggle, Patch Cable Puzzle
  4.  *  
  5.  *  Patch cable puzzle modified from Playful Technologies:
  6.  *  https://www.patreon.com/playfultech/
  7.  *  
  8.  *  Images of the final build here:
  9.  *  https://imgur.com/gallery/J6HdM0v
  10.  *  
  11.  *  Video demonstration of the electrical components here:
  12.  *  https://www.youtube.com/watch?v=WK6nwx5pwIw
  13.  */
  14.  
  15. //-----Defines-----//
  16.   #define numberOfSeconds(_time_) ((_time_ / 1000) % 60)  // For Countdown
  17.   #define numberOfMinutes(_time_) (((_time_ / 1000) / 60) % 60) //For Countdown
  18.   #define Password_Length 7 // For Keypad Passcode
  19.   //#define DEBUG
  20.   //#define STATEDEBUG;
  21.  
  22. //-----Includes-----//
  23.   #include <Wire.h>                 // Segment Display
  24.   #include <LiquidCrystal.h>        // LCD
  25.   #include <Keypad.h>               // Keypad
  26.   #include <Adafruit_NeoPixel.h>    // Neopixels
  27.   #include "Arduino.h"              // MP3 Player
  28.   #include "SoftwareSerial.h"       // MP3 Player
  29.   #include "DFRobotDFPlayerMini.h"  // MP3 Player
  30.   #include <TM1637Display.h>        // Segment Display
  31.   #include <SimpleRotary.h>         // Rotary Switch
  32.   #include "TM1637.h"               // Rotary 7-segment Display
  33.  
  34. //-----Patch Puzzle Setup-----//
  35.   int sA = 36; // 0
  36.   int sB = 34; // 1
  37.   int sC = 32; // 2
  38.   int sD = 30; // 3
  39.   int sE = 28; // 4
  40.   int sF = 26; // 5
  41.   int sG = 24; // 6
  42.   int sH = 22; // 7
  43.   int s1 = 37; // 8
  44.   int s2 = 35; // 9
  45.   int s3 = 33; // 10
  46.   int s4 = 31; // 11
  47.   int s5 = 29; // 12
  48.   int s6 = 27; // 13
  49.   int s7 = 25; // 14
  50.   int s8 = 23; // 15
  51.  
  52.   const byte numSockets = 16;
  53.   const byte signalPins[numSockets] = { sA, sB, sC, sD, sE, sF, sG, sH, s1, s2, s3, s4, s5, s6, s7, s8 };
  54.   const byte numConnections = 6;
  55.   const byte connections[numConnections][2] = { {3,14}, {5,8}, {7,12}, {1,13}, {6,9}, {2,11} }; // D7, F1, H5, B6, G2, C4
  56.   bool lastState[numConnections] = { false, false, false, false, false, false };
  57.   enum PuzzleState {Initialising, Running, Solved};
  58.   PuzzleState puzzleState = Initialising;
  59.   bool Patch_Puzzle_is_good = false;
  60.  
  61. //-----Missle Toggle Setup-----//
  62.   const int MissleLED =  4;                     // Missle LED pin
  63.   int MissleLEDState = LOW;                     // ledState used to set the LED
  64.   unsigned long MissleLEDpreviousMillis = 0;    // will store last time LED was updated
  65.   const long MissleLEDinterval = 200;           // interval at which to blink (milliseconds)
  66.   const int MissleSwitch = 2;                   // MissleSwitch pin
  67.   int MissleSwitchState = 1;
  68.  
  69. //-----BarrelSwitch Setup-----//
  70.   const int BarrelSwitch =  5;
  71.   int BarrelSwitchState = 1;
  72.  
  73. //-----DFPlayer Setup-----//
  74.   SoftwareSerial mySoftwareSerial(11, 10);      // RX, TX
  75.   DFRobotDFPlayerMini myDFPlayer;
  76.   void printDetail(uint8_t type, int value);
  77.  
  78. //-----Neopixel: Setup 7 LEDs on Pin 3-----//
  79.   Adafruit_NeoPixel strip = Adafruit_NeoPixel (7, 3, NEO_RGB + NEO_KHZ800);
  80.  
  81. //-----KeyPad Setup-----//
  82.   int signalPin = A0;                           // Signal pin when password is correct
  83.   char KeypadData[Password_Length];
  84.   char KeypadMaster[Password_Length] = "012798"; //PASSWORD
  85.   byte Keypad_data_count = 0, Keypad_master_count = 0;
  86.   bool KeypadPass_is_good = false;
  87.   char customKey; //Keypad Button Name
  88.   const byte ROWS = 4;
  89.   const byte COLS = 3;
  90.   char hexaKeys[ROWS][COLS] = {
  91.     {'1', '2', '3'},
  92.     {'4', '5', '6'},
  93.     {'7', '8', '9'},
  94.     {'*', '0', '#'}};
  95.   byte rowPins[ROWS] = {50, 40, 42, 46}; // Keypad Row Location
  96.   byte colPins[COLS] = {48, 52, 44}; // Keypad Column Location
  97.   Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
  98.  
  99. //-----LCD Setup-----//
  100.   const int rs = 17, en = 18, d4 = 39, d5 = 41, d6 = 43, d7 = 45;
  101.   LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
  102.   int lcdbacklight = 12;
  103.  
  104. //-----Segment Countdown Setup-----//
  105.   const uint8_t OFF[] = {0, 0, 0, 0};
  106.     // Byte order is .GFEDCBA
  107.   const uint8_t PLAY[] = {B01110011, B00111000, B01011111, B01101110};
  108.   const uint8_t DEAD[] = {0x5E, 0x79, 0x77, 0x5E};
  109.   const uint8_t colon = 0b01000000;
  110.   TM1637Display countdown1(7, 6);     // Display 1 (Clock pin, Data pin)
  111.    
  112.   // 1000ms in 1sec, 60secs in 1min, 60mins in 1hr. So, 1000x60x60 = 3600000ms = 1hr
  113.   unsigned long timeLimit = 3600000;
  114.   unsigned long timeRemaining = timeLimit - millis();
  115.   unsigned long countdowndelay;
  116.  
  117. //-----Morse Code Setup-----//
  118.   int morseunit = 250;
  119.   int dash = (3.3*morseunit);
  120.   int dot = (1.4*morseunit);
  121.   int shortspace = (1.3*morseunit);
  122.   int longspace = (4*morseunit);
  123.   int morsetiming[] =
  124.   {longspace, dash, shortspace, dot, shortspace, dash, shortspace, dot,             // "C" -.-.
  125.    longspace, dot, shortspace, dash,                                                // "A" .-
  126.    longspace, dot, shortspace, dot, shortspace, dot, shortspace, dash,              // "V" ...-
  127.    longspace, dot,                                                                  // "E" .
  128.    longspace, dot, shortspace, dot, shortspace, dot, shortspace,                    // "S" ...
  129.    longspace, longspace, longspace};                                                // Long pause
  130.  
  131.   unsigned long currentMorseMillis = 0;
  132.   unsigned long startMorseMillis = 0;
  133.   int morsestep = 0;
  134.  
  135. //-----7 Segment on 5 (CLK), 4 (D10)-----//
  136.   TM1637 rotaryLCD(A0, A1);
  137.  
  138. //-----Pin A, Pin B, Button Pin-----//
  139.   SimpleRotary rotary(14, 15, 16);
  140.   int rotarycount = 0;
  141.   int rotaryposition = 0;
  142.   char rotarynumbers[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  143.  
  144. //-----Rotary Password Setup-----//
  145.   int Rotary_data[4];
  146.   int Master_Password = 4295;
  147.   bool Rotary_pass_is_good = false;
  148.  
  149. //-----Puzzle States------//
  150.   bool puzzleStart = false;
  151.   bool puzzleComplete = false;
  152.  
  153. //-------------------------------------------------------------SETUP-----------------------------------------------//
  154.  
  155. void setup(){
  156.  
  157. //-----Missle Switch-----//
  158.   pinMode(MissleLED, OUTPUT);
  159.   pinMode(MissleSwitch, INPUT_PULLUP);
  160.  
  161. //-----Barrel Switch-----//
  162.   pinMode(BarrelSwitch, INPUT_PULLUP);
  163.  
  164. //-----Patch Puzzle-----//
  165.   for (int i=0; i<numSockets; i++){  
  166.       pinMode(signalPins[i], INPUT_PULLUP);}
  167.     #ifdef DEBUG
  168.       Serial.begin(9600);
  169.       Serial.println(F("Serial communication started"));
  170.     #endif
  171.     puzzleState = Running;
  172.  
  173. //-----LCD's number of columns and rows-----//
  174.   lcd.begin(16, 2);
  175.   pinMode(signalPin, OUTPUT);
  176.   pinMode(lcdbacklight, OUTPUT);
  177.  
  178. //-----Clear Programmable LEDs-----//
  179.   strip.begin();                  // Reset LEDs
  180.   strip.show();
  181.  
  182. //---------DFPlayer Setup Options-----------//
  183.   mySoftwareSerial.begin(9600);
  184.   Serial.begin(9600);
  185.    //-----Initialization-----//
  186.       #ifdef STATEDEBUG
  187.       Serial.println();
  188.       Serial.println(F("DFRobot DFPlayer Mini Demo"));
  189.       Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
  190.       #endif
  191.    //-----Debug-----//  
  192.       if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
  193.         #ifdef STATEDEBUG
  194.         Serial.println(F("Unable to begin:"));
  195.         Serial.println(F("1.Please recheck the connection!"));
  196.         Serial.println(F("2.Please insert the SD card!"));
  197.         #endif
  198.         while(true);}
  199.       #ifdef STATEDEBUG
  200.       Serial.println(F("DFPlayer Mini online."));
  201.       #endif
  202.       myDFPlayer.setTimeOut(500); //Set serial communictaion time out 500ms
  203.    //----Set volume and EQ----//
  204.       myDFPlayer.volume(25);  //Set volume value (0~30)
  205.       myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
  206.       myDFPlayer.outputDevice(DFPLAYER_DEVICE_SD);
  207.      
  208. //-----Neopixel Setup-----//    
  209.   // ClearLEDs();
  210.    
  211. //---------Segment Display Setup-----------//
  212.   countdown1.setBrightness(0x0c); // Set brightness
  213.   countdown1.setSegments(OFF);    // Clear the display
  214.  
  215. //---------Rotary and 7-seg Display Setup-----------//
  216.   rotaryLCD.init();               // Clears the display
  217.   rotaryLCD.set(2);               // TYPICAL = 2,BRIGHT_DARKEST = 0,BRIGHTEST = 7;
  218.   rotary.setTrigger(HIGH);        // Set trigger (Default: HIGH)
  219.   rotary.setDebounceDelay(5);     // Set debounce (Default: 2)
  220.   rotary.setErrorDelay(200);      // Set error correction (Default: 200)
  221. }
  222.  
  223. //--------------------------------------------------------LOOP------------------------------------------------------//
  224.  
  225. void loop(){
  226.   BarrelSwitchState = digitalRead(BarrelSwitch);
  227.   MissleSwitchState = digitalRead(MissleSwitch);
  228.  
  229.   #ifdef STATEDEBUG
  230.     STATEDEBUGPRINT();
  231.   #endif
  232.  
  233.   if (BarrelSwitchState == 0) {
  234.      Serial.println("In the Start Up if statement");
  235.      puzzleStart = true;
  236.      digitalWrite(lcdbacklight, HIGH);
  237.      rotaryLCD.display(0, 0);
  238.      rotaryLCD.display(1, 0);
  239.      rotaryLCD.display(2, 0);
  240.      rotaryLCD.display(3, 0);
  241.      countdowndelay = millis();
  242.      lcd.setCursor(0,0);
  243.      lcd.print("Enter Password:");
  244.      myDFPlayer.playMp3Folder(6);     // Power, 60 Minutes (SD/Mp3/0001.mp3)
  245.     }
  246.  
  247.   while (puzzleStart == true && Patch_Puzzle_is_good == false) {
  248.     #ifdef STATEDEBUG
  249.     STATEDEBUGPRINT();
  250.     Serial.println("In the Puzzle While statement");
  251.     delay(2000);
  252.     #endif
  253.    
  254.     if (KeypadPass_is_good == false) {
  255.     KeypadPuzzle();}
  256.    
  257.     countdowntimer();
  258.     RotaryEncoderPuzzle();
  259.     PatchPuzzle();
  260.    
  261.     if (KeypadPass_is_good == true){
  262.       //Serial.println("KeypadPass is good");
  263.       MorsePuzzle();}
  264.   }
  265.   while (Patch_Puzzle_is_good == true){
  266.    
  267.       #ifdef STATEDEBUG
  268.       STATEDEBUGPRINT();
  269.       Serial.println("In the Final if statement");
  270.       Serial.println(MissleSwitchState);
  271.       delay(2000);
  272.       #endif
  273.    
  274.     countdowntimer();
  275.     MissleLEDBlink();
  276.     MissleSwitchState = digitalRead(MissleSwitch);
  277.    
  278.     if (MissleSwitchState == 0) {
  279.     puzzleComplete = true;
  280.     myDFPlayer.playMp3Folder(10);         // Final Disarm (SD/Mp3/0001.mp3)
  281.     }
  282.     while (puzzleComplete == true) {
  283.       digitalWrite (MissleLED, HIGH);
  284.      
  285.       lcd.clear();
  286.       lcd.setCursor(0,0);
  287.       lcd.print("** EXPLOSIVES **");
  288.       lcd.setCursor(0,1);
  289.       lcd.print("**  Disarmed  **");
  290.       FlashGreenLEDs ();
  291.      
  292.       #ifdef STATEDEBUG
  293.         STATEDEBUGPRINT();
  294.         Serial.println("*****   Game Over!!!   *****");
  295.         delay(10000);
  296.       #endif
  297.     }
  298.   }
  299. }
  300.  
  301. //---------------------------------------------------SUBROUTINES-------------------------------------------------//
  302.  
  303. void KeypadPuzzle(){
  304.     customKey = customKeypad.getKey();
  305.   if (customKey){
  306.     KeypadData[Keypad_data_count] = customKey;
  307.     lcd.setCursor(Keypad_data_count,1);
  308.     lcd.print(KeypadData[Keypad_data_count]);
  309.     Keypad_data_count++; }
  310.  
  311.   if(Keypad_data_count == Password_Length-1 && KeypadPass_is_good == false){
  312.     lcd.clear();
  313.     //ClearPasskeyLEDs();
  314.  
  315.     if(!strcmp(KeypadData, KeypadMaster)){
  316.       lcd.setCursor(0,0);
  317.       lcd.print("Code OK: ");
  318.       lcd.print(KeypadMaster);
  319.       lcd.setCursor(0,1);
  320.       lcd.print("D7");
  321.       myDFPlayer.playMp3Folder(11); //Correct Code (SD/Mp3/0001.mp3)
  322.       KeypadPass_is_good = true;
  323.       }
  324.     else{
  325.       lcd.print("INCORRECT");
  326.       myDFPlayer.playMp3Folder(9); //incorrect Code (SD/Mp3/0001.mp3)
  327.       countdowndelay = countdowndelay - 60000; // add 1 minute penalty
  328.       delay(500);
  329.       lcd.clear();
  330.       clearData();
  331.       lcd.setCursor(0,0);
  332.       lcd.print("Enter Password:");}  
  333.   }
  334. }
  335.  
  336. void clearData(){
  337.     while(Keypad_data_count !=0){
  338.       KeypadData[Keypad_data_count--] = 0;}
  339.     return;
  340.     //ClearLEDs ();
  341.   }
  342.  
  343. void ClearLEDs   () {                                  // Turns all LEDs off
  344.     for (int i = 0; i < 6; i++) {
  345.     strip.setPixelColor(i, 0);}
  346.     strip.show();
  347.   }
  348.  
  349. void ClearPasskeyLEDs   () {                                  // Turns all LEDs off
  350.     for (int i = 0; i < 6; i++) {
  351.     strip.setPixelColor(i, 0);}
  352.     strip.show();
  353.   }
  354.  
  355. void FlashGreenLEDs () {                                // Flashes all LEDs Green
  356.    int repeat = 3;                                      // Number of flashes
  357.    for (int x = 0; x < repeat; x++) {
  358.     for (int i = 0; i < 6; i++) {
  359.       strip.setPixelColor(i, 0, 35, 0);
  360.       strip.show();}
  361.     delay(500);
  362.     ClearLEDs();
  363.     delay(500);
  364.     }
  365.    
  366.     for (int i = 0; i < 7; i++) {
  367.       strip.setPixelColor(i, 0, 35, 0);}
  368.       strip.show();
  369. }
  370.  
  371. void FlashRedLEDs () {
  372.    int repeat = 3;                                      // Number of flashes
  373.    for (int x = 0; x < repeat; x++) {
  374.     for (int i = 0; i < 7; i++) {
  375.       strip.setPixelColor(i, 35, 0, 0);
  376.       strip.show();}
  377.       ClearPasskeyLEDs();
  378.     }
  379. }
  380.  
  381. void MorsePuzzle () {
  382.     currentMorseMillis = millis();
  383.   if (currentMorseMillis - startMorseMillis <= (morsetiming[morsestep])) {}
  384.   else {
  385.     startMorseMillis = currentMorseMillis;
  386.     morsestep++;
  387.   }
  388.   if ((morsetiming[morsestep]) == dash) {
  389.     MorseLEDon();                               //Serial.println("Dash");
  390.   }
  391.   else if ((morsetiming[morsestep]) == dot) {
  392.     MorseLEDon();                               //Serial.println("Dot");
  393.   }
  394.   else if ((morsetiming[morsestep]) == longspace) {
  395.     MorseLEDoff();                              //Serial.println("Longspace");
  396.   }
  397.   else if ((morsetiming[morsestep]) == shortspace) {
  398.     MorseLEDoff();                              //Serial.println("Shortspace");
  399.   }
  400.   if (morsestep == 31) {
  401.   morsestep = 0;
  402.   }
  403. }
  404.  
  405. void MorseLEDon() {
  406.   strip.setPixelColor(6, 0, 65, 0);
  407.   strip.show();
  408.   //Serial.println("On");
  409. }
  410.  
  411. void MorseLEDoff() {
  412.   strip.setPixelColor(6, 0, 0, 0);
  413.   strip.show();
  414.   //Serial.println("Off");
  415. }
  416.  
  417. void countdowntimer() {
  418.  
  419.   if(timeRemaining > 0 && timeRemaining < 3602000) {
  420.     int seconds = numberOfSeconds(timeRemaining);
  421.     int minutes = numberOfMinutes(timeRemaining);
  422.     countdown1.showNumberDecEx(seconds, 0, true, 2, 2);           // Displays seconds in last two places
  423.     countdown1.showNumberDecEx(minutes, 0b01000000, true, 2, 0);  // Minutes first two places w/ colon
  424.     timeRemaining = timeLimit - millis() + countdowndelay;        // Update the time remaining
  425.     //Serial.println (timeRemaining/1000);
  426.   }
  427.   else {
  428.     countdown1.setSegments(DEAD);
  429.     delay(500);
  430.     countdown1.setSegments(OFF);
  431.     delay(500);
  432.   }
  433.   if(timeRemaining > 2699000 && timeRemaining < 2700000) {
  434.     myDFPlayer.playMp3Folder(100); // 45 minutes remaining
  435.   }
  436.   if(timeRemaining > 1801000 && timeRemaining < 1802000) {
  437.     myDFPlayer.playMp3Folder(101); // 30 minutes remaining
  438.   }
  439.   if(timeRemaining > 1201000 && timeRemaining < 1202000) {
  440.     myDFPlayer.playMp3Folder(102); // 20 minutes remaining
  441.   }
  442.   if(timeRemaining > 601000 && timeRemaining < 602000) {
  443.     myDFPlayer.playMp3Folder(103); // 10 minutes remaining
  444.   }
  445.   if(timeRemaining > 301000 && timeRemaining < 302000) {
  446.     myDFPlayer.playMp3Folder(104); // 5 minutes remaining
  447.   }
  448.   if(timeRemaining > 61000 && timeRemaining < 62000) {
  449.     myDFPlayer.playMp3Folder(105); // 1 minute remaining
  450.   }
  451.   if(timeRemaining > 31000 && timeRemaining < 32000) {
  452.     myDFPlayer.playMp3Folder(106); // 30 seconds remaining
  453.   }
  454.   if(timeRemaining > 11000 && timeRemaining < 12000) {
  455.     myDFPlayer.playMp3Folder(107); // 10 seconds remaining
  456.   }
  457.   if(timeRemaining > 6000 && timeRemaining < 7000) {
  458.     myDFPlayer.playMp3Folder(108); // 5 4 3 2 1... Final boom
  459.   }
  460. }
  461. void displayText() {
  462.   countdown1.setSegments(PLAY);
  463.   delay(2000);
  464. }
  465.  
  466. void RotaryEncoderPuzzle() {
  467.     if (Rotary_pass_is_good == false) {
  468.     byte r;
  469.     byte p;
  470.  
  471.     r = rotary.rotate();  // CW = 1, CCW = 2
  472.     p = rotary.push();    // 0 = not pushed, 1 = pushed
  473.  
  474.     if (r == 1 ) {
  475.       rotarycount++;
  476.       if (rotarycount == 10) {
  477.         rotarycount = 0;}
  478.       rotaryLCD.display(rotaryposition, rotarycount);
  479.       Rotary_data[rotaryposition] = rotarycount;
  480.     }
  481.  
  482.     if (r == 2) {
  483.       rotarycount--;
  484.       if (rotarycount == -1) {
  485.         rotarycount = 9;}
  486.       rotaryLCD.display(rotaryposition, rotarycount);
  487.       Rotary_data[rotaryposition] = rotarycount;
  488.     }
  489.  
  490.     if (p == 1) {
  491.       #ifdef STATEDEBUG
  492.       Serial.println(Rotary_data[rotaryposition]);
  493.       #endif
  494.      
  495.       rotaryposition++;
  496.       rotarycount = 0;
  497.       rotaryLCD.display(rotaryposition, rotarycount);
  498.     }
  499.    
  500.     if (rotaryposition == 4) {
  501.       int password = (Rotary_data[0] * 1000) + (Rotary_data[1] * 100) + (Rotary_data[2] * 10) + (Rotary_data[3] * 1);
  502.       #ifdef STATEDEBUG
  503.       Serial.print("Entered Password: ");
  504.       Serial.println(password);
  505.       #endif
  506.       if (password - Master_Password == 0) {
  507.         #ifdef STATEDEBUG
  508.         Serial.println("Password Match");
  509.         #endif
  510.         Rotary_pass_is_good = true;
  511.           rotaryLCD.init();
  512.           rotaryLCD.display(1, 15);   // "F"
  513.           rotaryLCD.display(2, 1);    // "1"
  514.           myDFPlayer.playMp3Folder(11);             // Correct Code (SD/Mp3/0001.mp3)
  515.         }
  516.       else {
  517.         #ifdef STATEDEBUG
  518.         Serial.println("Password Wrong");
  519.         #endif
  520.         myDFPlayer.playMp3Folder(9);               // Incorrect Code (SD/Mp3/0001.mp3)
  521.         countdowndelay = countdowndelay - 60000;   // Add 1 minute penalty
  522.         //else below this for not matching passcode
  523.         rotaryposition = 0;
  524.         rotaryLCD.display(0, 0);
  525.         rotaryLCD.display(1, 0);
  526.         rotaryLCD.display(2, 0);
  527.         rotaryLCD.display(3, 0);
  528.         rotarycount = 0;
  529.         rotaryLCD.display(rotaryposition, rotarycount);
  530.       }
  531.     }
  532.   }
  533. }
  534.  
  535. void PatchPuzzle() {
  536.  
  537.   if (puzzleState == Solved) {
  538.     //MissleLEDBlink ();
  539.   }
  540.   // Assume that all wires are correct
  541.   bool AllWiresCorrect = true;
  542.  
  543.   // Assume that the puzzle state has not changed since last reading
  544.   bool stateChanged = false;
  545.  
  546.   // Check each connection in turn  
  547.   for (int i=0; i<numConnections; i++){
  548.  
  549.     // Get the pin numbers that should be connected by this wire
  550.     byte pin1 = signalPins[connections[i][0]];
  551.     byte pin2 = signalPins[connections[i][1]];
  552.  
  553.     // Test whether the appropriate pins are correctly connected
  554.     bool currentState = isConnected(pin1, pin2);
  555.        
  556.     if (currentState != lastState[i]) { // Has the connection changed since last reading?
  557.            
  558.       strip.setPixelColor(i, 0, 65, 0); // turn on NeoPixel in order
  559.       strip.show();
  560.      
  561.       myDFPlayer.playMp3Folder(i);      // Patch Sequence Order (SD/Mp3/[i].mp3)
  562.      
  563.       stateChanged = true;              // Show state of the puzzle has changed
  564.      
  565.       lastState[i] = currentState;      // Update the stored connection state                
  566.     }
  567.    
  568.     // If any connection is incorrect, puzzle is not solved
  569.     if(currentState == false) {
  570.       AllWiresCorrect = false;
  571.     }        
  572.   }
  573.  
  574.   // If a connection has been made/broken since last time we checked
  575.   if(stateChanged) {
  576.     #ifdef DEBUG
  577.       // Dump to serial the current state of all connections
  578.       for (uint8_t i=0; i<numConnections; i++) {
  579.         Serial.print(F("Pin#"));
  580.         Serial.print(signalPins[connections[i][0]]);
  581.         Serial.print(F(" - Pin#"));
  582.         Serial.print(signalPins[connections[i][1]]);
  583.         Serial.print(F(" : "));
  584.         Serial.println(lastState[i] ? "CONNECTED" : "NOT CONNECTED");
  585.  
  586.       }
  587.       Serial.println(F("----------------"));
  588.     #endif
  589.   }
  590.  
  591.   // If the state of the puzzle has changed
  592.   if (AllWiresCorrect && puzzleState == Running){
  593.     onSolve();
  594.   }
  595.   // If the state of the puzzle has changed
  596.   else if (!AllWiresCorrect && puzzleState == Solved){
  597.     onUnsolve();
  598.   }
  599. }
  600.  
  601. void onSolve() {
  602.   #ifdef DEBUG
  603.     Serial.println(F("The puzzle has been solved!"));
  604.   #endif
  605.    
  606.   Patch_Puzzle_is_good = true;  
  607.   puzzleState = Solved;
  608. }
  609.  
  610. void onUnsolve(){
  611.   #ifdef DEBUG
  612.     Serial.println(F("The puzzle is no longer solved!"));
  613.   #endif
  614.   digitalWrite(MissleLED, LOW);
  615.   puzzleState = Running;
  616. }
  617.  
  618. bool isConnected(byte OutputPin, byte InputPin) {
  619.   pinMode(OutputPin, OUTPUT);
  620.   pinMode(InputPin, INPUT_PULLUP);
  621.   digitalWrite (OutputPin, LOW);
  622.   bool isConnected = !digitalRead(InputPin);
  623.   pinMode(OutputPin, INPUT_PULLUP);
  624.   return isConnected;
  625. }
  626.  
  627. void MissleLEDBlink () {                                // Based on blink without delay
  628.   unsigned long MissleLEDcurrentMillis = millis();
  629.   if (MissleLEDcurrentMillis - MissleLEDpreviousMillis >= MissleLEDinterval) {
  630.     MissleLEDpreviousMillis = MissleLEDcurrentMillis;
  631.     if (MissleLEDState == LOW) {
  632.       MissleLEDState = HIGH;
  633.     } else {
  634.       MissleLEDState = LOW;
  635.     }
  636.     digitalWrite(MissleLED, MissleLEDState);
  637.   }
  638. }
  639.  
  640. void STATEDEBUGPRINT () {
  641.     Serial.print("Puzzle start is: ");
  642.   Serial.print(puzzleStart);
  643.   Serial.print(" Patch Puzzle is: ");
  644.   Serial.print(Patch_Puzzle_is_good);
  645.   Serial.print(" Barrel Switch is: ");
  646.   Serial.print(BarrelSwitchState);
  647.   Serial.print(" Missle Switch is: ");
  648.   Serial.print(MissleSwitchState);
  649.   Serial.print(" Puzzle complete is: ");
  650.   Serial.println(puzzleComplete);
  651.   delay(2000);
  652. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement