Dual relay cover motor control

The following is a possible configuration file for common covers that use a motor with 2 inputs. Only one should be powered at a time (interlocking) to either move the cover up or down. For this the Sonoff Dual R2 can be used which has two independent relays. Additionally this configuration allows the single button on the Sonoff to control the motion by cycling between: open->stop->close->stop->…

These kind of motors automatically stop when the end of the cover movement is reached. However, to be safe, this automation stops powering the motor after 1 minute of movement. In the rare case of the end-stop switch in the motor failing this will reduce the risk for damage or fire.

Of the four main components (button sensor, 2 relays switches and the cover), only the cover will be visible to the end-user. The other three are hidden by means of not including a name. This is to prevent accidentally switching on both relays simultaneously from Home Assistant as that might be harmful for some motors.

Note

Controlling the cover to quickly (sending new open/close commands within a minute of previous commands) might cause unexpected behaviour (eg: cover stopping halfway). This is because the delayed relay off feature is implemented using asynchronous automations. So every time a open/close command is sent a delayed relay off command is added and old ones are not removed.

esphome:
  name: cover
  platform: ESP8266
  board: esp01_1m

wifi:
  ssid: '***'
  password: '***'

api:

logger:

ota:

binary_sensor:
- platform: gpio
  pin:
    number: GPIO10
    inverted: true
  id: button
  on_press:
    then:
      # logic for cycling through movements: open->stop->close->stop->...
      - lambda: |
          if (id(cover).state == cover::COVER_OPEN) {
            if (id(open).state){
              // cover is in opening movement, stop it
              id(cover).stop();
            } else {
              // cover has finished opening, close it
              id(cover).close();
            }
          } else {
            if (id(close).state){
              // cover is in closing movement, stop it
              id(cover).stop();
            } else {
              // cover has finished closing, open it
              id(cover).open();
            }
          }

switch:
- platform: gpio
  pin: GPIO12
  id: open
- platform: gpio
  pin: GPIO5
  id: close

cover:
- platform: template
  name: "Cover"
  id: cover
  open_action:
    # cancel potential previous movement
    - switch.turn_off: close
    # perform movement
    - switch.turn_on: open
    # wait until cover is open
    - delay: 60s
    # turn of relay to prevent keeping the motor powered
    - switch.turn_off: open
  close_action:
    - switch.turn_off: open
    - switch.turn_on: close
    - delay: 60s
    - switch.turn_off: close
  stop_action:
    - switch.turn_off: open
    - switch.turn_off: close
  optimistic: True
  assumed_state: True