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:
- Setup your Fronius Modbus as per @juande example above on your inverter.
- 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"
- 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!!]
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.
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
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:
There are many points to improve in the project, but I hope it’s useful for more people than just myself
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.
- Electricity Price ( Current price for grid import )
- Power Consumption Current ( range from -300 kWh to 600 kWh)
- 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
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
I’m not sure I follow why you would want to do this based on demand. I assumed the problem you are trying to solve is not to export when Amber charge c/kWh for feed in?
Anyway I actually started with HA controlling my inverter until @juande showed me the more elegant solution.
It is here Automate Fronius Soft Limit - #7 by tux43
If the wholesale price is negative enough (to offset various fixed and network charges) then you can be paid to consume energy.
Yes, understand this however it is driven from Amber price rather than power usage as per @MichaelBach comment.