Hi everyone. I am creating an escape room puzzle based on Alastair Aitchison's "Cut the Wires" project. I started with his code but cut a lot out because he was using LED lights, WiFi, and special effects lighting, which I am not. I added in 4 sound files using TMRpcm library to use during different stages.
I have it working almost perfectly, except the end result of "defusing the bomb" happens no matter the order of the 4 correct wires. I have 5 wires available, with only 4 needing to be cut, and of that, I did specify in the beginning of my code what the order should be. Any ideas on how to tweak my code so it ONLY defuses when wires from Pins 3, 4, 5, then 6 are cut in that exact order???
Attached is my wiring diagram and code. Thanks in advance for any suggestions!
```cpp
/**
* "Cut The Wires" defuse bomb puzzle
*
* Players must "cut" the correct wires in order(via releasing alligator clips) to stop
* the ticking clock. If the clock reaches zero (after 60 minutes), the bomb "explodes"
* with sound effects. If wires are "cut" out of order, the ticking will get faster.
*/
#define DEBUG
#define SD_ChipSelectPin 10
#include <SD.h>
#include <TMRpcm.h>
#include <SPI.h>
TMRpcm tmrpcm;
// CONSTANTS
const byte numWires = 5;
const int wirePins[numWires] = {2, 3, 4, 5, 6};
// Define the number of steps in the sequence that the player must follow
// GLOBALS
int lastState[numWires];
// What is the order in which wires need to be cut
// 0 indicates the wire should not be cut
int wiresToCut[numWires] = {0, 1, 2, 3, 4}; // (blue, red, yellow, green)
byte wiresCutCounter = 1;
// Keep track of the current state of the device
enum State {Inactive, Active, Defused, Exploded};
State state = State::Inactive;
//This is the timestamp at which the bomb will detonate
//It is calculated by adding on the specified number of minutes in the game time
// to the value of millis() when the code is initialised.
unsigned long detonationTime;
//The game length (in minutes)
int gameDuration = 60;
void Activate() {
state = State::Active;
// Set the detonation time to the appropriate time in the future
detonationTime = millis() + (unsigned long)gameDuration*60*1000;
Serial.println("Bomb activated!");
}
void Deactivate() {
state = State::Inactive;
}
void Detonate() {
state = State::Exploded;
}
void setup() {
tmrpcm.speakerPin = 9;
Serial.begin(9600);
if (!SD.begin(SD_ChipSelectPin)) {
Serial.println("SD fail");
}
// Initialise wire pins
for(int i=0; i<numWires; i++) {
pinMode(wirePins[i], INPUT_PULLUP);
lastState[i] = digitalRead(wirePins[i]);
}
// Set the detonation time to the appropriate time in the future
detonationTime = millis() + (unsigned long)gameDuration*60*1000;
// Print the initial state of the wires
for(int i=0; i<numWires; i++) {
Serial.println(F("Wire "));
Serial.print(i);
Serial.println(digitalRead(wirePins[i])? " Unconnected" : " Connected");
}
// Arm the bomb!
Activate();
tmrpcm.play("slow.wav");
tmrpcm.volume(5);
};
void loop() {
// First, see if any of the wires have been recently cut
for(int i=0; i<numWires; i++) {
// If the previous reading was LOW, but now it's HIGH, that means this wire must have been cut
if(digitalRead(wirePins[i]) == HIGH && lastState[i] == LOW) {
Serial.println("Wire ");
Serial.print(i);
Serial.println(" cut");
lastState[i] = HIGH;
// Was this the correct wire to cut?
if(wiresCutCounter == wiresToCut[i]) {
// Go on to the next counter
wiresCutCounter++;
}
// Incorrect wire cut
else {
// Play faster ticking sound effect
tmrpcm.setVolume(5);
tmrpcm.play("fast.wav");
}
}
// If the previous reading was LOW, but now it's HIGH, that means this wire must just have been cut
else if(digitalRead(wirePins[i]) == LOW && lastState[i] == HIGH) {
Serial.println(" Wire ");
Serial.println(i);
Serial.println( " reconnected");
lastState[i] = LOW;
}
}
// Now, test the current state of all wires against the solution state
//First, assume that the correct wires have all been cut
bool allWiresCut = true;
// Then, loop over the wires array
for(int i=0; i<numWires; i++) {
// Every wire that has a number > 0 in the wiresToCut array should be cut (at some point), after which they will read HIGH,
// So if any of them still read LOW, that means that there is at least one wire still to be cut
if (wiresToCut[i] !=0 && lastState[i] == LOW) {
allWiresCut = false;
}
}
// What to do next depends on the current state of the device
if(state == State::Active) {
// Retrieve the current timestamp
unsigned long currentTime = millis();
if(currentTime > detonationTime) {
Detonate();
Serial.println("BOOM!");
tmrpcm.setVolume(5); // play explosion sound effect
tmrpcm.play("expl.wav");
}
else if(allWiresCut == true) {
Deactivate();
Serial.println("Bomb defused!");
tmrpcm.setVolume(5); // Play Sousa music
tmrpcm.play("Sous.wav");
}
else {
}
}
}