Music Puzzle Box

by Mayhembyaden in Circuits > Arduino

174 Views, 2 Favorites, 0 Comments

Music Puzzle Box

20230813_140231.jpg
20230813_140550.jpg
Puzzlebox demo

For this project I am making a puzzle box that is inspired by vintage music boxes. I wanted to make something that you could find in an escape room. This project is beginner friendly, as it was my first time working with an Arduino, too (with minimal coding experience)

The puzzle box does the following: The five buttons correspond with a tone, if you play them in the wrong order, a red light will turn on. If you play the notes correctly, a green light will turn on and a lock on the inside will open. Sounds simple enough, right?

Supplies

Electronic components:

  • Arduino Uno
  • 1 green LED (5mm)
  • 1 red LED (5mm)
  • 5 small buttons
  • A buzzer
  • 1 servo motor
  • A breadboard
  • Circuit board
  • wires (approximately 25)
  • 2 resistors (270 ohm)
  • 5 resistors (10k ohm resistors)
  • a power source (I ended up using a power bank)

Software:

  • Arduino IDE 2.1.1

Tools used:

  • Soldering iron
  • Glue gun
  • Drill
  • Sanding paper

Other supplies:

  • A wooden jewelry box
  • Paint (I used acrylic paint and Posca markers)
  • Solder
  • Small corner anchor
  • a small mirror
  • air drying clay
  • little stones
  • glue

Test Your Supplies

20230802_121947.jpg
20230802_114222.jpg

For the first step, it is important to test all your electronics. We do this so we don't get confused when something ends up not working. For this, I used my breadboard, wires, LEDs, buzzer, buttons and servo. I used the following sources to test my supplies:

  • https://www.arduino.cc/en/Tutorial/BuiltInExamples/Button

I also modified the code to test the rest of the supplies this way. Make sure to download the libraries for the buzzer (Pitches.h) and for the servo (Servo.h).

Build Your Prototype, Arduino

20230802_144138.jpg
Arduino layout.png

It is time to finally make the prototype and to see how everything works together. For example, originally I wanted to incorporate way more lights in this project, which seemed very unnecessary and very messy when it came to cable management. So I ended up with 1 red LED and 1 green LED to tell the user if they entered the code in the correct order or not. The images will demonstrate how I connected everything.

How the lock is going to work, is that the servo motor will turn 90 degrees and hook behind a small corner anchor so the box won't be able to open.

Build Your Prototype, Code

Puzzlebox prototype

The code below is how I got everything working. The beginning of the code tells you what wires should go in what pin in the Arduino. It also determines what sequence of buttons is the right one. I also made the lock always unlock when you plug in your Arduino to a power source in case a battery runs out and you can't open your box anymore. Although this makes it easy to bypass as a security device, it is better this way if you place it in the context of an escape room. After 5 buttons are pressed the code determines if the right code has been entered. If it is incorrect the red LED turns on for one second and nothing happens. If you put in the correct code, the green LED turns on for one second and the servo turns 90 degrees and either switches to the locked state or the unlocked state.

Copy this code to the Arduino IDE. Check if everything is okay and then upload it to your Arduino.

#include "pitches.h"
#include <Servo.h>


//Define pins for the leds, number = pin arduino
const int green0 = 2;
const int red0 = 4;


//define pins for the buttons, number = pin arduino
const int button0 = 9;
const int button1 = 10;
const int button2 = 11;
const int button3 = 12;
const int button4 = 13;


//Define pin for the buzzer, number = pin arduino
const int buzzer = 8;
const int servoPin = 6;


//Define angles for the servo
const int servoLockedVal = 0;
const int servoUnlockedVal = 90;


int lastPressedButton  = -1;
int noteIndex = 0;


int correctButtons[] = {0, 2, 1, 2, 4};
bool codeCorrect;
bool ledsOn = false;
bool isLocked;
unsigned long timer;


Servo servo;


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);


  pinMode(green0, OUTPUT);
  pinMode(red0, OUTPUT);


  pinMode(button0, INPUT);
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
  pinMode(button3, INPUT);
  pinMode(button4, INPUT);


  pinMode(buzzer, OUTPUT);


  servo.attach(servoPin);
  servo.write(servoUnlockedVal);
}


void loop() {
  int buttonPressed = detectButtonPressed();
  playNote(buttonPressed);


  //if the leds are on and have been on for 1000 milliseconds, turn them off
  //if 1000 millis passed from start time, light turns off.
  if(ledsOn && millis() - timer >= 1000)
  {
    ledsOn = false;
    digitalWrite(green0, LOW);
    digitalWrite(red0, LOW);
  }

  //If the button pressed is different from the last button pressed, AND a button is pressed
  if(buttonPressed != lastPressedButton && buttonPressed != -1)
  {
    //set last pressed button to currently button
    lastPressedButton = buttonPressed;


    //If we are at the first note, reset the boolean
    if(noteIndex == 0){
      codeCorrect = true;
    }


    //If the button pressed is correct, keep codeCorrect in its current state. Otherwise, set it to false
    codeCorrect = codeCorrect && buttonPressed == correctButtons[noteIndex];


    //Increase index in sequence
    noteIndex++;
   
    //If we have gone through the entire array, check if the code was correct and handle that
    if(noteIndex > 4)
    {
      noteIndex = 0;


      if(codeCorrect)
      {
        toggleLock();
        digitalWrite(green0, HIGH);
        digitalWrite(red0, LOW);
      }
      else
      {
        digitalWrite(green0, LOW);
        digitalWrite(red0, HIGH);
      }


      //set a timer to turn the leds back off
      ledsOn = true;
      timer = millis();
    }
  }
}


//Returns -1 if no button is pressed, or the number of the rightmost pressed button if one or multiple are pressed
int detectButtonPressed()
{
  int result  = -1;
  if(digitalRead(button0) == HIGH)
  {
    result = 0;
  }


  if(digitalRead(button1) == HIGH)
  {
    result = 1;
  }


  if(digitalRead(button2) == HIGH)
  {
    result = 2;
  }


  if(digitalRead(button3) == HIGH)
  {
    result = 3;
  }


  if(digitalRead(button4) == HIGH)
  {
    result = 4;
  }


  return result;
}


void playNote(int note)
{
  //C5
  //D5
  //E5
  //F5
  //G5
  if(note == 0)
  {
    tone(buzzer, NOTE_C5);
    return;
  }


  if(note == 1)
  {
    tone(buzzer, NOTE_D5);
    return;
  }


  if(note == 2)
  {
    tone(buzzer, NOTE_E5);
    return;
  }


  if(note == 3)
  {
    tone(buzzer, NOTE_F5);
    return;
  }


  if(note == 4)
  {
    tone(buzzer, NOTE_G5);
    return;
  }


  noTone(buzzer);
}


//Turns the lock off if it was on, and on if it was off
//0 = unlocked, 90 = locked
void toggleLock()
{
  isLocked = !isLocked;
  if(isLocked)
  {
    servo.write(servoLockedVal);
  }
  else
  {
    servo.write(servoUnlockedVal);
  }
}

Soldering Everything Together

20230809_154508.jpg
20230812_135012.jpg

It is time to transfer all the wires and electrical components onto the circuit board. I personally like to use a soldering gun for this. Soldering everything together can be tricky, and it is important to keep your ground and positive separate. It is also imported to do this in a well ventilated area. Working with hot tools can be dangerous so make sure to proceed with caution.

I kept all the lights, buttons and the buzzer separate so I could freely install them in the box afterwards. Make sure to check if everything still works before assembly.

The Box

20230811_133335.jpg
20230811_232947.jpg
20230811_232940.jpg
20230812_153623.jpg

I got a simple wooden jewelry box from a crafting store and drilled holes in it. 5 small ones for the buttons and 2 small ones for the LED's at the front. I also drilled 2 larger ones on the side for the power source and the buzzer. I recommend getting a slightly bigger box than I have here, as all the components ended up a bit cramped together. You also have to make sure that the wood doesn't snap while drilling.

After the holes were drilled, I sanded them down to make them a bit more neat and to make sure everything fit perfectly.

Once I made sure everything fits, I started painting the box. I was inspired by vintage music boxes that had scenes painted on them. I painted a swan lake, inspired by the ballet.

I also made a plaque out of air drying clay, which I painted and glued on top of the box. I also glued some little stones on them, which I painted and dry brushed to give a nice textured effect.

Lastly, I painted the notes, so the user could determine what the correct code is. I also glued a mirror and the corner anchor inside of the box.

optional: spray everything with a fixative to protect the paint. Make sure there are no electronic components inside the box while doing this.

Assembly

20230812_153709.jpg

Now it is time to assemble everything and put them into place. I used hot glue for this. I also tried to do some cable management, but this ended up being a pretty difficult task as everything is so tight together. The most important thing is that no metal pins are touching each other.

When everything is installed, make sure to test your project, and it is done!

Conclusion

I learned a lot from this project. I learned how to work with an Arduino and how to code with an Arduino. I was pretty intimidated at first, but I quickly learned that it isn't as scary as I thought. I also learned how to solder, which was the most difficult and frustrating part for me, especially when my soldering iron broke halfway through. I had the most fun assembling everything together, but in the future I would give all the electronics a bit more room to make sure nothing is touching each other. I also think I should have made the holes for the button better, as they don't really fit properly. In the end, I think it turned out pretty neat!