Simple then, else

I am stuck on this piece of yaml code. I have spent 2 days trying to make it work, I have trolled the web.

I am making a self starter for my generator. The starter is triggered by the utility power failing. A relay drops out and its contact drops an ESP32 GPIO from 3V3 to GND. Simple. All this then triggers a number of events and the generators starts and the 200Amp Automatic swich operates and generator power flows into my house. When utility power is restored, the same relay activates and the same GPIO pin goes high. More things happen and the generator shuts down.

There is an I2C 8 channel relay board doing the various timed events.

I need a then, else or an if, then for this to work and I cannot do so. My yaml code is below. I would like some help getting this to work, please. I gotta say that I am a lot better with hardware than I am with software. Lastly this is not a finished project – obviously.

A code snippet would be best.

Thanks
Pete

esphome:
  name: generator-8750w
  friendly_name: Generator 8750W

esp32:
  board: esp32dev
  framework:
    type: esp-idf

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "eZJ1g9ZJUVzY5RwlETiB4MS1hcIdZ1nE/UA6kDmVyAc="

ota:
  - platform: esphome
    password: "xxxxxxxxxxxxx"

wifi:
  #ssid: !secret wifi_ssid
  #password: !secret wifi_password
  ssid: !secret wifi_IoT_ssid
  password: !secret wifi_IoT_password
  min_auth_mode: WPA

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Generator-8750W Fallback Hotspot"
    password: "xxxxxxxxxxx"

captive_portal:

# GPIO Pins Used
# GPIO32 Input detects utility power failure
# GPIO21 i2c sda
# GPIO22 i2c scl

i2c:
  scl: GPIO22  # Pin 39 D22
  sda: GPIO21  # Pin 42 D21 
  scan: True
  frequency: 100kHz # Options: 100kHz, 400kHz, 1MHz, etc.

# xl9535 8 channel i2c realay board.
xl9535:
  - id: xl9535_hub
    address: 0x20

# Relay outputs
switch:
  # Relay 0, Turns on the gasoline fuel line valve.  This is a 12V operated valve.
  - platform: gpio
    id: r0_gasoline
    name: Gasoline
    pin:
      xl9535: xl9535_hub
      number: 0
      mode:
        output: true
      inverted: false
  
  # Relay 1, the Generators ESC switch.  this must be OFF to start and switched on once the generator has stabilized, sbout 10-15 seconds.
  - platform: gpio
    id: r1_generator_esc
    name: Generator ESC Switch
    pin:
      xl9535: xl9535_hub
      number: 1
      mode:
        output: true
      inverted: false

  # Relay 2, Choke.  Needs to be on to start generator and then off after about 15 seconds.
  - platform: gpio
    id: r2_generator_choke
    name: Generator Choke
    pin:
      xl9535: xl9535_hub
      number: 2
      mode:
        output: true
      inverted: false

  # Relay 2, Start the generator.  This drives a larger 12V relay DPDT relay
  - platform: gpio
    id: r3_generator_start
    name: Generator Start
    pin:
      xl9535: xl9535_hub
      number: 3
      mode:
        output: true
      inverted: false

  # Relay 4, Stop the generator.  THis drives a larger 12V DPDT relay
  - platform: gpio
    id: r4_generator_stop
    name: Generator Stop
    pin:
      xl9535: xl9535_hub
      number: 4
      mode:
        output: true
      inverted: false

  # Relay 5, 
  - platform: gpio
    id: r5_battery_charger_12v_atf
    name: "Battery Charger / 12V to ATS"
    pin:
      xl9535: xl9535_hub
      number: 5
      mode:
        output: true
      inverted: false

  # Relay 6, Operate the ATF.  This is the automatic switch between utility power and generator power
  - platform: gpio
    id: r6_ats_switch_over
    name: "ATS: Utilty / Generator Power"
    pin:
      xl9535: xl9535_hub
      number: 6
      mode:
        output: true
      inverted: false

 # Relay 7,
  - platform: gpio
    id: r7_7
    name: A7
    pin:
      xl9535: xl9535_hub
      number: 7
      mode:
        output: true
      inverted: false

# Turn the relays on and off.  In the correct sequences, of course.
# Utility power on/off detect.  This is what triggers the generatpor start/stop sequences and the ATS
binary_sensor:
  - platform: gpio
    device_class: power
    pin: 
      number: GPIO32 # GPIO32 Detect utilty power
      mode:
        input: true
        pullup: false
      inverted: false
    id: utility_power
    name: "Utility Power"

    on_press:
      then:
        if:
          condition:
             and:
                - delay: 10s
                - switch.turn_off: r1_generator_esc            # Turn OFF the ESC switch to start
                - switch.turn_on: r0_gasoline                  # Turn ON the fuel
                - switch.turn_on: r2_generator_choke           # Set the choke to start
                - switch.turn_on: r5_battery_charger_12v_atf
                - delay: 5s                                    # Wait 3 secs for the fuel to run into the carburettor
                - switch.turn_on: r3_generator_start           # start the bloody thing Run the stater motor
                - delay: 1s
                - switch.turn_off: r3_generator_start     
                - delay: 2s                                    # Give it a blip
                - switch.turn_on: r1_generator_esc             # Turn ON the ESC swich for run
                - delay: 5s                                    # wait a few seconds before switching off the choke
                - switch.turn_off: r2_generator_choke          # Set the choke to off for running
                - switch.turn_on: r5_battery_charger_12v_atf
                - delay: 2s                                    # Let everything stabilize before switching
                - switch.turn_on: r6_ats_switch_over           # This does the ATS switch from Utility (currently off) to Generator
                - delay: 1s                                    # Just a blip
                - switch.turn_off: r6_ats_switch_over          # 
           then:
                - delay: 12s
                # Turn off the generator and restore utility power
                - switch.turn_off: r5_battery_charger_12v_atf
                - switch.turn_off: r0_gasoline       # Turn OFF the fuel and let the carburettor empty and the engibe dies
                - delay: 10s                         # Lete the gasoline in the pipe run dry
                - switch.turn_off: r1_generator_esc  # Turn OFF the ESC switch when the engine is stopping
                - delay: 10s                          # Let it die
                - switch.turn_on: r4_generator_stop
                - delay: 5s
               - switch.turn_off: r4_generator_stop
          else:
               - delay: 1s

https://esphome.io/components/script/

Show, in English or psuedo code what you need and you might get better answers.

Also what is not working in what you have?

What is not working is the needed then, else part.

This bit:

on_press:
then:
if:
condition:
and:
- delay: 10s
- switch.turn_off: r1_generator_esc # Turn OFF the ESC switch to start
- switch.turn_on: r0_gasoline # Turn ON the fuel
- switch.turn_on: r2_generator_choke # Set the choke to start
- switch.turn_on: r5_battery_charger_12v_atf
- delay: 5s # Wait 3 secs for the fuel to run into the carburettor
- switch.turn_on: r3_generator_start # start the bloody thing Run the stater motor
- delay: 1s
- switch.turn_off: r3_generator_start
- delay: 2s # Give it a blip
- switch.turn_on: r1_generator_esc # Turn ON the ESC swich for run
- delay: 5s # wait a few seconds before switching off the choke
- switch.turn_off: r2_generator_choke # Set the choke to off for running
- switch.turn_on: r5_battery_charger_12v_atf
- delay: 2s # Let everything stabilize before switching
- switch.turn_on: r6_ats_switch_over # This does the ATS switch from Utility (currently off) to Generator
- delay: 1s # Just a blip
- switch.turn_off: r6_ats_switch_over #
then:
- delay: 12s
# Turn off the generator and restore utility power
- switch.turn_off: r5_battery_charger_12v_atf
- switch.turn_off: r0_gasoline # Turn OFF the fuel and let the carburettor empty and the engibe dies
- delay: 10s # Lete the gasoline in the pipe run dry
- switch.turn_off: r1_generator_esc # Turn OFF the ESC switch when the engine is stopping
- delay: 10s # Let it die
- switch.turn_on: r4_generator_stop
- delay: 5s
- switch.turn_off: r4_generator_stop
else:
- delay: 1s

Thank you.

have you read this section

it seems to have what you asked about

not sure how to parse that, you seen to have an if then else in your yaml

Yes, I have indeed read that one. It is one near the top of a search list.

What I need is t happen here is for one action to happen when a GPIO is high and an different actio to happen when it is low.

How, please may I accomplish this? As I said arlier. I have spent a lot of time searching and trying to do this myself and, failing before I posted. I’m just looking for a code snippet upon which I can build.

I don’t think you need any if statement at all, unless I’m missing something?

In basic English, I think what you want is:

  • When the utility power changes from “not detected” to “detected” then do a bunch of actions.
  • When the utility power changes from “detected” to “not detected” then do a bunch of other actions.

Is that correct?

If so, this is the structure you’d want:

binary_sensor:
  - platform: gpio
    device_class: power
    pin: 
      number: GPIO32 # GPIO32 Detect utilty power
      mode:
        input: true
        pullup: false
      inverted: false
    id: utility_power
    name: "Utility Power"

    on_press:
      then:
        #<your actions here>
    on_release:
      then:
        #<your actions here>
1 Like

Sorry, I forgot to add that I do not want to do this with HA automation. Why? If the power goes out, even with my huge UPS it might just glitch the power enough to cause my HA server (an HP i5) to glitch. This would stop the generator from going through its startuip and switch the 200Amp Automatic Transfer Switch. Hence I really want this local to the ESP32.

I have seen if statements within yaml files using lambda and C++ code. That would work fine if somebody gave me some code.

I have two altenatives to using if statements: 1). use two GPIOs. one for utility power and another for generator power. 2). use a stand alone arduino to do the switching and use the ESP32 just to talk to HA. Both seem a bit klugy to me.

What I provided is not HA automation, it is ESPHome YAML. It’s nearly identical to what you provided in the first post but I added on_release:

You don’t need lambda code. You can use it if you want, but there’s no benefit in this case.

Something like this. I moved your initial delays into a debounce filter; I assumed that’s what you were intending those for. I also assume that this GPIO becomes active when utility power is detected. (If not, just swap on_press and on_release)

binary_sensor:
  - platform: gpio
    device_class: power
    pin: 
      number: GPIO32 # GPIO32 Detect utilty power
      mode:
        input: true
        pullup: false
      inverted: false
    id: utility_power
    name: "Utility Power"
    filters:
      - delayed_on_off:
          time_on: 10s
          time_off: 12s
    on_press:
      # Utility power has been detected for 10s
      then:
        # Turn off the generator and restore utility power
        - switch.turn_off: r5_battery_charger_12v_atf
        - switch.turn_off: r0_gasoline       # Turn OFF the fuel and let the carburettor empty and the engibe dies
        - delay: 10s                         # Lete the gasoline in the pipe run dry
        - switch.turn_off: r1_generator_esc  # Turn OFF the ESC switch when the engine is stopping
        - delay: 10s                          # Let it die
        - switch.turn_on: r4_generator_stop
        - delay: 5s
        - switch.turn_off: r4_generator_stop
    on_release:
      # Utility power has been lost for 12 seconds
      then:
        - switch.turn_off: r1_generator_esc            # Turn OFF the ESC switch to start
        - switch.turn_on: r0_gasoline                  # Turn ON the fuel
        - switch.turn_on: r2_generator_choke           # Set the choke to start
        - switch.turn_on: r5_battery_charger_12v_atf
        - delay: 5s                                    # Wait 3 secs for the fuel to run into the carburettor
        - switch.turn_on: r3_generator_start           # start the bloody thing Run the stater motor
        - delay: 1s
        - switch.turn_off: r3_generator_start     
        - delay: 2s                                    # Give it a blip
        - switch.turn_on: r1_generator_esc             # Turn ON the ESC swich for run
        - delay: 5s                                    # wait a few seconds before switching off the choke
        - switch.turn_off: r2_generator_choke          # Set the choke to off for running
        - switch.turn_on: r5_battery_charger_12v_atf
        - delay: 2s                                    # Let everything stabilize before switching
        - switch.turn_on: r6_ats_switch_over           # This does the ATS switch from Utility (currently off) to Generator
        - delay: 1s                                    # Just a blip
        - switch.turn_off: r6_ats_switch_over          # 

So, do you understand the basics of how things flow and the significance of why the lines of code are aligned the way they are and why some lines are further to the the Left or right Right and what that means?

Thats a wise decision! IDK why so many others just love separating their entities and logic and automations between multiple devices when its unnecessary and dumb IMO.

How are you reading those 2 with just some gpio binary_sensors?

Also, all of these long lines of multiple switch state toggles and hard delays for multiple seconds is no good at all to do like that and it needs cleaned up, simplified, and remove lines that may trigger false positives or false negatives which will screw the whole automation up on you.

1 Like

Yes, that is exactly what I need. Thank you. I shall try it immediately and get back to you.

Thank you again. The on_release: worked perfectly. In between, I tried the two GPIO fix (one for utility and one for generator) and that works too.

Most of the delays are to do something and wait for it to happen. For example, turn on the gasoline valve requires a few seconds for the gas (petrol) to run down the pipe and into the carburettor float chamber. Similarly when I shut down the generator I close the gasoline valve and wait for the generator run the carburettor dry. This means that if the generator sits for several weeks or months, I do not try to start it with the carb full of guck.

Other things do need debounce and I was intending to put them in so, thank you. The final reason for the delay was to not overload or surge the power supply by not switching everything on at once. The gas valve alone takes 1.2 amps at 12V. So I am just being careful at the testing stage. Ovbiously I wish as short a delay as possible between the utility power going off and my generator restoring it.

Thanks again for your help.
Pete

To clearify a bit on your code
You have this.
If everything in the following condition is TRUE then do some thing

All these line must give a boolean TRUE to make that condition also true.
That will be impossible because you have all kind of actions for your condition.

I do quite a bit of mundane autotomation in the ESP32s. I find Helpers and Automation a bit arcane and I hate the Helper UI. So, it gets done where I can see it and if the HA server falls over most of my stuff keeps tickin’

You ask the question about do I understand indentation. Yes, I do but I get confused and have to move things left and right sometimes when I make changes to the coding logic. I usually get there in the end. YAML is a serial script. It does a lot but not always what I want. A bit like the wife then.

Now, why do I have all those delays? Here I am dealing with the real world. I said earlier today that these are necessary since I need a delay after I turn the gasoline line on to allow the gravity feed gas pipe to fille the carburettor and not to have too much inrush current to DC inductive devices.

How an I doing this. I am using an 8 channel I2C relay board from Amazon https://www.amazon.com/dp/B0FBCB66D9?ref=ppx_yo2ov_dt_b_fed_asin_title. It will arrive tomorrow. I like relays for going to the outside world. All sorts of nasty things happen out there. Some of the little relays cannot handle Start, Stop, Gasoline devices which are high current and inductive and some need more than one contact (DPDT) so I use the little relay to drive a bigger one in some cases. Inelegant yes but very, very safe. That’s what and why.

If this project is interesting, I can take some ics when it is done. Right now I am in the process of havinf a 2 x 200Amp Automatic Transfer Switch (ATS) fitted. It has specific conditions to make it swich from utility power to generator. So that needs to be handled too.

I need to pull a permit and have a qualified electrician to come wire and terminate the 2 x 200 Amp feed from my meter to the ATS and then to the house load center. MY long term plan is to put in a Generac 18kW natural gas generator next year but the piggy bank won’t allow that this year hence my current ffort to fabricate and auto start/stop/switchover system on my current Predator 8750W generator. It is quite a fun project apart from the hitherto unknown cinditionals in yaml. However that is all fixed now thanks to you guys.

Lastly, yes, I know my code is crap but it works right now and so far it seems to be 100% reliable. I fully expect to write v2.0 after the summer when it is all wired up.

Pete

Thanks, you are right of course. After I nitially posted I continued banging my head against this particular wall until I fell over what you just said. In my defense, I had already tried about ten other “solutions” and this was another, “let’s try this.”

I have now moved to a two GPIO solution. One is held low when utility power is present. When the 240V relay held in my utility opower drops out, the grounding switches to another GPIO which is for generator power. WHilst less elegant than many other solutions, it has proven solid in testing.

Thanks again.
Pete

1 Like