Super Secret Lock Box W/ Capacitive Touch
by rclymer in Living > Hiding Places
75218 Views, 873 Favorites, 0 Comments
Super Secret Lock Box W/ Capacitive Touch
The Arduino stays asleep to conserve battery and only wakes when the button is pressed. Upon waking, there are two paths to go down, flash the green LED, unlock, and go back to sleep OR light up the red LED and wait for 20 seconds for the right passcode, then go to sleep. In the period before it goes to sleep, if you touch(not press) the button for 5 seconds, the passcode will be set to whatever the code is currently. It will then unlock and go back to sleep. The 20 seconds timer restarts every time the button is pressed.
Parts
ATmega168/328 on a PCB or an Arduino with a breadboard
Wood Box
small servo
3x Potentiometers & knobs
push button
RGB LED
2x 100 ohm resistors
150 ohm resistors
battery pack
wire
depending on how you make the latch, these parts will be up to you, I used 1/4" square dowels to make the latch and supports
Tools
Skills with a Dremmel
Soldering Iron
Hot Glue Gun
Wood Glue (I recommend Gorilla Wood Glue, the non-foaming kind)
If anyone can decipher the suspected Japanese characters, I would really love to know the original purpose of the box.
UPDATE:
He loved it!
Cut and Wire It Up!
If you plan to use the arduino development board instead of a standalone version, be sure to bypass the 5V regulator by using the 5V pin to power it instead of VIN or the barrel jack. Trying to conserve any battery is pointless if it is being used.
Connect 5V, GND and data lines to the appropriate pins. Remember to use resistors on the LED, red needs 150 ohms while blue and green need 100 ohm resistors.
Remember, the pots must be connect to analog pins.
Whichever battery pack you choose must output a max voltage of 5.5V and a minimum of 4.5v. (3AA wired in series should work). The ATmega328 will run nicely anywhere from 1.8 to 5.5v but the servo requires a bit more juice. The data sheet for a 9g servo says 4.8v minimum. Since it is more common to find packs with 4 batteries which would produce 6v, a Shottkey diode can be used to drop to voltage to 5.6v. I don't think an extra .1v will damage the ATmega.
EDIT:
3x 1.5v alkaline AA wired in series = 4.5v
I used 4x 1.2v lithium batteries for 4.8v
Downloads
Code
Interrupts can be tricky, digital pin 2 is also PCINT0. that is why the button is connected to pin 2 but the interrupt is attached to 0.
#include <Servo.h>
#include <CapacitiveSensor.h>
#include <avr/sleep.h>
const byte red = 6;
const byte green = 7;
const byte blue = 8;
const byte pot1 = A0;
const byte pot2 = A1;
const byte pot3 = A2;
const byte button = 2;
int code1 = 1;
int code2 = 1;
int code3 = 1;
int pot_val1 = 0;
int pot_val2 = 0;
int pot_val3 = 0;
int button_val = 0;
int touch;
unsigned long currentMillis = 0;
unsigned long codeMillis = 0;
unsigned long buttonMillis = 0;
unsigned long sleepMillis = 0;
CapacitiveSensor cs_10_11 = CapacitiveSensor(3,4);
Servo myservo;
int sleepCounter = 0;
boolean state = LOW;
void setup()
{
Serial.begin(9600);
pinMode(red, OUTPUT);
pinMode(green, OUTPUT);
pinMode(blue, OUTPUT);
pinMode(button, INPUT);
pinMode(pot1, INPUT);
pinMode(pot2, INPUT);
pinMode(pot3, INPUT);
cs_10_11.set_CS_AutocaL_Millis(20000);
digitalWrite(button, HIGH);
attachInterrupt(0, interrupt, RISING);
}
void loop()
{
getPots(); //read in pot values
mapAllPots(); //adjust them to the correct scale
if(pot_val1 == code1 && pot_val2 == code2 && pot_val3 == code3) //if password is correct
{
Serial.println("Success!");
g(); //light green led
unlock(); //unlock the latch
sleepNow(); //go to sleep
}
else
{
Serial.println("Failure");
r(); //turn on red led
}
currentMillis = millis();
button_val = !digitalRead(button); //read the button value
//Serial.println(button_val);
//Serial.println(sleepCounter);
if(button_val == 1) //if button is pressed, reset the timers.
{
sleepMillis = currentMillis;
codeMillis = currentMillis;
}
if((currentMillis - sleepMillis) > 20000) //if timer expires, go to sleep
{
sleepMillis = currentMillis;
sleepNow();
}
touch = highLow(cs_10_11.capacitiveSensor(30)); //read touch capacitance and map it to binary HIGH or LOW
Serial.println(touch);
currentMillis = millis();
if(touch == 1)
{
if((currentMillis - codeMillis) > 5000) //if touch is 1 for 5 seconds
{
b(); //light th blue led
storeCode(); //store code from pot values
delay(300);
codeMillis = currentMillis;
}
}
if(touch == 0) //if no touch reset timer to prevent time accumulation
{
codeMillis = currentMillis;
}
}
//end of loop
////////////////////////////////
void interrupt()
{
currentMillis = millis();
if((currentMillis - buttonMillis) > 200)
{
buttonMillis = currentMillis;
}
}
void sleepNow() // here we put the arduino to sleep
{
off(); //turn off all leds
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
sleep_enable(); // enables the sleep bit in the mcucr register
// so sleep is possible. just a safety pin
attachInterrupt(0, interrupt, RISING); // use interrupt 0 (pin 2) and run function
// wakeUpNow when pin 2 gets LOW
MCUCR = bit (BODS) | bit (BODSE); // turn on brown-out enable select
MCUCR = bit (BODS); // this must be done within 4 clock cycles of above
sleep_mode(); // here the device is actually put to sleep!!
// THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
sleep_disable(); // first thing after waking from sleep:
// disable sleep...
detachInterrupt(0); // disables interrupt 0 on pin 2 so the
// wakeUpNow code will not be executed
// during normal running time
}
int highLow(unsigned long x)
{
if(x >= 300)
{
return 1;
}
else
{
return 0;
}
}
void getPots()
{
pot_val1 = analogRead(pot1);
pot_val2 = analogRead(pot2);
pot_val3 = analogRead(pot3);
}
void mapAllPots()
{
pot_val1 = mapPot(pot_val1);
pot_val2 = mapPot(pot_val2);
pot_val3 = mapPot(pot_val3);
}
int mapPot(int in)
{
if(in > 1010){
return 1;
}
else if(in > 950){
return 2;
}
else if(in > 900){
return 3;
}
else if(in > 630){
return 4;
}
else if(in > 480){
return 5;
}
else if(in > 190){
return 6;
}
else if(in > 80){
return 7;
}
else if(in > 30){
return 8;
}
else if(in > 3){
return 9;
}
}
void storeCode()
{
code1 = pot_val1;
code2 = pot_val2;
code3 = pot_val3;
}
void r()
{
digitalWrite(red, HIGH);
digitalWrite(green, LOW);
digitalWrite(blue, LOW);
}
void g()
{
digitalWrite(red, LOW);
digitalWrite(green, HIGH);
digitalWrite(blue, LOW);
}
void b()
{
digitalWrite(red, LOW);
digitalWrite(green, LOW);
digitalWrite(blue, HIGH);
}
void off()
{
digitalWrite(red, LOW);
digitalWrite(green, LOW);
digitalWrite(blue, LOW);
}
void unlock()
{
myservo.attach(9);
myservo.write(75);
delay(750);
myservo.write(96);
delay(250);
myservo.detach();
}
Latch
In my latch, the servo is not connected to the latch. It simply pushes it and hold it open for a brief period. A clothespin style spring I bent from a paper clip keeps the latch down and locked at all times. You will have to mess with the tension of the spring so that it doesn't fight the servo too hard but still remains securely latched.
I used wood glue to join pieces of 1/4" dowel rods together and carved them with a dremmel to make the latch system. It is secured to the box with wood glue.