LowKey

by Josh Huang

LowKey device that looks like a grey rectangular box with a green bottom plate and a orange bar in the bottom left corner extending to the left.

Top left corner view of the LowKey device in its blocking state. Corresponding door sensor, door handle flag, and power cable not shown.

Overview

This device is made to prevent me from leaving my apartment without my key because my door self locks and I need to have my key with me when I leave. It has sensors to tell when the door handle has turned, whether the door is closed, and whether or not I tapped my key on the box. If I try to leave without the key by turning the door handle without tapping my key on the box, a little plastic arm swings up to physically indicate that I did not tap the key as well as block the door from opening. 

LowKey device mounted on the wall to the left of a door with a battery bank sitting on top of the device for power.

LowKey door blocker mounted in my apartment. Currently powered by a power bank sitting on top of the device.

Image of LowKey door blocker on white background.

LowKey door blocker with the blocker raised.

Close up picture showing cardboard piece taped to the door handle on the left side, door sensor stuck onto the door on cardboard, and the LowKey device mounted to the right.

Closer look at laser door handle sensor and door sensor. A cut out in the enclosure allows the laser distance reader inside to tell the distance to the cardboard flag taped to the door handle. When the door handle turns, the laser reads a different distance. The door sensor is a magnet, mounted with cardboard spacers and double sided tape to line up with the corresponding sensor in the blocker device. 

Close up of under side of blocker box showing the cutout hole for the USB port.

A cutout is built into the lid to allow access to the Arduino Uno USB port. This is for power and debugging purposes.

LowKey device mounted to a wall next to the door. The door handle is turned and the door blocker is raised.

The door blocker is raised as the door handle is turned without tapping a key on the device.

Orthogonal corner view of the LowKey device in Solidworks program with transparent lid.

Solidworks CAD of the blocker device, showing internal electronics configuration as well as lid and mounting plate design.

GIF of me trying to leave the my apartment and the device blocking me from doing so without tapping my key on the device.

Usage Demonstration

As I try to leave my apartment, the LowKey door blocker detects that I have turned the door handle without tapping my key on the box. To prevent me from locking myself out, it raises the blocker arm to block the door from opening. I then pick up my key and tap it on the box so the device will let me open the door without raising the blocker.

Build Process

The first steps of the build is concepting the layout and useage of the device and then finding and testing sensors that I would need. I took photos of my door to figure out how exactly the device should be mounted and what sensors need to be placed where to collect all the information I need. As seen in the below image, I ended up with a narrow cone laser distance sensor and a cardboard flag on the door handle to detect whether the door handle has been turned. Then, some kind of magnetic switch that can detect whether or not the door is closed can be mounted right next to the door. The image shows a Hall Effect sensor but a reed sensor was used instead. Finally, an RFID reader is needed to read whether or not a key was tapped on the device to allow the user to leave without the blocker interfering. 

Next, I collected the sensors I needed and wired them up to an Arduino Uno to figure out the code needed to read from all of the sensors.

Image of my door and wall with a drawing of the device and labels for sensors overlaid on the image.

How I envisioned the device mounted on my wall during prototyping.  I would need to prove the viability of each of the sensors in the image.

Image of an Arduino Uno, bread board, and loose sensors wired together on a table.

The laser distance sensor, door sensor, RFID reader, and output micro servo wired up to an Arduino Uno for code development.

After completing code development and making sure all the computing components works as expected. I need to mount all components to a plate with correct positioning and height. This step involves making a mounting sled in CAD using Solidworks. Knowing that I will be using M3 screws, I designed in the holes needed to use brass threaded heat inserts as well as designed everything to be easily printed on a FDM 3D printer. This means I am able to use a soldering iron to melt the brass heat inserts into the printed plastic and be able to thread M3 screws directly into the sled. 

The lid also has holes for heat inserts and will be attached by screws. There are also cutouts in the lid for the laser and the USB port on the Arduino.

However, the printers used by Ideate had problems with the print lifting off the print bed, which results in the deformed part shown in the second image. This affects the RFID reader mounting positions and makes it impossible to install the lid. New iterations of the mounting sled and lid were printed on a different 3D printer after the critic session.

The bottom mounting sled of the device in Solidworks.

The bottom mounting sled in Solidworks. Holes for heat inserts are placed according to where the components will be. Standoffs are built into the design to avoid damaging the circuitry on the bottom of components as well as lifting the RFID reader to be near the lid surface. Wiring holes and guides are built in where needed.

Image of the printed mounting sled with one corner lifting off the table.

The deformed mounting sled caused by the piece lifting off the print bed. I had ideas for fixing this issue, namely using Elmer's glue stick on the print bed prior to starting the print, but there was no time to make another iteration before the project critic.

The LowKey door blocker without the lid, showing internal components and wiring.

The internals of the LowKey door blocker showing the laser, door sensor, door blocker micro servo, Arduino Uno, RFID Reader, and soldered breadboard mounted with screws.

Me holding the device on the wall next to the door while the device is plugged into my laptop nearby.

Here, I am holding the box up to the wall to calibrate the door handle sensor trigger distance. I print out the laser's detected distance, status of the door sensor, and status of the RFID reader in the Arduino IDE.

IMG_4456.MOV

Walkthrough and Demo

This video explains all the components and features of the LowKey door blocker in depth. With a walkthrough of components and demonstration of various features.

Discussion

In general the project turned out great. I am satisfied with that I have because it does what I intended it to do with some extra features sprinkled in. For example, I found during installation that I can place the door sensor in such a way that the device would detect door opening if I continue to try to open the door while the blocker is up. This means that if I really wanted to, I can still leave my apartment without my key if I open the door carefully. This can be helpful in emergencies, although I can always unplug the device and turn the blocker manually.

During the critic session in class, there was not much actual criticism. There does not seem to be any dissatisfaction in the critic document, but there are several comments suggesting a desire to install it in their own homes. I call that a success. While some even suggested turning this into a commercial product, I do not see much economic value in perusing this route as there is not much actual need for this product. Housing managements usually have solutions for lockout situations. I may consider making a few upon individual request given the resources to acquire parts.

"I want to buy this " - fellow student

"Do need to go on shark tank with a sales pitch " - another fellow student

While I mostly used existing skills in this project, there are still learnings to be had. Most of the techniques like CAD, soldering, using heat inserts, 3D printing etc. were from past experiences making avionics for rockets. However, I learned about how points of failure works and why some components should be made to fail before others. I had put a lot of effort into making the device easy to assemble and very structurally sound. For example, all standoffs and cutouts were built into the CAD model as one piece, and nearly all components are hard mounted with screws. The only obvious point of failure was the blocker arm's micro servo motor, and I learned a hard lesson on designing safeties and failure points. The device actually fell once during installation, and the blocker arm struck the ground, breaking the micro servo's internal gears. I had attached the arm to the servo using a large piece of double sided tape, and the servo gears failed before the tape did. I do not think there is much value in designing a more robust solution for mounting the blocker arm, but I will use less adhesive on fragile parts like servos in the future. 

Apart from the learnings above, there are other improvements I would like to make. I think the device is too large and heavy in its current state. The fall mentioned previously probably could have been avoided if the box wasn't so heavy in the first place. There are ways to reduce the amount of 3D printed material to save mass, like making the walls thinner and designing structs instead of using full solid surfaces. Internal components can also be placed better and stacked to reduce overall footprint. Another addition I would like to make is adding status LED indicators on the top of the box. The door blocker operates on timers triggered by the sensors, and I would like to know when the blocker is primed and when it is not. Currently, if I tap my key but the RFID reader fails to read it, I would not know until I turn the door handle and the blocker raises. This is fine for my personal use since I know the behavior and placement of the RFID reader very well, but it would be nice anyways.

Block Diagram and Schematic

Code and CAD

All code and CAD models available at this repository, MIT license: https://github.com/joshHuang02/60223-project-2

/*

Project LowKey

by Josh Huang


This is the controller code for the LowKey lock-out prevention device.

Its main function is to read inputs from a VL53L0X laser distance reader, door sensor, and MFRC522 RFID reader to determine when

the user is attempting to leave their residence without their key. Thus preventing locking the user out.

The output is a micro servo that raises a physical blocker to stop the user from leaving the residence without their key.


This file includes example code from Adafruit_VL53L0X and MFRC522 libraries


Pin map starting line 28


Copyright 2023 Junzhe Huang


Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:


The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.


THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/


#include "Adafruit_VL53L0X.h"

#include <SPI.h>

#include <MFRC522.h>

#include <Servo.h>


// pin map (vl53l0x requires using I2C pins not listed here)

#define DOOR_PIN        2

#define SERVO           3

#define RST_PIN         5

#define SS_PIN          10


Servo servo;

MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance

Adafruit_VL53L0X lox = Adafruit_VL53L0X();


// limiter values

int handleDistLimit = 130;

int rfidTimeoutMS = 2000;

int servoDefault = 150;

int servoTimeoutMS = 5000;


// vars

unsigned long rfidScanTime = 0;

unsigned long servoTime = 0;


// status booleans

bool rfid;

bool handleTurned;

bool doorOpen;

bool doorBlocked;

bool servoTriggered;


// most lines in setup are taken from example code

void setup() {

  Serial.begin(115200);


  pinMode(DOOR_PIN, INPUT);


  //Servo

  servo.attach(SERVO);

  servo.write(servoDefault);


  // laser 

  // wait until serial port opens for native USB devices

  while (! Serial) {

    delay(1);

  }

  

  Serial.println("Adafruit VL53L0X test");

  if (!lox.begin()) {

    Serial.println(F("Failed to boot VL53L0X"));

    while(1);

  }

  // power 

  Serial.println(F("VL53L0X API Simple Ranging example\n\n")); 


  // RFID Reader

  while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)

SPI.begin(); // Init SPI bus

mfrc522.PCD_Init(); // Init MFRC522

delay(4); // Optional delay. Some board do need more time after init to be ready

mfrc522.PCD_DumpVersionToSerial(); // Show details of PCD - MFRC522 Card Reader details

Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks..."));

}



void loop() {

  // read inputs and set conditonal booleans

  readLaser(); // reads laser distance measurement and sets handleTurned bool

  readRFID(); // scans for rfid tag and sets rfid bool

  doorOpen = !digitalRead(DOOR_PIN);

  bool servoTimedOut = millis() > servoTime + servoTimeoutMS;


  // printStatus();


  // control blocker

  if (!doorBlocked) { // blocked down

    if (handleTurned && !doorOpen && !rfid) {

      servoTime = millis();

      servo.write(servoDefault - 65); // lift blocker

      doorBlocked = true;

    }

  } else { //blocker up

    if ((servoTimedOut && !handleTurned) || rfid || doorOpen) {

      servo.write(servoDefault); // drop blocker

      doorBlocked = false;

    }

  }

}


// reads the laser distance to flag on door handle, update the handleTurned boolean 

void readLaser() {

  VL53L0X_RangingMeasurementData_t measure;

    

  lox.rangingTest(&measure, false); // pass in 'true' to get debug data printout!


  if (measure.RangeStatus != 4) {  // phase failures have incorrect data

    Serial.print("Distance (mm): "); Serial.println(measure.RangeMilliMeter);

    handleTurned = measure.RangeMilliMeter > handleDistLimit;

  }

}


void readRFID() {

  // RFID Reader

  // set rfid bool

  rfid = millis() < rfidTimeoutMS + rfidScanTime;


  // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.

if ( ! mfrc522.PICC_IsNewCardPresent()) return;


  // At this point there is a RFID device present

  rfidScanTime = millis();

// Select one of the cards

if ( ! mfrc522.PICC_ReadCardSerial()) {

return;

}

}


// debugging status of each input

void printStatus() {

  Serial.print("Handle Turned: ");

  Serial.print(handleTurned);

  Serial.print(" | RFID: ");

  Serial.print(rfid);

  Serial.print(" | Door Open: ");

  Serial.println(doorOpen);

}