Automatic Garage Door
I am one of the lucky few who happens to have a covered parking lot in the basement of my apartment in Amsterdam. When I moved in here, it was one of those things that I didn’t really care too much about. In fact, for the first two years that I lived here, I didn’t even use it. However I bought a car a couple of years ago to explore Europe a little more by road, and I’m loving it. It’s also how I commute to my new office which is about 25km from home.
I bought a used car because one of the first things that happens when you buy a new car is that it loses a large chunk of value the moment it leaves the Dealer’s door. However, buying a cheap car had two advantages for me - I could buy it outright with cash, and I could tinker with it without feeling much guilt. I set about fixing, upgrading and buying all kinds of things that I could - polishing the headlights, installing dash cams (this was out of necessity), a TPMS system, a little vacuum cleaner, a tarp for covering things I might transport, a beach mat, phone holder, etc.
Things didn’t end there - I wasn’t happy with the media player. It had bluetooth support, which was great, but the interface was old and slow, and it sported a CD player and a proprietary navigation system that I had to buy upgrades for. I decided to buy an Android based Head unit and upgrade this experience for myself. That was an interesting experience that I will get to another day.
What this upgrade now lets me do is that I can run code on my car. It’s still a bit too clunky for my taste, but it’s better than what I had. Armed with this new power, I set out looking for something to do with it.
I had recently picked up building hardware and learning more about microcontrollers and electronics. I am also very lazy, to a fault. I didn’t want to fiddle with the keys to unlock the door to my parking lot as I drove home, and wondered if it would be possible for me to automate this. I decided to write an app that would run on my new head unit, and make a piece of hardware that using an ESP32 to actually control the gate. There were a few challenges:
- Reverse engineer the existing gate key fob, and control via an ESP32
- Communicate key fob commands to the ESP32 via Bluetooth
- Wire this system into my car
- Somehow identify when I was in front of the gate
- Write this post to talk about it
I must say, so far the last one is the one that took the most time.
Reverse engineering the protocol
I gave up almost immediately on this. I opened up my key fob and checked the chip onboard. Seemed generic enough, but the protocol was too safe for me to reverse engineer. I would have to buy another circuit that would emit the same wavelength of signal, and learn how to program it, and then figure out how to copy the code of my existing key fob to the new one. Apparently copying this code was only possible from the “master” key.
The solution that I ended with short-circuited all these problems. I remembered that a couple of years ago I wanted to park my bicycle in the parking lot and the key fob that I received while I moved in had damaged buttons. I requested it to be fixed and the landlord just mailed me a new key fob instead.
I opened the old key fob and saw that it was powered by two 3V button cells and had a few push buttons. I wired it up with my bench power supply and completed the button circuits with a breadboard wire and the fob seemed to work just fine.
Now all that was left is to be able to control this button from my ESP32. This was fairly simple, I just had to use a relay that I could control with the ESP32. This was problem 1 solved.
Communicate key fob commands to the ESP32 via Bluetooth
The ESP32 is a beautiful bit of hardware. I look forward to using it in several applications in the future. It has built in WiFi and Bluetooth, a fast dual-core processor, low power mode, and several other nice things going for it.
As I was learning about Bluetooth Beacons, I decided that I was going to use it to communicate my commands. However there needs to be some factor of security involved. I decided to go with the following approach:
- The ESP32 generates a random 6-digit PIN code on startup, and uses the onboard LED to flash this code to the user
- The user enters this PIN into the app
- The app transmits a beacon containing: i. The PIN in the “major” section of the beacon ii. 0 in the “minor” section of the beacon iii. A UUID to identify the app as the owner iv. Transmission power
- The ESP32 scans for beacons, and when it finds one with a “major” value equal to the PIN, it stores the UUID as the owner of the device and gets ready to accept commands from it
- The app can now transmit the same major and UUID, but either 0 in the minor to lock, or any other value in the minor to unlock
- When the ESP32 receives the beacon with the correct UUID and Major, it calculates the distance between itself and the beacon by its TX and RX power. If the distance is close enough, it performs the action
This approach works, and it’s included in the repository. This was also problem 2 solved.
Wire this system into my car
The fuse box in the car is generally around 12V, and most components in the car run at this voltage. The ESP32 and the relay runs at 5V or 3.3V, so in order to power them, the voltage needs to be stepped down to 5V. To do this, I wired a LM2596 DC-DC step down converter with a JST connector socket on one end, and powered the controller, relay and fob on the other end.
I 3D printed an enclosure for the ESP, relay, fob and the JST connector socket and made sure that the LEDs were pointing correctly to the outside so it would be visible when the box was closed up.
I then wired a JST connector plug to a fuse tap in order to tap into the fuse box of the car. In the car, I used my multimeter to identify a fuse which was only powered when my car was on, and was delivering 12V, and wasn’t connected to anything important like my airbags. I found one, tapped it, and connected the electronics to it.
In the dark near the fusebox of the car the LEDs really lit up well. I tested the app on my phone and it seemed to be triggering the relay perfectly. I drove the car out, and tried this out for the first time at the actual gate. Everything worked perfectly! This was problem 3 solved.
Somehow identify when I was in front of the gate
I had only heard about the promise of Geofencing, but had never actually used it personally, let alone develop an app that uses Geofencing. There’s always a first time for everything!
After looking through a bunch of different libraries, paid or otherwise, I decided to go with Expo Location
. It had all the functionality required, and it seemed to work on my phone just fine. I checked what the geo-coordinates of my parking garage’s gate was, put it as the geofence’s center, and installed the app on my Android’s head unit.
However there was still the problem that whenever my car turns off and on again, all the apps are killed. I didn’t want to manually start up the app on my phone every time - that makes it more of a hassle than clicking on the button on the key fob. Thankfully there’s a library called React Native Autostart
that let me configure my app to start up every time my phone or car starts up, and it works great! I reinstalled the app with this on my car, and tested it out and it worked just fine.
The first time I drove to my gate it didn’t work. But turning off my car and back on again restarted the app, and it seemed to work just fine. The first time I saw the gate opening using my contraption, I felt such a huge sense of achievement! So many moving parts, so many lessons learned! With that, all major problems were solved, and the system continues to work today! I just have to drive up to my gate and it opens automagically!
Write this post to talk about it
With this post, this is now done and I can call this project wrapped up! The code is pushed to GitHub here. Of course your own key fob might be different, but most of this should transfer just fine!
edit: Since writing the code for the app, my React Native and Typescript skills have vastly improved, making the code an eyesore. However I do not have the time to go back and fix things that aren’t necessarily broken, just bad. If you would like to fork this and make a better one yourself, please feel free to do so and I would appreciate it if you could raise a pull request to this repo as well!