Smart Lock with Gears

Tags: #<Tag:0x00007fc40384ef58> #<Tag:0x00007fc40384ee68>

Summary

This is my 2nd version of a smart lock which is using a stepper motor which allows the user to turn the key manually. This is very useful if the lock supports anti-lockout which will enable someone from the outside still use his key manually.
It’s designed to be used for European Cylinders and it’s possible to fit it without the need of screws.

Checkout my video demonstration:

Usage

To control the lock from the inside you can add a button on the ESP32, but on the outside you need something more secure. These are some of my ideas:

  • Using buttons on Home Assistant interface.
  • If you have the Home Assistant app on your phone, you can stick NFC tags and program them to unlock the door.
  • Use an RFID controller like the RDM6300, RC522 and PN532. You can have your personal NFC tags that you can scan on the device. Be warned that the Tag UID can be replicated and the phones emit a random UID.
  • Add a Fingerprint sensor like the R503. Check this on how I did it.

For locking you can be more creative because security is not a concern.

  • Using a button connected to the ESP32.
  • Automatically lock every time the door closes with a magnetic sensor.
  • With a Bluetooth LE toothbrush using the ESPHome integration.
  • Zigbee/ZWave smart buttons.
  • If you are using Asterisk, you can create an extension that calls the Home Assistant API to unlock.
  • Using a smart speaker. Be careful with these because they allow you to unlock, but you need to provide a pin. You are heavily depending on an online service that can be hacked, so I wouldn’t recommend it.

Installation

The components that I used are these:

  • ESP32s
  • Nema 23 Stepper Motor
  • A4988 Stepper Motor Driver
  • 3D printed model available here

And this is how everything is connected:

I am using ESPHome to control the motor because it can easily integrate with Home Assistant and supports all features I need out of the box.
The code is designed so when unlocked, the latch will open for 2 seconds and then go to neutral position. After that it will set the neutral position to 50 in case the lost of steps on the motor. This is considered Unlocked.
When it’s locked, it will turn all the way to the desired position and send the locked state on Home Assistant.

Here is the configuration on ESPHome:

esphome:
  name: smartlock
  platform: ESP32
  board: nodemcu-32s

wifi:
  ssid: <yourssid>
  password: <yourpassword>

# Enable logging
logger:

# Enable OTA updates
ota:

# Enable Home Assistant API
api:

globals:
  - id: is_locked
    type: bool
    restore_value: yes
    initial_value: 'true'

switch:
  - platform: template
    name: "Lock Switch"
    id: lock_switch
    lambda: "return id(is_locked);"
    turn_on_action:
      - stepper.set_target:
          id: my_stepper
          target: 2300
      - globals.set:
          id: is_locked
          value: 'true'
    turn_off_action:
      - stepper.set_target:
          id: my_stepper
          target: -500
      - wait_until: # Wait until endstop reached
          lambda: 'return (id(my_stepper).current_position == id(my_stepper).target_position);'
      - globals.set:
          id: is_locked
          value: 'false'
      - delay: 2s # Leave latch open
      - stepper.report_position:
          id: my_stepper
          position: -370
      - stepper.set_target:
          id: my_stepper
          target: 0

stepper:
  - platform: a4988
    id: my_stepper
    step_pin: GPIO18
    dir_pin: GPIO05
    max_speed: 600 steps/s
    sleep_pin: GPIO19

This lock doesn’t have a feedback if the motor actually reached its destination so I created a new switch that forces to unlock the door:

switch:
  - platform: template
    name: "Reset Position"
    id: reset_position
    lambda: "return false;"
    turn_on_action:
      - stepper.report_position:
          id: my_stepper
          position: 750

Final Words

I’ve been using this smart lock for several days now and the only problem I faced is that sometimes the motor didn’t move enough, which resulted the latch not opening all the way. This was not a problem getting inside because of the reset_position button I created. [update after 2 months] The problem was with the motor driver which I replaced and now it works perfectly without the need of reset_position.

As I mentioned this is my 2nd version of the Smart Lock. If you want, you can check the 1st version here which is using a worm motor that locks the key in place.

Hope you like it!

8 Likes

Hallo, let me show my own Smart Lock, the idea is similar, I moved the code from Tasmota to EPShome just today so it needs to be polished and some features are still missing, I added an extra button that will close the door when I exit, or open, if closed, a buzzer to let me know if it closes when I exit, open/close action can be accessed from the web interface in case HA is down, next step will be to add a IR sensor for proper homing and a finger print reader, running on Nodemcu8266.
I also added a switch inside the lock, that has been a bit tricky, but now I can get a feedback from the lock and know whether it is open or not.
In my first iteration I also used a gear but it did not work well, the gear would easily skip as the cylinder/key can be quite loose. So I bought a cylinder without key slot in the inside, removed the handle and coupled to the Nema shaft with a shaft coupler.

esphome:
  name: portero_casa
  platform: ESP8266
  board: nodemcuv2
  on_boot:
    priority: 100 # Highest priority, ensures light turns on without delay.
    then:
      - output.turn_on: gpio_d6
      - output.turn_on: gpio_d7
      - output.turn_on: gpio_d8

wifi:
  ssid: "cccc"
  password: "dddd"

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Portero Casa Fallback Hotspot"
    password: "dddd"

captive_portal:

web_server:
  port: 80

# Enable logging
logger:

# Enable Home Assistant API
api:
  services:
  - service: open
    then:
      - switch.turn_on: open_portero_casa
  - service: close
    then:
      - switch.turn_on: close_portero_casa
   
ota:

switch:
  - platform: template
    name: "Open portero casa"
    id: open_portero_casa
    turn_on_action:
      - stepper.report_position:
          id: nema
          position: 0
      - output.turn_on: stepper_en
      - if:
          condition:
            binary_sensor.is_on: door_state
          then:
            - stepper.set_target:
                id: nema
                target: -4488
            - delay: 6s
            - stepper.set_target:
                id: nema
                target: -3200
            - delay: 2s 
          else:          
            - stepper.set_target:
                id: nema
                target: -1288
            - delay: 3s 
            - stepper.set_target:
                id: nema
                target: -100
            - delay: 2s 
      - output.turn_off: stepper_en
      - switch.turn_off: open_portero_casa

  - platform: template
    name: "Close portero casa"
    id: close_portero_casa
    turn_on_action:
      - stepper.report_position:
          id: nema
          position: 0
      - output.turn_on: stepper_en
      - if:
          condition:
            binary_sensor.is_off: door_state
          then:         
            - stepper.set_target:
                id: nema
                target: 3200
            - delay: 4s
      - output.turn_off: stepper_en
      - switch.turn_off: open_portero_casa

output:
  - platform: gpio
    pin: D6
    id: gpio_d6
  - platform: gpio
    pin: D7
    id: gpio_d7
  - platform: gpio
    pin: D8
    id: gpio_d8
  - platform: esp8266_pwm
    pin: D0
    frequency: 1000 Hz
    id: pwm_output
  - platform: gpio
    pin: D4
    inverted: True
    id: stepper_en

stepper:
  - platform: a4988
    id: nema
    step_pin: D3
    dir_pin: D2
    max_speed: 1600 steps/s

    # Optional:
    acceleration: inf
    deceleration: inf

# Example usage in a light
light:
  - platform: monochromatic
    output: pwm_output
    name: Buzzer

binary_sensor:
  - platform: gpio
    pin: D1
    name: "Door Button"
    on_click:
      min_length: 100ms
      then:
        - switch.turn_on: close_portero_casa

  - platform: gpio
    pin: D5
    name: "Door State ON is closed"
    device_class: door
    id: door_state
2 Likes

I bought the R503 fingerprint sensor which I have connected it to my Raspberry PI. I’ve chosen not to connect it with ESP32 because I already had installation going to my Raspberry, so I didn’t have to drill a new hole on my wall.
The easiest way to mount it is to use an old CD/DVD and widen the hole in the middle.

I’ve released a service for Raspberry which communicates through MQTT messages with the fingerprint sensor and it works flawlessly till now. I highly recommend it for unlocking the door.

You can find it in my github repository here.

hi, this looks interesting, what power supply are you using? thanks for any info.
Mark

I am using a standard 5V Micro USB for the ESP32 and a 12V power supply for the motor, though you can use any voltage from 8-35V. I would recommend checking the specs of your motor though.

I have added a 502 grow fingerprint sensor too, had not to drill any hole as I was able to route them through the hole of the handle´s screw.
I am also going to try and use a TMC2130 as stepper driver to get proper homing and latch opening roation, using its GuardStall feature.

Tell us more about this stallGuard tech. I’ve never heard of it before. From what I found out it can understand when it reaches the end, but I don’t understand exactly how it’s achieved.
Also will this work with the existing ESPHome integration for stepper?

P.S. Could you show us a video/photo of your implementation?

The driver senses the current flow so it can detect when the motor is under torque stress or finds an obstacle to whatever it is moving. Basically you get a sensorless homing device.
That said there is no direct implementation in HA, but you can get this data both from SPI or from a cfg pin which gets high whenever the stall flag is triggered. The current sensing limit has to be set with SPI.
Yes let me write down some documentation and I ll post it here.

You can get started here: https://github.com/simonemarin/esphome_smartlock

Thanks for sharing your process.
I’ve also tried using the motor directly on the key, but the latch needed more power to move it even with my Nema23 motor. Maybe it was my 12V charger fault because I am using just 2 Amps.
Also another concern of mine was that it would stick too much out of the door, so the gears help a lot.
If I redesigned it, I would use a nema17 with less gear ratio so that it would be more compact and also add a case for esthetics.

Yes I have actually modified slightly the mechanical door lock loosing a bit the tension of the latch spring and I am even using what seems to be an even smaller stepper than yours, iirc it is a 34mm. I have plenty of current on my power supply though. I have added a picture of the casing, as far as I am concerned there is no practical issue with the stepper sticking a bit out. As mentioned before the looseness of the cylinder made it very difficult to mesh the gear together, maybe a different design removing the strain from the cylinder may work too, it should be counterbalanced on the other side.