Garage Door Position and Raising, Lowering or Idle detection ESPHome - Lambdas

Hey All,

Having a bit of trouble trying to get my garage door sensor right. Have the basics working, but want it to be a bit more advanced.

Door components:

  • Merlin Garage Door with Momentary Trigger input
  • No access to limit switches

Project Parts:

  • Wemos D1 Mini
  • US-100 Ultrasonic Sensor
  • Momentary Relay

What am i trying to achieve?

  1. Garage Door can be opened, closed or sent to a specific position
  2. Sensor is the US-100 Distance sensor

Where am i at?

  • Door Trigger Works
  • US-100 Can detect is Door is open ( < 0.1) or Closed (> 1.0)

Currently i’m a bit stuck on using Lambdas to detect if the door is Rising or Lowering. My concept is to take the current reading of the sensor, compare it to the current value. If the reading is less than store, then door is rising, if the reading is greater than, the door is lowering.

Can all my evaluations be in the one Lambda block?
How do i set some variables?
Am i going about this the right way?

Ultimately, i would also like to have a position indicator in Home Assistant. Heres my current ESP Code:

esphome:
  name: garage_distance_sensor
  platform: ESP8266
  board: d1_mini

wifi:
  ssid: "*******"
  password: "*********"

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Garage Distance Sensor"
    password: "YJo95f2jXJER"

captive_portal:

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:

switch:
  - platform: gpio
    pin: 13
    id: relay
    internal: true

sensor:
  - platform: ultrasonic
    name: "Garage Distance"
    id: position
    trigger_pin: GPIO12
    echo_pin: GPIO14
    update_interval: 2s
    pulse_time: 10us
    timeout: 20m
    internal: true

globals:
  - id: last_door-reading
    type: int
    restore_value: no

      
cover:
  - platform: template
    device_class: garage
    name: "Garage Door"
    id: template_cov
    lambda: |-
      if(id(position).state < 0.1) {
        return COVER_OPEN;
      } 
      else if(id(position).state > 1) {
        return COVER_CLOSED;
      }
      else 
      {
        return{};
      }
    
    open_action:
      - switch.turn_on: relay
      - delay: 0.5s
      - switch.turn_off: relay
    close_action:
      - switch.turn_on: relay
      - delay: 0.5s
      - switch.turn_off: relay

image

Any thoughts or suggestions appreciatated.

Ok, so i have got most of this working. But, i’m still having trouble working out how to get the ‘Actual’ position of the door using the Ultrasonic sensor.

Heres the code i’ve hacked together from some different posts online. I’ll try and get some pictures of the physical setup shortly.

substitutions:
  devicename: garagedoor
  description: OpenGarage.io Device
  friendly_name: Garage Overhead Door
  auto_close_delay: "600s" # 10 minutes
  buzzer_delay: "0.5s"
  open_distance: "40" # fully open less than or equal in cm
  closed_distance: "230" #closed is greater than 230 
  open_close_time: "20s" # allow 20s for motion to complete
  reporting_delta: "3" # minimum 25cm change

esphome:
  name: garage_distance_sensor
  platform: ESP8266
  board: d1_mini

wifi:
  ssid: "*********"
  password: "*********"

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Garage Distance Sensor"
    password: "YJo95f2jXJER"

captive_portal:

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:

switch:
    # The door opener contact (internal)
  - platform: gpio
    id: garage_button
    pin: 13
    restore_mode: ALWAYS_OFF
    internal: true
    on_turn_on:
    - delay: 500ms
    - switch.turn_off: garage_button

sensor:
  - platform: ultrasonic
    name: "${friendly_name} Distance"
    id: ${devicename}_distance
    trigger_pin: GPIO12
    echo_pin: GPIO14
    update_interval: 0.25s
    unit_of_measurement: cm
    accuracy_decimals: 0
    pulse_time: 10us
    timeout: 20m
    internal: false
    filters:
      - filter_out: nan  # filter timeouts
      - multiply: 100    # from meter to cm
      - median:
          window_size: 5
          send_every: 4
          send_first_at: 3
      #- sliding_window_moving_average:
       #   window_size: 5
        #  send_every: 3
         # send_first_at: 3
      - delta: ${reporting_delta}



globals:
  - id: last_door_reading
    type: float
    restore_value: no

      
cover:
  - platform: template
    device_class: garage
    name: "${friendly_name} Control"
    id: ${devicename}_control
    # set the distance so it is equal or less than $open_distance when open
    lambda: !lambda |-
      if (id(${devicename}_distance).state >= ${closed_distance}) {
        return COVER_CLOSED;
      } else {
        return COVER_OPEN;
      }
    open_action:
       - if:
          condition:
            lambda: "return id(${devicename}_control).position == cover::COVER_CLOSED;"
          then:
            - switch.turn_on: garage_button
            - delay: ${open_close_time}
            - script.execute: auto_close
    stop_action:
      - switch.turn_on: garage_button
    close_action:
      - if:
         condition:
           lambda: "return id(${devicename}_control).position == cover::COVER_OPEN;"
         then:
           - switch.turn_on: garage_button
           # Disable any auto close pending action
           - script.stop: auto_close
           - delay: ${open_close_time}
            
script:
  - id: auto_close
    then:
      - logger.log: "Automtically closing in ${auto_close_delay}"
      - delay: ${auto_close_delay}
      - logger.log: "Initiating automatic garage closing"
      - cover.close: ${devicename}_control