# Servo-Controlled IoT Doggie Door

<img src="doggie-door-perspective.png" width="40%" />
<img src="photo.jpg" width="40%" />
<br style="clear:both">

## Materials

- [Medium sized PetSafe Wall Entry doggie door](https://www.petsafe.com/product/wall-entry-pet-door/?sku=ZPA00-16201&collection-location=/shop/dog/doors/)
- 3D Printer
- Arduino Ethernet
- Normal-size continuous-rotation hobby servo (~40mm x ~20mm) with appropriate mounting plate/arms
  - A 180-degree steering servo can sometimes be made continuous by taking it apart and removing the limiting pin.
- Small pointy screws (apx 4mm head, 5mm length, 2.5mm thread, coarse)
- 9v (or whatever your voltage regulator and Arduino will take) Power Supply within reach of the door
- Appropriate connectors and wire to split out the 9v power supply to both the Arduino and breadboard
- 7805 or similar voltage regulator
- Ethernet cable within reach of the door
- 5v voltage regulator and breadboard/wires
- 2x Medium-sized limit switches
- About 40 inches of 3mm or 1/8" ball-chain (like ceiling fan pull chain) -- packaged it's often sold in shorter lengths so look for it online or by-the-foot at your local chain supplier (hardware/drapery/locksmith/etc)
- 2x Ball-chain mounting brackets (small eyelets and cups for attaching ball-chain to things with a screw)
- A nut and ~1cm x ~4mm bolt for attaching the limit switch flag to the doggie door (or however you prefer)
- A thin sturdy piece of metal to disable the door latch
- M-M jumper wires
- A breadboard, proto-shield, or other wire prototyping method
- Moderately sized capacitor (about 220uF, at least 100uF or more, for reducing voltage spikes on the servo)
- Appropriate cable management

## Printing

Print the following files:
- [[doggie-door.stl]]
  - It's currently split up with dovetails into two parts; feel free to edit the SCAD to split it elsewhere for your printer.
  - I also suggest printing only a small section of dovetail and screw hole at first to see if tolerances need adjusting. Try using the Hole or Subtraction/Difference feature of your slicer or OpenSCAD to remove all but these areas.
- 2x [[parametric_ball_pulley-improved-with-flares-and-hole.stl]]
- [[limit-switch-flag-and-chain-mount.stl]]
  - I suggest printing it on its flattest side (rotate 90 degrees)
- [[LBracket_Parametric_rev9.stl]]

The other files are just for posterity.

## Assembly

<img src="doggie-door-perspective.png" />

Refer to the doggie-door.scad file or screenshots above for assembly.

- Solder jumper wires to the limit switches: they should be Normally Closed so that the Arduino knows that they're connected (fails safe if they get disconnected) -- on my switches these are the first and third pins, not middle.
- Attach the parts of the doggie-door.stl together, gently use a hammer and/or knife if it's too tight, or firm plastic glue if too loose.
- Attach the LBracket to the tall narrow mounting block (bottom area) with the hole facing left
- Attach the limit switches to the top and bottom limit switch mounts: each one attaches with two screws on the back of the switch, and they need to make reliable contact with the door's limit switch flag -- top switch pointing down and to the left, bottom switch pointing up and to the left -- so pay attention to which flip or rotation of the switch makes sense.
- Attach the servo to the servo mount (top area with triangles labeled Futaba) with the axle at the far end of the assembly (for maximum door travel distance)
- Attach the ball pulleys to the servo and to the LBracket. Leave the LBracket pulley a bit loose so it spins freely.
- Attach the ball-chain mounts to the thick far end of the limit switch flag, stacked onto one screw, one pointing each way
- Attach the limit switch flag and chain mount to the bottom-right corner of the doggie door, just above the corner radius and snugly so the flag can't rotate. I drilled a hole into the door about 20mm from the bottom of the main body and about 10mm from the right edge, removed some of the bracing, and attached it with a bolt to accomplish this. Alternately, find a piece of wood or plastic the right thickness and cut to size to form a new door and attach the flag/mount to that (may require some reengineering of the flag). Hold the printed flag along the edge of the door to guide where to drill/etc.
  - The limit switch flag should firmly contact the bottom limit switch when the door is closed, so ultimately try to place it appropriately based on that.

## Programming

- Flash your Arduino Ethernet with doggie-door.ino
- Go to the Arduino's mDNS URL in your browser: http://doggie-door.local
  - If for some reason mDNS doesn't work, look for the IP Address corresponding to D0:99:1E:D0:99:1E in your router's DHCP table.
  - It may take 10-30 seconds to boot and register on the network.
- It should display a status page with buttons that you can use to control the door.
- Web requests that include `?u`, `?d`, `?s` or `?q` in the URL and `application/json` in the header will return JSON.

## Wiring

- Use a breadboard to wire up your voltage regulator to deliver power to the servo:

```
         [  7805 ]
          |  |  |        Capacitor (+ to +, - to -)
        +9v  G  +5v     /
---------IN  |  OUT----o--- Servo +
             +---------o--- Servo -
```

- Wire the servo's control pin to Arduino pin 9
- Wire the limit switch common pins to Arduino Ground
- Wire the limit switch NC pins to Arduino 2 (top) and 3 (bottom)

## Testing

- With the chain unattached, try the Up and Down buttons on the web interface (or via serial, if preferred) and ensure that the servo works and motion stops promptly when the limit switches are hit.
- The side of the chain closest to the wall should move up until the top limit switch is touched (really any limit switch, but that's ok) and importantly should refuse to continue up as long as the top switch is engaged. It should be able to move downwards. Repeat this test for the opposite direction and switch.
- Attach the chain to the door but leave everything on a clear table so the door can slide freely without damage. Try again while gently guiding the door up and down.

## Installation

- Wire the 9v power and an ethernet cable to the door's location.
- Insert a thin sturdy piece of material in between the door's latch and the door body so it never fully latches. I used a found street sweeper bristle (a thin strip of hardened steel often found in gutters) for this, but anything could work, including simply cutting out the latch.
- Reinsert the doggie door with limit switch into its rightful place in the door frame.
- Unscrew the right-hand side screws of the doggie door and use them to install the doggie door control assembly.
- Connect one end of the ball chain to the door, and loop it gently around the pulleys without attaching the other end.
- Power everything on and run a final test.
- Measure and cut (if neede) the chain to the proper length, and attach the other end. Ensure that the chain is tight: slack will cause the pulleys to skip, fail to move the door, and eventually strip out the pulley plastic.

## Usage

- Either use the buttons on the Arduino's webpage
OR
- Create RESTful entries in HomeAssistant or similar:

```configuration.yaml

rest:
  - scan_interval: 30
    resource: "http://doggie-door.local/"
    params:
      q: "q"
    headers:
      Accept: "application/json"
    binary_sensor:
      - name: "Doggie Door Maxup"
        value_template: "{{ value_json['maxup'] }}"
      - name: "Doggie Door Maxdown"
        value_template: "{{ value_json['maxdown'] }}"

rest_command:
  doggie_door_up:
    url: "http://doggie-door.local/?u"
  doggie_door_down:
    url: "http://doggie-door.local/?d"
  doggie_door_stop:
    url: "http://doggie-door.local/?s"
```
  - Restart HomeAssistant and create buttons or automations to the appropriate services and entities:

```
square: false
type: grid
cards:
  - show_name: true
    show_icon: true
    type: button
    tap_action:
      action: call-service
      service: rest_command.doggie_door_up
      target: {}
    icon: mdi:window-shutter-open
    name: Open
    state_color: true
    entity: binary_sensor.doggie_door_maxup
  - show_name: true
    show_icon: true
    type: button
    tap_action:
      action: call-service
      service: rest_command.doggie_door_down
      target: {}
    icon: mdi:window-shutter
    name: Close
    state_color: true
    entity: binary_sensor.doggie_door_maxdown
  - show_name: true
    show_icon: true
    type: button
    tap_action:
      action: call-service
      service: rest_command.doggie_door_stop
      target: {}
    icon: mdi:alert-octagon
    name: Stop
columns: 3
title: Doggie Door
```

  - Note that depending on installation specifics, the "up" (maxup) status may not be very reliable. It's easy for the door to shift downwards slightly after opening.

## TODO

- Mount holes and cable management for Arduino