ESPHome garage door opener with hardware button

Hi all,

A few years back i cobbled together a garage door opener for my mother.
I used a sparkfun thething esp 8266 with a relay attached to it.
I want to be able to open the garage door with Siri (homekit) and via a push button in the garage itself.
The push button works great, however siri sometimes can’t find the esp 8266 or the connection is lost or whatever. The point is that sometimes the “remote” opening isn’t optimal. Also, i am having problems with actually being able to open the garage door with the hardware button in case i don’t have a connection to the wifi.
I guess that wifi reconnect code isn’t that optimal so all the cpu time goes there iso to detect the HW button state.

Anyway, time to get rid of all the hassle.

Now recently i discovered home assistant and ESPHome so i wanted to give that a try. I think this would provide a much more stable platform and i don’t have to re-invent the wheel again with my custom code.
Also, i want to get rid of that MQTT server if possible.

However, for some reason it is a complete mistery on which components i actually need to use to make it work.

I have 3 pins that i use to control the entire setup.

// PINS
#define RELAY_TRIGGER_PIN 12
#define SENSOR_GARAGE_CLOSED_PIN 4
#define BUTTON_PIN 13

// Timings
#define RELAY_TRIGGER_DELAY 300

This is what i currently came up with for ESPHome

binary_sensor:
  - platform: gpio
    device_class: garage_door
    pin:
      number: 4
      mode: INPUT_PULLUP
      inverted: false
    name: Garage poort sensor
    filters:
      - delayed_on: 10ms
      - delayed_off: 10ms
    on_press:
      - switch.turn_on: garage_relay

switch:
  - platform: gpio
    pin: 12
    name: Garage Knop
    id: garage_relay
    icon: "mdi:gate"
    on_turn_on:
      - delay: 500ms
      - switch.turn_off: garage_relay

If possible, i want the software button and the state to be combined in 1 component like it would be in homekit.
I am not even sure which components i actually need to use to make the hardware button work.
I don’t really want to display the hardware button in home assistant since there isn’t really any point to do so.
Can anyone point me in the right direction to make that happen.
The hardware button is on pin 13 and this i how the button currently works.

void checkOpenGarageDoorButtonPressed() {
  // read the state of the switch into a local variable:
  int reading = digitalRead(BUTTON_PIN);

  // check to see if you just pressed the button
  // (i.e. the input went from LOW to HIGH), and you've waited long enough
  // since the last press to ignore any noise:

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;

      if (buttonState == HIGH) {
        digitalWrite(LED_PIN, HIGH);
        triggerRelay();
        digitalWrite(LED_PIN, LOW);
      }
    }
  }

  // save the reading. Next time through the loop, it'll be the lastButtonState:
  lastButtonState = reading;
}

2nd, pin 4 is used to determine if the garage is open or closed via a reed sensor.
Here is how that currently works.

void checkGarageDoorOpenIgnoreLastState() {
  int closedState = 0;
  closedState = digitalRead(SENSOR_GARAGE_CLOSED_PIN);
  
  if (closedState == HIGH) {
    digitalWrite(LED_PIN, HIGH);
    client.publish("home/garage/door/status/open", "", false);
  }
  else {
    digitalWrite(LED_PIN, LOW);
    client.publish("home/garage/door/status/closed", "", false);
  }
}

3rd, pin 12 is used to actually trigger the relay.
This is how it works atm

void triggerRelay() {
  if (digitalRead(RELAY_TRIGGER_PIN) == LOW) {
    digitalWrite(RELAY_TRIGGER_PIN, HIGH);
    delay(RELAY_TRIGGER_DELAY);
    digitalWrite(RELAY_TRIGGER_PIN, LOW);
  }
}

Oh yeah, i must mention that i actually didn’t upload the yaml code i paste above, because it is kind of important that the garage door keeps working :slight_smile:

every time i post to this forum, i seem to find the possible solution right after i posted my question.
I will keep you up to date in case it works :slight_smile:

thought i had it, but no sigar

if you didn’t upload the code yet, how do you know it doesn’t work? you are looking for a solution, but I don’t yet understand the problem you are looking to solve.

in the mean time i uploaded the code but i can’t get the hardware button to work.

The hardware button is hooked up to pin13.
When i press it, the ESP needs to trigger the relay in the same way as if i would use the software button.
Pressing the hardware button in the garage currently does nothing.
Also, i find it very weird that in the ‘on_turn_on’ for pin12 i have to specify to turn itself on… in the on_turn_on state… what??? but otherwise it doesnt work via software as well.

This is my current code.

binary_sensor:
  - platform: gpio
    device_class: garage_door
    pin:
      number: 4
      mode: INPUT_PULLUP
      inverted: false
    name: Garage poort sensor
    filters:
      - delayed_on: 10ms
      - delayed_off: 10ms
#    on_press:
#      - switch.turn_on: garage_relay

switch:
  - platform: gpio
    pin: 12
    name: Garage Relay
    id: garage_relay
    internal: true
    on_turn_on:
      - switch.turn_on: garage_relay
      - delay: 300ms
      - switch.turn_off: garage_relay

  - platform: gpio
    pin: 13
    name: Garage Knop
    id: garage_button
    icon: "mdi:gate"
    on_turn_on:
      - switch.turn_on: garage_relay
      - delay: 300ms
      - switch.turn_off: garage_button

  - platform: restart
    name: Garage poort herstarten

From your description, you want to use pin 13 as a binary sensor. You have it set up as a GPIO switch.

Ok, i think i followed your advice.
now my config looks like this.

The hardware button now seems to work, but now the software button isn’t working anymore.

binary_sensor:
  - platform: gpio
    device_class: garage_door
    pin:
      number: 4
      mode: INPUT_PULLUP
      inverted: false
    name: Garage poort sensor
    filters:
      - delayed_on: 100ms
      - delayed_off: 100ms
      
  - platform: gpio
    pin: 13
    name: Garage Hardware Knop
    id: garage_hardware_button
    internal: false
    filters:
      - delayed_on: 50ms
      - delayed_off: 50ms
    on_press:
      - switch.turn_on: garage_relay
      - delay: 300ms
      - switch.turn_off: garage_relay

switch:
  - platform: gpio
    pin: 12
    name: Garage Relay
    id: garage_relay
    internal: true
    
#  - platform: gpio
#    pin: 13
#    name: Garage software Knop
#    id: garage_software_button
#    internal: true
#    on_turn_on:
#      - switch.turn_on: garage_relay
#      - delay: 300ms
#      - switch.turn_off: garage_relay

  - platform: template
    name: Garage Knop
    id: garage_button
    icon: "mdi:gate"
    on_turn_on:
      then:
        - switch.turn_on: garage_relay
        - delay: 300ms
        - switch.turn_off: garage_relay
        - switch.turn_off: garage_button
      
      
  - platform: restart
    name: Garage poort herstarten

this seemed to do the trick.
but can anyone explain me why?
because i thought the template switch would trigger the relay, but that didn’t work (see previous post).
I changed it back to a gpio switch on the pin that is also used by the HW button and that seems to work. But i don’t understand why i HAVE to use a GPIO switch pin to actually trigger the relay.

binary_sensor:
  - platform: gpio
    device_class: garage_door
    pin:
      number: 4
      mode: INPUT_PULLUP
      inverted: false
    name: Garage poort sensor
    filters:
      - delayed_on: 100ms
      - delayed_off: 100ms
      
  - platform: gpio
    pin: 13
    name: Garage Hardware Knop
    id: garage_hardware_button
    internal: false
    filters:
      - delayed_on: 50ms
      - delayed_off: 50ms
    on_press:
      - switch.turn_on: garage_relay
      - delay: 300ms
      - switch.turn_off: garage_relay

switch:
  - platform: gpio
    pin: 12
    name: Garage Relay
    id: garage_relay
    internal: true
    
  - platform: gpio
    pin: 13
    name: Garage software Knop
    id: garage_software_button
    internal: false
    on_turn_on:
      - switch.turn_on: garage_relay
      - delay: 300ms
      - switch.turn_off: garage_relay
      - switch.turn_off: garage_software_button

#  - platform: template
#    name: Garage Knop
#    id: garage_button
#    icon: "mdi:gate"
#    on_turn_on:
#      then:
#        - switch.turn_on: garage_relay
#        - delay: 300ms
#        - switch.turn_off: garage_relay
#        - switch.turn_off: garage_button
      
      
  - platform: restart
    name: Garage poort herstarten

i made it way too complicated.
Made it work like this now.

binary_sensor:
  - platform: gpio
    device_class: garage_door
    id: garage_sensor
    pin:
      number: 4
      mode: INPUT_PULLUP
      inverted: false
    name: Garage poort sensor
    filters:
      - delayed_on: 100ms
      - delayed_off: 100ms
      
  - platform: gpio
    pin: 13
    name: Garage Hardware Knop
    id: garage_hardware_button
    internal: false
    filters:
      - delayed_on: 50ms
      - delayed_off: 50ms
    on_press:
      - switch.turn_on: garage_relay
      - delay: 300ms
      - switch.turn_off: garage_relay

cover:
  - platform: template
    name: "Garage poort"
    device_class: garage
    lambda: |-
      if (id(garage_sensor).state) {
        return COVER_OPEN;
      } else {
        return COVER_CLOSED;
      }
    open_action:
      - switch.turn_on: garage_relay
      - delay: 300ms
      - switch.turn_off: garage_relay
    close_action:
      - switch.turn_on: garage_relay
      - delay: 300ms
      - switch.turn_off: garage_relay

switch:
  - platform: gpio
    pin: 12
    name: Garage Relay
    id: garage_relay
    internal: true

  - platform: restart
    name: Garage poort herstarten