Automate Fronius Soft Limit

All that said, adding load is also another strategy I used to help with voltage issues. My water heater helps keeps daytime voltages on its phase down. I use a smart PV diverter so it varies the power delivered to the water heater based on available excess energy on that phase.

The other load I use is a ducted aircon system which during summer operates on that white phase.

Very useful posts, thanks to you all.

So, can this fronius stuffs be configured purely over modbus cos I don’t have the service password to get to those menus on my inverter :frowning:

I’ve queried a few of the modbus addresses I’ve seen in this thread but I just get back 0xffff from them all

Seems mine is a Symo 15.0-3-M

I’ve managed to get a start on this, I have the template sensor for solar trim, and trim+150 watts but I’m confused about how to apply it as an automation cos once you send 40236=1 the trim value crashes to near zero …

- sensor:
    - name: "Solar Trim Percent"
      state: '{{ (((states("sensor.solarnet_power_grid")|float(0))|multiply(-1))/15000)|multiply(10000)|int }}'
    - name: "Solar Trim Percent Surplus"
      state: '{{ (((states("sensor.solarnet_power_grid")|float(0)-150)|multiply(-1))/15000)|multiply(10000)|int }}'

Is that where solar_trim_percent_when_greater_load comes into it?

I tired doing this with my inverter but it keeps turning one of the solar arrays off so the inverter is only producing half of what it can actually output

So I would like to implement something similar with my setup due to negative FIT on Amber.

I’m very new to Home Assistant and finding some of the config side of things a bit confusing.

Currently have Fronius Primo 5kw and Tesla PW2 setup and I’d like the solar to keep charging my battery even if the FIT is negative and then once full, try to mimic the load in the house until FIT goes positive again.

I’ve got as far as setting up an automation that needs to see the FIT (from Amber API) drop below 0.01c for 1 min and also my PW2 charge level is above 99%. This then triggers my “input_boolean.solarlimitor”

After this point I’m not sure how to proceed as the examples in this thread are for different fronius models and from what I can tell they all have different modbus addresses for the function.

I’m also wondering if this all relies on having the extra Fronius Smart Meter to be able to do it because of the complication of the battery or can I use the metering values from the PW2 for this?

Any pointers or examples would be greatly appreciated.

My suggestions would be to:

  1. Setup your Fronius Modbus as per @juande example above on your inverter.
  2. Create an automation that will trigger when feedin price is negative and your battery is full, example of action below (your address might be different, but this works for me)
service: modbus.write_register
data:
  unit: 1
  hub: mb_fronius
  address: 40236
  value: "0"
  1. Create the inverse to allow Fronius full output when feed-in is positive.
action:
  - service: modbus.write_register
    data:
      unit: 1
      hub: mb_fronius
      address: 40236
      value: "0"
  - service: modbus.write_register
    data:
      unit: 1
      hub: mb_fronius
      address: 40232
      value: "10000"
  - service: modbus.write_register
    data:
      unit: 1
      hub: mb_fronius
      address: 40236
      value: "1"

Thank you very much for that, greatly appreciated.

Makes it much clearer now.

Will give it a shot when I get home and see how it goes.

According to the modbus Excel file from Fronius register 40232 only accepts a value of 1 or 0, not what you have there unless I am reading the file wrong.

Ok, if I remember this confused me too and I spent a lot of time doing trial by error.

For some reason the register is off by 1 on mine anyway!! Hoping somebody else who is a modbus guru can answer why this is!

So in the spreadsheet 40233 and 40237 are the actual entries. The modbus logic is:-

My guess is it is related to the ‘String control address offset’ and it starts at 100 therefore incremented by 1. [If others that understand modbus better could help that would be appreciated!!]

1 Like

Ahhhhh

Going to mess with this tomorrow as I have the same offset!

Thank you guys for sharing the above, took some inspiration and made a variant with multiple inverters.

This is like a Plant Controller where multiple inverters (different in size) need to be adjusted in parallel based on information coming from a single Fronius SmartMeter. Actually I think any kind of “smart” meter could be used with this approach, as it doesn’t interact directly with any of the inverters, only through HA automation.

See attached picture. The SmartMeter (in consumption path) is attached to one of the inverters with DataManager card, but there’s two new GEN24 inverters added to the system, which don’t connect to the SmartMeter.

I have no automated limiting options enabled in any of the inverters. I only define the priorty so that “Controlling via Modbus” will be first, and of course enable “Inverter control via Modbus”. SunSpec model tpye is “Int + SF”.

With these settings to limit manually the output power, one has to change the percentage output at holding register 40233, and then enables throttling by writing value 1 to register number 40237 (In Fronius’s docs the addresses are base1, but since HA uses base0, we use address numbers decreased by 1, that’s why also in the examples above we have addresses 40232 and 40236 accordingly).


As a cleaner approach, I decided to read the data from the inverters with the same modbus integration as is used to write the registers. This is independent from the Fronius or SunSpec integrations.

modbus:
- name: inverter_symo #repeat this section for other two gen24 inverters
  type: tcp
  host: 192.168.1.80
  port: 502
  retry_on_empty: true
  retries: 3
  delay: 3
  sensors:
    - name: smartmeter_w_raw  #adding this only to the inverter where the SmartMeter connects
      slave: 240 #(snapinverter symo: 240, gen24 default: 200)
      input_type: holding
      address: 40087 
      scan_interval: 5
      unique_id: smartmeter_w_raw
      count: 5
      data_type: custom
      structure: ">hhhhh"
    - name: inverter_symo_raw_lim
      slave: 1
      input_type: holding
      address: 40232
      scan_interval: 5
      unique_id: inverter_symo_raw_lim
      count: 5
      data_type: custom
      structure: ">hhhhh"
    - name: inverter_symo_raw_w
      slave: 1
      input_type: holding
      address: 40083 
      scan_interval: 5
      unique_id: inverter_symo_raw_w
      count: 2
      data_type: custom
      structure: ">hh"

Template sensors to calculate from modbus raw registers and scaling factors:

sensor:
    - name: "Smartmeter W"
      unique_id: smartmeter_W
      state_class: measurement
      device_class: power
      unit_of_measurement: W
      icon: mdi:home-lightning-bolt
      availability: "{{ has_value('sensor.smartmeter_w_raw') }}"
      state: >
        {{ 
        (states('sensor.smartmeter_w_raw').split(',')[0]) | int(default=0)
        /10**(states('sensor.smartmeter_w_raw').split(',')[4] | int(default=0)*-1)
        }}

    - name: "Inverter Symo W"
      unique_id: inverter_symo_W
      state_class: measurement
      device_class: power
      unit_of_measurement: W
      icon: mdi:solar-power
      availability: "{{ has_value('sensor.inverter_symo_raw_w') }}"
      state: >
        {{ 
        (states('sensor.inverter_symo_raw_w').split(',')[0]) | int(default=0)
        /10**(states('sensor.inverter_symo_raw_w').split(',')[1] | int(default=0)*-1)
        }}

    - name: "Inverter Symo limiter percentage"
      unique_id: inverter_symo_WMaxLimPct
      state_class: measurement
      unit_of_measurement: "%"
      icon: mdi:car-cruise-control
      availability: "{{ has_value('sensor.inverter_symo_raw_lim') }}"
      state: >
        {{ (states('sensor.inverter_symo_raw_lim').split(',')[0] | int(default=10000))/100 }}

binary_sensor:
    - name: "Inverter Symo limiter enabled" 
      unique_id: inverter_symo_limiter
      icon: mdi:car-speed-limiter
      availability: "{{ has_value('sensor.inverter_symo_raw_lim') }}"
      state: >
        {{ (states('sensor.inverter_symo_raw_lim').split(',')[4] | bool(default=false)) }}

The above is for the Symo, similar config is added for the other two inverters (without the SmartMeter sensor of course).

What I did so far is I decided to also have an input_number to configure the maximum export value. Note that this can also be negative, for some very strict conditions when you want to make 100% sure that absolutely no power is fed into the grid, but some little is always drawn:

input_number:
- max_export:
    name: Maximum export
    min: -300
    max: 10000
    step: 100
    icon: mdi:transmission-tower-import
    unit_of_measurement: 'W'

The approach here is that you can use a separate automation to simply adjust this number when you don’t want to feed in, or you want to feed just until a maximum value.

Calculation of the target percentage happens similarly as in the examples above. My smartmeter is in the consumption path.

Needed to define two sensors because the Symo is 3700W, the other two GEN24s are 6000W (they can use the same template sensor).
Note that since there are 3 inverters, we divide the sum by 3, so we distribute the limits accordingly to the inverters.

    - name: "Inverter Symo limit"
      unique_id: inverter_target_limit_sym
      state_class: measurement
      state: >
        {% set proc = ((states("sensor.smartmeter_w")|float(default=0)-states("input_number.max_export")|float(default=0))/3/3700)|multiply(-1)|multiply(10000)|int %}
        {% if proc > 10000 %}10000{% elif proc < 0 %}0{% else %}{{ proc }}{% endif -%}

    - name: "Inverter Gen24 limit"
      unique_id: inverter_target_limit_gen
      state_class: measurement
      state: >
        {% set proc = ((states("sensor.smartmeter_w")|float(default=0)-states("input_number.max_export")|float(default=0))/3/6000)|multiply(-1)|multiply(10000)|int %}
        {% if proc > 10000 %}10000{% elif proc < 0 %}0{% else %}{{ proc }}{% endif -%}

And the automations:

- alias: Inverter limiter Symo
  mode: single
  trigger:
    - platform: state
      entity_id:
        - sensor.inverter_symo_limit
  action:
    - choose:
        - conditions:  # this is for the case when export limit is to be disabled
            - condition: template
              value_template: "{{ states('sensor.inverter_symo_limit')|int == 10000}}"
          sequence:
            - service: modbus.write_register
              data:
                unit: 1
                hub: inverter_symo
                address: 40232
                value: "10000"
            - service: modbus.write_register
              data:
                unit: 1
                hub: inverter_symo
                address: 40236
                value: "0"
      default:
        - service: modbus.write_register
          data:
            unit: 1
            hub: inverter_symo
            address: 40232
            value: "{{ states.sensor.inverter_symo_limit.state }}"
        - service: modbus.write_register
          data:
            unit: 1
            hub: inverter_symo
            address: 40236
            value: "1"

- alias: Inverter limiter Gen24
  mode: single
  trigger:
    - platform: state
      entity_id:
        - sensor.inverter_gen24_limit
  action:
    - choose:
        - conditions:
            - condition: template
              value_template: "{{ states('sensor.inverter_gen24_limit')|int == 10000}}"
          sequence:
            - service: modbus.write_register
              data:
                unit: 1
                hub: inverter_gen24_a
                address: 40232
                value: "10000"
            - service: modbus.write_register
              data:
                unit: 1
                hub: inverter_gen24_b
                address: 40232
                value: "10000"
            - service: modbus.write_register
              data:
                unit: 1
                hub: inverter_gen24_a
                address: 40236
                value: "0"
            - service: modbus.write_register
              data:
                unit: 1
                hub: inverter_gen24_b
                address: 40236
                value: "0"
      default:
        - service: modbus.write_register
          data:
            unit: 1
            hub: inverter_gen24_a
            address: 40232
            value: "{{ states.sensor.inverter_gen24_limit.state }}"
        - service: modbus.write_register
          data:
            unit: 1
            hub: inverter_gen24_b
            address: 40232
            value: "{{ states.sensor.inverter_gen24_limit.state }}"
        - service: modbus.write_register
          data:
            unit: 1
            hub: inverter_gen24_a
            address: 40236
            value: "1"
        - service: modbus.write_register
          data:
            unit: 1
            hub: inverter_gen24_b
            address: 40236
            value: "1"

Result (with max_export set to 1700):

The production of the 3 inverters dynamically follows the house demand, always feeding in not more than 1700W.

Recently just setup a new standalone instance of HA on a new Raspberry Pi as my Qnap server was having some issues.

After much messing around I believe I finally have it working (Tesla app confirms solar production dropping to zero).

Many thanks to everyone that has contributed here. I was able to piece together different bits of info to make something that woks for me.

My setup is as follows;

Fronius Primo 5.0 & Tesla PW2

The target addresses are 40236 - WMaxLim_Ena & 40232 - WMaxLimPct (addresses in documentation are 40237 & 40233 but as someone else posted above there is an offset of 1 number)

I added both of these into the modbus sensors in config.yaml so I could see if my automations were working.

Under Normal Conditions

And with Solar Curtailment Activated

modbus:
  - type: tcp
    name: "primo1_fronius"
    host: 192.168.1.14
    port: 502
    retry_on_empty: true
    retries: 3
    sensors:
      - name: Inverter Primo WMaxLimPct
        slave: 1
        input_type: holding
        address: 40232
        scale: 0.01
        scan_interval: 15
        state_class: measurement
        unique_id: inverter_primo_WMaxLimPct
        unit_of_measurement: "%"
      - name: Inverter Primo WMaxLimEna
        slave: 1
        input_type: holding
        address: 40236
        scale: 1
        scan_interval: 15
        state_class: measurement
        unique_id: inverter_primo_WMaxLimEna

I’ve just got a toggle button on my homepage for testing currently but I will link that to further automations based on battery charge level & feed in tarrif price.

And these are the Activation & De-Activation automations

alias: Solar Curtailment Activation
description: ""
trigger:
  - platform: state
    entity_id:
      - input_boolean.solar_curtailment
    from: "off"
    to: "on"
    for:
      hours: 0
      minutes: 0
      seconds: 5
condition: []
action:
  - service: modbus.write_register
    data:
      unit: 1
      hub: primo1_fronius
      address: 40232
      value: "0"
  - service: modbus.write_register
    data:
      unit: 1
      hub: primo1_fronius
      address: 40236
      value: "1"
alias: Solar Curtailment Deactivated
description: ""
trigger:
  - platform: state
    entity_id:
      - input_boolean.solar_curtailment
    from: "on"
    to: "off"
    for:
      hours: 0
      minutes: 0
      seconds: 5
condition: []
action:
  - service: modbus.write_register
    data:
      unit: 1
      hub: primo1_fronius
      address: 40236
      value: "0"
  - service: modbus.write_register
    data:
      unit: 1
      hub: primo1_fronius
      address: 40232
      value: "10000"

I’m sure there are improvements to be made but so happy to just have this basic form working for now and hopefully this can help anyone else with the same setup.

So I’ve been using the curtailment successfully since I last posted and have also managed to make another automation that adjusts the solar output based on the load being drawn in the house.

The issue I’m having and I’m not sure if anyone else has played with this is the time it takes to ramp up and down to the given setpoint. It appears to adjust approximately 100w every 5 seconds.

There were a couple of elements in the modbus address map that I thought might be the correct ones to speed it up but when activated they don’t seem to make any difference.

I tried setting both of them to 10 seconds and the value does change on my dashboard but it doesn’t seem to make any difference on how long it takes to adjust the output.

image

2 x automations below for setting those 2 elements

alias: Fronius Export Limit Activation Ramp Time
description: ""
trigger: []
condition: []
action:
  - service: modbus.write_register
    data:
      address: 40235
      slave: 1
      hub: primo1_fronius
      value: 10
mode: single

alias: Fronius Export Limit Set Activation Time
description: ""
trigger: []
condition: []
action:
  - service: modbus.write_register
    data:
      address: 40233
      slave: 1
      hub: primo1_fronius
      value: 10
mode: single

if anyone has any ideas I’d be glad to hear them so I can get the curtailment moving setpoints quicker.

First of all, thank you for all the contributions on the thread :slight_smile:

In my case, my preference is to normally provide as much energy as possible to the network, with exceptions where the electricity price is extremely low or negative, where my preference would be to set it to export a maximum of 150W.

I did not find the possibility of configuring this as @aldifesu showed on his screenshot, so I decided to try different possibilities. (https://community-assets.home-assistant.io/original/4X/d/0/c/d0c7856ce08ce3a387d2984ff9f4fe72d823689b.png)

As a possible solution to the problem, I have written a small tool that serves as an authentication proxy for the Fronius controller, making it easier to perform HTTP calls to the Fronius from Home Assistant as if it was a web browser: GitHub - sergioperez/fronius-auth-proxy: Authentication proxy to avoid using the HTTP digest implementation used on the Fronius inverter controllers

This makes it possible to configure settings on the Fronius that are not available via the standard integration or the Modbus interface, as the exact power that the Fronius feeds to the network:

imagen

There are many points to improve in the project, but I hope it’s useful for more people than just myself :slight_smile:

2 Likes

Hi all. I’ve been reading this thread great progress. I need a similar setup. The Challenge is, that I have several sensors. That should be taken into account.

  1. Electricity Price ( Current price for grid import )
  2. Power Consumption Current ( range from -300 kWh to 600 kWh)
  3. 5x 100 kWh Fronius Tauro Inverters.

The Challenge here, is when the Price is between 0.10 and 0.19 (example), I need to limit the inverters, so the Power output equals the Power consumption, so the inverters produce enough power to keep me a float, but not to export.

If the price drops below 0, the inverters should stop production. I have established Solar API, and modbus access. I’ve reached out to Fronius, to get a more specific explanation regarding modbus, but haven’t got an answer yet. But maybe some of you guys, have an idea how to build this. I would prefer, to do the calculations myself, as I don’t have Fronius smartmeter, but another similar meter, that I poll from modbus.

My idea is to do it like this.

every 5 seconds, I read the meter, and the inverters production. So if the price triggers. then it should compare these, and send a limiter command to the inverters. I’ve been looking at the same excel modbus register map, and the 40233 reads 0 and 40237 reads 1000. So in my head the logic is flawed.

any help is highly appreciated.

As an alternative. I can read the hourly Import/export values, and limit the inverters if the Export exceeds the import. As I’m charged by the summariced Hourly values.

I have achieved the same by monitoring the feed in price and when it drops to negative then reducing the inverter to cover only what is required, no export.

It is far easier to get the inverter to do this heavy lifting and either limit the export to matching the house demand (if feed-in price is negative) or stop the inverted (when price is negative).

Can I see you programming for the Fronius modbus, also of course the code, that compares Inverter production with Consumption :slight_smile:

Have a look at this above post. Automate Fronius Soft Limit - #39 by tux43

Oh, so you use the build-in function of the inverter. I was hoping to not use that, as my power usage, can be between 6kWh an Hour or 500 kWh an hour, so I need to limit it by percentage, this is why I wanted to use the modbus limter register instead.

I’ll see if I can find out how to do that then :slight_smile: