Help with ATS diesel generator

Howdy! I made an esp for an electrical energy generator (ATS) in esphome. I don’t have internet where it is installed. The idea is to start the engine when it feels that there is no voltage on the mains, then connect the load after a minute. If the voltage comes, it remains on the generator for one minute, then it switches to the mains, the generator remains on for another 5 minutes to cool down. I have a problem if the voltage comes on the network and it goes away, in these 5 minutes, that is, it feels that voltage has come and the generator still stops after 5 minutes, without there being voltage on the network.
This is how the configuration looks like:
binary_sensor:

  • platform: gpio
    pin:
    number: GPIO5
    inverted: true
    name: “Sensor Retea”
    id: sensor_retea
    on_press:
    then:
    - delay: 60s
    - switch.turn_on: switch_retea
    - delay: 300s
    - switch.turn_off: switch_start_stop_generator
    - delay: 60s
    - switch.turn_off: switch_generator
    on_release:
    then:
    - switch.turn_on: switch_start_stop_generator
    - delay: 60s
    - switch.turn_off: switch_retea
    - delay: 60s
    - switch.turn_on: switch_generator
    switch:
  • platform: gpio
    pin: GPIO14
    name: “Switch Retea”
    id: switch_retea
    inverted: true
    interlock: switch_generator
  • platform: gpio
    pin: GPIO4
    name: “Switch Generator”
    id: switch_generator
    inverted: true
    interlock: switch_retea
  • platform: gpio
    pin: GPIO16
    name: “Switch Start/Stop Generator”
    id: switch_start_stop_generator
    inverted: true

Can you help me with other config, or any idea?
Thanks!

This can be done but could I suggest that you contact your local electrical authority and or a local electrical contractor as if you don’t set this up properly you could cause death and or serious injury to others. Normally your authority has special requirements that you must follow when doing this.

Generators supplying power down main supply is bad. Scenario: You loose power due to power lines down in the street. Authority automaticity isolates power to safeguard the public… then your generator comes on and powers up the lines in the street… someone touches it and dies. That’s bad

That is impossible. I have two power contactors interconnected in such a way that they are never both connected, if you look in the configuration, they have interlock, and not only that, they also have hardware interlock. I was asking about something else, I am aware of the risks, I am an electrician.

A electrical energy generator is a Genset.

ATS stands for “Automatic Transfer Switch” and it is doing exactly what you are intending to accomplish: If a electricity blackout happens it starts the Genset, cuts the public electricity line to the premises at the Main MCB and switches to the power input of the Genset. After the public power is back it does the opposite: Turns off the Genset and connects the premises back to the public power. The warm-up and cool-down time of the Genset itself is programable through the ATS.

We have one for the Genset at home and the ATS does exactly what you describe. Unfortunately they are a bit costly though.

The worst case scenario Blacky is describing can not happen since the public electricity line to the house is automatically cut by the ATS whenever the Genset is supplying power to the house.

1 Like

It would take some looking behind the scenes in ESPHome to verify this, but I believe that your four event sections are acting independently, and that that architecture is what’s interfering with the logic you intend.
What could help here is a logical ‘state machine’, and a loop to discover when a state-change has occurred, or is needed. If you’re not familiar with the term, a ‘state machine’ is not a device, but is a logic-construct that helps you confirm that the state-transition logic is correct and without surprises.

Consider a 2x2 grid.
Along one side are the conditions: Utility on / Utility off
Along the opposite axis are: Generator on / Generator off

(you could store these states in 2 global variables, but it would be far better to directly examine the sensor/control GPIOs to determine states)

Then in each quadrant, you have logic, for example:
in the UtilOn+GenOn quadrant it tests: utilOn for > 5 minutes? Turn Gen off

Using a state machine model for this helps to ensure that the logic doesn’t have pitfalls such as you’re seeing when independent timeouts occur, despite being obsolete.

Mapping those quadrants’ logic into triggers in the ESPHome YAML syntax would be the next step.
I’d attempt it further, but have not yet had my coffee. Hoping, though, that this suggestion perhaps provides an approach that helps you.

I will try this option as well. Can someone check if I did it right? Maybe I’m missing something…

script:

  • id: my_script1
    then:
    • delay: 60s
    • switch.turn_on: switch_retea
    • delay: 300s
    • switch.turn_off: switch_start_stop_generator
    • delay: 60s
    • switch.turn_off: switch_generator
  • id: my_script2
    • switch.turn_on: switch_start_stop_generator
    • delay: 60s
    • switch.turn_off: switch_retea
    • delay: 60s
    • switch.turn_on: switch_generator
      binary_sensor:
  • platform: gpio
    pin:
    number: GPIO5
    inverted: true
    name: “Sensor Retea”
    id: sensor_retea
    on_press:
    then:
    - script.execute: my_script1
    - script.stop: my_script2
    on_release:
    then:
    - script.execute: my_script2
    - script.stop: my_script1
    switch:
  • platform: gpio
    pin: GPIO14
    name: “Switch Retea”
    id: switch_retea
    inverted: true
    interlock: switch_generator
  • platform: gpio
    pin: GPIO4
    name: “Switch Generator”
    id: switch_generator
    inverted: true
    interlock: switch_retea
  • platform: gpio
    pin: GPIO16
    name: “Switch Start/Stop Generator”
    id: switch_start_stop_generator
    inverted: true

I see a potential problem with this approach because of the embedded delays.
During those delays, the real-world conditions could change (such as utility coming back on, or going off again) and the delay just keeps going, followed by the action it precedes. The trouble being, of course, that you no longer want that action to happen.

That is the essence of my suggestion above for how the quadrant logic should look, and should rely on ESPHome’s ability to determine something like “is Utility off, and has been for at least 1 minute?”
The key to this is the “for” which is a built-in conditional keyword in ESPHome’s condition logic.

(I’m trying to find a good example of using ‘for’ in the ESPHome docs. Will update this with a link when I do)

It seems like that is how you want your generator to respond. By relying on ESPHome’s “for” condition, your logic doesn’t have to rely on delays. Every test results in either inaction, or immediate-and-complete action (e.g. stop the generator), and that action will only occur if all your criteria are met
(e.g., Utility is on, and it’s been that way for 5 minutes.)

1 Like

Ok, this is what I get for answering before coffee.
the ‘for’ test I’m thinking about is a feature in HomeAssistant, not in ESPHome. You need this to be able to operate standalone, which ESPHome can do, but it doesn’t have a built-in ‘for’ test.

So, to follow my suggestion, you’d need a timer (like the built-in millis() function) and a few Global Variables.
Whenever you make a change to a device, or detect a change in the utility (gen on, relay on, util on, etc) store the current millis() in a global related to that sensor or switch (e.g. Relay_Changed_When, Utility_Changed_When).

Then, when testing to see if the state needs to change (has the util been on for 5 minutes?) you just test whether your stored ‘when’ is more than 300000mS older than the current millis().
Now, you have the ability to tell how long the utility has been back on, so your logic knows if and when it should turn off the generator.

There’s one risky point about using the built-in millis() timer for this, and that is that the counter rolls over about every 64 days. So, if events were to occur right when it’s about to rollover, and it does, your tests for time could yield inaccurate results, once.

To avoid that, you would also want to test for how high the millis() counter is getting, and, if it’s maybe about halfway (i.e. 32 days) and if the whole system is in quiescent state (util on, gen off, it’s been so for > an hour or two), reboot itself. The reboot takes just a few seconds, but now you have another 32 days of accurate millis().
There are more elegant ways to handle counter rollover, but that adds complexity and thus the opportunity for bugs. By just rebooting every 32 days, you solve the rollover issue without extra logic, and it presumes that your generator isn’t ever likely to be in operation for > 30 days at a stretch.

I’m just at the beginning of esphome programming, I’m trying to learn. It is also a challenge, an ambition. Can you give me an example of the code, in my mind, I see how it should be, but the lack of experience in python… shows its face. As you can see, I tried several options. That’s why I turned to this forum, maybe someone more experienced can guide me in the right direction.

Happy to. Might take me a while, though. I’ve got some other tasks to take care of this morning, and then will sit down and try to compose YAML that does what I’m talking about.

Can you clarify for me what the ‘retea’ switch and sensor are? What’s ‘retea’?

‘start/stop generator’ looks like a simple binary switch: generator on, generator off, depending on the state of that [ESP] output.

I am doing something like this, you can check out my post. While I have some issues I did some of the things that you might need.

It is not a rush. The “retea switch” is the relay that controls the power main line switch, which comes from the electricity supplier.
The “retea sensor” is a relay placed on one of the electricity input phases from the supplier, it senses when there is voltage or not.
start/stop generator, is the relay which, when it is closed, starts the electricity generator, when it is open, it stops it. It is a diesel electric generator.
That’s right, a simple switch.

Thank you!

I tend to do most of my programming while doing other things. The algorithm takes shape in my head in the background.
In this case, I think two truth tables (one for the transfer relay, and one for the generator, since you don’t always want to activate them both simultaneously), and an Interval trigger.

This will therefore be a ‘polled’ control, where it tests conditions every second, and takes any appropriate action.
Ideally it would be implemented as an interrupt-driven system, but using interrupts for this can introduce subtle (not to mention surprising, even dangerous in this case) race-conditions unless you also employ mutex wrappers around the decisions to ensure they are made atomically, and that is better programmed directly in C[++].

In the simpler, 1-Second polling approach, there will be an average response delay of 0.5 Seconds (+/- 0.5S) to any change of conditions, if that’s tolerable for your application?

Polling could be done more rapidly by using a shorter interval, but if it’s made too short there becomes a risk of starving the system of ‘idle’ time during which it does housekeeping and maintains the WiFi link, etc. I chose 1S arbitrarily, there’s no math behind it, just intuition.

One second is ok, maybe more, there is no need for such precision. The idea is that when it goes from the generator to the main line, it should be fast.

Can you clarify what is the difference between:
switch_start_stop_generator
and
switch_generator
?

In addition to the above question, does this set of states accurately describe what actions you’d want taken under the varying conditions?

# State Tables
# These will tell us if we are going to be operating the system properly
# by guiding the condition-testing code we write below
# There are only 4 situations in these tables where we need to take action
# I used two separate tables in order to be sure we don't accidentally introduce
# side-effects from the combination of delays between turning the relay off versus turning the generator off.
# The logic could certainly be made more visually efficient, but that introduces risk of side-effects, and
# in this case I think you would prefer it to be provably correct, than pretty.

#### ==== Generator State Table

# UtilOn & GenOff
#   - quiescent state, take no action

# UtilOff & GenOff
#   >>> turn generator on

# UtilOn & GenOn
#   - has util been on > 5 minutes?
#     >>> turn generator off

# UtilOff & GenOn
#   - steady-state, operationally active, take no action

#### ==== Relay State Table

# UtilOn & RelayOff?
#   - quiescent state, take no action

# UtilOff & RelayOff?
#   >>> turn relay on

# UtilOn * RelayOn?
#   - has util been on > 10 seconds?
#     >>> turn relay off

# UtilOff & RelayOn?
#   - steady-state, operationally active, take no action

#### =================

Switch_start_stop_generator = the switch that starts and stops the generator engine.
Switch_generator = the switch that switches the utilities (electrical installation of the house) to the voltage from the generator

I am sending you a diagram to see logically.

I think I get it now, thanks. The name had me a bit confused.
I have logic for this in YAML that compiles, but I have yet to fully desk-check if I got it right.
Will post in a moment.