t r o n i x s t u f f

fun and learning with electronics

Project – Single button combination lock

Time for something different  - a single button combination lock. Allow me to explain…

Updated 18/03/2013

Normally a combination lock would require the entry of a series of unique numbers in order to unlock something or start an action. For example:

(image information)

A more contemporary type of lock could be controlled electronically, for example by a keypad where the user enters a series of digits to cause something to happen. Such as the keypad on this dodgy $30 safe from Officeworks:

As you can see there is a button for each digit. You would think that this would be a good idea –  however people can watch you enter the digits, or users can be silly enough to write down the combination somewhere. In some cases the more cunning monkeys have even placed cameras that can observe keypads to record people entering the combination. There must be a better way. Possibly! However in the meanwhile you can consider my idea instead – just have one button. Only one button – and the combination is made up of the time that elapses between presses of the button. There are many uses for such an odd lock:

  • A type of combination lock that controls an electric door strike, or activates a device of some sort;
  • A way of testing mind-hand coordination for skill, or the base of a painfully frustrating game;
  • Perhaps an interlock on motor vehicle to prevent drink driving. After a few drinks there’s no way you could get the timing right. Then again, after a double espresso or two you might have problems as well.
How does it work? Consider the following:

We measure the duration of time between each press of the button (in this case – delay 1~4). These delay times are then compared against values stored in the program that controls the lock. It is also prudent to allow for some tolerance in the user’s press delay – say plus or minus ten to fifteen percent. We are not concerned with the duration of each button press, however it is certainly feasible.

To create this piece of hardware is quite easy, and once again we will use the Arduino way of doing things. For prototyping and experimenting it is simple enough to create with a typical board such as a Uno or Eleven and a solderless breadboard – however to create a final product you could minimise it by using a bare-bones solution (as described here). Now let’s get started…

For demonstration purposes we have a normally-open button connected to digital pin 2 on our Arduino-compatible board using the 10k ohm pull down resistor as such:

The next thing to do is determine our delay time values. Our example will use five presses, so we measure four delays. With the following sketch, you can generate the delay data by pushing the button yourself – the sketch will return the delay times on the serial monitor (download).

/*
  Single-button combination lock
  Delay Time data generation sketch - John Boxall June 2011
  http://tronixstuff.wordpress.com/projects | CC by-sa-nc
*/

int count=0;
unsigned long a[]={0,0,0,0,0,0};
unsigned long del[]={0,0,0,0,0};

void setup()
{
  pinMode(2, INPUT);
  Serial.begin(115200);
  Serial.println("Ready...");
}

void dataCapture()
{
  a[count]=millis();
  delay(500); // for button debounce, your value may differ
  count++;
}

void displayData()
{
    // calcualate delays between keypresses
    del[0]=a[1]-a[0];
    del[1]=a[2]-a[1];
    del[2]=a[3]-a[2];
    del[3]=a[4]-a[3];

    // display delay data for use in combination lock sketch
    for (int a=0; a<4; a++)
    {
      Serial.println();
      Serial.print("Delay ");
      Serial.print(a);
      Serial.print(" use ");
      Serial.print(del[a]);
      Serial.println(" ms");
    }
    Serial.println("- - - - - - - - -");
    count=0;
}

void loop()
{
  if (digitalRead(2)==HIGH)
  {
    dataCapture();
  }
  if (count>4)
  {
    displayData();
  }
}

So what’s going on the this sketch? Each time the button is pressed a reading of millis() is taken and stored in an array. [More on millis() in the tutorial]. Once the button has been pressed five times, the difference in time between each press is calculated and stored in the array del[]. Note the use of a 500 ms delay in the function dataCapture(), this is to prevent the button bouncing and will need to be altered to suit your particular button. Finally the delay data is then displayed on the serial monitor. For example:

The example was an attempt to count one second between each press. This example also illustrates the need to incorporate some tolerance in the actual lock sketch. With a tolerance of +/- 10% and delay values of one second, the lock would activate. With 5% – no. Etcetera.

Now for the lock sketch. Again it measures the millis() value on each button press and after five presses calculates the duration between each press. Finally in the function checkCombination() the durations are compared against the stored delay values (generated using the first sketch) which are stored in the array del[]. In our example lock sketch we have values of one second between each button press. The tolerance is stored as a decimal fraction in the variable tolerance; for example to have a tolerance of ten percent, use 0.1.

Download link

/*
  Single-button combination lock - John Boxall June 2011
  http://tronixstuff.wordpress.com/projects | CC by-sa-nc
*/

int count=0;
unsigned long a[]={0,0,0,0,0};
unsigned long b[]={0,0,0,0,0};
unsigned long del[]={1000,1000,1000,1000}; // these are the values obtained from running combilock1.pde
// delay between each button press is 1000 ms
float tolerance=.2;

void setup()
{
  pinMode(2, INPUT);
  Serial.begin(115200); // for testing purposes
  Serial.println("Start"); // for testing purposes
}

void dataCapture()
{
  a[count]=millis();
  delay(500); // for button debounce, your value may differ
  count++;
}

void checkCombination()
{
    int compare=0;
    count=0;
    // calcualate delays between keypresses
    b[0]=a[1]-a[0];
    b[1]=a[2]-a[1];
    b[2]=a[3]-a[2];
    b[3]=a[4]-a[3];

    // compare the button delay values
    if (b[0]<=(del[0]*(1+tolerance)) && b[0]>=(del[0]*(1-tolerance))) { compare++; }
    if (b[1]<=(del[1]*(1+tolerance)) && b[1]>=(del[1]*(1-tolerance))) { compare++; }
    if (b[2]<=(del[2]*(1+tolerance)) && b[2]>=(del[2]*(1-tolerance))) { compare++; }
    if (b[3]<=(del[3]*(1+tolerance)) && b[3]>=(del[3]*(1-tolerance))) { compare++; }
    if (compare==4) { success(); }
    if (compare!=4) { failure(); }
}

void success()
{
   // contains code to run when combination successfully entered
   Serial.println("Success!");
   delay(5000);
   Serial.println("- - - - -");
}

void failure()
{
   // contains code to run when combination unsuccessfully entered
   Serial.println("Failure!");
   delay(5000);
   Serial.println("- - - - -");
}

void loop()
{
  if (digitalRead(2)==HIGH)
  {
    dataCapture();
  }
  if (count>4)
  {
    checkCombination();
  }
}

When choosing your time delays, ensure they are larger than the value used for button debounce (the delay() function call) in the dataCapture() function. Notice the two functions success() and failure() – these will contain the results of what happens when the user successfully enters the combination or does not.

For a demonstration of the final product, I have connected an LCD to display the outcomes of the entry attempts. You can download the sketch from here. The key used in this example is 1,2,3,4 seconds:

Although there are four buttons on the board used in the video, only one is used. Well I hope someone out there found this interesting or slightly useful…

In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column? And join our friendly Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

 

July 2, 2011 - Posted by | arduino, education, learning electronics, microcontrollers, projects, tutorial, twitter | , , , , , , , , , , , , , , , , , , , , ,

6 Comments »

  1. Nice tutorial as always.

    Our Subaru Legacy uses something similar with the drivers door handle. Lift it a certain number of times in a sequence to unlock the door if you lock the keys in the car etc.

    hads

    Comment by Hadley Rich | July 2, 2011 | Reply

    • Thanks for your feedback.
      Interesting about the Subaru, that was news to me. What a good idea… much better than the magnetic keybox we used to use :)
      cheers
      john

      Comment by John Boxall | July 3, 2011 | Reply

  2. Thanks so much for the great tutorial! It was just in time for my project, which involves leaving a light on for half an hour (delay wouldnt work) and I also needed to make a clapper which this tutorial was perfect for! Thanks once again, and keep ‘em rolling! :)

    Comment by James Watson | July 17, 2011 | Reply

    • Hello James. Thank you for your positive feedback, I really appreciate it.
      Have a great week
      John

      Comment by John Boxall | July 17, 2011 | Reply

  3. A few years back, I’ve implemented a serial combination lock on an ATtiny2313.

    The combination consists of multiple digits like you’d have it for keypad-based locks. It is entered as short periods (time from one key press to the next one, key release times don’t matter) to count up the current digit and long periods to jump to the next digit.

    The detection algorithm only considers the ratio between short and long pulses and so adapts itself to the typing speed of the user. The only fixed timing is a global timeout that resets the state machine when typing is stopped prematurely.

    I plan to properly document and publish it at some point, but didn’t get around to it yet.

    Comment by rmax | February 22, 2012 | Reply

    • What a great idea, you should write about that if you can.
      Cheers
      John

      Comment by John Boxall | February 23, 2012 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 4,018 other followers

%d bloggers like this: