The making of: My smart doorknob
There’s not really a sensible reason or purpose behind this project, beside me wanting to experiment with a random potentiometer I had lying around. I thought it would be fun to transform something unassuming into something smart, that could perform IoT actions, while remaining hidden and fairly normal looking.
A potentiometer is a device that can adjust resistance based on its rotation, so in order for a device to remain suitably hidden, it would have to be connected to an object which had rotational symmetry, and was durable enough to be rotated and touched many times, without breaking. I thought about this for a while, considering many different objects I could convert, until I concluded that my doorknob would be the most fitting base for my contraption.
Why a doorknob? Well there were several factors that lead to me deciding on it:
- My doors’ latch mechanism completely broke several months ago, as a result of the “spring” being permanently deformed, and rendered useless.
- Metalworking is by no means my ::forte::, and given that the lock mechanism is circa 1900, my attempts to fix it were unsuccessful.
- A doorknob is an item that is purpose built for being rotated many thousands of times, so would likely be durable enough for the project
- It’s cool. And it feels like an, albeit nerdy, James Bond gadget
Now for the fun part…
How I made it
When I was prototyping (this is a fancy word for “messing around and seeing what works”), I initially thought I’d use a Raspberry Pi Pico to interpret the resistance value, connected to a Raspberry Pi Zero which would actually perform the IoT function. However, this wasn’t feasible for a multitude of reasons, one of which being that I didn’t have a battery pack for the Pi, and would have to run a very long cable from my doorknob. Not very hidden, or cool…
With this initial failure, I decided to think about the most energy efficient and most discrete solution, that would work with my existing hardware (I’m quite impatient, so I didn’t want to have to wait for a component something to arrive). After pondering this, I realised that I had been gifted a first generation BBC Micro:Bit at a birthday, and it checked a lot of boxes:
- Includes a 2xAA battery pack, so could be powered without a plug
- Includes a Bluetooth radio, capable of sending UART messages
- Can read analog resistance values
- The kit it came with included crocodile clips, which are easier (and less permanent) than soldering*
As the Micro:Bit doesn’t have an internet connection, and is very limited in programming capability, it would have to merely act as a communication layer between the potentiometer and a beefier, more capable SoC (in my case, this was the Raspberry Pi 4 I have on my desk).
This is the contraption that would be stuffed in my doors lock mechanism, but first I had to test the communication between the Micro:Bit and the Raspberry Pi.
I was initially intending to run MicroPython on the Micro:Bit, as… well in honesty, I thought I was too cool to use the simplistic MakeCode interface. However, it so happens that the Micro:Bit doesn’t have a large enough memory chip to load the MicroPython Bluetooth libraries and run my code. So I was stuck with MakeCode, and… it wasn’t all that bad 😆
Some of the blocks might seems unnecessary or redundant, but my primary concern was power efficiency, as I didn’t want to take out the batteries and recharge them on a regular basis (we’ll see how this goes though — I couldn’t find much online about Micro:Bit battery life).
Here’s the rundown of what this “code” does:
- Checks whether another device (i.e. my RPi) is connected, and hence enables the UART service and sets the “connected” variable to
But what is UART? The Microsoft MakeCode website has an excellent explanation:
The Bluetooth UART service allows another device such as a smartphone to exchange any data it wants to with the micro:bit, in small chunks which are intended to be joined together.
2. If connected is
true, we query the potentiometer analog pin and code the value to be a float between 0 and 1. I also checked if its value had sufficiently changed (±5%) because I encountered some variation in values, which I wanted to account for.
3. We send the new rotation value over UART to my RPi, with the key “x” (the “x” is arbitrary, as we’re only sending one variable).
4. If the RPi disconnects, we set connected to
false and reset the Micro:Bit — I did this in order to disable the bluetooth UART service, in order to save battery.
Raspberry Pi Code
I was fairly unfamiliar with Bluetooth communication protocols, so I went searching to see if someone had attempted something similar before, and sure enough, they had. I found this excellent Python library designed for interfacing with Bluetooth devices, particularly Micro:Bits
I followed the steps provided in their Getting Started guide, to obtain the MAC address of the Micro:Bit:
GitHub - ukBaz/python-bluezero: A simple Python interface to Bluez
A simple Python interface to BlueZ stack The aim of this library is to provide an API to access to Bluez with zero…
I then used a modified version of their example UART script, to display the UART data. This worked brilliantly!
python-bluezero/microbit_uart.py at main · ukBaz/python-bluezero
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below…
Now comes the hard part…
I’m primarily a software engineer, so whenever it comes to physical engineering, I don’t really know what I’m doing 😝. Additionally, I take quite a gun-ho attitude to these projects, so I went in without much of a plan, and tried anything that came to my mind. This led to, well a lot of failure…
I knew that I needed to connect the spindle to the potentiometer in some way, so I went for the least destructive idea first, which was to use a makeshift gear system, to connect the spindle to the potentiometer. I attempted to use some small plastic gears from an old kit, but upon attempting to enlarge the bore with a hand-drill, the idea fell apart.
The primary problem was attempting to enlarge the holes evenly, which on gears with a roughly 2cm diameter, is easier said than done (especially for someone who has no idea what they’re doing). I also encountered significant cracking and deforming of the gears, which was a big problem, as gears are very precise mechanisms which don’t fare well if they are damaged. As I possess neither the skills nor equipment to 3D print something more custom, gears probably weren’t the answer. Back to square one.
My second idea was to cut down the lock mechanism spindle so it could be connected in some way to the potentiometer.
This worked well, but took some time, as I had to manually cut through the spindle with a coping saw. After cutting through the spindle, I toyed with a few ideas about connecting the spindle to the potentiometer:
- Glue: Not durable enough, and I didn’t want to permanently modify my potentiometer
- Drilling a hole through the centre of the rod: This is a lot harder than it sounds, especially without a drill press, or the correct bits. The rod was also very narrow, and I wasn’t confident in the tools or my own abilities to continue this approach.
Then I had the idea to create a slit in the metal rod and create something the internet now informs me is a “splined miter” joint.
This was achieved by cutting two consecutive slits in the metal spindle and then cutting and sanding part of a wooden popsicle stick until I got a perfect wooden “spline”
Side note: I also experimented with some scrap metals, salvaged from a USB connector, however it was too difficult to work with, and I couldn’t get it to be the right dimensions I wanted.
The feeling of elation I felt of getting the perfect join, after several hours of trial and error with other joining techniques, was amazing 🥳. Now I could get to assembling the final product.
I experimented with several bodge-y methods of fixing the potentiometer to the now empty lock mechanism housing. Unfortunately I neglected to photograph the solution I ended up with, which was a very inelegant criss-cross of T-Rex tape strips (the Blue-Tak pictured turned out to be completely useless).
Then came one of the more surprisingly annoying parts of the project — fitting it all in. I hadn’t done any test fits, but it mercifully all squashed in. It took several attempts of rerouting cables and making sure there wasn’t any short circuiting with the housing or the other wires, and removing the back panel of the housing was necessary, but in the end, it works!
I made a few small changes to the script running on the Raspberry Pi, in order to allow the doorknob rotation to adjust the volume playing from my Sonos speakers (I have an Sonos API server running in Docker on the RPi as well: https://github.com/jishi/node-sonos-http-api/issues). Here’s a video of it in action:
(Pardon the very messy room, this project took most of my energy/focus)
I’m probably going to adapt the script in the future, to allow for more complex gestures, that can cause different actions, but right now its just a very cool, hidden-in-plain-sight volume knob.