Automate Fronius Soft Limit

I have the same issue with the Primo Gen24 even when setting ramp time to 0, might be worth a try setting other values to see?

Donā€™t think so! Thatā€™s the whole point of being able to limit close to 0 the feed-in, you need fast updates.
Official plant controllers do the same.

yeah I was hoping that was the case but couldnā€™t find anything confirming either way. Currently Iā€™ve gone with a 60sec timer which will still be pretty good but will cause more battery use than preferred. This is hopefully just as a stop gap until I get the service password an can enable dynamic load control. Then it becomes a basic on/off function.

Did you end up getting yours working? I also have a Symo 15.0-3-M and also donā€™t have the service password. Iā€™ve managed to get mine working using modbus only with a node-red flow.

I used the blog tux43 created to get me going and just didnā€™t do the bits that required the service password.

My flow isnā€™t the most elegant solution but it does the job. When I want to limit the feed-in Iā€™m just grabbing the house load calculating the % that is of the max (15000). I have a Tesla Powerwall so Iā€™m getting the house load from that but Iā€™m sure you could get it from the inverter. Because of the battery Iā€™m also adding 5000 to the house load if the battery isnā€™t full to allow for it to charge.

[{"id":"a1b569689c9fb5b9","type":"tab","label":"Solar","disabled":false,"info":"","env":[]},{"id":"64f5948d1a54ea3b","type":"function","z":"a1b569689c9fb5b9","name":"WMaxLim_Ena = 0","func":"msg.payload = 0\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":650,"y":320,"wires":[["b5a692b34fb9b14f"]]},{"id":"a1cf70f33ab43475","type":"delay","z":"a1b569689c9fb5b9","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":360,"y":480,"wires":[["a81b29df450c4e96"]]},{"id":"687b4cef1b23cb29","type":"delay","z":"a1b569689c9fb5b9","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":480,"y":360,"wires":[["4deb2e80ff67f2c1"]]},{"id":"b5a692b34fb9b14f","type":"modbus-write","z":"a1b569689c9fb5b9","name":"Set Load Limiting","showStatusActivities":false,"showErrors":false,"showWarnings":true,"unitid":"","dataType":"HoldingRegister","adr":"40236","quantity":"1","server":"a8fd59b042a4efe5","emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":870,"y":340,"wires":[[],[]]},{"id":"4deb2e80ff67f2c1","type":"function","z":"a1b569689c9fb5b9","name":"WMaxLim_Ena = 1","func":"msg.payload = 1\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":650,"y":360,"wires":[["b5a692b34fb9b14f"]]},{"id":"0df27afcdd2df2ae","type":"modbus-write","z":"a1b569689c9fb5b9","name":"Set limit %","showStatusActivities":false,"showErrors":false,"showWarnings":true,"unitid":"","dataType":"HoldingRegister","adr":"40232","quantity":"1","server":"a8fd59b042a4efe5","emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":1050,"y":480,"wires":[[],[]]},{"id":"0d7f9d3df15fb643","type":"function","z":"a1b569689c9fb5b9","name":"Calculate %","func":"if (msg.battery_percent < 100) {\n    msg.ifstatement = \"true\";\n    msg.payload = Math.round(((msg.house_load + 5000) / 15000) * 10000);\n    msg.payloadpercent = msg.payloadtest / 100;\n} else {\n    msg.ifstatement = \"false\";\n    msg.payload = Math.round((msg.house_load / 15000) * 10000);\n    msg.payloadpercent = msg.payloadtest / 100;\n};\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":870,"y":480,"wires":[["0df27afcdd2df2ae","687b4cef1b23cb29"]]},{"id":"a81b29df450c4e96","type":"api-current-state","z":"a1b569689c9fb5b9","name":"House Load","server":"f8a50b9a.39c988","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.justin_ward_load_power","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"house_load","propertyType":"msg","value":"","valueType":"entityState"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":530,"y":480,"wires":[["bc8f80a44f16d3b1"]]},{"id":"bc8f80a44f16d3b1","type":"api-current-state","z":"a1b569689c9fb5b9","name":"Battery %","server":"f8a50b9a.39c988","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.justin_ward_battery","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"battery_percent","propertyType":"msg","value":"","valueType":"entityState"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":700,"y":480,"wires":[["0d7f9d3df15fb643"]]},{"id":"5def8ff4b053af5d","type":"poll-state","z":"a1b569689c9fb5b9","name":"Amber Feed-In Price Negative","server":"f8a50b9a.39c988","version":2,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"updateinterval":"60","updateIntervalType":"num","updateIntervalUnits":"seconds","outputinitially":true,"outputonchanged":false,"entity_id":"sensor.amber_feedin_price_negative","state_type":"str","halt_if":"True","halt_if_type":"str","halt_if_compare":"is","outputs":2,"x":160,"y":340,"wires":[["64f5948d1a54ea3b","a1cf70f33ab43475"],[]]},{"id":"4929b39f787590a0","type":"delay","z":"a1b569689c9fb5b9","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":440,"y":640,"wires":[["5ef987f2e6b35af3"]]},{"id":"2c49c9c71c06b9b5","type":"modbus-write","z":"a1b569689c9fb5b9","name":"Set limit %","showStatusActivities":false,"showErrors":false,"showWarnings":true,"unitid":"","dataType":"HoldingRegister","adr":"40232","quantity":"1","server":"a8fd59b042a4efe5","emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":830,"y":640,"wires":[[],[]]},{"id":"5ef987f2e6b35af3","type":"function","z":"a1b569689c9fb5b9","name":"Set Limit to 100%","func":"msg.payload = 10000;\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":630,"y":640,"wires":[["2c49c9c71c06b9b5"]]},{"id":"2174b70e5d14d3fe","type":"server-state-changed","z":"a1b569689c9fb5b9","name":"Amber Feed-In Price Positive","server":"f8a50b9a.39c988","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.amber_feedin_price_negative","entityidfiltertype":"exact","outputinitially":true,"state_type":"str","haltifstate":"False","halt_if_type":"str","halt_if_compare":"is","outputs":2,"output_only_on_state_change":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"Amber Feed-In Price Positive","valueType":"str"}],"x":160,"y":580,"wires":[["4929b39f787590a0","580aa7fcaf942fd9"],[]]},{"id":"580aa7fcaf942fd9","type":"function","z":"a1b569689c9fb5b9","name":"WMaxLim_Ena = 0","func":"msg.payload = 0\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":630,"y":580,"wires":[["ef0719d6430a5180"]]},{"id":"ef0719d6430a5180","type":"modbus-write","z":"a1b569689c9fb5b9","name":"Set Load Limiting","showStatusActivities":false,"showErrors":false,"showWarnings":true,"unitid":"","dataType":"HoldingRegister","adr":"40236","quantity":"1","server":"a8fd59b042a4efe5","emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":850,"y":580,"wires":[[],[]]},{"id":"a8fd59b042a4efe5","type":"modbus-client","name":"Fronius","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"192.168.20.71","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"0x3A","unit_id":"1","commandDelay":"1","clientTimeout":"1000","reconnectOnTimeout":true,"reconnectTimeout":"2000","parallelUnitIdsAllowed":true,"showWarnings":true,"showLogs":true},{"id":"f8a50b9a.39c988","type":"server","name":"VASHA01","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":"30","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true}]

Just saw this, so I need to call the installer to change the grid profile to International 50z not AUS to get the ramping done instantly?

That may be in contravention of National Electricity Rules as set out in Australian standards (AS/NZS 4777.2:2020), Grid connection of energy systems via inverters Part 2: Inverter requirements, which require grid connected inverters to have specific power quality response settings, which is why there is the AUS A, B & C country code (grid profile) options, for which most of Australia is AUS A.

https://www.energynetworks.com.au/miscellaneous/power-quality-response-mode-settings/

1 Like

Just curious if youā€™re able to post up the modbus command youā€™re sending to your Primo unit? Iā€™ve tried all sorts of values on the ramp time command and I can see that the Primo has accepted the value but it still will only ramp in 100w increments every few seconds as you were experiencing with your Gen24 unit.

Here is my automation to my inverter, the addressā€™s are advanced by +1 from the offical spreadsheet as my address offset is +101 on the inverter

The 100W issue needs the installer to come out and change the grid setttings, you have 3 levels of access on the Gen24

Customer: see basic production infomation
Technican: enable control features like modbus and power limiting
Grid: only companies that have been through the approval access with Fronius have these codes as you can damage the inverter if you use the wrong settings

They need to set the grid profile to International 50hz
after the change i also ensured to block my inverters from accessing the internet incase Fronius tries to change something

alias: 3.2 Dynamic Inverter Power - Gen24
description: Negtive FIT solar will match consumption of house and battery
trigger:
  - platform: time_pattern
    enabled: true
    seconds: /5
condition:
  - condition: state
    entity_id: binary_sensor.amber_grid_price_negative
    state: "off"
  - condition: state
    entity_id: sun.sun
    state: above_horizon
  - condition: state
    entity_id: binary_sensor.amber_feedin_price_negative
    state: "on"
  - condition: time
    after: "10:30:00"
    enabled: false
  - condition: state
    entity_id: binary_sensor.tesla_wall_connector_contactor_closed
    state: "off"
    enabled: false
action:
  - service: modbus.write_register
    data:
      hub: MBFronius_Gen24
      address: 40232
      slave: 1
      value: "{{ states('sensor.v2_scaled_power') | int }}"
    alias: Set scaling factor 0-10000 being max
  - service: modbus.write_register
    data:
      address: 40233
      unit: 1
      value: 0
      hub: MBFronius_Gen24
    alias: Move to new power factor immediately
  - service: modbus.write_register
    data:
      address: 40234
      unit: 1
      value: 0
      hub: MBFronius_Gen24
    alias: Set revert time to 0 - Stay at set power
  - service: modbus.write_register
    data:
      address: 40235
      unit: 1
      value: 0
      hub: MBFronius_Gen24
    alias: Move to new power setpoint immediately
  - service: modbus.write_register
    data:
      address: 40236
      unit: 1
      value: 1
      hub: MBFronius_Gen24
    alias: Enable throttle control - required for command to work
  - service: modbus.write_register
    data:
      address: 40237
      unit: 1
      value: 1
      hub: MBFronius_Gen24
    enabled: false
mode: single

Converting the scaling factor, as I have 2 inverters that have a max output of 5100 watts this sensor will ensure that if my home comsupmtion is very high it can never calculate a factor above 5100.

      v2_scaled_power:
        friendly_name: "Inverter Scaled Power"
        value_template: "{{ ((states('sensor.YOUR HOME COMSUPMTION SENSOR IN WATTS') | float) * 10000 / 5100) | round(0, 'floor') }}"

Cheers for that, I was more interested to see the automation for your primo unit as it changes setpoint instantly going by the video you posted earlier.

Iā€™m having the issue with my primo unit that you were having with your gen24 unit. As far as I can tell Iā€™m writing to the correct modbus addresses.

40235 ( WMaxLimPct_RmpTms 40236-1 ) should be the ramp time for changing set points but no matter what i set it to, the inverter still ramps down in 100w increments every few seconds. I really want to get it to snap insantly to the value like yours does.

This is one of the automations, I have several depening on the setpoint required.

description: ""
trigger:
  - platform: state
    entity_id:
      - input_boolean.solar_0_3kw_export_limit
    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: "600"
  - service: modbus.write_register
    data:
      unit: 1
      hub: primo1_fronius
      address: 40236
      value: "1"
  - service: modbus.write_register
    data:
      unit: 1
      hub: primo1_fronius
      address: 40235
      value: "0"
  - service: input_boolean.turn_off
    data: {}
    target:
      entity_id: input_boolean.solar_zero_export_limit
  - service: input_boolean.turn_off
    data: {}
    target:
      entity_id: input_boolean.solar_1kw_export_limit
  - service: input_boolean.turn_off
    data: {}
    target:
      entity_id: input_boolean.solar_3kw_export_limit
  - service: input_boolean.turn_off
    data: {}
    target:
      entity_id: input_boolean.solar_no_export_limit
mode: single


As I said. You need to get the installer out.

The only way to change the ramp rate is to have the installer change the grid profile.

After the installer changed the profile on my inverter it started to snap to the new value instantly.

Grid profiles override any local or cloud control request.

Found all of this out by emailing Fronius. They were the ones that told me the grid profile needs to be changed to International 50hz

I was wondering if it were possible not just to use HA to turn off (and on) PV export, but to also do so with PV generation altogether? This would then allow forcing of grid import (instead of using PV first) which would be favourable when grid prices were negative ā€¦ and hence be paid to use power.

Yes -

Send a 0 to Conn - FLOAT register 20242 will disconnect it

With a 60s timeout period - so it turns back on without having to send another command (when inverter is off - you canā€™t turn it back on by sending a command - or maybe you can, havenā€™t tested it)

Node Red Implementation:

[{"id":"a7c2f25572869968","type":"inject","z":"2460b7dd22fc0358","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1420,"y":200,"wires":[["63ff76dd4044d2c1"]]},{"id":"63ff76dd4044d2c1","type":"function","z":"2460b7dd22fc0358","name":"Disconnect for 60s","func":"var values = [(0),(60),(0)];\n\nmsg.payload = { \n    'value': values,\n    'fc': 16,\n    'unitid': 1,\n    'address': 40239,\n    'quantity': 3\n} \n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1630,"y":200,"wires":[["cd261cfd805ee9b4"]]},{"id":"251aa0df40bfa818","type":"group","z":"2460b7dd22fc0358","name":"Main Inverter Connected to Smart Meter","style":{"label":true},"nodes":["571488de2ce5e132","1323876d1cc1cbe7","da918a91c50b2e52","cd261cfd805ee9b4"],"x":1794,"y":119,"w":552,"h":142},{"id":"571488de2ce5e132","type":"debug","z":"2460b7dd22fc0358","g":"251aa0df40bfa818","name":"PRIMARY: Inverter Set","active":false,"tosidebar":true,"console":true,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload","statusType":"auto","x":2190,"y":220,"wires":[]},{"id":"1323876d1cc1cbe7","type":"modbus-response","z":"2460b7dd22fc0358","g":"251aa0df40bfa818","name":"","registerShowMax":20,"x":2170,"y":160,"wires":[]},{"id":"da918a91c50b2e52","type":"modbus-flex-write","z":"2460b7dd22fc0358","g":"251aa0df40bfa818","name":"Fronius-Storage","showStatusActivities":true,"showErrors":true,"showWarnings":true,"server":"bcc4229c.180ac","emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"10","x":1940,"y":200,"wires":[["1323876d1cc1cbe7","571488de2ce5e132"],["571488de2ce5e132"]]},{"id":"cd261cfd805ee9b4","type":"junction","z":"2460b7dd22fc0358","g":"251aa0df40bfa818","x":1820,"y":200,"wires":[["da918a91c50b2e52"]]},{"id":"bcc4229c.180ac","type":"modbus-client","name":"Fronius 10kw","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":true,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"192.168.0.179","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"","unit_id":"1","commandDelay":"1","clientTimeout":"1000","reconnectOnTimeout":true,"reconnectTimeout":"2000","parallelUnitIdsAllowed":true}]

Many thanks, Iā€™ll do some experimentation

I finally got around to looking into this further. Turns out you donā€™t need the installer. If you push the back button on the inverter 5-6 times it will ask for a 5 digit code. Enter 73887 and then you can change the grid profile.

Iā€™ve just changed mine so will test it tomorrow to see if it snaps to the new setpoint instantly or not.

1 Like

How did you get that code? Is it universal or device-specific?

Ah found it:

Page 7.

Iā€™m trying to get the current power generation out of modbus because I want to have a go at calculating the WMaxLimPct in HA. Mostly because I have a 5kw export limit to try and respect.

This part works;

modbus:
  - type: tcp
    # ...
    sensors:
     - name: modbus_dc_power
       slave: 1
       data_type: uint16
       address: 40277 # with offset of -1

But that information appears to be useless without the scale factor. But I canā€™t work out what data type the scale factor is inā€¦ my spreadsheet says sunssf which I figured might be a float, but float16/32 donā€™t workā€¦

Has anyone else successfully done this?

I havenā€™t, Iā€™m sure it is possible and get a headache thinking about it. Doesnā€™t the smart meter do this for you now? If not, why are you trying to solve a problem that you currently have just to be a good citizen?

No? At least not to my knowledgeā€¦ is that a thing newer ones do, or can they OTA the thing?

just to be a good citizen

I had enough of a fight getting them to let me export in the first place due to a paperwork screwup by the electricianā€¦ but not just that.

When the battery is filling up, I need to allow a trickle out so the battery can detect the excess and soak it up. I donā€™t need to do that when the battery is already fullā€¦ so basically itā€™s microoptimisations.

This is normally managed either by:

  • the inverterā€™s output capacity being no more than 5 kW anyway, or
  • if the inverterā€™s output capacity is greater than the export limit, the Fronius smart meter supplies the data used by the inverter which has the export limit set in its Dynamic Power Reduction options.

The setting is in the DNO editor section of the inverterā€™s web portal, and requires service level password access:

Assuming you can access that, then scroll down to find Dynamic Power Reduction:

If you were required to apply an export limit less than the inverterā€™s output capacity, then the smart meter would have been a compulsory part of the installation and the dynamic power reduction limit set.