Crypto Locker – Yaakulya’s Final Project

Concept Introduction : The Crypto Locker Puzzle is an interactive project designed to challenge users with a series of numbers-cracking tasks under time constraints. The objective is to solve hints and enter correct codes using a custom-built interface to unlock a cardboard box and win the prize inside. This game combines physical computing with digital elements to create an engaging and educational experience.

Link to P5.js Sketch: Click Here

Images of the project:

Initial Design , Credits to Dall-E.

Image of the unlocked candy box

Image of the wirings and breadboard (backside)

Image of the main user controller box.

User testing video:

1) Initial Testing: https://youtu.be/sKT85G0hJLI

2) Final Testing: https://youtu.be/hXSzTsB5x3o

Key Features:

1) Dynamic Countdown Timer: A prominently displayed timer adds a sense of urgency and excitement to the gameplay. It counts down from a set time, pushing players to think and act quickly, which enhances the challenge and engagement of the puzzle.

2) Cryptic Hints Display: As players progress, cryptic hints are displayed on the screen to aid in decoding the puzzle. This feature helps to balance the difficulty level and ensures that the puzzle remains solvable while still challenging.

3) Feedback on Input Accuracy: When players enter a code, the interface immediately provides feedback. If the code is incorrect, players are prompted to try again, and if correct, a success message is displayed, and the box unlocks. This immediate feedback loop keeps players engaged and informed.

Components I used:

1) Arduino Uno: Serves as the main controller for input and output operations.
2) Servo Motor: Operates the locking mechanism of the box.
3) Potentiometer: Allows users to select digits for the code
4) Button: Used for entering selected digits and navigating through the game.
5) P5.js: It acts like a digital interface that provides instructions, feedback, and manages the timer and attempt counter.

IM Show Pictures: People interacting with my project

Auto Locking Video: https://youtube.com/shorts/AAga9JHQt6c?feature=share


 

What’s the role of P5.js and Aurdino in this project?

P5.js Sketch: The P5.js sketch handles the game logic and user interface. It displays hints and the countdown timer.

Images:


Arduino Sketch: The Arduino controls the hardware aspects of the project. It uses a servo motor to lock and unlock the box. A potentiometer is used for dialing in digits (0-9), and a button confirms the entry of each digit. The Arduino sends these inputs to the P5.js program, which processes them to determine if the entered code matches the required one.

#include <Servo.h> // Include the Servo library

const int buttonPin = 2; // Push button connected to digital pin 2
int buttonState = 0;     // Variable to store the button state
const int potPin = A0;   // Potentiometer connected to analog pin A0
Servo servoMotor;        // Create a servo motor object

void setup() {
  pinMode(buttonPin, INPUT); // Set button pin as input
  Serial.begin(9600);        // Initialize serial communication
  servoMotor.attach(9);      // Attach the servo motor to digital pin 9
  servoMotor.write(0);       // Set initial position of the servo motor to 0 degrees
}

void loop() {
  buttonState = digitalRead(buttonPin); // Read the state of the button
  
  // If the button is pressed (buttonState is LOW)
  if (buttonState == LOW) {
    Serial.println("Button pressed!"); // Send message to serial monitor
    delay(1000); // Delay to debounce the button
  }
  
  // Read the value from the potentiometer and send it to the serial port
  int potValue = analogRead(potPin); // Read the value from the potentiometer
  int mappedValue = map(potValue, 0, 1023, 0, 10); // Map the value to the range 0-9
  Serial.println(mappedValue); // Send the mapped value to the serial port
  
  // Check if a signal is received from p5.js to control the servo motor
  while (Serial.available() > 0) {
    int signal = Serial.read(); // Read the signal from serial port
    if (signal == '0') { // Signal to reset servo motor to 0 degrees
      servoMotor.write(5); // Turn the servo motor to 0 degrees
    } else if (signal == '1') { // Signal to turn servo motor to 90 degrees
      servoMotor.write(90); // Turn the servo motor to 90 degrees
    }
  }
  
  delay(100); // Delay for stability
}

How the communication between P5.js and Aurdino Worked??

Initially I prepared the Arduino sketch to transmit data over the serial port. I wrote code to read sensor inputs, such as button presses or potentiometer values, and sent this data as messages over the serial port using functions like Serial.println() or Serial.write(). In my P5.js sketch, I initialized a serial port object within the setup() function using the new p5.SerialPort() constructor. This object represented the communication channel between my P5.js sketch and the Arduino connected to my computer.

Later I configured the serial port to listen for incoming data by using the serial.on('data', serialEvent) function. This setup ensured that whenever data was received on the serial port, the serialEvent function was automatically called, allowing my P5.js sketch to react to data sent from the Arduino.  Within the serialEvent function of my P5.js sketch, I read incoming data from the serial port using the serial.readLine() function. This function retrieved a line of text sent from the Arduino over the serial port. I then processed this data based on its content, performing actions such as updating the display or triggering events in my P5.js sketch.

Additionally, I enabled bidirectional communication by allowing my P5.js sketch to send data back to the Arduino. This allowed me to control actuators connected to the Arduino, such as servo motors or LEDs, from my P5.js sketch. I used the serial.write() function to send data from my P5.js sketch to the Arduino and vice-versa, facilitating interactive control over hardware components.

Schematics of the complete circuit:

How the initial game works:

Challenges and Code I’m Particularly Proud of:

Among various aspects of my project, there’s one particular area that stands out – the locking mechanism.

Initially, the locking mechanism was designed to activate when the user entered all the codes correctly within a specific time frame. Subsequently, P5.js was supposed to send a signal to Arduino instructing it to rotate the servo motor to 90 degrees. However, I encountered challenges in implementing this functionality. Despite extensive debugging efforts, I struggled to achieve the desired outcome. It took numerous tutorial videos and multiple attempts, but eventually, I successfully resolved the issue.

// Check if the final number matches the correct code
  if (finalNumber === currentNumCode) {
    currentImage = congratsImg; // Display 'congrats.png'
    // Stop all other sounds and play win
    stopAllSounds();
    winSound.play();
    // Send signal to turn servo motor to 90 degrees
    serial.write('1');
  } else {
    currentImage = wrongImg; // Display 'wrong.png'
    // Stop all other sounds and play error
    stopAllSounds();
    errorSound.play();
  }

  // Reset values for the next round
  dashValues = [0, 0, 0, 0];
  currentDashIndex = 0;
  allowNumberSelection = false;
  clearInterval(timerInterval); // Stop the timer
}

Following the adjustment, I found that relying solely on correct numerical input wasn’t effective. Instead, I implemented a solution where upon displaying the “congrats.png” image in P5.js, the servo motor rotates 90 degrees, indicated by the code serial.write('1');. Conversely, if the “congrats.png” image is not displayed, the servo motor remains at 0 degrees, signified by serial.write('0');.

function serialEvent() {
  let message = serial.readLine(); // Read the incoming serial data

  if (message.includes("Button pressed!")) {
    // Toggle between images based on currentImage
    if (currentImage === welcomeImg) {
      serial.write('0');
      currentImage = instImg;
      // Stop all other sounds and play bgm
      stopAllSounds();
      bgmSound.play();
      // Reset the dashes to 0 when returning to welcomeImg
      dashValues = [0, 0, 0, 0];
      currentDashIndex = 0;
      allowNumberSelection = false;
      // Send signal to reset servo motor to 0 degrees
      
    } else if (currentImage === instImg) {
      allowNumberSelection = true; // Allow number selection

After successfully implementing this functionality, I extended its use beyond just locking mechanisms. I ensured that the system would automatically lock after the user restarted the game, enhancing the overall user experience.

Future Improvements and Comments  from Users:

1. As initially planned in the game development, I would like to introduce a concept of levels. This will give players a strong sense of achievement as they complete each level. This is what one of my friend suggested after playing the game after multiple times.

2. To enhance this project even more, I aim to create a compelling story that will engage players deeply in the crypto game and enhance their overall gaming experience. In addition I would also like to add the SFX, for the number selection and opening the box.

3. Finally, I plan to add more locks (servo motors) to the candy box to make it more challenging to open. This will further motivate players to experience the thrill of unlocking the box.

Overall, I would say this has been an incredible opportunity to test my hardware skills. Admittedly, I struggled at the beginning. However, as I delved deeper into the project, things gradually became more interesting. At one point, I even assembled the circuit without consulting any references, which I’m really proud of!

I would like to wholeheartedly thank my friends, professor, and everyone who played the Crypto Locker Game. The excitement people showed when unlocking the box under time constraints made me forget all the challenges I faced during the build. This experience has significantly heightened my interest in physical computing! Looking forward…

 

 

 

 

 

 

Leave a Reply