Open-DTU / Solar Inverter - Export Limiter (Zero Export/Nulleinspeisung)

Open your Home Assistant instance and show the blueprint import dialog with a specific blueprint pre-filled.


Open-DTU Export-Limiter v1.0

This automation enables you to achieve “zero export” / “Nulleinspeisung” with your Open DTU-Powered solar inverter whilst adjusting the output to be as high as possible within the configured boundaries. This can potentially work with any other solar-inverter exposing the necessary entities as well!

This automation also requires a device measuring grid-export (for Example a Shelly 3EM)

It uses a simplified version of hysterisis. This means, that it will try to keep your inverter’s export in between two values which can be customized below. The automation tries to achieve this by attempting to set the inverter’s output-limit in the middle of these “border”-values and reacting once they are reached. Similar to the image shown below. Just less fancy curves and more “dumb on&off” since I’m not smart enough for fancy curves!

1000067782
‎‎

The automation can be tweaked to be less aggressive by setting the min- and max values further apart or to be more aggressive by setting them closer together.

The automation can aslo be set to always keep the limiter below a certain wattage by adjusting the ‘Open-DTU Max Output’ accordingly.

Like this blueprint? Consider hitting the :heart: button below :+1:

Feel free to leave feature requests / suggestions or contribution-ideas below!

Example with simulated Solar

Open-DTU Max-Output: 1600, Zero-Range-Min.: 0, Zero-Range-Max.: 100

1000067780

!WARNING!

I barely have any idea of what im actually doing here. Please monitor your system’s behavior closely when using this automation! Solar-Systems or any other energy/power-related systems can be dangerous and even life-threatening. I hold no responsibility for any incidents that may be caused by this autmation. Please inspect the code carefully before use. I have tested this code only in a simulated environment with simulated input-delay and cannot guarantee for it to work as expected in a live environment.

Code

blueprint:
  name: Open DTU - Zero Export
  description: "\n ## Open-DTU Zero Export\n\n\n ### !WARNING!\n\n I barely have any idea of what im actually doing here. Please monitor your system's behavior closely when using this automation! Solar-Systems or any other energy/power-related systems can be dangerous and even life-threatening. I hold no responsibility for any incidents that may be caused by this autmation. Please inspect the code carefully before use. I have tested this code only in a simulated environment with simulated input-delay and cannot guarantee for it to work as expected in a live environment.\n\n\n ### Description \n\n This automation enables you to achieve zero export with your Open DTU inverter. \n\n It uses a simplified version of hysterisis. This means, that it will try to keep your inverter's export in between two values which can be customized below. The automation tries to achieve this by attempting to set the inverter's output-limit in the middle of these values and reacting once they are reached. \n\n The automation can be tweaked to be less aggressive by setting the min- and max values further apart or to be more aggressive by setting them closer together. \n\n The automation can aslo be set to always keep the limiter below a certain wattage by adjusting the 'Open-DTU Max Output' accordingly." 
  domain: automation
  input:
    sensor_grid_export:
      name: Grid-Export Sensor Entity
      description: Select a sensor displaying your total current grid-export wattage. (for example a Shelly 3EM). The selected entity MUST display a positive value for the automation to work properly.
      selector:
        entity:
    sensor_dtu_output:
      name: Open-DTU Output Entity
      description: Select the output-entity provided by Open-DTU displaying the current output wattage.
      selector:
        entity:
    number_dtu_limit:
      name: Open-DTU Limit Entity (Non Persistent, Absolute)
      description: Select the limit-entity provided by Open-DTU. This entity is expected to be a "Input-Number" type. It's max value should reflect the inverter's max output.
      selector:
        entity:
    input_dtu_max:
      name: Open-DTU Max Output (Enter manually)
      description: Enter your inverter's max output wattage (For example, 1600 for Hoymiles HMS-1600 inverters). This should be identical with the DTU-Limiter's max value.
      selector:
        number:
          min: 0
          max: 999999
          step: 1
          unit_of_measurement: W
          mode: box
    input_user_min:
      name: Zero-Range-Minimum
      description: Enter the lower cap of the power-export-range which the automation will attempt to keep. In this case "lower" means the smallest export-value (for example 50w export). The minimum is 0. 
      selector:
        number:
          min: 0
          max: 999999
          step: 1
          unit_of_measurement: W
          mode: box
    input_user_max:
      name: Zero-Range-Maximum
      description: Enter the upper cap of the power-export-range which the automation will attempt to keep. It is suggested to keep a 100 W range between the min & max values. However, the blueprint does not enforce this.
      selector:
        number:
          min: 0
          max: 999999
          step: 1
          unit_of_measurement: W
          mode: box
variables:
  sensor_grid_export: !input sensor_grid_export
  sensor_dtu_output: !input sensor_dtu_output
  number_dtu_limit: !input number_dtu_limit
  input_dtu_max: !input input_dtu_max
  input_user_min: !input input_user_min
  input_user_max: !input input_user_max
trigger:
  - platform: state
    entity_id: !input sensor_grid_export
condition:
  - condition: or
    conditions:
      - condition: template
        value_template: "{{(states(sensor_grid_export)|float()|abs()) > ((input_user_max)|float()|abs())}}"
      - condition: template
        value_template: "{{(states(number_dtu_limit)|float()|abs()) < ((input_dtu_max)|float()|abs())}}"
action:
  - if:
      - condition: template
        value_template: "{{(states(sensor_grid_export)|float()|abs()) > ((input_user_max)|float()|abs())}}"
    then:
      - service: input_number.set_value
        data_template:
          entity_id: !input number_dtu_limit
          value: >-
            {{ ((states(sensor_dtu_output)|float()) - 
            ((states(sensor_grid_export)|float()|abs()) -
            ((((input_user_max)|float()|abs()) + ((input_user_min)|float()|abs())) /2|abs())))|int()}}
  - if:
      - condition: and
        conditions:
          - condition: template
            value_template: "{{(states(number_dtu_limit)|float()|abs()) < ((input_dtu_max)|float()|abs())}}"
          - condition: template
            value_template: "{{(states(sensor_grid_export)|float()|abs()) == ((input_user_min)|float()|abs())}}"
    then:
      - service: input_number.set_value
        data_template:
          entity_id: !input number_dtu_limit
          value: "{{((input_dtu_max)|float()|abs())}}"
mode: restart
max_exceeded: silent
2 Likes

The import do not work the link to blueprint is corrupt.

Import doesn’t work

Hope it’s fixed now!

Does it work with negative values for the Grid Meter as well? Or what is the best way to fix it?

There is a bunch of tutorials to get positive sensors out of your existing ones that show negative values by using template sensors. Search YouTube for Shelly 3em home Assistant

Yeah, this calculated template Sensor would be my approach as well, thanks for hinting.

Is there a pre-condition for an integration? Maybe link that in the top post.

Somehow it does not work for me.
In the Code i found some Conditions which will never be met:

- if:
  - condition: and
    conditions:
    - condition: template
      value_template: '{{(states(number_dtu_limit)|float()|abs()) < ((input_dtu_max)|float()|abs())}}' # <
    - condition: template
      value_template: '{{(states(sensor_grid_export)|float()|abs()) == ((input_user_min)|float()|abs())}}' # ==
  then:
  - service: input_number.set_value
    data_template:
      entity_id: !input number_dtu_limit
      value: '{{((input_dtu_max)|float()|abs())}}'

the DTU-LImit will never be greater than the DTU max limit…
Also the Export will only for a short time be equal to the user min level… Power generation and power usage are changing all the time…

That is my testing configuration which did not work as it should:

use_blueprint:
  path: NikGro/opendtu_zero_export.yaml
  input:
    sensor_grid_export: sensor.power_export
    sensor_dtu_output: sensor.pv_dach_power
    number_dtu_limit: number.pv_dach_limit_nonpersistent_absolute
    input_dtu_max: 600
    input_user_min: 0
    input_user_max: 10

Are my thoughts correct, or where did i went wrong?

Is it possible to use this also with 1 Open-DTU and 2 or more Inverters?

Only a short Follow up to the Topic:
I found a more easy way to get the Same behaviour.
Simply write every 10 Seconds the Power Consuption (+optional offset) to the Limit Topic of the Inverter.

alias: Zero Export
description: ""
trigger:
  - platform: time_pattern
    seconds: "10"
condition: []
action:
  - service: mqtt.publish
    data:
      topic: solar/11*******360/cmd/limit_nonpersistent_absolute
      payload: |-
        {{ (states('sensor.power_consumption')|float +50)|float if
            (states('sensor.power_consumption') |float +50)| int < 800
        else 800 }}W
mode: single

This should also be easy usable with many inverters if they all have the same Direction to the sun

This works perfect. Thank you!!

It is not working for me.
The input field “Open-DTU Limit Entity (Non Persistent, Absolute)” is never set.

The HA Trace shows:
'Ausgeführt: 30. April 2024 um 13:11:17
Ergebnis:
params:
domain: input_number
service: set_value
service_data:
entity_id: number.pv_garage_limit_nonpersistent_absolute
value: 846
target: {}
running_script: false

but in HA the input field still displays 1600 and if i change this input filed tin HA to any othe number then 1600 the change is shown some seconds later in the DTU.
The same happend, if i change the input filed in Developer view. it dos not work.

Maybe target: is missing.
image

and in Template: