Group 1: Escape Room Game Treasure Hunt

Upon successful completion of your last task, you were given an RFID tag. You must place this tag on the scanner inside the treasure box to start this game. In this game, there are 3 levels you must complete. In each level, you will be presented with a riddle you must solve. After you have solved all 3 riddles, you will find a key inside the treasure box that will allow you to start the next game in the escape room.

Prototyping

2-D Prototype: The top image represents the display board and the interactive board. On the display board, the user sees the riddle and the 3 LED lights that indicates which levels they have completed. The interactive board is where the user completes each level. We use three different components for each level: buttons, potentiometers, and sensors. On the top left corner is the scanner, where the user taps their RFID tag to begin the game. The bottom image represents the hidden components within the cardboard box (i.e. the brain of the game). This contains the breadboard and Arduino Uno. Additionally, the key is hidden within the box as well, and is only shown when the user completes the game. Upon completion, the servo rotates 90 degrees to unlock the box so the the user can retrieve the key.

3-D Prototype: As you can see below, we built a physical prototype of what our final design would potentially look like, for the purposes of making sure all of our components can fit in the cardboard box. On the top is the display, where the riddle is shown. On the bottom is the interactive board. The user must flip the covering to reveal the light sensors. The user must press the 3 buttons in a certain order. And finally, the user must adjust the potentiometers to be at a certain degree.

Digital Prototype: On the left is the basic design of the escape room game, where the user interacts with the User Interaction Board and the Riddle and Level Display. The backend is contained within the treasure box, which the user is unable to see. This includes the wires, breadboard, and Arduino. Additionally, the Lockbox is hidden inside the treasure box, and only revealed to the user once they complete the game. On the top right corner is the Riddle and Level Display. When the user receives the RFID tag from the previous game, they must scan it on the top left corner. There are 3 LED lights that indicate to the user which level they are on, as well as the successful completion of each level. For example, the first light will light up after the user completes the first level. Additionally, there is a screen that contains the riddle for each level. And on the bottom right corner is the User Interaction Board. On the top left corner, there is covering that reveals a single light sensor. Below it are 3 buttons. On the right, there are 2 potentiometers. These 3 interactive features represent the 3 levels of the game. For example, the first level requires the user to interact with the buttons.

Project Timeline

Week 9We created 3 types of prototypes: a 2D model, a 3D model, and a digital model. Details of all prototypes are described above in the design blog.
Week 10We ordered our external tool, an RFID tag and scanner. We were also able to find a display screen in the “junk” pile. Additionally, we wrote pseudocode to run our program, as well as compiled all the internal tools we needed, including different types of wires, potentiometers, LED lights, and light sensor.
Week 11The external components we ordered arrived this week, so we tested the RFID scanner and LED display screen to work individually. Once we got them functional and understood the functions of the code syntax, we implemented them into our project’s code. After compiling the code to ensure that each level of the game worked and each component was functional in regards to the game, we built the physical infrastructure for our game. This included using a cardboard box to contain the breadboard and Arduino. We cut holes in the cardboard to fit the LED lights, buttons, and potentiometers.
Week 12In the last week, we tested our game to make sure everything worked by putting ourselves in the shoes of users. We even had some other students who were non-technical to play our game in order to receive user feedback, which we incorporated into our final design.

Project Tasks

KatherinePrototyping 
Documentation and Design blog
PeterCode 
Testing
NickCode
Testing

Maker Manual

Overview

Below is the final product of our escape room game! It differs slightly from our prototypes, such that we decided against the hidden key box and Servo required to open it at the end of the game. Instead, we chose to show that the user won on the display screen. Additionally, we moved the scanner from being shown on the outside of the box to inside the box, due to wire length restraints.

To begin the game, the user must tap the RFID tag to the scanner on the side of the box. The game will then begin by showing the first riddle on the display screen. To complete the first riddle, the user must press the first button 5 times, the second button 1 time, and the third button 1 time (this is the module number!). After successful completion, the second riddle is prompted on the display screen. To complete the second riddle, the user must turn the top potentiometer to the right, and the bottom potentiometer down. Once this is complete, the final riddle will appear on the display screen. In order to solve the final riddle, the user must lift the covering on the board to reveal a light sensor. Once all three levels are solved (in consecutive order), the user has won, which will also be displayed on the screen.

Components

  • Arduino Uno, breadboard, wires, resistors 
  • 3 LED lights (to indicate level of completion)
  • RFID (for user to begin game)
  • Cardboard box 
  • Screen (to display riddles for user)
  • 1 Light sensor
  • 3 Buttons
  • 2 Potentiometers

Breadboard Layout

Build

Most components needed for this project were available to us in the electronics lab. We used one of the unused cardboard boxes as our escape room’s container, and only had to cut and tape some areas of it for parts of the game. The Arduino Uno, breadboard, and wires are all contained within the box, with a cardboard cover to hide it underneath the buttons, potentiometers, and lights. We attached the RFID scanner and the riddle screen to the top of the box. Most of the connections were straightforward and can be seen in the breadboard layout. However some of the wires needed to be stripped in order to properly connect to the buttons.

Code

#include <SPI.h>
#include <MFRC522.h>
 
#define RST_PIN         9          // Configurable, see typical pin layout above
#define SS_PIN          10         // Configurable, see typical pin layout above
 
MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance
 
//libraries for display
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
 
//set pins
int ledPins[] = {6,7,8};
int potPin1 = A0;
int potPin2 = A1;
const int butPin1 = 3;
const int butPin2 = 4;
const int butPin3 = 5;
int photoPin1 = A2;
 
//set inital values for input
int potV1 = 0;
int potV2 = 0;
int butState1 = 0;
int butState2 = 0;
int butState3 = 0;
 
int s1=0;
int s2=0;
int s3=0;
 
int s1Done = 0;
int s2Done = 0;
int s3Done = 0;
 
int butc1 = 0;
int butc2 = 0;
int butc3 = 0;
 
int ll1 = 0;
int ll2 = 0;
 
//Declare display
LiquidCrystal_I2C lcd(0x27, 16, 2);
 
void setup() {
  Serial.begin(9600);   // Initialize serial communications with the PC
  while (!Serial);    // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
  SPI.begin();      // Init SPI bus
  mfrc522.PCD_Init();   // Init MFRC522
  delay(4);       // Optional delay. Some board do need more time after init to be ready, see Readme
 
  lcd.begin();
  lcd.print("Scan ID badge to    unlock game");
  // Turn on the blacklight
  lcd.backlight();
 
 
  //set pins as input or output
  pinMode(butPin1, INPUT);
  pinMode(butPin2, INPUT);
  pinMode(butPin3, INPUT);
 
 
  for(int i=0; i<3; i++){
    pinMode(ledPins[i], OUTPUT);
  }
}
 
void loop() {
  // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return;
  }
 
  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) {
    return;
  }
  Serial.println("scanned");
 
  //checks for failure
  if(s2Done == 2){
    s1Done = 0;
    butc1 = 0;
    butc2 = 0;
    butc3 = 0;
  }
 
  if(s1 == 0){
    lcd.clear();
    lcd.print("Clue 1: What module are we currently in?");
    stageOne();
    digitalWrite(ledPins[2], HIGH);
  }
 
  if(s2 == 0){
    lcd.clear();
    lcd.print("Clue 2: right,      then down");
    stageTwo();
   
  }
  if(s3 == 0){
    lcd.clear();
    lcd.print("Clue 3: One button  is different");
    stageThree();
  }
  finish();
 
}
 
void finish(){
   lcd.clear();
   lcd.print("Congratulations     You beat the box!");
}
 
void stageOne(){
  while(s1Done == 0){
 
    //check for button presses
    butState1 = digitalRead(butPin1);
    butState2 = digitalRead(butPin2);
    butState3 = digitalRead(butPin3);
 
    readButtonInput();
  }
  //check for failure state
  if(s1Done = 2){
    return;
  }
  //write to corresponding indicator LED
  else{
 
  s1 = 1;
  }
}
 
void failure(){
  //reset all button values
  s1Done = 0;
  butc1 = 0;
  butc2 = 0;
  butc3 = 0;
  //run stage one again
  stageOne();
}
 
void stageTwo(){
  while(s2Done == 0){
    //read potentiometer values
    potV1 = analogRead(potPin1);
    potV1 = map(potV1, 0, 1022, 0, 10);
    potV2 = analogRead(potPin2);
    potV2 = map(potV2, 0, 1022, 0, 10);
    Serial.println(potV1);
    Serial.println(potV2);
 
    //check for proper input
    if(potV1 == 8 && potV2 == 1){
      s2Done = 1;
    }
 
 
  delay(100);
  }
  //write to corresponding indicator LED
  digitalWrite(ledPins[1], HIGH);
  s2 = 2;
}
 
void stageThree(){
  while(s3Done == 0){
    //read light values
    ll1 = analogRead(photoPin1);
    Serial.println(ll1);
 
    //check for proper light values
    if(ll1 < 200){
      s3Done = 1;
    }
 
    delay(100);
  }
  //write to corresponding indicator LED
  digitalWrite(ledPins[0], HIGH);
  s3 = 3;
 
}
 
int readButtonInput() {
  unsigned long duration = 2000;
  unsigned long lastPress = millis();
  boolean firstPress = true;
 
  do {
    // get at least one press
    if (digitalRead(butPin1) == LOW) {
      Serial.println("press1");
      butc1 += 1;
      delay(300);
      lastPress = millis();
      firstPress = false;
    }
    if (digitalRead(butPin2) == LOW) {
      Serial.println("press2");
      butc2 += 1;
      delay(300);
      lastPress = millis();
      firstPress = false;
    }
    if (digitalRead(butPin3) == LOW) {
      Serial.println("press3");
      butc3 += 1;
      delay(300);
      lastPress = millis();
      firstPress = false;
    }
  } while(firstPress || (butc1 < 10 && butc2 < 10 && butc3 < 10 && millis() - lastPress <= duration));
 
  Serial.println(butc1);
  Serial.println(butc2);
  Serial.println(butc3);
 
  //check for failure state
    if(butc3 > 1 || butc2 > 1 || butc1 > 5){
      butc1 = 0;
      butc2 = 0;
      butc3 = 0;
      s1Done == 2;
    }
 
     //check for win state
    if(butc3 == 1 && butc2 == 1 && butc1 == 5){
      s1Done = 1;
    }
    delay(100);
  return;
}

Testing & Shortcomings

We tested each phase of the game separately. The first phase is scanning the RFID tag to begin the game. We used serial print statements to ensure that the tag initiated the game once scanned. We also tested to see if we could scan the tag if the scanner was placed inside the cardboard box. The second phase is the three levels of the game. We first ensured that each component (buttons, light sensor, and potentiometers) were working. We then tested that upon successful completion of each game, the display will show the riddle for the next level, and that the code switched to the correct case. The final phase is the finale of the game, where the user completes all 3 levels. We made sure that once the 3 LED lights were lit, the display will show that the user won.

In our initial prototypes, we were hoping to use a servo that would rotate 90 degrees to reveal the key inside the cardboard box. However, due to space constraints and reliability, we decided against using the servo. Instead, we chose to display a message on the screen, indicating that the user has won.

Additionally, you may have noticed that we changed the placement of some of our components, such as the 3 LED lights moved to the bottom left corner. This was due to the wire being too short, and we were not able to extend it to be at the top of the cardboard box.