Pssst – want some high tech protection for your home office, or a secret lock for your “workshop” (ok, you got me, it’s actually a dungeon/gaming room) that the kids won’t be able to figure out? We’ve got you covered. Let’s build a DIY smart lock that automatically detects when you’re there, and locks when you’re not.
How does it work? NOBODY KNOWS! Or more specifically, Bluetooth.
Your smartphone is a powerful device that’s constantly revealing information about itself to the outside world; one way it does this is Bluetooth.
In discovery mode, it broadcasts a unique identification number – but even when not specifically allowing itself to be discovered, anything that knows that address can try to ping it. If a response is heard, that would indicate whether it’s in range or not.
We’ll be setting up a Raspberry Pi with a Bluetooth adapter to constantly be on the lookout for when your smartphone is out of range, and when it is, the relay will snap into action and lock the door.
You Will Need
- Raspberry Pi – any model should work since it’s not an CPU intensive task, but I’m using a older model B, and the GPIO pinouts may be slightly different on your model. See the section on board mode below. You’ll also need some basics like a wired Ethernet connection or Wi-Fi configured; plus SD card and micro USB power cable.
- Bluetooth USB adaptor. Adafruit sells a Bluetooth 4.0 BLE module confirmed working (what’s Bluetooth 4.0?), but you should test any you already have lying around before purchasing a new one just for this project. I found an old standard Bluetooth mini adaptor I bought in Japan that appears to work fine. We don’t care about transfer speeds or connection reliability, as all we’re doing is sending out a quick handshake to see if a device is alive and well.
- GPIO breakout board (“cobbler”) and jumper cables. You could work directly from the pins on the Pi, but it’s a lot easier if you have labels on each pin, and they’re only $6 anyway.
- Relay board. You’ve got a wide variety of choices here, and anything will work if it’s designed for use with a microcontroller and can drive at least 12 volts at 5 amps. I’ve used a generic 4-channel board similar to this one for around $5, but I’m going to assume you know how to work yours.
- 12/24V electromagnet lock, though an electronic solenoid lock should also work. The one I purchased has 180KG holding force and comes complete with mounting plates and instructions, for about $35.
- 12/24V power supply. The magnet lock must have a separate power supply – whatever you do, don’t try to pull power for it from the Pi.
- Lock.py Python app, but we’ll write this as we go along.
Working with Bluetooth
Bluetooth is central to this project, so let’s start by installing some Bluetooth support and test our adapter. You can either do this directly from the Pi, or SSH in remotely (how to set up Windows to SSH into you Pi).
sudo apt-get install bluez python-bluez
Insert your dongle if you haven’t already, and let’s have a look at what it’s reporting.
If you have something listed in the output, you’re good to go. Next we’ll use a Python script to poll for nearby Bluetooth devices, and grab the unique device address. We only need to do this once for each device.
wget https://pybluez.googlecode.com/svn/trunk/examples/simple/inquiry.py python inquiry.py
If you see “0 devices found”, you either don’t have a compatible USB Bluetooth dongle, or your smartphone isn’t discoverable. Don’t despair though: I found I had to actually open the Bluetooth settings page on my iPhone to kick it into discovery mode, then this happened:
Great, now let’s create the first stage of our software that do the detection. Create a Python app called detect.py, and open it with Nano.
Paste in this sample code:
#!/usr/bin/python import bluetooth import time while True: print "Checking " + time.strftime("%a, %d %b %Y %H:%M:%S", time.gmtime()) result = bluetooth.lookup_name('78:7F:70:38:51:1B', timeout=5) if (result != None): print "User present" else: print "User out of range" time.sleep(10)
and adjust the following line with your Bluetooth device address:
result = bluetooth.lookup_name('78:7F:70:38:51:1B', timeout=5)
Press CTRL-X and Y to close and save. Run the same code, and you see something like this:
The code should be very simple to understand even if you’ve never touched Python before: it’s scanning for a particular Bluetooth device every 10 seconds, and it prints out a different message depending on whether it’s found or not. Toggle the Bluetooth on your phone to simulate moving in and out of range (probably about 4m in reality). You can decrease or increase the time between scans, but I felt 10 seconds was a reasonable amount of time to potentially have to wait for the door to unlock, which is where we’re going with this whole project after all.
I should add, I don’t know about the power consumption of doing this, but I would assume pinging a device more often would necessarily consume more power. I haven’t seen any obvious performance issues in testing, but if battery life is a serious concern for you, consider having a switch inside your office which activates and deactivates the scan loop, so once you’re inside, you can pause the lock system, then re-activate the scanning when you leave.
Congratulations, you now have a Python app that knows when you’re within range, so we can start to act on that.
GPIO Board Modes
Before continuing, you need to figure out which board mode you’re going to use. There’s no right or wrong answer, it just affects whether you specify the literal pin number or the virtual GPIO pin number.
The default is to use the literal pin number (“board mode”), starting with pin 1 in the bottom left (if looking down at the Pi with USB ports on the right). Pin 2 is just above that.
However, if you have a GPIO breakout (“cobbler”) board, the labels you have are from an alternate mode, called “BCM” (Broadcom SOC channel), and are commonly written with GPIO or P prefixing the number. You don’t strictly need a GPIO breakout – it just makes things easier. If you don’t have a breakout board and don’t want to buy one, use this diagram:
Note that the original model B revision 1, revision 2, and the model B+ and Pi2 all have different pin outs. Refer to this StackExchange question for a diagram correct to your board.
In this project code, I’m using the BCM GPIO numbering system which corresponds to the Adafruit breakout board I have. Minor modifications are needed if you wish to use the literal pin mode.
Wire in a Relay
Attach the breakout board, ensuring that the wire from pins 1 and 2 (the ones in the corner of your Pi) attach to 3v3 and 5V0 on the breakout. You might want to pull out a voltage tester to check this.
Before proceeding, check if anyone else has used your particular relay with the Raspberry Pi (or find one beforehand that you know works). Some may require 5V to activate – but the RPi can only provide 3.3V on the GPIO output pins. By chance, the one I’m using is happy with 3.3V, so I didn’t need any additional circuitry, just the 5V0 to VCC, GND to GND, and GPIO pin 23 for the first relay input.
My previous tutorial on GPIO showed how to wire up a transistor circuit to scale up 3.3V to a full 5V if you need to (in fact, I used the same relay board for that tutorial, but it turns out I didn’t need 5V after all).
No need to wire in the electromagnet yet, as you’ll be able to hear an audible click when the relay fires.
Next up, let’s grab some code to interact with the GPIO ports.
We’ll start by testing outside of Python to confirm everything is working on the ports themselves. Install wiringPi, which gives you some useful command line tools.
git clone git://git.drogon.net/wiringPi cd wiringPi ./build
Once installed, configure GPIO pin 23 to be an output.
gpio -g mode 23 out
Now, do a quick scan of all the ports to confirm
gpio -g readall
You’ll have something similar to this, though yours may be longer on a model B+ or Pi2 since it has more GPIO pins:
For more detail: Make An Auto-Locking Office Door with Smartphone Proximity Sensor