ITTT - Digital Money Safe

by joyderuijter in Circuits > Arduino

274 Views, 3 Favorites, 0 Comments

ITTT - Digital Money Safe

RenderModel3.png
RenderModel4.png

I created a digital money safe using an Arduino Uno, for an assignment from a course called ITTT provided by HKU (Hogeschool van de Kunsten Nederland).

In this instructable I will guide you through all the steps I took to create a completely functional digital money safe / secured piggy bank.

The safe is lasercut (lasercut-file included) and will ask the user to enter their chosen pincode in order to open te door, this pincode can be changed as well and will be saved on the local storage of the Arduino Uno, thus it will remember your pincode, even after turning the Arduino completely off.

Let's get to it!

Supplies

ELECTRONICAL COMPONENTS

  • 1 x Arduino Uno
  • 1 x LCD Display 16x2
  • 1 x Potentiometer Rotary 10K Ohm
  • 1 x Adjustable Potentiometer Rotary Angle Sensor Module
  • 2 x Tactile Push Button Switch Momentary 12x12x7.3mm with Button Caps
  • 1 x Micro Servo SG90 180degrees
  • 1 x Green LED 5mm
  • 1 x Resistor 1K Ohm
  • 1 x Resistor 220 Ohm
  • At least one big enough PCB board (I used one 20x80mm and one 30x70 PCB)
  • Male to Male jumper wires
  • Female to Female jumper wires

CASING

  • At least 400x400mm regular MDF board 3mm
  • At least 700x500mm black MDF board 3mm
  • A small hinge for the door (I used a 22x25mm hinge)
  • Nuts and bolts for the hinge (I used 4 nuts and bolts M3 10mm)
  • A cabinet knob of your liking (I used a wooden round knob 25mm)

TOOLS & OTHER SUPPLIES

  • A drill with a wood drill bit
  • A laser cutter machine
  • A wrench that fits your hinge bolts
  • A soldering iron with solder
  • A wire stripper
  • Wood glue (preferably one that turns transparent when dry)
  • Masking tape (or something else that can hold your MDF pieces together when the glue is drying)
  • Duct tape (or other really strong adhesive tape)
  • Electrical tape
  • Scissors

PROTOTYPING (skip This Step If You Are Not Interested in My Design Process)

WhatsApp Image 2022-04-14 at 12.32.30 PM.jpeg
WhatsApp Image 2022-04-14 at 12.39.51 PM (1).jpeg
Screenshot_20220525-151641_Sketchbook.jpg
Screenshot_20220525-230635_Sketchbook.jpg
Copy of Arduino simulator AND (1).png
20220526_134620.jpg

The concept of the final product originated from a smaller project I had a few months before this project (Seminar Using Arduino For Evil). In this smaller project I created a simple piggybank that used a LCD screen to tell the user that they were broke once they threw coins in it.

For this larger project I decided to completely upgrade this idea into something that is actually functional and still uses some of the components I already tested before e.g. the LCD screen.

I started designing a simple safe that used a potentiometer as code input and the LCD screen as visual output, as you can see in my sketches. For the circuit I decided to use an Arduino Simulator online (Tinkercad) to test my concept. When I got this circuit working online, I copied it onto 2 real breadboards and started testing my self-written code until it worked perfectly. As soon as this was the case, I moved on to the next step.

CODE

Upload this code to your Arduino:

(It won't work yet ofcourse, so you can do this later as well, but this was my first step)

// WRITTEN BY: JOY DE RUIJTER

#include <LiquidCrystal.h>
#include <EEPROM.h>
#include <Servo.h>

LiquidCrystal lcd (12,11,5,4,3,2);
//                (RS,E,D4,D5,D6,D7)

Servo servoLock;

int ledPin = 8;
int saveButtonPin = 9;
int resetButtonPin = 10;

int turnButtonValue = 0;
int lastTurnButtonValue = 0;

int lastResetButtonState = 0;
int resetButtonState = 0;

int lastSaveButtonState = 0;
int saveButtonState = 0;

int currentCodeIndex = 0;
int code[4]; 
int inputCode[4];

bool isUnlocked = false;
bool isResettingCode = false;

byte leds = 0;

void setup()
{
  Serial.begin(9600);
    
  pinMode(ledPin, OUTPUT); // GREEN LED
  pinMode(saveButtonPin, INPUT_PULLUP); // WHITE BUTTON
  pinMode(resetButtonPin, INPUT_PULLUP); // RED BUTTON
  pinMode(A5, INPUT); // TURNBUTTON

  // READ THE STORED CODED FROM MEMORY
  code[0] = EEPROM.read(0); 
  code[1] = EEPROM.read(1);
  code[2] = EEPROM.read(2);
  code[3] = EEPROM.read(3);

  lcd.begin (16,2); // LCD SCREEN

  // SET START VALUES
  lcdStartRoutine();
  lastTurnButtonValue = turnButtonValue;
  digitalWrite(ledPin, LOW);

  Serial.print(String(code[0]) + " " + String(code[1]) + " " + String(code[2]) + " " + String(code[3]));
}

void loop()
{
  resetButtonState = digitalRead(resetButtonPin); 
  saveButtonState = digitalRead(saveButtonPin);
  turnButtonValue = convertAnalogInput((int)analogRead(A5));
  
  if (!isUnlocked) // IF THE VAULT IS LOCKED
  {
    if (turnButtonValue != lastTurnButtonValue) // IF THE TURN BUTTON HAS BEEN USED
    {
        Serial.println(String((int)analogRead(A5)));
        updateCode(turnButtonValue);
    } 
  
    lastTurnButtonValue = turnButtonValue;
  
    if (lastSaveButtonState == 1 && saveButtonState == 0) // IF THE WHITE BUTTON HAS BEEN PRESSED
      saveInputCodeNumber(turnButtonValue);
  
    lastSaveButtonState = saveButtonState;
    
    if (lastResetButtonState == 1 && resetButtonState == 0) // IF THE RED BUTTON HAS BEEN PRESSED
      resetInput();
    
    lastResetButtonState = resetButtonState;
  }
  
  else // IF THE VAULT IS UNLOCKED
  {
    if (lastSaveButtonState == 1 && saveButtonState == 0) // IF THE WHITE BUTTON HAS BEEN PRESSED
    {
      lock();
      return;
    }

    lastSaveButtonState = saveButtonState;
    
    if (lastResetButtonState == 1 && resetButtonState == 0) // IF THE RED BUTTON HAS BEEN PRESSED
      resetCode();
    
    lastResetButtonState = resetButtonState;
    
    while (isResettingCode) // WHILE THE USER IS SETTING A NEW PASSCODE
    {
      resetButtonState = digitalRead(resetButtonPin); 
      saveButtonState = digitalRead(saveButtonPin);
      turnButtonValue = convertAnalogInput((int)analogRead(A5));;
      
      if (turnButtonValue != lastTurnButtonValue) // IF THE TURN BUTTON HAS BEEN USED
        updateCode(turnButtonValue);
  
      lastTurnButtonValue = turnButtonValue;
      
      if (lastSaveButtonState == 1 && saveButtonState == 0) // IF THE WHITE BUTTON HAS BEEN PRESSED
        saveCodeNumber(turnButtonValue);
  
      lastSaveButtonState = saveButtonState;
      
      if (lastResetButtonState == 1 && resetButtonState == 0) // IF THE RED BUTTON HAS BEEN PRESSED
        resetInputNewCode();
    
      lastResetButtonState = resetButtonState;
      
      delay(50);
    }
  }
  delay(50);
}

void lcdStartRoutine() // START THE LCD AND PLAY IT'S START ROUTINE, ENDS AT THE INPUT SCREEN
{
  lcd.setCursor (0,0);
  lcd.print ("       HI       ");
  lcd.setCursor (0,1);
  lcd.print ("       :)       ");
  delay (1500);
  
  lcd.setCursor (0,1);
  lcd.print ("       ;)       ");
  delay (1000);
  
  lcd.setCursor (0,1);
  lcd.print ("       :)       ");
  delay (1000);
  
  lcd.clear();
  lcd.setCursor (0,0);
  lcd.print ("ENTER THE CODE");
  lcd.setCursor (0,1);
  lcd.print("_ _ _ _");
}

void updateCode(int number) // UPDATE THE CODE ON THE LCD, DISPLAYING THE NUMBER THAT HAS BEEN PASSED ON
{
  if (currentCodeIndex == 0) // IF THE USER IS SELECTING THE FIRST NUMBER OF THE CODE
  {
    lcd.setCursor (0,1);
    lcd.print(String(number) + " _ _ _"); 
  }
  else if (currentCodeIndex == 1) // IF THE USER IS SELECTING THE SECOND NUMBER OF THE CODE
  {
    lcd.setCursor (0,1);
    lcd.print(String(inputCode[0]) + " " + String(number) + " _ _");
  }
  else if (currentCodeIndex == 2) // IF THE USER IS SELECTING THE THIRD NUMBER OF THE CODE
  {
    lcd.setCursor (0,1);
    lcd.print(String(inputCode[0]) + " " + String(inputCode[1]) + " " + String(number) + " _");
  }
  else if (currentCodeIndex == 3) // IF THE USER IS SELECTING THE FOURTH NUMBER OF THE CODE
  {
    lcd.setCursor (0,1);
    lcd.print(String(inputCode[0]) + " " + String(inputCode[1]) + " " + String(inputCode[2]) + " " + String(number));
  }
}

void resetInput() // RESET THE USERS GIVEN INPUT SO FAR AND START OVER WITH ENTERING THE CODE
{
  inputCode[0] = 0;
  inputCode[1] = 0;
  inputCode[2] = 0;
  inputCode[3] = 0;
  
  currentCodeIndex = 0;
  
  lcd.clear();
  lcd.setCursor (0,0);
  lcd.print ("ENTER THE CODE");
  lcd.setCursor (0,1);
  lcd.print("_ _ _ _");
}

void resetInputNewCode() // RESET THE USERS GIVEN INPUT SO FAR AND START OVER WITH SETTING A NEW CODE
{
  inputCode[0] = 0;
  inputCode[1] = 0;
  inputCode[2] = 0;
  inputCode[3] = 0;
  
  currentCodeIndex = 0;
  
  lcd.clear();
  lcd.setCursor (0,0);
  lcd.print ("SET NEW CODE");
  lcd.setCursor (0,1);
  lcd.print("_ _ _ _");
}

void resetCode() // RESET THE PASSCODE BY GIVING THE USER THE POSSIBILITY TO SET A NEW ONE
{
  isResettingCode = true;
  currentCodeIndex = 0;
  
  lcd.clear();
  lcd.setCursor (0,0);
  lcd.print ("SET NEW CODE");
  lcd.setCursor (0,1);
  lcd.print("_ _ _ _");
}

void wrongCode() // THE ROUTINE THAT IS PLAYED WHEN THE USER ENTERS A WRONG CODE
{
  digitalWrite(ledPin, HIGH);
  delay(500);
  digitalWrite(ledPin, LOW);
  delay(500);
  digitalWrite(ledPin, HIGH);
  delay(500);
  digitalWrite(ledPin, LOW);
  delay(500);
  
  lcd.clear();
  lcd.setCursor (0,0);
  lcd.print ("   INCORRECT!   ");
  delay(1000);
  lcd.setCursor (0,1);
  lcd.print ("  TRY AGAIN...  ");
  delay(2000);
  
  resetInput();
}

void correctCode() // THE ROUTINE THAT IS PLAYED WHEN THE USER ENTERS THE RIGHT CODE
{
  digitalWrite(ledPin, HIGH);
    
  lcd.clear();
  lcd.setCursor (0,0);
  lcd.print ("    CORRECT!    ");

  // UNLOCK DOOR WITH SERVO
  servoLock.attach(13); // SERVO MOTOR
  servoLock.write(90);  
  delay(1000);

  servoLock.detach();
  lcd.setCursor (0,1);
  lcd.print (" DOOR UNLOCKED! ");

  isUnlocked = true; 
  
  delay(1500);
  lcd.clear();
  lcd.setCursor (0,0);
  lcd.print ("PRESS WHITE");
  lcd.setCursor (0,1);
  lcd.print ("BUTTON TO LOCK");
}

void lock() // THE ROUTINE THAT LOCKS THE DOOR AND THE ROUTINE THAT COMES WITH THAT
{
  // LOCK DOOR WITH SERVO
  servoLock.attach(13); // SERVO MOTOR
  servoLock.write(0);  

  lcd.clear();
  lcd.setCursor (0,0);
  lcd.print ("   LOCKING...   ");
  digitalWrite(ledPin, HIGH);
  delay(500);
  digitalWrite(ledPin, LOW);
  delay(500);
  digitalWrite(ledPin, HIGH);
  delay(500);
  digitalWrite(ledPin, LOW);
  delay(500);
  lcd.clear();
  lcd.setCursor (0,0);
  servoLock.detach();
  lcd.print (" DOOR IS LOCKED ");
  delay(1000);
  isUnlocked = false;
  resetInput();
}

bool checkCode() // A BOOL THAT RETURNS TRUE IF THE CODE THE USER ENTERED IS THE SAME AS THE PASSCODE, AND RETURNS FALSE IF IT IS NOT
{
  if (code[0] == inputCode[0] && code[1] == inputCode[1] && code[2] == inputCode[2] && code[3] == inputCode[3])
    return true;
  else
    return false;
}

void saveInputCodeNumber(int number) // SAVE THE NUMBER THAT IS PASSED ON IN THE INPUTCODE ARRAY, IF IT IS THE 4TH NUMBER, CHECK IF IT IS THE WRONG OR RIGHT CODE
{
  inputCode[currentCodeIndex] = number;
  if (currentCodeIndex == 3)
  {
    if (checkCode())
      correctCode();
    else
      wrongCode();
  }
  else
    currentCodeIndex = currentCodeIndex + 1;
}

void saveCodeNumber(int number) // SAVE THE NUMBER THAT IS PASSED ON IN THE CODE ARRAY, IF IT IS THE 4TH NUMBER, SAVE THE NEW CODE AND RUN THE ROUTINE THAT COMES WITH IT
{
  code[currentCodeIndex] = number;
  inputCode[currentCodeIndex] = number;
    
  if (currentCodeIndex == 3)
  {
    digitalWrite(ledPin, HIGH);
    delay(500);
    digitalWrite(ledPin, LOW);
    delay(500);
    digitalWrite(ledPin, HIGH);

    // WRITE THE NEW CODE TO THE ARDUINO INTERNAL MEMORY
    EEPROM.write(0, code[0]);
    EEPROM.write(1, code[1]);
    EEPROM.write(2, code[2]);
    EEPROM.write(3, code[3]);  
        
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(" NEW CODE SAVED ");
    delay(1000);
      
    isResettingCode = false;
      
    lcd.clear();
    lcd.setCursor (0,0);
    lcd.print ("PRESS WHITE");
    lcd.setCursor (0,1);
    lcd.print ("BUTTON TO LOCK");
  }
  else
    currentCodeIndex = currentCodeIndex + 1;
}

int convertAnalogInput(int value) // CONVERT THE ANALOG INPUT INTO AN INT USED FOR THE PIN
{ if(value <= 120) return 0; else if (value >= 121 && value <= 320) return 1; else if (value >= 321 && value <= 470) return 2; else if (value >= 471 && value <= 600) return 3; else if (value >= 601 && value <= 670) return 4; else if (value >= 671 && value <= 750) return 5; else if (value >= 751 && value <= 790) return 6; else if (value >= 791 && value <= 800) return 7; else if (value >= 801 && value <= 810) return 8; else if (value >= 811) return 9; else return 0; }

CASING

UnfoldedDesign2.png

Now it's time to create the casing of the safe!

I attached the .dxf file I created, feel free to use my design if you'd like.

Use your lasercutter machine to cut all 6 sides of the safe out of black MDF 3mm and the door out of normal MDF 3mm. Use for the circulair arrows and the money bags an etching setting, so you don't cut completely through the material. Afterwards, you are ready to attach the hinge(s) and knob to your door, and consecutively the door to the front panel. Now don't assemble the casing just yet! We still have a lot of work to do before we can start glueing.

SOLDERING

20220603_113432.jpg
20220603_113644.jpg
20220603_113706.jpg
20220528_194103.jpg
Copy of Arduino simulator AND.png

Now it is time to move on from breadboards to PCB boards, get your soldering iron hot and ready because this will take some time.

I used a seperate PCB board for my green LED and two buttons, one for my LCD screen and all the other components are just wired directly to the Arduino Uno. Use the schematical tinkercad image I provided to clearly see the connections I made and pins I used. Also make sure that you use long-enough wires, so you won't come in trouble later when you are attaching all parts to the casing.

Good luck with this step, it gets easier from here on!

ATTACHING ELECTRONICS TO CASING

20220603_134827.jpg
20220603_134906.jpg

We are almost there...

Get your duct tape, electrical tape and scissors ready to start attaching almost all electronical parts to the top side of the casing. I started with grouping my wires together with electrical tape, to keep things somewhat organized... I also used this to strengthen the connection between male and female pins and pins in the Arduino, better safe than sorry (it's hard to get to the electronics after the process is over).

After organizing my wires, I started placing the two PCBs into their holes and the Rotary Angle Sensor Module as well. Find a good place to attach your Arduino, without blocking the coin slot or getting too close to the edges, and attach it using duct tape. I used a plastic Arduino holder so I wouldn't have to tape directly onto the Arduino, but was able to double-side tape it from the bottom of the holder. For the other parts, protect the electronic elements with electrical tape, just to make sure (again better safe than sorry) no short circuiting can happen.

Now start attaching the elements with duct tape to the casing side, mind the buttons and Rotary Angle Sensor Module, they shouldn't be too tight to the casing, otherwise the buttons can't be pressed and the module can't be turned.

If all main elements are stuck to the top side, find a good spot for the LCD's potentiometer and attach it as well (it's only used for the brightness of the LCD screen, so make it so that you can still reach it and use it if you have to).

Now, the wires. Start with attaching them with duct tape as well and use electrical tape wherever you see necessary to group wires.

If everything is attached and steady, check if your buttons and Rotary Angle Sensor Module still function. If they do, move on to the final step!

FINAL / GLUEING

20220603_153433.jpg
20220603_172347.jpg
20220603_172414.jpg

In this final step, it is time for you to grab your wood glue, and start glueing all parts together. I used masking tape to hold the pieces tightly together while the glue was drying, but use any method u please.

Make sure you save the right side for last, this allows you to attach the servo motor to the left side of the safe, without too much struggle. See the first picture for the placement of this piece in my safe.

After the glue is completely dry, you are ready to attach your safe to a computer/powerbank/battery to supply energy and there you go. That's it. Have fun saving and protecting your money with this DIY digital safe!

Some small instructions for people that are not all that familiar with code:

  • Turning the rotary angle module will result in changing the value of the number of the pin you are currently entering.
  • By pressing the white button while the safe is locked, you will confirm the value that is currently displayed on the LCD screen. Start turning the rotary angle module again to select the next number.
  • By pressing the red button while the safe is locked, you will clear the pin you entered so far, in case you made a mistake.
  • The green LED lights up when the code is correct and the servo will move out of the way, so the door can be opened.
  • Pressing the white button while the safe is open, you will lock it again, so make sure the door is closed when you perform this action.
  • Pressing the red button while the safe is open, will give you the opportunity to create and save a new pincode.

VIDEO

ITTT - Joy de Ruijter - Digital Money Safe

REFLECTIE (this Is for the School Assignment, Ignore This If You Are Not One of My Teachers)

Tijdens dit project heb ik enorm veel geleerd en heb ik mijzelf vooral verbaasd. Ik wilde eigenlijk iets zeer simpels gaan maken omdat hardware echt niet mijn ding is, maar ik merkte dat ik geen motivatie kon vinden voor die concepten omdat ik ze te saai vond en niet uitdagend genoeg. Toen ik had besloten om een volledig werkende kluis te maken, ging alles eigenlijk vrij snel. Ik was heel enthousiast over mijn eigen design, maar was nog zeer sceptisch of ik dit überhaupt waar kon maken. Tot mijn verbazing ging eigenlijk vrijwel iedere stap soepel. Het solderen was wat lastig, maar is tot mijn verbazing uiteindelijk gelukt. Ook het lasersnijden ging volgens plan en het was super satisfying dat alle onderdelen in 1x perfect pasten in de gaatjes die ik had uitgemeten.

Naast het leren van de hardskills zoals solderen en lasersnijden, heb ik vooral geleerd hoe het is om een product van een schets tot een eindwerk te krijgen. Dit had ik nog nooit eerder gedaan en heeft mij verrassend genoeg best wat interesse gegeven in hardware. Ook heb ik geleerd dat ik meer buiten mijn comfort zone moet stappen en dat ik blijkbaar tot meer in staat ben dan ik zelf dacht.

Ik ben trots op mijn eindresultaat en hoop dat jullie hier net zo enthousiast over zullen zijn als ik zelf ben!

Bedankt voor het lezen van mijn documentatie!