I think you could do it via Modbus TCP.
I’m trying to do the same as you but still investigating how to. My initial idea is by writing some registers about grid feed
I think you could do it via Modbus TCP.
I’m trying to do the same as you but still investigating how to. My initial idea is by writing some registers about grid feed
Yes, I got it working exactly as you said with modbus.
Within configuration.yaml I’ve defined my Fronius Primo inveter with the modbus Sunspec model type as “int + SF”
modbus:
- type: tcp
name: mb_fronius
host: 192.168.1.165
port: 502
retry_on_empty: true
retries: 3
I’ve then have two automations, one which increases the inverter output and the other which decreases to keep it so it is only feeding in when price is not negative.
Here is the action for one which I am sure will help.
I got the modbus details from here
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: "{{ states.sensor.solar_trim_percent_when_greater_load.state }}"
- service: modbus.write_register
data:
unit: 1
hub: mb_fronius
address: 40236
value: "1"
Hi there!
Thanks for this. This is actually what I’m looking for.
One question: actually I’m manually configuring the GEN24 inverter to limit a max 150W grid feed to have some threshold in case of a sudden demand
I see you are using a sensor (sensor.solar_trim_percent_when_greater_load) to configure a percentage. How do you have this configuration? is this sensor something fixed that you have?
Could you please elaborate a little bit more?
Appreciated
I have two sensors defined. The first one calculates what the trim percentage should be when the house is consuming more than the current trimmed output. The other when it is less than the trimmed output. I then have two automations that automatically increase or decrease the inverter % to keep feed in as close to 0. It works well.
NB: My inverter is 6000W hence the devision in the below.
solar_trim_percent_when_greater_load:
friendly_name: 'Solar Trim Percent When Greater Load'
value_template: '{{ ((states("sensor.feed_into_power_grid")|float(0)|multiply(-1)+states("sensor.power_load_fronius_power_flow_0_http_fronius")|float(0)|multiply(-1))/6000)|multiply(10000)|int}}'
solar_trim_percent:
friendly_name: 'Solar Trim Percent'
value_template: '{{ ((states("sensor.power_load_fronius_power_flow_0_http_fronius")|float(0))/6000)|multiply(-1)|multiply(10000)|int}}'
Hi Brett.
Thanks for this
To summarize:
I would like to have dynamic_power_reduction activated with max grid feed set to 150W from the inverter
On certain occasions, I would like Home Assistant to:
My question is: can this be done with HA?
I guess the way of doing this is by having manually configured the dynamic power reduction through the web page (at the inverter), then through modbus enable immediate control mode and setting WMaxLimPct = 100%, and once finished something at home, disable the immediate control through modbus so the inverter returns again to dynamic power reduction with max 150w feed.
Am I right?
Thanks for your help
Yes, I’m doing something similar.
No (of course I’ve only tested on one inverter), however, on mine which is a Fronius Primo you do not need the web browser. You enable WMaxLim_Ena through modbus and this switches on WMaxLimPct. So, if you don’t want limiting just turn off WMaxLim_Ena and your inverter will run flat out.
Then you need to do the calculations as per those sensors and have an automation that triggers when it wants to INCREASE or DECREASE the output.
Hope these automations help.
I was actually thinking of writing a blog on this since it works really well.
alias: >-
ON: Throttle (INCREASE) solar output if house load is GREATER than solar
output
description: >-
Providing that the load on the house is greater than solar output other maths
is wrong
trigger:
- platform: state
entity_id:
- sensor.solar_trim_percent
condition:
- condition: template
value_template: "{{ states('sensor.solar_trim_percent')|int < 10000 }}"
enabled: true
- condition: or
conditions:
- condition: template
value_template: |
{{ trigger.to_state.state|float > trigger.from_state.state|float }}
- condition: template
value_template: |
{{ trigger.to_state.state|float < trigger.from_state.state|float }}
- condition: template
value_template: >
{{ as_timestamp(now()) -
as_timestamp(state_attr('automation.on_throttle_solar_if_feed_in_is_negative','last_triggered'))
> 30 }}
enabled: true
- condition: state
entity_id: sun.sun
state: above_horizon
- condition: state
entity_id: sensor.amber_feedin_price_negative
state: "True"
- condition: state
entity_id: sensor.amber_price_negative
state: "False"
- condition: template
value_template: >-
{{
states('sensor.power_load_fronius_power_flow_0_http_fronius')|multiply(-1)|int
>= states('sensor.current_solar_power_output')|multiply(1)|int }}
alias: Test if load in house is less than solar output
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: "{{ states.sensor.solar_trim_percent_when_greater_load.state }}"
- service: modbus.write_register
data:
unit: 1
hub: mb_fronius
address: 40236
value: "1"
mode: single
And
alias: "ON: Throttle (DECREASE) solar output if house load is LESS than solar output"
description: >-
Providing that the load on the house is less than solar output other maths is
wrong
trigger:
- platform: state
entity_id:
- sensor.solar_trim_percent
condition:
- condition: template
value_template: "{{ states('sensor.solar_trim_percent')|int < 10000 }}"
enabled: true
- condition: or
conditions:
- condition: template
value_template: |
{{ trigger.to_state.state|float > trigger.from_state.state|float }}
- condition: template
value_template: |
{{ trigger.to_state.state|float < trigger.from_state.state|float }}
- condition: template
value_template: >
{{ as_timestamp(now()) -
as_timestamp(state_attr('automation.on_throttle_solar_output_if_house_load_is_greater_than_solar_output',
'last_triggered')) > 30 }}
enabled: true
- condition: state
entity_id: sun.sun
state: above_horizon
- condition: state
entity_id: sensor.amber_feedin_price_negative
state: "True"
- condition: state
entity_id: sensor.amber_price_negative
state: "False"
- condition: template
value_template: >-
{{
states('sensor.power_load_fronius_power_flow_0_http_fronius')|multiply(-1)|int
< states('sensor.current_solar_power_output')|multiply(1)|int }}
alias: Test if load in house is less than solar output
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: "{{ states.sensor.solar_trim_percent.state }}"
- service: modbus.write_register
data:
unit: 1
hub: mb_fronius
address: 40236
value: "1"
mode: single
This would be great!
Thank you
Hi Brett
I have finally configured successfully my setup. Thanks for your help
My setup is slightly different than yours as my company is not charging me for any excess fees, but I don’t want to give for free also.
In case anyone wants las is interested, this is my configuration for my Fronius Gen 24 5KW
This way the inverter is managing automatically any increase of power generation due to increased home loads without Home Assistant (also avoids HA point of failure)
So to achieve this, HA sends a modbus write message to activate maximum throttle as per Brett indications
Then HA manages based on events and automations the excess of power by activating loads accordingly so there is minimum power unused
To accomplish this, I have needed to modify priority of modes as follows:
1.Modbus control
2. Dynamic power reduction
3. Generic I/O
This way is very efficient and works perfectly, with the benefit that the inverter manages increased loads with zero injection in case HA fails
Thank you @tux43 for all your support
Hi Juande, Your setup is more similar to my requirements but the offer of a blog from Brett is a good idea too. As I’m wanting to setup the same sort of thing with limiting export (due to unpredictable negative FIT pricing on the wholesale market). Can you post your additions to the .yaml file & the automations you have. Not sure if you have setup modbus switches or just the raw actions in the automations. I have 3 Fronius inverters & am confident I can adapt your code ideas to my setup.
Hi Ccspack
My Setup is quite simple. Here is how it works
As mentioned before, I have some appliances that must run their function every day:
Those actions normally run every day, and they normally run if there is solar power enough, otherwise HA stops those appliances.
To achieve this, there is an event that at sunrise shuts down zero injection, allowing maximum power generation.
As the sun rises up, power will be increasing more and more, and those 3 appliances will be activated ensuring there is no extra grid demand
For any sudden power demand coming from the rest of the house, HA will be monitoring and deactivating/activating those 3 appliances that normally run on power surplus
Once those 3 appliances have completed their daily function, then there is an event that activates again zero power injection, so the inverter generates just what is only needed by the house.
This way, we ensure that there is no “free electricity” for the grid company (I’m not doing power compensation)
As mentioned before I have a minimum of 150W sent to the grid (so in reality is not true zero injection). This is to absorb sudden minimal peaks.
So here it is my configuration:
First establish the control priorities as modbus control first, then power limitation as shown in the image:
Then, configure power limitation (zero injection), in my case min 150w, but you could put just 0
Then define 2 events to activate and deactivate export limitation (as you can see in my case those events respond to an input_boolean helper that also allows to manually activate/disable mode)
This event deactivates via Modbus full throttle (MAX power generation) in the inverter, so the inverter then stays in the second mode configured in controlling priorities:
alias: Gestión de excedentes - Activa Inyección CERO
description: ""
trigger:
- platform: state
entity_id:
- input_boolean.zero_injection
from: "off"
to: "on"
condition: []
action:
- service: modbus.write_register
data:
address: 40236
unit: 1
value: 0
hub: mb_fronius
mode: single
This event activates via Modbus full throttle (MAX power generation) in the inverter, so the inverter then stays in the first mode configured in controlling priorities:
alias: Gestión de excedentes - Desactiva Inyección ZERO
description: ""
trigger:
- platform: state
entity_id:
- input_boolean.zero_injection
from: "on"
to: "off"
condition: []
action:
- service: modbus.write_register
data:
address: 40236
unit: 1
value: 0
hub: mb_fronius
- 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
mode: single
This way I’m able to optimize my power generation based on my house’s needs
I hope it helps
Hey @tux43 this is perfect.
I’m an Amber customer with a Fronius Symo and yes I just started to think about rate limiting, so started my investigation some 15mins back and found your post
Did you write a blog on this, or is this the only record of what you did?
I ask as I would love to validate the procedure end to end as I implement it .
Cheers Simon
No, not yet. I havent’ had a quiet moment!
Did you get it working?
Hey @tux43, yes I think it is working OK. I went a different track similar to the way @juande implemented it.
I will have 100% certainty tomorrow if exports run negative (again). The Fronius Modbus setup tripped me up for a bit - but I think all is working now…
Thanks heaps
I’ve just re-read @juande implementation and it seems better than mine. Mine was way too complicated getting the calulations right. I am going to give it a go, with what I understand how it works and report back (no sun at the moment)
I have @juande solution working. It is great and better than mine since the inverter does the ‘heavy lifting’. I don’t need to continually send ModBus commands to the inverter since the settings below limit exporting when my feed-in tarrif is negative.
Glad it worked for you Brett!
I found this was the best solution as the inverter makes everything automatic and HA only selects the desired mode: Full throttle or zero injection.
OK, it’s taken me probably far too long, but here is my setup. Ive go two 8.2kW Symos linked to together & a 5kW Sumo Hybrid inverter at our place, as we are with Amber & paying wholesale prices, we wanted our inverter to all ramp down to just match household consumption when ever the FIT price goes negative.
I have setup all inverters to be controlled by ModBus as a priority, on the Sunspec Float type. when the inverters aren’t receiving any commands they revert to the Dynamic Power Reduction settings.
Inside the configuration.yml file I have added:
modbus:
- type: tcp
name: symo_fronius
host: 192.168.1.18
port: 502
retry_on_empty: true
retries: 3
- type: tcp
name: hybrid_fronius
host: 192.168.1.14
port: 502
retry_on_empty: true
retries: 3
I am using a input_boolean as the mechanism (switch), so that it can be controlled manually or with automations:
input_boolean:
solarlimitor:
initial: 0
Now I have 4 automations, 2 as triggers & 2 as instructions for each mode. The triggers:
alias: Amber SolarLimiter Deactivate when FIT returns Positive
description: ""
trigger:
- platform: numeric_state
entity_id: sensor.amber_feed_in_price
above: -0.01
for:
hours: 0
minutes: 1
seconds: 0
condition: []
action:
- wait_for_trigger:
- platform: numeric_state
entity_id: sensor.opennem_price
above: -0.5
timeout:
hours: 0
minutes: 16
seconds: 0
milliseconds: 0
continue_on_timeout: false
- service: input_boolean.turn_off
data: {}
target:
entity_id: input_boolean.solarlimitor
mode: single
alias: Amber SolarLimitor Activate when FIT is Negative
description: ""
trigger:
- platform: numeric_state
entity_id: sensor.amber_feed_in_price
for:
hours: 0
minutes: 1
seconds: 30
below: 0
condition: []
action:
- wait_for_trigger:
- platform: numeric_state
entity_id: sensor.opennem_price
below: 0
timeout:
hours: 0
minutes: 16
seconds: 0
milliseconds: 0
continue_on_timeout: false
- service: input_boolean.turn_on
data: {}
target:
entity_id: input_boolean.solarlimitor
mode: single
I’m using the data from OpenNEM as second reference to prevent false positive triggering. And the notification for the mobile is probably an overkill, but helpful in the early days. I realise these are different address then everyone else has posted, but they work for my inverters. So these are the 2 actions:
alias: Amber SolarLimitor when Turned On
description: ""
trigger:
- platform: state
entity_id: input_boolean.solarlimitor
from: "off"
to: "on"
action:
- service: notify.mobile_app_name_of_phone
data:
message: >-
The FIT price has Dropped to {{
(states('sensor.amber_feed_in_price')|float * 100) }}c. Solar {{
(states('sensor.solar_production')|float / 1000) | round(1) }}kW,
Battery {{ (states('sensor.battery')|float / 1000) | round(1) }}kW,
Consumption {{ (states('sensor.household_consumption')|float / 1000) |
round(1) }}kW & exporting {{
(states('sensor.smappee_grid_realtime')|float / -1000) | round(2) }}kW.
title: Amber Alert - Stopping Export!
- repeat:
until:
- condition: state
entity_id: input_boolean.solarlimitor
state: "off"
sequence:
- service: modbus.write_register
data:
unit: 1
hub: hybrid_fronius
address: 40242
value: >-
{{ ((states('sensor.smappee_consumption_realtime') | float * 0.25
) / 5000 * 10000 ) | round(0) }}
- service: modbus.write_register
data:
unit: 1
hub: hybrid_fronius
address: 40246
value: 1
- service: modbus.write_register
data:
unit: 1
hub: symo_fronius
address: 40242
value: >-
{{ ((states('sensor.smappee_consumption_realtime') | float * 0.44)
/ 8000 * 10000 ) | round(0) }}
- service: modbus.write_register
data:
unit: 1
hub: symo_fronius
address: 40246
value: 1
- service: modbus.write_register
data:
slave: 2
hub: symo_fronius
address: 40242
value: >-
{{ ((states('sensor.smappee_consumption_realtime') | float *
0.315) / 8000 * 10000 ) | round(0) }}
enabled: true
- service: modbus.write_register
data:
slave: 2
hub: symo_fronius
address: 40246
value: 1
- delay:
hours: 0
minutes: 0
seconds: 10
milliseconds: 0
mode: single
The more often you repeat the loop above, the more accurately is follows the usage. The 2 inverters together, each receive the codes on seperate slave addresses.
alias: Amber SolarLimitor when Turned Off
description: ""
trigger:
- platform: state
entity_id: input_boolean.solarlimitor
from: "on"
to: "off"
action:
- delay:
hours: 0
minutes: 0
seconds: 15
milliseconds: 0
- service: notify.mobile_app_name_of_phone
data:
message: >-
The FIT price has returned to Positive {{
(states('sensor.amber_feed_in_price')|float * 100) }}c. Solar {{
(states('sensor.solar_production')|float / 1000) | round(1) }}kW,
Battery {{ (states('sensor.battery')|float / 1000) | round(1) }}kW,
Consumption {{ (states('sensor.household_consumption')|float / 1000) |
round(1) }}kW & exporting {{
(states('sensor.smappee_grid_realtime')|float / -1000) | round(2) }}kW.
title: Amber Alert - Restarting Export!
- service: modbus.write_register
data:
address: 40246
unit: 1
value: 0
hub: hybrid_fronius
enabled: true
- service: modbus.write_register
data:
address: 40246
unit: 1
value: 0
hub: symo_fronius
enabled: true
- service: modbus.write_register
data:
address: 40246
unit: 2
value: 0
hub: symo_fronius
mode: single
Hopefully that all makes sense & will be useful to some. It has been a lot of work to figure out, but happy to help if anyone has any questions about it all. I am currently working on the same sort of thing the automate the charging & discharging of my battery when it is the most profitable
That’s looking great!
What settings did you use on the fronius inverter when enabling modbus? I’m having trouble working out what I’m missing. The logs do show a “GatewayNoResponse” message, but apart from that I really don’t get anything at all…
[EDIT: I had modbus on the inverter set to float instead of int+SF. Now I’m not getting any messages in the logs, which leads me to assume that the message is actually getting through to the inverter now]
Is there any feedback on the inverter side I can check to ensure the modbus is actually working?
Hi @tux43
Wondering if you have any other tips/setup knowledge.
I am running a Fronius Primo 5, and for the life of me cannot write to the Fronius Modbus. Other devices on LAN can (Victron Cerbo), but I can’t get HA to do it.
Config.Yaml
modbus:
- type: tcp
name: primo1_fronius
host: 192.168.10.122
port: 502
retry_on_empty: true
retries: 30
sensors:
- name: MB_FRONIUS_1_40072_AC_Current
slave: 1
count: 1
address: 40071
data_type: uint16
unit_of_measurement: "A"
scale: 0.01
precision: 1
scan_interval: 5
device_class: current
state_class: measurement
..........
Automation
alias: Fronius Negative Power - Limit Output
description: ""
trigger:
- platform: state
entity_id:
- input_boolean.negative_fit_state
from: "off"
to: "on"
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: "9000"
- service: modbus.write_register
data:
unit: 1
hub: primo1_fronius
address: 40236
value: "1"
mode: single
Fronius:
HA Dashboard showing data on Modbus
HA Logs:
2023-02-05 13:29:27.606 ERROR (SyncWorker_0) [homeassistant.components.modbus.modbus] Pymodbus: primo1_fronius: Modbus Error: [Input/Output] Modbus Error: [Invalid Message] No response received, expected at least 8 bytes (0 received)
2023-02-05 13:44:47.522 ERROR (SyncWorker_11) [homeassistant.components.modbus.modbus] Pymodbus: primo1_fronius: Modbus Error: [Input/Output] Modbus Error: [Invalid Message] No response received, expected at least 8 bytes (0 received)
2023-02-05 13:53:04.623 ERROR (SyncWorker_0) [homeassistant.components.modbus.modbus] Pymodbus: primo1_fronius: Modbus Error: [Input/Output] Modbus Error: [Invalid Message] No response received, expected at least 8 bytes (0 received)
2023-02-05 13:59:46.316 ERROR (SyncWorker_0) [homeassistant.components.modbus.modbus] Pymodbus: primo1_fronius: Modbus Error: [Input/Output] Modbus Error: [Invalid Message] No response received, expected at least 8 bytes (0 received)
Wondering if there is a setting/adding/code I’ve missed that seems obvious to others?
It looks like you are restricting the control from IP address 192.168.10.81? I assume this isn’t your HA instance. Try removing this within the Fronius. Mine looks like this.