Introduction: Lego Head Safe

This instructable was created in fulfillment of the project requirement of the Makecourse at the University of South Florida (www.makecourse.com). This oroject was done by Kaitlin Bellerose, a student in the course.

The idea behind the safe is that a servo spins into place in an aperture, either opening or closing the Lego head safe. The Arduino code controls the functionality of the safe and password entry/storage.

The following materials and tools are needed for successful creation of the project:

1) Arduino Uno

2) 4x4 matrix keypad

3) Jumper wires and resistors

4) 9V battery and connector to Arduino Uno

5) Black box or similar secure box

6) LCD screen

7) Mini servo and stand

8) Mini breadboard

9) Square oak dowel

10) Black acrylic paint

11) White acrylic paint

12) Dremel and pads

13) Super glue

14) Philips head screwdriver with small head

15) 3D printer to make head

16) Fine paintbrush

17) Fine-grain and coarse-grain sandpaper

Step 1: Circuit Schematic

The circuit is pinned out as follows:

The LCD is hooked to pins AREF and GND.

The servo is attached to pin 11.

The 4x4 matrix keypad is tied to pins 8, 7, 6, 5, and 4, 3, 2, 10. I have a dead pin at 9, so the wiring is a bit jumbled. Wire yours the way it makes sense to you and what pins you have available. Keep in mind that pins 1 and 0 are reserved for TX and RX.

Step 2: 3D Printed Parts

The dimensions were scaled from the example found on the Instructables site of a Lego figurine: https://www.instructables.com/id/LEGO-Man-Costume/s...

The head was scaled in millimeters to approximately 4 times the size of the example. As for the actual printing of the part, I did not have much of a decision with regard to the orientation of the item prior to print. I received the head parts from the university visualization lab.

Once you print out the required part, super glue the pieces together. I initially tried to print out the heads that would fit snugly inside each other, but I could not get the tolerances correct to fit.

The opening at the bottoms of the Lego head is rectangular, allowing for the oblong horn (wings) of the servo. The wing is short on the vertical axis and longer on the horizontal. You may need to adjust the width of the rectangular hole (or trim the servo horn as a last resort).

The MAKE project for our class required that we use a DC-47 enclosure case. The box can be found here: http://www.polycase.com/dc-47p.

Step 3: Physical Construction

After you finish wiring the components outside of the enclosure, you will realize that choices have to be made to get the wiring to fit. But before you ever put the case together, you have to mark and cut the apertures needed to have the LCD fit into the side of the box and the servo arm fit through the top of the box.

When cutting with the Dremel, please take great care to have proper ventilation because the fumes that come off the heated-up plastic box are noxious. A safe route would be to redesign and reprint the box.

The stand I used was a castaway item provided by a classmate that happened to serve its purpose. For your purposes, find a stand or stack of stable items (like connected Lego blocks) to place the servo on.

The mess of wires is difficult to control. You will need to attach the matrix pad to the Arduino via a female-to-female connector. The servo will also need to be attached to its stand so it does not fall over due to the item being knocked or the twisting wires settling, causing it to fall. Super glue is a good choice, though, again, watch for the fumes.

The Lego head needs to have the support material removed and the roughness sanded off. I cannot recommend any particular kind or grain of sandpaper because I just used leftover fine and coarse grain sandpaper I had left over when I painted my car. As with most things, test sand in a spot that will not be visible prior to completely sanding the whole area completely.

For the cosmetic portion of the project, reference the look of a Lego head before proceeding. I recommend that you practice your strokes on a paper plate or any older iterations prior to committing the paint to the final product.

The Lego head as it is designed can easily be twisted and picked off the servo regardless of whether the servo is in closed or locked position. To stop this ability to defeat this lock by twisting the head, I glued a small piece of square dowel to the neck of the head and glue two corresponding pieces on the box lid that would straddle the dowel to prevent the head from being twisted. I painted the dowel pieces black to match the box. The dowel was obtained from Home Depot.

The matrix keypad has adhesive on the back of it, but I elected to apply the matrix keypad with super glue. To ensure that the keypad stays in place, put something heavy on top that would not necessarily set off the keypad itself (like the water glass I used).

Once done, completely fasten the screws of the box. Please keep in mind that the life of the safe is not very long because the 9V battery lasts about four hours of continuous use To keep it constantly powered, you will have to use the USB cable and cut a corresponding hole in the box for it. For the purposes of the demo, I used the 9V to have an independent system to present.

Step 4: Code

The code used existing libraries for the LCD, Servo, and Keypad. I created my own code with regard to the password system and overall functionality. The code provides three options for the safe: open, close, and set password. In order to change the password, the user has to know the existing password. The code is fully commented for the ease of a person new to programming.

The following and attached is my code. Please feel free to use it!

/***************************************************************************************************************************
Title: Lego Head Safe

Author: Kaitlin Bellerose

Date: 11/01/2014

Updated: 12/03/2014

Purpose: This sketch provides the control system for the Lego Head safe.

This sketch borrows from multiple sources. The original sources will be cited here in the title block when general approaches were followed.

1) Keypad.h library written by Mark Stanley and Alexander Brevig (mstanley@technologist.com, alexanderbrevig@gmail.com)

2) There is a password.h library available on Instructables and similar sites. I did not care for the implementation, so I created my own. ****************************************************************************************************************************/

#include <Wire.h>

#include <LiquidCrystal_I2C.h>

#include <Servo.h>

#include <Keypad.h>

LiquidCrystal_I2C lcd(0x27,16,2); // Instantiate a 16x2 I2C LCD display with address 0x27

Servo myServo; // Instantiate a servo

int pos; // Declare variable to hold servo position value (NOTE: "position is a reserved word)

int servoSpeed; // Declare variable to hold servo speed value (NOTE: "speed" is a reserved word) char password[3]; // Array that holds master password. Set to length you would like. I chose 3 for ease of demo char entry[3]; // Array that holds the user-entered password attempt

boolean isAlreadyOpen; // Flag that tracks whether safe is already open

boolean isAlreadyClosed; // Flag that tracks whether safe is already closed

const byte ROWS = 4; // Four rows in 4x4 keypad matrix

const byte COLS = 4; // Four columns in 4x4 keypad matrix

char keys[ROWS][COLS] = { // Maps the keypad values {'1','2','3', 'A'}, {'4','5','6', 'B'}, {'7','8','9', 'C'}, {'*','0','#', 'D'} };

byte rowPins[ROWS] = {8, 7, 6, 5}; // Connect to the row pinouts of the keypad

byte colPins[COLS] = {4, 3, 2, 10}; // Connect to the column pinouts of the keypad

// Use 1 or more appropriate pin for what I have labeled as "10"

// My Arduino has many dead ports I have to navigate around

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); // Instantiates a keypad with the values passed.

/********************Set-up Function*********************/

void setup(){ Serial.begin(9600); // Set serial to 9600 baud

myServo.attach(11); // Set servo to pin 11

isAlreadyOpen = 0; // Sets open flag to false

isAlreadyClosed = 1; // Sets closed flag to true

pos = 90; // Sets value for servo arm position at 90 degrees

servoSpeed = 3; // Sets servo speed to 3 degrees per second

myServo.write(pos); // Sets servo arm to 90 degrees

password[0] = '1'; // Be sure to put initial value in single quotes due to its char nature

password[1] = '2'; // Second value in password array

password[2] = '3'; // Last value in password. The password will default to "123" when // power is lost.

keypad.setDebounceTime(250); // Sets the button debounce time for the keypad

lcd.init(); // Initialize the LCD

lcd.backlight(); // Set the display to be backlit

lcd.print("Welcome Home!"); // Print welcome message to LCD

delay(1000); // Have message display for 1000 milseconds

lcd.clear(); // Clear the display

lcd.print("1) Open 2) Close"); // Print menu options

lcd.setCursor(0,1); // Move cursor to second line

lcd.print("3) Set Code"); // Print second part of menu options

delay(3000); // Delay

}

/***************Main Loop*****************/

void loop(){

entry[0] = NO_KEY; // Reset the entry array with each loop or else

entry[1] = NO_KEY; // you'll get "false" entries from existing values

entry[2] = NO_KEY; // Set the final keypad to NO_KEY (similar to setting //
value to NULL in C++)

char key = keypad.getKey(); // Get the first key press with regard to menu.

if (key == '1'){ // Initiates logic if "Open safe" option is selected

if(isAlreadyOpen == 1) // Checks to see if the safe is already open. No point in opening something already open

{

lcd.clear(); // Clear LCD

lcd.print("Safe is already"); // Prints message

lcd.setCursor(0,1); // Move cursor to second line

lcd.print("open."); // Print second part of menu options

delay(2000); // Delay 2000 miliseconds }

else // If the safe is not already open, the following code engages {

lcd.clear(); // Clear the LCD

lcd.print ("Enter 1st key:"); // Message to solicit the first key press

lcd.setCursor(0,1); // Moves cursor to second line

while (entry[0] == NO_KEY) // The loop runs until a valid key press is made

`{

entry[0] = keypad.getKey(); // Stores the first value of the user-entered attempt at password

}

lcd.print(entry[0]); // Prints value for display on LCD. Use for debugging and ease of use. delay(1000); // Delays for 1000 miliseconds

lcd.clear(); // Clears LCD

lcd.print("Enter 2nd key:"); // Enter the second key press

lcd.setCursor(0,1); // Move curosr

while (entry[1] == NO_KEY) // Another loop that will run endlessly unless a valid keypress is made

{ entry[1] = keypad.getKey(); // Stores the second value of the user-entered attempt at password }

lcd.print(entry[1]); // Prints value for display on LCD. Use for debugging and ease of use. delay(1000); // Delay for 1000 miliseconds

lcd.clear(); // Clear LCD

lcd.print("Enter 3rd key:"); // Solicit third key press

lcd.setCursor(0,1); // Moved the cursor

while (entry[2] == NO_KEY) // Again, a while loop to continuously poll unti a valid key press is made. {

entry[2] = keypad.getKey(); // Gets the final key press

}

lcd.print(entry[2]); // Prints value for display on LCD. Use for debugging and ease of use. delay(1000); // Delay for 1000 miliseconds

lcd.clear(); // Clear LCD

if ((entry[0] == password[0]) && entry[1] == password[1] && entry[2] == password[2]) // If what the user entered matches the stored password, this loop executes

{

isAlreadyOpen = 1; // Set isAlreadyOpen flag to true/high

isAlreadyClosed = 0; // Set isAlreadyClosed flag to false/low

pos = 180; // Set position to 180 degrees

myServo.write(pos); // Set the servo to 180 degrees

lcd.clear(); // Clear LCD in anticipation of message

lcd.print("Safe is open."); // Message that the safe is open

delay(2000); // Delay of 2000 miliseconds }

else // If the wrong code was entered, this executes

{

lcd.clear(); // Clear LCD

lcd.print("Invalid code."); // Invalid code message

delay(1000); // Delay 1000 miliseconds

lcd.clear(); // Clear LCD } }

mainLCDMenu(); // Regardless of whether password entry was successful, this kicks back to the main menu functions }

else if (key == '2')

{ // Initiates if "Close safe" is selected

if(isAlreadyClosed == 1) // If the head is already closed, why close it again?

{

lcd.clear(); // Clear LCD

lcd.print("Safe is already"); // Begin message that the safe is already closed lcd.setCursor(0,1); // Move cursor to second line

lcd.print("closed."); // Finish message

delay(2000); // Delay for 2000 miliseconds delay }

else // If the safe is not already closed, this executes

{ isAlreadyOpen = 0; // Sets isAlreadyOpen flag to false/low

isAlreadyClosed = 1; // Sets isAlreadyClosed flag to true/high

pos = 90; // Sets pos to 90 degrees

myServo.write(pos); // Sets servo to 90 degrees

lcd.clear(); // Clears LCD

lcd.print("Safe is closed."); // Message that the safe is closed

delay(2000); // Delay 2000 miliseconds }

lcd.clear(); // Clear LCD

mainLCDMenu(); // Either way, go back to main menu }

else if (key == '3'){ // If "Set code" option is selected

lcd.clear(); // Clear LCD

lcd.print ("Enter 1st key:"); // The code that follow is a repeat of code in option 1 lcd.setCursor(0,1); // The user has to enter the password successfully before changing it

while (entry[0] == NO_KEY)

{ entry[0] = keypad.getKey(); }

lcd.print(entry[0]);

delay(1000);

lcd.clear();

lcd.print("Enter 2nd key:");

lcd.setCursor(0,1);

while (entry[1] == NO_KEY)

{ entry[1] = keypad.getKey(); }

lcd.print(entry[1]);

delay(1000);

lcd.clear();

lcd.print("Enter 3rd key:");

lcd.setCursor(0,1);

while (entry[2] == NO_KEY)

{ entry[2] = keypad.getKey(); }

lcd.print(entry[2]);

delay(1000);

lcd.clear();

if ((entry[0] == password[0]) && entry[1] == password[1] && entry[2] == password[2]) // If the password was correctly entered, this logic executes

{ password[0] = NO_KEY; // Reset the password value 0 to NO-KEY password[1] = NO_KEY; // Reset the password value 1 to NO-KEY password[2] = NO_KEY; // Reset the password value 2 to NO-KEY

lcd.print ("Set 1st key:"); // Set first key value

lcd.setCursor(0,1);

while (password[0] == NO_KEY) // Loops endlessly until valid key press received { password[0] = keypad.getKey(); // Sets password[0] to new value } lcd.print(password[0]); // Prints out new value

delay(1000);

lcd.clear(); // Clear LCD

lcd.print("Set 2nd key:"); // Message for 2nd key

lcd.setCursor(0,1); // Move code

while (password[1] == NO_KEY) // Loops endlessly until valid key press received { password[1] = keypad.getKey(); // Sets password[1] to new value } lcd.print(password[1]); // Prints out new value

delay(1000); // Delay 1000 miliseconds

lcd.clear(); // Clear LCD

lcd.print("Set 3rd key:"); // Message for third key

lcd.setCursor(0,1); // Move cursor

while (password[2] == NO_KEY) // Loops endlessly until valid key press received { password[2] = keypad.getKey(); // Sets password[2] to new value }

lcd.print(password[2]); // Prints out new value

delay(1000); // Delay 1000 miliseconds

lcd.clear(); // Clear LCD }

else // This executes if the user enters the wrong password for verification prior { // to changing the password. User cannot change password without knowing the password

lcd.clear(); // Clear LCD

lcd.print("Invalid code."); // Invalid code message

delay(1000); // Delay 1000 miliseconds

lcd.clear(); // Clear LCD }

mainLCDMenu(); // Regardless of outcome, go back to the main menu

} }

Step 5: Final Product

Once the final screw is tightened, enjoy!

Comments

author
seamster made it!(author)2014-12-11

Nicely done!

About This Instructable

457views

5favorites

License:

More by kbeller09:Lego Head Safe
Add instructable to: