Gate controller using cover

So here’s the thing,

I am a long time (more than 10 years now) Arduino hobbyist and I am having trouble wrapping my mind around ESPhome though I am totally into it…

I can set pretty much anything up but setting interdependencies between them is causing me issues. Normally I would just set a loop to read everything, then put all the values into variables, then another loop to evaluate those input variables, producing output variables that I use another loop to change the physical states of all the output pins. There seems to be implicit behavior built into the esphome modules that I do not understand.

Project setup
I have an Apollo gate control. Basically it does one thing. on a press (connecting a sig to gnd on the board) the gate opens. another press results in the gate closing.
1 output
4 inputs, closed switch, open switch, motor open and motor close.
So I reused an old project for a water timer to start this. I have actually managed to get most of it working except I can’t get the timer to start based on the condition of one of the binary sensors.


I need to start the gate close timer (the time the gate will remain open before shutting automatically) at the point the gate fully opens (gateisopen goes high) rather than at the point of activating the template switch. code is below. Please know I don’t really know what I am doing here and since I can’t just make a bunch of loops to do the jobs I need done, like Arduino, I probably am missing some very fundamental understandings here.

code below

###############################subs###############################
substitutions:
  devicename: gatecontrol ##this will be the device name like "water_station_1" "outdoor_light_5"
  purpose: entry ##this will be the purpose of the switch like recirculation, illumination, or irrigation
  subject: gate  ## this is what its interface is acting on like "garden", "water heater", or "zone_1"
  outputpin: GPIO05 #D01 #output wire
  gateisclosed: GPIO04 #D02 #orange wire 5v
  gateisopen: GPIO13 #D07 #white wire 5v
  gateisopening: GPIO12 #D06 #black wire 12v
  gateisclosing: GPIO14 #D05 #red wire 12v
##################################################################
packages:
  device_base: !include /config/esphome/common/eas8266common.yaml  # wifisig/uptime/status

esphome:
  name: $devicename


esp8266:
  board: d1_mini

mdns:
  disabled: false

# Enable logging
logger:
  level: DEBUG

# Enable Home Assistant API
api:

ota:
  password: ""

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  domain: .local
  fast_connect: true

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Gatecontrol Fallback Hotspot"
    password: "HMzrqenCwpHt"

captive_portal:



globals:

  - id: gatestate
    type: int
    restore_value: no
    
# 1 is fully closed 2 is opening, 3 is fully open and 4 is closing 
    
  # ============================================================================= #
   # Irrigation time remaining
  - id: remaining_time_1
    type: int
    restore_value: no
    initial_value: "0"
  # Store previous values to verify change.
  - id: remaining_time_1_previous
    type: int
    restore_value: no
    initial_value: "0"
#===============================================================================#    
  - id: runonce
    type: bool
    initial_value: "false"

    
#################self contained onoff for gate===================

switch:  
  - platform: gpio
    pin: $outputpin
    id: ${devicename}_${subject}_switch
    name: "Gate Control Switch"
    icon: "mdi:gate"
    on_turn_on:
    - delay: 500ms
    - switch.toggle: ${devicename}_${subject}_switch


############################################################

###########template switch functions##############

  - platform: template
    id: ${devicename}_${subject}_open_close
    name: "Gate Remote Open/Close"
    icon: "mdi:gate"
    optimistic: true
    on_turn_on:
      then:
        if:
          condition:
            lambda: 'return id(${purpose}_${subject}_duration).state > 0 && (id(${subject}_open_switch) == 1);'
          then:
        # Start the countdown timer.
            - globals.set:
                id: remaining_time_1
                value: !lambda return (id(${purpose}_${subject}_duration).state);
        # Show the remaining time.
            - sensor.template.publish:
                id: ${purpose}_${subject}_remaining
                state: !lambda return id(${purpose}_${subject}_duration).state;
            - switch.toggle: ${devicename}_${subject}_switch
    on_turn_off:
      - switch.toggle: ${devicename}_${subject}_switch
      

############################################




################switch sensors####################


binary_sensor:   
  - platform: gpio
    pin: 
      number: $gateisopen
      id: ${subject}_open_switch
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Gate is open"


  - platform: gpio
    pin: 
      number: $gateisclosed
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Gate is closed"
##################################################

#############Motor running sensors################
    
  - platform: gpio
    pin: 
      number: $gateisopening
      id: ${subject}_opening_motor
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Gate is opening"
    
  - platform: gpio
    pin: 
      number: $gateisclosing
      id: ${subject}_closing_motor
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Gate is closing"
##################################################    


sensor:
  # ============================================================================= #
  # Retrieve durations settings from the Home Assistant UI.
  - platform: homeassistant
    id: ui_${subject}_duration
    entity_id: input_number.${purpose}_${subject}_duration
    on_value:
      #if:
      #  condition:
      #    api.connected:
      then:
        - sensor.template.publish:
            id: ${purpose}_${subject}_duration
            state: !lambda return id(ui_${subject}_duration).state;
  # ============================================================================= #
  # Store durations so if HA cant be reached the last value still remains
  - platform: template
    name: ${purpose} duration - ${subject}
    id: ${purpose}_${subject}_duration
    accuracy_decimals: 0
    unit_of_measurement: sec
    icon: mdi:camera-timer
  # ============================================================================= #
  # Countdown sensors.
  - platform: template
    name: Remaining Time - ${subject}
    id: ${purpose}_${subject}_remaining
    #lambda: "return 0;"
    accuracy_decimals: 0
    unit_of_measurement: sec
    icon: mdi:timer
    #on_value:
    #  then:
    #    - if:
    #        condition:
    #          lambda: return id(remaining_time_1) == 0;
    #        then:
    #         - switch.toggle: ${devicename}_${subject}_switch

###############################virtual visual indicator lights#######################

  - platform: template
    name: ${subject} Status
    id: ${purpose}_${subject}_status

cover:
  - platform: template
    name: "Main Gate"
    device_class: Gate

    open_action:
      # Cancel any previous action
      - switch.toggle: ${devicename}_${subject}_switch

    close_action:
      - switch.toggle: ${devicename}_${subject}_switch
      
    stop_action:
      - switch.toggle: ${devicename}_${subject}_switch
    optimistic: true
    assumed_state: true
# Update the countdown timers every 1 seconds.
interval:
  - interval: 1s
    then:
      - lambda: |-
          if (id(remaining_time_1) > 0) {
            // Store the previous time.
            id(remaining_time_1_previous) = id(remaining_time_1);
          }
            
            // When the open/close switch is on.
          if (id(${devicename}_${subject}_open_close).state) {
            if (id(${subject}_open_switch)) {
              // Decrement the timer.
              id(remaining_time_1) -= 1;
                if (id(remaining_time_1) <= 0) {
                  id(remaining_time_1) = 0;
                  id(${devicename}_${subject}_open_close).turn_off();
              }
            }
          }     
               // Update the remaining time display.
          if (id(remaining_time_1_previous) != id(remaining_time_1)) {
              id(${purpose}_${subject}_remaining).publish_state( (id(remaining_time_1) ) );
              }


Endstop Cover

1 Like

Right, and that looks exactly what I need, except the switches I need are just indicators of position. My gate controller isn’t actually going to be stopping the gate, that happens internally. What I need is something that I can use to open stop, close or “open/wait/close” with the wait controlled by a slider in HA but all timers internal to ESphome. I got the slider and countdown part working sorta, however right here
In my lambda I am trying to start the gate countdown after the gate is opened so the timer doesn’t decrement until the gate has reached fully open position.

If I flip the open/close template switch <initial user action
then Lambda
If timer slider ${purpose}_${subject}_duration has a value > than 0 AND ${subject}_open_switch has become +V then put the duration value into global variable remaining_time_1

This however fails to compile and appears to have trouble with &&

I know this is probably a hodgepodge of syntax errors, please let me know what they are.

###########template switch functions##############

  - platform: template
    id: ${devicename}_${subject}_open_close
    name: "Gate Remote Open/Close"
    icon: "mdi:gate"
    optimistic: true
    on_turn_on:
      then:
        if:
          condition:
            lambda: |- 
              if ((id(${purpose}_${subject}_duration).state > 0)  &&  (id(${subject}_open_switch).state)) {
                  id(remaining_time_1) = return (id(${purpose}_${subject}_duration));
                  }
          then:
        # Show the remaining time.
          - sensor.template.publish:
              id: ${purpose}_${subject}_remaining
              state: !lambda return id(${purpose}_${subject}_duration).state;
    on_turn_off:
      - switch.toggle: ${devicename}_${subject}_switch
      

############################################

So I think feedback cover would work like this below, but I cant get it to compile


###############################subs###############################
substitutions:
  devicename: gatecontrol ##this will be the device name like "water_station_1" "outdoor_light_5"
  purpose: entry ##this will be the purpose of the switch like recirculation, illumination, or irrigation
  subject: gate  ## this is what its interface is acting on like "garden", "water heater", or "zone_1"
  outputpin: GPIO05 #D01 #output wire
  gateisclosed: GPIO04 #D02 #orange wire 5v
  gateisopen: GPIO13 #D07 #white wire 5v
  gateisopening: GPIO12 #D06 #black wire 12v
  gateisclosing: GPIO14 #D05 #red wire 12v
##################################################################
#packages:
#  device_base: !include /config/esphome/common/eas8266common.yaml  # wifisig/uptime/status


esphome:
  name: $devicename

esp8266:
  board: esp01_1m

# Enable logging
logger:
  level: DEBUG
  
# Enable Home Assistant API
api:
  
ota:
  password: !secret ota_password

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Gatecontrol Fallback Hotspot"
    password: "w5GlHwn6uPkD"

captive_portal:



#################self contained onoff for gate===================

switch:  
  - platform: gpio
    pin: $outputpin
    id: ${devicename}_${subject}_switch
    name: "Gate Control Switch"
    icon: "mdi:gate"
    on_turn_on:
    - delay: 500ms
    - switch.toggle: ${devicename}_${subject}_switch


############################################################

################switch sensors####################


binary_sensor:   
  - platform: gpio
    device_class: opening
    pin: 
      number: $gateisopen
      id: gate_open_switch
      inverted: true
    name: "Gate is open"

              
  - platform: gpio
    device_class: opening
    pin: 
      number: $gateisclosed
      id: gate_close_switch
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Gate is closed"
##################################################

#############Motor running sensors################
    
  - platform: gpio
    pin: 
      number: $gateisopening
      id: ${subject}_opening_motor
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Gate is opening"
    
  - platform: gpio
    pin: 
      number: $gateisclosing
      id: ${subject}_closing_motor
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Gate is closing"
##################################################    


sensor:
  # ============================================================================= #
  # Retrieve durations settings from the Home Assistant UI.
  - platform: homeassistant
    id: ui_${subject}_duration
    entity_id: input_number.${purpose}_${subject}_duration
    on_value:
      #if:
      #  condition:
      #    api.connected:
      then:
        - sensor.template.publish:
            id: ${purpose}_${subject}_duration
            state: !lambda return id(ui_${subject}_duration).state;
  # ============================================================================= #
  # Store durations so if HA cant be reached the last value still remains
  - platform: template
    name: ${purpose} duration - ${subject}
    id: ${purpose}_${subject}_duration
    accuracy_decimals: 0
    unit_of_measurement: sec
    icon: mdi:camera-timer
  # ============================================================================= #
  # Countdown sensors.
  - platform: template
    name: Remaining Time - ${subject}
    id: ${purpose}_${subject}_remaining
    lambda: "return 0;"
    accuracy_decimals: 0
    unit_of_measurement: sec
    icon: mdi:timer
  # ============================================================================= #
  
  # ==============================feedback cover function======================== #

cover:
  - platform: feedback
    name: "Gate"
    id: gate

    open_action:
      - switch.turn_on: ${devicename}_${subject}_switch
    open_duration: 30sec
    open_endstop: ${subject}_open_switch
    open_sensor:  ${subject}_opening_motor
    
    close_action:
      - switch.turn_on: ${devicename}_${subject}_switch
    close_duration: 30sec
    close_endstop: ${subject}_close_switch
    close_sensor: ${subject}_closing_motor

    stop_action:
      - switch.turn_on: ${devicename}_${subject}_switch
      
 # ==============================feedback cover function======================== #


For some reason or another it doesn’t seem to care for my binary sensors, but I am struggling to see how they are different than in the example. Can someone point out the flaw?

the id doesn’t belong under the pin definition, correct would be something like this:

binary_sensor:   
  - platform: gpio
    device_class: opening
    id: gate_open_switch
    pin: 
      number: $gateisopen

Wow! Thanks!

That totally fixed it. I very much appreciate the assist.

@CGriff did you have to do anything for the 12v to step it down for the board? I’m getting ready to basically copy your setup here for my own gate. I have the open/close switch on the board and they’re NO. I haven’t measured what voltage is coming out of them yet but I’m assuming I can’t just send 12V or whatever is in there to the nodemcu as I’m sure it would fry it lol. I am going to use a relay to trigger the gate open/close so that I can at least get that bit working in case I need to order up some more parts to be able to sense if the gate is open/closed. Thank you

Yeap, I use the standard LM2596S board adjusted then I put a drop of locktite over the screw so it wont get moved. I bought a pile of 20 probably 5 years ago and use them for almost everything (because almost everything need lower voltage than I have) :slight_smile: None have blown so far.

As soon as this project is 100% I am going to try a full replacement of the Apollo board using an H-Bridge for motor control.

1 Like

so I think that my buck converters will finally arrive today (they were supposed to be here yesterday). My gate motor doesn’t have any method to tell whether its opening or closing like yours does so I’ll only be able to monitor the open close limit switches to see if they’re powered or not. I used your code for my build but I think I’ll have to rip out the opening/closing sensors unless you know of some hackery that if neither sensor is currently powered and then based off of the state of the cover have it show it as opening or closing. I’m still pretty new to esphome. At my old house I used it for monitoring sump pits so there wasn’t much to it compared to this masterpiece that you’ve written here.

Ok so my gate controller has 3 terminals for the gate operation. Open Close and Stop. How would you configure esphome for just the open Close using 2 pins? My limit switches are magnetic and I sat down there with a volt meter and no matter what state the gate was in I constantly got .03 volts off of those terminals they have the open Close and common terminals. I’ll include some pics of the control board here as well.



Let me know if you need more info. This appears to be the controller
CO-Z Automatic Sliding Gate Opener with 2 Remote Controls, Electric Rolling Driveway Slide Gate Motor, Complete Gate Operator Hardware Security System Kit for Sliding Gate Up to 40 Feet Amazon.com
The gate is about a quarter mile from my house so WiFi isn’t really an option for this install so I’m using a board with a built in nic hooked to my switch which then goes over my wireless bridge to the house

check out THIS MANUAL
according to manual you can convert input “CLS” to single button “open-stop-close-stop” by setting DIP switch 1 to OFF.
Regarding limit switches: try to measure voltage between +24V - CLLM and voltage between +24V - OPLM and see if you get any usable output.

Thank you @Protoncek so much. I’ll have to give it a whirl in the morning and see how it works. I’ll report back and I’ll also take a measurement off of the oplm and the 24V and see what it shows me when the gate is moving. I don’t think though that I have opening/closing sensors though as the motor runs on 110AC unless I convert those voltages over to DC and then buck convert them down but that is a lot of extra equpipment to put into my little solar charging box. I’ll need to build me a little box to hold the relay and the buck converters in. I tried to power the device with a raspberry pi POE splitter and hooked the wires up to the controller but my switch was only putting out 4v so it just wasn’t getting the job done. I finally hooked some wires straight up to the battery in the box and then buck converted it down to 5V so now I know that the ESP board is getting exactly 5V .

Ok so good news to report in this morning. I can now open/stop/close the gate.
Took a voltage reading as per your suggestion and yep going from the 24V terminal to the limit switch sensors they do report back in 24V so I’ll need to step those down.
Now I have a question. I’m assuming that we’ll send a 24V wire from the terminal to a buck converter and then send the stepped down voltage from the buck converter to the sensor wire on the board. I’ll be using 2 independent buck converters. So as I understand it by doing this only the sensor that is currently in the closed state will have its buck converter powered up. Once that sensor changes it status back to open then the circuit will open and that buck converter will power down. So from the ESP board I’ll hookup the sensor wire to the output + of the buck converter and then hookup the ground wire from the buck converter to one of the gnd terminals on the board. I wouldn’ve done all of this, this morning before work started but had other things that needed tending to (ranch life) Thank you all for your help with this little project.

Ok. i’m glad that you’ve found a button.

Regarding limit switches: i assume you only need information if gate is open or closed and you intend to connect this information to ESP’s input. Correct? If so, you don’t need two buck converters. ESP’s inputs are very high impedance, so only thing you need is a resistor and 3.3V zener diode. Then you connect one part of resistor to limit switch (24V), other part to zener, second part of zener to GND. resistor-zener connection is the part you connect to ESP’s input (where 3.3V is). Repeat for other limit switch and you’re done. (it’s just classic zener voltage regulator).
That way you’ll convert 24V to 3.3V in a very simple manner. Resistor can be quite high value, i guess even in the range of 4k7 or 10k would be ok (try and see).

Ok, other option is to use optocouplers, if you want to isolate motor from ESP. But, i think that resistor-zener will also do the trick.

I’ll have to look into the resistors and the zen diode. I haven’t ever played with stuff like that yet. For now I have the buck converters down there. Living out in the middle of nowhere things aren’t exactly quick to get to me. I think that an octocoupler would be a better fit since I can just get 1 board with 2 input/outputs on it and keep things looking neater in the end. Right now lol its a mess of wires in the battery box so once I get this all hooked up and working properly I’ll have to go in there with a tuperware container and make this look nicer. I was smart with 1 bit and I used a length of cat 5 cable to run from the motor to the battery box so at least I was able to just use that for the main cabling. I did lookup to ensure that the cat5 was capable of doing what I needed it to do.

Ok so here is my current board rendition just thought I’d share it with the community. Soldering and design is not one of my strong suits, the 2 buck converters together on the board will for now be the limit switches being stepped down until I get the solution working from @Protoncek working (need to order parts, had buck converters on hand so went that route for now) I still need to dial the bucks in for the limit switches so that is why they are not hooked up to the other board yet. Also ignore the middle screw terminal on the buck converters, I need to get some of that solder whicking stuff so I can pull that out.
Anyways I at least did it with what I thought was the right approach by using a PCB board (permanent holiday lights v1 parts I bought years ago) and put in screw terminals and female header pins for the ESP board. I didn’t do header pins for the bucks they’re just single pins on their corners soldered to the PCB. I even took a stab at doing solder lines on the bottom of the PCB instead of running wires. This only worked on the buck board because the controller board had too much going on with the different pins for stuff.

1 Like

Nice!
I forgot to mention a third option for detecting gate status: reed relays. You can install one for closed and one for open position. However, this solution needs wire from main electronics to install position of reed switches…

@TheFuzz4 Thanks for this topic. I know it’s old, maybe you thinkered some stuff about the open and closed position (and maybe opening and closing).
I’m also looking for some variant of reverse engeenirng of gate opener controller board.

Did you solve this with reed relays or are you just using open/close/stop signals?

I am using open, close and stop signals. The gate has 2, 5v high lines when fully open or closed and since its on a gear drive controller (gate company) I can monitor the 12v lines of the motor to detect opening and closing (in between fully open/closed).

Sorry @CGriff for a mistake :slight_smile:
Aha, monitoring the power of motor on both phases - great!

I managed to get end positions (closed and opened) - from build in high (28V) and low (0V) output which I could use as digital in. So no additional reeds needed. Now I have to choose HW (esp or shelly UNI).

Thanks for the useful info about closing and opening!

1 Like