Introduction: Hacking the Apartment Buzzer to Unlock With a Code

Are you: prone to losing your keys? Tired of letting in your party guests via intercom? Hanging out on the roof and can't let anyone in the old fashioned way? This apartment buzzer hack replaces the need for an RFID device with a secret code based on the rhythm of buzzer presses - no more hassle when you or your friends get locked out! If your building has multiple units, it leaves the other units unaffected.

Step 1: Figure Out Which System You Have

There are many different systems, I will be going over the kind where a panel at the front door connects visitors to an intercom and allows them to buzz a specific apartment's handset. The handset can then be used to open the door by pressing a button.

Even within such systems, there can be a fair bit of variation. At a minimum, you will need to open up your handset's base unit and figure out which terminals need to be connected to open the door, and which terminal the buzzer connects to. You can use a multimeter to do this, or use good old Google to find out based on manufacturer names or what you see inside your handet's base.

Step 2: Gather Up the Ingredients

I used an ATTiny85 microprocessor as the brains of my operation. You may choose to use an entire Arduino devboard - the Nano would be a good choice due to the compact size. In order to program the ATTiny85, you will need a separate Arduino board, or a programmer such as the TinyAVR programmer.

Bearing that in mind, here are the components and the circuit diagram:

  • 1x ATTiny85 (optional, see note above)
  • 1x Arduino Uno/Duemilanove (optional, see note above)
  • 1x Optocoupler (e.g. Fairchild's 4n35)
  • 1x CR2032 battery + battery holder (Can be replaced with a different voltage source)
  • 2x 100kΩ resistors
  • 1x 1kΩ resistor
  • 1x 470Ω resistor
  • 1x Mini breadboard + jumper wires

Step 3: Circuit Diagram and Explanation

The gist of this solution is that the optocoupler (4n35) will allow current from the battery to reach the ATTiny85 whenever the buzzer activates. When that happens, the ATTiny85 will listen for a pre-programmed series of buzzes, which is our secret code. Once such a series is received, current is supplied to the base of the transistor which bridges the door terminal and ground, completing the circuit and unlocking the door.

This tutorial is inspired by the simpler buzzer hack here. However, if you compare the solutions, this one is slightly more complicated. Why?

There are two reasons. The first is that my own buzzer uses the frequency of the buzzer to produce a tone at the speaker. This means that I cannot simply determine the state of the buzzer without some sort of attenuation to get a stable reading. This is accomplished by the low pass filter created by the 1kΩ resistor and the 22µF capacitor.

The second reason for the complication is that this solution is more compact via the elimination of having to include the entire Ardunio. The ATTiny85 is tiny, but it is a bigger pain to program it (although it isn't so bad once you get the hang of it).

Lastly, I am using two pull-down resistors (100kΩ each) to ensure the sensitive terminals remain grounded.

Step 4: Programming the ATTiny85

Here is a nice tutorial on how to program your ATTiny85 using the Arduino. If the tutorial is not sufficient, please let me know in the comments!

This is the code you will be uploading when you are all set up (the mySerial lines can be uncommented for debug info over serial, the secret code is in checkArray, by default it is set to 1sec buzz + 0.5sec buzz + 0.5sec buzz):

//TinyDebugSerial mySerial = TinyDebugSerial();

const int BUZZCOUNT = 3; const int FUZZFACTOR = 500; const float TIMEOUT = 5000;

const int inputPin = 2; const int outputPin = PIN_B1;

int currentBuzzNumber = 0; float millisAtStateStart = 0; float checkArray[BUZZCOUNT] = {1000, 500, 500}; float codeArray[BUZZCOUNT];

float buzzStrength = 20; // Used dynamically to offset the capacitors storage

typedef enum State{ idling, buzzing, waiting };

State currState;

void changeStateTo(int newState) { // mySerial.println("Changing to state:"); // mySerial.println((State) newState); currState = (State) newState; millisAtStateStart = millis(); }

boolean isBuzzing() { // mySerial.println("Checking if buzzing"); float currentReading = analogRead(inputPin); // mySerial.print("Reading was: "); // mySerial.println(currentReading); // mySerial.print("Buzzstrength was: "); // mySerial.println(buzzStrength); if(currentReading > (buzzStrength + 10)) { // Need a min jump of 10 to buzz buzzStrength = currentReading; return true; } else if (currentReading < (buzzStrength - 10)) { buzzStrength = currentReading; return false; } // If we get here we are indecisive delay(20); return isBuzzing(); }

void checkAndUnlock() { boolean isCorrect = true; for(int i=0; i checkArray[i] - FUZZFACTOR && codeArray[i] < checkArray[i] + FUZZFACTOR) { // Correct, do nothing! } else { isCorrect = false; } } if(isCorrect) { // mySerial.println("Code correct, unlocking."); digitalWrite(outputPin, HIGH); delay(3000); digitalWrite(outputPin, LOW); } else { // mySerial.println("Code incorrect."); } }

void setup() { // mySerial.begin(9600); pinMode(inputPin, INPUT); pinMode(outputPin, OUTPUT); currState = idling; }

void loop() { switch(currState) { case idling: if(isBuzzing()) { currentBuzzNumber = 1; changeStateTo(buzzing); } break; case buzzing: if(!isBuzzing()) { float buzzTime = millis() - millisAtStateStart; codeArray[currentBuzzNumber - 1] = buzzTime; if(currentBuzzNumber < BUZZCOUNT) { changeStateTo(waiting); } else { checkAndUnlock(); changeStateTo(idling); } } break; case waiting: if(isBuzzing()) { currentBuzzNumber += 1; changeStateTo(buzzing); } else if(millis() - millisAtStateStart > TIMEOUT) { changeStateTo(idling); } break; } }

Step 5: Assembling the Circuit

I've used Fritzing to make the circuit diagram and the breadboard image above. The breadboard here might be larger or smaller than one you might have, so adjust accordingly - there is plenty of free space on both sides of this arrangement!

Once you have assembled this circuit, you will need to connect wires in your handset base to the appropriate locations on breadboard.

Step 6: Test Your Buzzer!

At this point everything is ready to go - get to your front door and try the programmed sequence of buzzes. The door should unlock.

The code can be updated to take advantage of the ATTiny85's low power mode, which would give you a much better battery life. Further enhancements could include the removal of recursion, which could theoretically cause a crash under some circumstances (although I haven't experienced that myself).

NOTE: The first image is using a 9V cell, but the rest of the tutorial uses a standard button cell (CR2032) since that's what I decided to go with eventually.