Dr Z's garage door opener with ultrasonic sensor HC-SR04 how to code the sensors

I’ve built Dr Z’s Garage door opener found here Add Wifi Control to your Garage Opener using Sonoff SV, ESPhome, and Home Assistant - YouTube using the sonoff sv and hc-sr04 but no reed switch. So far its been working as advertised.

I’ve made a small alteration to the install and placed the UltraSonic sensor above were the door comes to rest when its open. When the door is up the distance is aprox 0.21 to 0.22 meters shown on US sensor. When the door is down and a vehicle is parked the distance shown is aprox 1.11 to 1.19 meters. When the door is down and no vehicle is parked the distance shown is aprox 2.61 to 2.67.

I wondered if somebody could show me what it would look like to have binary sensors for each of these instances:Door open,Door closed,vehicle at home,vehicle not at home. I can see a limitation here that when the garage door is open, that vehicle detection is not possible which is ok for me right now. It would be good though if the at home/not at home sensor were to just show unknown so as to be accurate when this was the case.

What combination of code/templating in HA and in the sonoff SV would anybody suggest here.
Here is what I have now which is just copying what was suggested in the video

esphome:
  name: garage-door-1

esp8266:
  board: esp01_1m

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:
  password: "redacted"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Garage-Door-1 Fallback Hotspot"
    password: "redacted"

captive_portal:

binary_sensor:
  - platform: template
    name: "Parking space 1"
    device_class: presence
    lambda: |-
      if (id(ultrasonic_sensor1).state < 1.5) {
        // car is in the garage
        return true;
      } else {
        // no car
        return false;
      }   
      
switch:
  - platform: gpio
    pin: GPIO12
    id: relay
  - platform: template
    icon: "mdi:arrow-up-down-bold-outline"
    name: "Garage Door 1 Control"
    turn_on_action:
    - switch.turn_on: relay
    - delay: 500ms
    - switch.turn_off: relay

sensor:
  - platform: ultrasonic
    id: ultrasonic_sensor1
    trigger_pin: GPIO05
    echo_pin: GPIO04
    name: "Garage Door 1 Sonar"
    update_interval: 60s
    filters:
      filter_out: nan
    timeout: 9m
1 Like

No direct experience, but would this help?

… skimmed through the yaml there, looks like he has thought of many aspects already - even with filters to help manage the noises from the ultrasonic sensor.

Thanks for taking the time and responding.
I am looking at the yaml too and it looks fairly complex. It seems to include a warning buzzer too which is nice and kind of standard on the production wifi garage door opener.

Unfortunately it doesn’t help me decipher the needed language to define binary sensors for my use case. I feel I could cobble together a template in HA but inside esphome i dont think the lamba distance part is yaml.

Looks like a bit of a dead end for me. At least I have thrown off the MYQ yoke though. I will revisit and see what i can figure out. Was just hoping there was somebody who could show me as its maybe not an uncommon setup. I perused the esphome page regarding the US sensor but I couldnt just figure it out from looking at it.

As I see it you should be making a template sensor, not binary sensor.

Template Sensor — ESPHome

So something like:

sensor:
  - platform: template
    name: "Garage state"
    lambda: |-
      if (0.21 <= id(ultrasonic_sensor1).state <= 0.22) {
        return "Garage open";
      } else if (1.11 <= id(ultrasonic_sensor1).state <= 1.19) {
        return "Car parked, Garage closed";
      } else if (2.61 <= id(ultrasonic_sensor1).state <= 2.67) {
        return "Garage closed, No car";
      } else { 
        return "unknown";  
      }
    update_interval: 60s

You are probably right.
I think because of the complication of the unknown possibility. Is that correct?

Thanks so much for writing this for me. What would be the simplest way to figure this out on my own?

Is there any advantage to doing this on device versus a template using the distance from the platform ultrasonic sensor platform?

Il will give this a try as soon as I can

edit getting this output when I try to install with ESPhome

/config/esphome/garage-door-1.yaml: In lambda function:
/config/esphome/garage-door-1.yaml:65:16: warning: comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses]
       if (0.21 <= id(ultrasonic_sensor1).state <= 0.22) {
                ^
/config/esphome/garage-door-1.yaml:66:16: error: could not convert '(const char*)"Garage open"' from 'const char*' to 'esphome::optional<float>'
         return "Garage open";
                ^
/config/esphome/garage-door-1.yaml:67:23: warning: comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses]
       } else if (1.11 <= id(ultrasonic_sensor1).state <= 1.19) {
                       ^
/config/esphome/garage-door-1.yaml:68:16: error: could not convert '(const char*)"Car parked, Garage closed"' from 'const char*' to 'esphome::optional<float>'
         return "Car parked, Garage closed";
                ^
/config/esphome/garage-door-1.yaml:69:23: warning: comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses]
       } else if (2.61 <= id(ultrasonic_sensor1).state <= 2.67) {
                       ^
/config/esphome/garage-door-1.yaml:70:16: error: could not convert '(const char*)"Garage closed, No car"' from 'const char*' to 'esphome::optional<float>'
         return "Garage closed, No car";
                ^
/config/esphome/garage-door-1.yaml:72:16: error: could not convert '(const char*)"unknown"' from 'const char*' to 'esphome::optional<float>'
         return "unknown";  
                ^
/config/esphome/garage-door-1.yaml:74:3: warning: control reaches end of non-void function [-Wreturn-type]
     update_interval: 60s
   ^
*** [/data/garage-door-1/.pioenvs/garage-door-1/src/main.cpp.o] Error 1

using this build file

esphome:
  name: garage-door-1

esp8266:
  board: esp01_1m

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:
  password: "redacted"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Garage-Door-1 Fallback Hotspot"
    password: "redacted"

captive_portal:

binary_sensor:
  - platform: template
    name: "Parking space 1"
    device_class: presence
    lambda: |-
      if (id(ultrasonic_sensor1).state < 1.5) {
        // car is in the garage
        return true;
      } else {
        // no car
        return false;
      }   
      
switch:
  - platform: gpio
    pin: GPIO12
    id: relay
  - platform: template
    icon: "mdi:arrow-up-down-bold-outline"
    name: "Garage Door 1 Control"
    turn_on_action:
    - switch.turn_on: relay
    - delay: 500ms
    - switch.turn_off: relay

sensor:
  - platform: ultrasonic
    id: ultrasonic_sensor1
    trigger_pin: GPIO05
    echo_pin: GPIO04
    name: "Garage Door 1 Sonar"
    update_interval: 60s
    filters:
      filter_out: nan
    timeout: 9m
  - platform: template
    name: "Garage state"
    lambda: |-
      if (0.21 <= id(ultrasonic_sensor1).state <= 0.22) {
        return "Garage open";
      } else if (1.11 <= id(ultrasonic_sensor1).state <= 1.19) {
        return "Car parked, Garage closed";
      } else if (2.61 <= id(ultrasonic_sensor1).state <= 2.67) {
        return "Garage closed, No car";
      } else { 
        return "unknown";  
      }
    update_interval: 60s

Sorry it should be text sensor.

text_sensor:
  - platform: template
    name: "Garage state"
    lambda: |-
      if (0.21 <= id(ultrasonic_sensor1).state <= 0.22) {
        return {"Garage open"};
      } else if (1.11 <= id(ultrasonic_sensor1).state <= 1.19) {
        return {"Car parked, Garage closed"};
      } else if (2.61 <= id(ultrasonic_sensor1).state <= 2.67) {
        return {"Garage closed, No car"};
      } else { 
        return {"unknown"};  
      }
    update_interval: 60s

The benefit of doing it on the device is probably because you can make the actual distance internal and it won’t clutter HA.

Not sure why there is an warning on the if x <= id <= y.
Try it and see if it works otherwise we need to change this too.

1 Like

Thanks so much for checking back.
It appears to have compiled with some warnings:

/config/esphome/garage-door-1.yaml: In lambda function:
/config/esphome/garage-door-1.yaml:67:16: warning: comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses]
       if (0.21 <= id(ultrasonic_sensor1).state <= 0.22) {
                ^
/config/esphome/garage-door-1.yaml:69:23: warning: comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses]
       } else if (1.11 <= id(ultrasonic_sensor1).state <= 1.19) {
                       ^
/config/esphome/garage-door-1.yaml:71:23: warning: comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses]
       } else if (2.61 <= id(ultrasonic_sensor1).state <= 2.67) {

I can post the full log if required.
I have the sensor in HA and it appears to be working. I will keep an eye on it and see if its working as expected. I think I can expand the values using the code you provided to make it work as long as those warnings aren’t important
Thanks for your help…and hope it helps others too as this seems a fairly common setup

I really don’t understand why it’s complaining.

But if you want to remove the warnings then you need to make it:

      if (id(ultrasonic_sensor1).state >= 0.21 && id(ultrasonic_sensor1).state <= 0.22) {
        return {"Garage open"};

And so on....

I could have sworn that it was working despite the warnings but today I’m away quite a bit and the state appears to be incorrect. I then adopted the suggested code to remove the warnings and I have:

  name: garage-door-1

esp8266:
  board: esp01_1m

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:
  password:  "redacted"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Garage-Door-1 Fallback Hotspot"
    password: "redacted"

captive_portal:

binary_sensor:
  - platform: template
    name: "parking space 1"
    device_class: presence
    lambda: |-
      if (id(ultrasonic_sensor1).state < 1.5) {
        // car is in the garage
        return true;
      } else {
        // no car
        return false;
      }
      
switch:
  - platform: gpio
    pin: GPIO12
    id: relay
  - platform: template
    icon: "mdi:arrow-up-down-bold-outline"
    name: "Garage Door 1 Control"
    turn_on_action:
    - switch.turn_on: relay
    - delay: 500ms
    - switch.turn_off: relay

sensor:
  - platform: ultrasonic
    id: ultrasonic_sensor1
    trigger_pin: GPIO05
    echo_pin: GPIO04
    name: "Garage Door 1 Sonar"
    update_interval: 60s
    filters:
      filter_out: nan
    timeout: 9m

text_sensor:
  - platform: template
    name: "Garage state"
    lambda: |-
      if (id(ultrasonic_sensor1).state >= 0.21 && id(ultrasonic_sensor1).state <= 0.22) {
        return {"Garage open"};
      } else if (id(ultrasonic_sensor1).state >= 1.10 && id(ultrasonic_sensor1).state <= 1.20) {
        return {"Vehicle parked,Garage closed"};
      } else if (id(ultrasonic_sensor1).state >= 2.61 && id(ultrasonic_sensor1).state <= 2.65) {
        return {"Vehicle away,Garage closed"};
      } else { 
        return {"unknown"};  
      }
    update_interval: 60s

type or paste code here

I’ve probably made an error as it works periodically. The actual state is vehicle away garage door closed which I confirmed with mine own eyes.

Set up a history graph card in Lovelace on a new tab set to panel mode and add both sensors to it.
This should be beg enough so that you can see the text sensor state and the distance reading at the exact same time.
Most likely the distance reported is outside of the ranges you have listed.

You are probably right. I’ve widened the parameters and it shows the correct state currently.
I kind of did what you said a little differently but similar. I went into the history and marked the values at certain times trying to see (matching state and distance) the pattern for when the correct state was shown.
It’s kind of confusing though since I thought = and > together would be inclusive of the value beside them. It didn’t seem to be so I thought I got the code wrong.

Thanks for helping me along. I work in health care and trouble shooting this has been a welcome distraction.

I’ll do what you suggested when I can get a chance