Garage Door and wired I/O expander for RPI4

Hello You all.

I have RPI4 With HA Core (0.106.5) that will be sitting in a attic. I have also garage. I am really determined to control them by wire because this is most important (country) house entrance.
Distance between these two points is about 15-20 m. For that I decided to use Waveshare MCP23017, but of course distance is to great. Sice I have Nice Spido drive that has limit switches i decided to monitor 2 binary sensors to get 3 states (closes, opened, unknown). Drive has “start-stop-reverse logic” input and I am fine with that.
Also i would like to achieve really minimalistic thing: one icon representing state of gate, name and one switch.
After reading this topic i noticed that it is closest to my desired but i was not able to control button image with sensor state.
After reading this other solutions i had also problem with setting this cover as switch with “toggle script”
Finally i used this solution, but it has minimum of two buttons. I can live with that but it is arguing with logic of gate driver input (“start-stop-reverse logic” = toggle).
Now it looks like this:

cover:
  - platform: template
    covers:
      garage1_door:
        friendly_name: "DRZWI LEWE"
        icon_template: >
          {% if is_state('binary_sensor.garage_door_13', 'on') %}
            mdi:garage
          {% elif is_state('binary_sensor.garage_door_12', 'on') %}
            mdi:garage-open
          {% else %}
            mdi:garage-alert
          {% endif %}
        open_cover:
          service: script.garruchlewe
        close_cover:
          service: script.garruchlewe
      garage0_door:
        friendly_name: "DRZWI PRAWE"
        icon_template: >
          {% if is_state('binary_sensor.garage_door_15', 'on') %}
            mdi:garage
          {% elif is_state('binary_sensor.garage_door_14', 'on') %}
            mdi:garage-open
          {% else %}
            mdi:garage-alert
          {% endif %}
        open_cover:
          service: script.garruchprawe
        close_cover:
          service: script.garruchprawe

I know that in practice this topic will is, a little bit about hardware. But I want to keep this expander in garage because i will be adding few things and I don`t want to drag all those wires to attic itself. I do not want to use any complicated system such as arduino as I/O communicating with RPI by RS and that is because I am new to pretty much all of it.

  1. Is there any other wired solution ? - If no I will just use P82B715P - I2C expander.
  2. Does anyone know how to change Input/Output direction for i2c?
  3. Does anyone have an idea how to achieve what I made with cover.template but in button minimalistic form ?

PS Thanks to my friend “SZU” that lured me into this HA community :slight_smile:

This might not be the right solution, but my first thought would be to make a template sensor like this:

sensor:
  - platform: template
    sensors:
      drzwi_lewe:
        friendly_name: "Drzwi Lewe"
        value_template: >-
          {% if is_state('binary_sensor.garage_door_15', 'on') %}
            open
          {% elif is_state('binary_sensor.garage_door_14', 'on') %}
            closed
          {% else %}
            alert
          {% endif %}

Then you would have a single sensor to build the button off of instead of trying to get the button to track multiple binary_sensor states. That would allow you to build a button like this:

  - type: 'custom:button-card'
    tap_action:
      action: call-service
      service: script.garruchlewe
      service-data:
        entity: script.garruchlewe
    entity: sensor.drzwi_lewe
    state:
      - value: 'open'
        icon: 'mdi:garage-open'
      - value: 'closed'
        icon: 'mdi:garage'
      - value: 'alert'
        icon: 'mdi:garage-alert'

Which should get you the single button that acts as a toggle you ask about in #3. I’m not 100% confident that the code above (especially the part building the sensor) is correct, so it may require some troubleshooting. Also, not sure if that completely gets you to where you want, but it’s just a thought.

1 Like

Your advice solved button issue, that is exactly what I wanted. It occurred that I knew nothing about custom buttons add from HACS.
I have ordered P82B715 by Philips. When i wil get it i will to compose one post with final arrangements.

Update:
I will attach codes at bottom.
First thing for newbies attached code is for custom button. I did not knew that at the beginning and was struggling a little bit with it.

Here are some hardware clues some may be in fact flaw, or obvious:

  1. Do not attach MCP23017 outputs directly to inputs motor board. Mine was 24 AC … so it is better to check it out then getting some boards fired. For inputs I did not used internal resistors I have added external 10kOhm pull-ups.
  2. For separation i used dual 5v relay (SRD-05VDC-SL-C) with transoptors (EL817).
    Advantage of that solution is that You can set leave i2c bus on 3V3 and get additional power supply for relays 5V. In fact I had to use old nokia power adapter that was 5,7DC because relay#2 was not responding.
  3. I2C extender was 2x P82B715 SMD with pull-up resistors that I did not even calculated just used values as in datasheet. Main thing is that You should get VCC / SDA in one twisted pair and SCL /GND with other.
  4. Like I wrote before I wanted to use existing internal limit switches. They are NC and surprise was that when MCP was powered off it was holding inputs closed. Motor driver was not able to sens closed and opened position. Solution for that was to add simple diodes on input wires, blocking inputs of motor board running trough MCP. Just figure out geniue current direction and make MCP other direction
  5. Cable is 21 meters long and switches are lagging sometimes but i do believe that is Pi fault since sensors are always up to date.
    6 Last part was that i slowed down I2C bus to 50kHz, since in this case reliability was more important than speed.

Additionally You can check out P82B96 which is also I2C extender. One more thing for beginners if You will not get DIP version of these, know that there are these little helpful boards:
image

Ok so here are:
configuration.yaml

  - platform: template
    sensors:
      drzwi_lewe:
        friendly_name: "Lewe"
        value_template: >-
          {% if is_state('binary_sensor.garage_door_13', 'off') %}
            open
          {% elif is_state('binary_sensor.garage_door_12', 'off') %}
            closed
          {% else %}
            alert
          {% endif %}

  - platform: template
    sensors:
      drzwi_prawe:
        friendly_name: "Prawe"
        value_template: >-
          {% if is_state('binary_sensor.garage_door_15', 'off') %}
            open
          {% elif is_state('binary_sensor.garage_door_14', 'off') %}
            closed
          {% else %}
            alert
          {% endif %}
binary_sensor:
  - platform: mcp23017
    i2c_address: 0x27
    scan_interval: 5
    invert_logic: true
    pins:
    #garaz lewy PB4-5
      12: garage_door_12
      13: garage_door_13
    #garaz prawy PB6-7
      14: garage_door_14 
      15: garage_door_15
 
switch:
  - platform: mcp23017
    i2c_address: 0x27
    invert_logic: true
    pins:
      #lewe
      0: Garage0 Switch
      #prawe
      1: Garage1 Switch

scripts:

'garruchlewe':
  alias: Ruch Lewe drzwi
  sequence:
  - data:
      entity_id: switch.garage0_switch
    service: switch.turn_on
  - delay:
      milliseconds: 100
  - data:
      entity_id: switch.garage0_switch
    service: switch.turn_off
    
'garruchprawe':
  alias: Ruch prawe drzwi
  sequence:
  - data:
      entity_id: switch.garage1_switch
    service: switch.turn_on
  - delay:
      milliseconds: 100
  - data:
      entity_id: switch.garage1_switch
    service: switch.turn_off

custom button:

aspect_ratio: 1/2
entity: sensor.drzwi_lewe
state:
  - color: 'rgb(255, 235, 5)'
    icon: 'mdi:garage-open'
    value: open
  - color: 'rgb(24, 134, 45)'
    icon: 'mdi:garage'
    value: closed
  - color: 'rgb(230, 5, 5)'
    icon: 'mdi:garage-alert'
    value: alert
styles:
  card:
    - height: 120px
tap_action:
  action: call-service
  service: script.garruchlewe
  service-data:
    entity: script.garruchlewe
type: 'custom:button-card'