Criticism and/or Comments on my Victron Automation

So I hope to invite some constructive criticism (or destructive if you think it will be better) on an automation I made today. I haven’t tested it thoroughly yet and might have made some big blunders in my logic, which is why I am turning to this forum.

The logic is set out below. If anyone is interested in the YAML, I can share it.

  1. I want to get my batteries full before sunset (this is a “want”, not a “need”, as another forum user likes to state).
  2. I do not want to use my batteries to optimally save power, because I know I currently have too small a capacity, I want to use them only when the sun isn’t out and I hope this behaviour of mine will make them last longer.
  3. I do not want to discharge my batteries too hard.

The way I’ve implemented this is with three automations in Home Assistant:

  1. After sunrise, but before the battery is at 100 SOC, limit inverter power to DC power generated by PV plus some number (I put this as 100W for now, but it is an input).
    In theory (ignoring DC conversion losses) this should limit my discharge to 100W. Because this is before my battery is at 100 SOC, during this time the PV will work flat out (ignoring the last bit where the battery drops its charging current) so I won’t introduce a “lag” into the system that limiting the inverter power to the PV + some offset would create after the batteries are full.
  2. After sunrise and after the battery reached 100 SOC, switch ESS mode to Keep Batteries Charged and remove inverter limit
  3. After sunset but before sunrise, switch ESS mode to Without Battery Life and introduce inverter limit of 750W (this is also an input).

I understand the above would limit my overall production during the day, especially after the batteries are full and the PV starts to reduce below the levels needed to fully power a big load, but still enough to charge the batteries back up should it have been used in conjunction with the available PV to power the big load. However, this is a price I am willing to pay until I had the opportunity to buy more batteries so that they don’t need to work so hard.

All the above would be completely unnecessary had I stayed on my own, but as I have stated before, it is very difficult to control all the variables in a house with a few other people, and I’m not a big fan of my 7kWh bank trying to run 5kW of loads if there isn’t enough available PV.

1 Like

But that’s what I’ve done.

Blockquote00 07 * * * root /usr/bin/dbus -y com.victronenergy.settings /Settings/CGwacs/MaxDischargePower SetValue 4000
00 14 * * * root /usr/bin/dbus -y com.victronenergy.settings /Settings/CGwacs/MaxDischargePower SetValue 2900
00 15 * * * root /usr/bin/dbus -y com.victronenergy.settings /Settings/CGwacs/MaxDischargePower SetValue 2300
00 16 * * * root /usr/bin/dbus -y com.victronenergy.settings /Settings/CGwacs/MaxDischargePower SetValue 800
00 17 * * * root /usr/bin/dbus -y com.victronenergy.settings /Settings/CGwacs/BatteryLife/State SetValue 10
00 17 * * * root /usr/bin/dbus -y com.victronenergy.settings /Settings/CGwacs/BatteryLife/MinimumSocLimit SetValue 30

Then using HomeAssistant, I increase the SOC from 30% at after sunset, to 100% SOC before sunset.

To “protect” the batteries, limit the inverter power to be inline with the solar production.

1 Like

I do everything in HomeAssistant:

#Set maximum inverter power based on PV generation before sunset and battery full

  • alias: Set Maximum Inverter Power Based on PV Generation before SOC 100 and Sunset
    trigger:
    platform: state
    entity_id: sensor.DC_from_PV
    condition:
    condition: and
    conditions:
    - condition: sun
    before: sunset
    - condition: sun
    after: sunrise
    - condition: template
    value_template: “{{ (states(‘sensor.Battery_SOC’)|int) < 100 }}”
    action:
    service: modbus.write_register
    data_template:
    unit: 100
    value: “{{ states(‘sensor.dc_from_PV’)|int / 10 + states(‘input_number.input_maximum_battery_discharge_after_sunrise_before_battery_full’)|int / 10 }}”
    hub: victron
    address: 2704

#Set to Keep Batteries Charged after SOC 100 and remove inverter maximum cap

  • alias: Set Victron ESS Mode to Keep Batteries Charged after SOC 100 and before Sunset
    trigger:
    platform: time_pattern
    minutes: /1
    condition:
    condition: and
    conditions:
    - condition: sun
    before: sunset
    - condition: sun
    after: sunrise
    - condition: state
    entity_id: sensor.Battery_SOC
    state: ‘100’
    action:
    service: modbus.write_register
    data_template:
    unit: 100
    value: 9
    hub: victron
    address: 2900

  • alias: Remove Inverter Cap after Keep Batteries Charged was set
    trigger:
    #platform: state
    #entity_id: sensor.Battery_SOC
    platform: time_pattern
    minutes: /1
    condition:
    condition: and
    conditions:
    - condition: sun
    before: sunset
    #before_offset: +00:30:00
    - condition: sun
    after: sunrise
    #after_offset: -00:30:00
    - condition: state
    entity_id: sensor.Battery_SOC
    state: ‘100’
    action:
    service: modbus.write_register
    data_template:
    unit: 100
    value: 500
    hub: victron
    address: 2704

#Set ESS Mode to Without Battery Life after Sunset and introduce the after sunset inverter maximum cap

  • alias: Set Victron ESS mode to Without Battery Life after Sunset
    trigger:
    platform: time_pattern
    minutes: /1
    condition:
    condition: and
    conditions:
    - condition: sun
    after: sunset
    action:
    service: modbus.write_register
    data_template:
    unit: 100
    value: 10
    hub: victron
    address: 2900

  • alias: Set Inverter Maximum Cap after Sunset
    trigger:
    platform: time_pattern
    minutes: /1
    condition:
    condition: and
    conditions:
    - condition: sun
    after: sunset
    action:
    service: modbus.write_register
    data_template:
    unit: 100
    value: “{{ states(‘sensor.dc_from_PV’)|int / 10 + states(‘input_number.input_maximum_battery_discharge_after_sunset’)|int / 10 }}”
    hub: victron
    address: 2704

Seems to actually work so far (expected something to break!) and it nicely switched over at sunset, did its thing before sunset. Will now just see how tomorrow goes.

I’m actually quite excited about this, because I just couldn’t find a setting in ESS that allows me to have the following effect:

  1. All available PV first goes to service load, then charge battery
  2. If not enough PV available, take from grid

I’ll still refine it a bit, for example, if I note that the battery early in the day, I don’t need to go to “Keep Batteries Charged until Sunset”, I can actually keep the batteries available for discharge up to a preset amount.

I tried to do that crudely, but I didn’t appreciate that the “ramping up” of solar production is delayed with the ModBus updates (like once every 30 seconds) should the batteries already be full. Because I don’t have a reliable way of knowing how much PV is available when the batteries are already full, I still limit the inverter to DC from PV + X (where X is the max battery discharge I want to allow). So then if it needs to ramp up say 3000W, it will take 3000/X/2 minutes to ramp up. This I just found more frustrating than just putting it on Keep Batteries Charged without any inverter limit. Then it can ramp up as quickly as required.

It would be so nice if there is a way to know what your PV potential is at any point in time… Victron should sell a little panel that you can put on your roof that then integrates with your GX to give you that info… :sweat_smile:

Btw, do you know if it is possible to put two actions in one “automation”? I hate that I have to duplicate it to do two things… Just feels super inefficient having to test the same conditions twice…

1 Like

It does make quite a bit of sense and as per usual there are more than one way to do this.

If you would like to use the batteries only as a backup and not for energy saving a another way would be to limit the battery discharge when on grid to something like 95% . That way , if you have a bad weather day , batteries wont get discharged more than that amount as long as the grid is available.

Then use the Solar Output and Battery watts to adjust the ESS you could add a factor in to ensure that the batteries never discharges during daytime. I use Node Red , located on the Venus GX and the script has been running for almost a year and half with no issues.
One advantage is that should the script go belly up you will still have the Min Soc setting to “protect” the batteries.
The other is that you do not need time as the panels output determines the cutoff and startup time.

Here is the flow just for fun :slight_smile:

[{“id”:“eeffa000.c4b4e”,“type”:“victron-input-battery”,“z”:“9b1de2c7.ff15”,“service”:“com.victronenergy.battery.ttyO4”,“path”:“/Dc/0/Power”,“serviceObj”:{“service”:“com.victronenergy.battery.ttyO4”,“name”:“BMV-702”,“paths”:[{“path”:“/Dc/0/Voltage”,“type”:“float”,“name”:“Battery voltage (V)”},{“path”:“/Dc/1/Voltage”,“type”:“float”,“name”:“Starter battery voltage (V)”},{“path”:“/Dc/0/Current”,“type”:“float”,“name”:“Current (A)”},{“path”:“/ConsumedAmphours”,“type”:“float”,“name”:“Consumed Amphours (Ah)”},{“path”:“/Soc”,“type”:“float”,“name”:“State of charge (%)”},{“path”:“/TimeToGo”,“type”:“float”,“name”:“Time to go (h)”},{“path”:“/Relay/0/State”,“type”:“enum”,“name”:“Relay status”,“enum”:{“0”:“Open”,“1”:“Closed”}},{“path”:“/Dc/0/Temperature”,“type”:“float”,“name”:“Battery temperature (C)”},{“path”:“/Dc/0/MidVoltage”,“type”:“float”,“name”:“Mid-point voltage of the battery bank (V)”},{“path”:“/Dc/0/MidVoltageDeviation”,“type”:“float”,“name”:“Mid-point deviation of the battery bank (%)”},{“path”:“/Alarms/LowVoltage”,“type”:“enum”,“name”:“Low voltage alarm”,“enum”:{“0”:“No alarm”,“2”:“Alarm”}},{“path”:“/Alarms/HighVoltage”,“type”:“enum”,“name”:“High voltage alarm”,“enum”:{“0”:“No alarm”,“2”:“Alarm”}},{“path”:“/Alarms/LowStarterVoltage”,“type”:“enum”,“name”:“Low starter-voltage alarm”,“enum”:{“0”:“No alarm”,“2”:“Alarm”}},{“path”:“/Alarms/HighStarterVoltage”,“type”:“enum”,“name”:“High starter-voltage alarm”,“enum”:{“0”:“No alarm”,“2”:“Alarm”}},{“path”:“/Alarms/LowSoc”,“type”:“enum”,“name”:“Low state-of-charge alarm”,“enum”:{“0”:“No alarm”,“2”:“Alarm”}},{“path”:“/Alarms/LowTemperature”,“type”:“enum”,“name”:“Low battery temperature alarm”,“enum”:{“0”:“No alarm”,“2”:“Alarm”}},{“path”:“/Alarms/HighTemperature”,“type”:“enum”,“name”:“High battery temperature alarm”,“enum”:{“0”:“No alarm”,“2”:“Alarm”}},{“path”:“/Alarms/MidVoltage”,“type”:“enum”,“name”:“Mid-voltage alarm”,“enum”:{“0”:“No alarm”,“2”:“Alarm”}},{“path”:“/Dc/0/Power”,“type”:“float”,“name”:“Battery power (W)”}]},“pathObj”:{“path”:“/Dc/0/Power”,“type”:“float”,“name”:“Battery power (W)”},“name”:“BMV Watts”,“x”:100,“y”:380,“wires”:[[“7275330e.fb869c”,“ff2f0f32.e74ed”]]},{“id”:“7275330e.fb869c”,“type”:“delay”,“z”:“9b1de2c7.ff15”,“name”:“”,“pauseType”:“rate”,“timeout”:“1”,“timeoutUnits”:“seconds”,“rate”:“1”,“nbRateUnits”:“15”,“rateUnits”:“second”,“randomFirst”:“1”,“randomLast”:“5”,“randomUnits”:“seconds”,“drop”:true,“x”:190,“y”:430,“wires”:[[“1df46a74.dab466”]]},{“id”:“1df46a74.dab466”,“type”:“function”,“z”:“9b1de2c7.ff15”,“name”:“Calculate”,“func”:“b = msg.payload.toFixed(0)\n\nvar batw = b1 ;\nvar sol = flow.get("solarw")1\nvar maxstate = flow.get("maxstate"); // Max Dischage Value\nvar maxstatesw = "ON";\n\n\nminEss = 250 // Min Battery Discharge value for ESS \nMaxBattDc = -250 // Battery Discharge value before Activation \nfactor = 1 // Factor by with the ESS vaule is set - this is to ensure that the pannels match the dischrge\nMaxBattCh = 150 // Battery is charging and can adjust the Max discharge \n\nif (sol <= minEss){\nnewMax = minEss; \n}else{\nnewMax = (Math.ceil(sol / 10) * 10) ; //-(solfactor) - round to 10\n}\n\n\n// Debug Info\nif (maxstatesw == "ON"){\ncolor = "green" \n}else if (maxstatesw === "OFF"){\ncolor = "red" \n}\n\n\n\n\nnode.status({fill:color,shape:"ring",text:"Bw:"+batw+" Ess:"+maxstate + " Sol:"+sol}); \n\n if(maxstatesw=="ON"){ // Check if Switch is ON\n if (batw <= MaxBattDc && maxstate > minEss || maxstate < minEss ) { // Battery is Discharging and ESS is still to high\n msg.payload = (newMax1).toFixed(0)1;\n return msg; \n } else if (batw >= MaxBattCh ){ // Solar is enough to sustain the curr house load load\n msg.payload = (newMax1).toFixed(0)*1;\n return msg; \n }\n \n }\n”,“outputs”:1,“noerr”:0,“initialize”:“”,“finalize”:“”,“x”:350,“y”:430,“wires”:[[“9f11fe50.5c2c4”]]},{“id”:“9f11fe50.5c2c4”,“type”:“rbe”,“z”:“9b1de2c7.ff15”,“name”:“”,“func”:“rbe”,“gap”:“”,“start”:“”,“inout”:“out”,“property”:“payload”,“x”:510,“y”:430,“wires”:[[“c00e69c7.7a1058”]]},{“id”:“c00e69c7.7a1058”,“type”:“victron-output-ess”,“z”:“9b1de2c7.ff15”,“service”:“com.victronenergy.settings”,“path”:“/Settings/CGwacs/MaxDischargePower”,“serviceObj”:{“service”:“com.victronenergy.settings”,“name”:“ESS System Settings”,“paths”:[{“path”:“/Settings/CGwacs/AcPowerSetPoint”,“type”:“integer”,“name”:“Grid set-point (W)”,“writable”:true},{“path”:“/Settings/CGwacs/BatteryLife/MinimumSocLimit”,“type”:“integer”,“name”:“Minimum Discharge SOC (%)”,“writable”:true},{“path”:“/Settings/CGwacs/BatteryLife/State”,“type”:“enum”,“name”:“ESS state”,“enum”:{“1”:“BatteryLife enabled (GUI controlled)”,“2”:“Optimized Mode /w BatteryLife: self consumption”,“3”:“Optimized Mode /w BatteryLife: self consumption, SoC exceeds 85%”,“4”:“Optimized Mode /w BatteryLife: self consumption, SoC at 100%”,“5”:“Optimized Mode /w BatteryLife: SoC below dynamic SoC limit”,“6”:“Optimized Mode /w BatteryLife: SoC has been below SoC limit for more than 24 hours. Charging the battery (5A)”,“7”:“Optimized Mode /w BatteryLife: Inverter/Charger is in sustain mode”,“8”:“Optimized Mode /w BatteryLife: recharging, SoC dropped by 5% or more below the minimum SoC”,“9”:“‘Keep batteries charged’ mode is enabled”,“10”:“Optimized mode w/o BatteryLife: self consumption, SoC at or above minimum SoC”,“11”:“Optimized mode w/o BatteryLife: self consumption, SoC is below minimum SoC”,“12”:“Optimized mode w/o BatteryLife: recharging, SoC dropped by 5% or more below minimum SoC”},“writable”:true},{“path”:“/Settings/CGwacs/Hub4Mode”,“type”:“enum”,“name”:“ESS mode”,“enum”:{“1”:“Optimized mode or ‘keep batteries charged’ and phase compensation enabled”,“2”:“Optimized mode or ‘keep batteries charged’ and phase compensation disabled”,“3”:“External control”},“writable”:true},{“path”:“/Settings/CGwacs/MaxDischargePower”,“type”:“integer”,“name”:“Max inverter power (W)”,“writable”:true},{“path”:“/Settings/CGwacs/OvervoltageFeedIn”,“type”:“enum”,“name”:“Feed-in excess solar charger power”,“enum”:{“0”:“No”,“1”:“Yes”},“writable”:true},{“path”:“/Settings/CGwacs/PreventFeedback”,“type”:“enum”,“name”:“PV Inverter zero feed-in (on/off)”,“enum”:{“0”:“No”,“1”:“Yes”},“writable”:true},{“path”:“/Settings/SystemSetup/MaxChargeCurrent”,“type”:“float”,“name”:“Charge current limit (A)”,“writable”:true}]},“pathObj”:{“path”:“/Settings/CGwacs/MaxDischargePower”,“type”:“integer”,“name”:“Max inverter power (W)”,“writable”:true},“initial”:“”,“name”:“Max Power”,“x”:690,“y”:430,“wires”:}]

Yeah I was thinking about this, but the reason I added the time was because I want to play around with an offset before sunset or offset after sunrise based on the length of the night. I.e if the night is 16 hours, I need to cut the stretch a little before starting to use the batteries (or stop a little before sunrise).

The reason for this is that when ESS hits the min SOC, it goes into this mode that wants to first charge 3% into the battery before anything else. If I could disable that feature (and just let the battery sit on min SOC) it would also solve that problem…

So, this seems like functionality many people are implementing using their own automations. @plonkster do you think this is something that Victron would be able to start supporting natively? I’d prefer it to be integrated into the GX instead of me running it over ModBus from a Pi.

I’ve tested mine now for a few days and it works great. Obviously doesn’t react that fast, so intermittent cloud cover would use the battery a little every now and then (for a max of the ModBus update frequency) before I get to the point where I switch the batteries to keep charged. I’m happy to live with this.

I think I can channel the big boss for you on this one: This is why we have NodeRed support, so people can do it themselves.

:slight_smile:

There is room for a HomeAssistant integration, to at least make it easier without requiring the editing of a text file.

1 Like

So you don’t see another ESS mode (for example) making its appearance?

Does NodeRed run directly on the Venus or is it also as part of a Home Automation setup?

*Edit: Nevermind, I see I can install it directly on the Venus by updating my firmware to the latest release candidate and then getting the Venus OS Large.

Guess then I’ll just have to figure out how to use NodeRed. :smiley:

I cannot say. There are no plans for one… but sometimes things happen suddenly… like the vebus firmware updates :slight_smile:

The large image includes NodeRed.

Great! I’ll make some time to do the update and learn myself some NodeRed. Probably take another 6 months or so before I get it set up…

1 Like

I’m running NodeRed on the large image. Pretty easy to do and would not take 6 months :smiley:
Here is something to get you started

1 Like

Oh but it will so take 6 months for me to get time again to allocate to this project. :sweat_smile:

Thanks for the guide! I’ll have a look.

1 Like

I’m just thinking about this. Is this not something that is covered by a scheduled charge with a low SOC? So you can do something like set a schedule to start after sunrise and end when you want to start using batteries again. You then set it with a SOC lower than your normal minimum SOC (like 15%) and also tick the Stop charge on SoC. And then you can limit the inverter power overnight like you have at the moment.

The way I understand it is that during this charge window you will not use your batteries to power loads (except for a loss of mains), but all your other loads will be powered by PV and then grid if needed. Your batteries will also not get charged from the grid unless they are less than the set SOC (15% being a value that you’ll most likely not hit which is why I suggest it) and will still charge with excess PV.

From what you mentioned I’m not 100% sure if you don’t want to use the batteries at all or if you are looking for something like TTT has where it can use a little bit while it’s charging up from excess PV in which case I guess his automations should work for the charging part.

It would in principle, yes. But I’ve found the following issues with it:

  1. The solar day moves, so it becomes a bit manual.
  2. When the battery is full with scheduled charging on, the MPPTs just don’t want to ramp up production.
  3. It doesn’t protect my batteries when I want to use them, like at night.

I could live with all the above except number 2. It happened every time I forgot to turn off scheduled charging after the batteries got full.

I also don’t want to use the increase in SOC method, because every time it hits min SOC, all PV would be diverted to the batteries for the next 3%.

The one thing we must not lose focus of is that it took years and years for Victron to develop their software so that with the correct size battery bank/panels, based on where you live and all that, that ESS optimizes ones savings.

My CORE principal was to not interfere with that yet to keep the BIG loads away from the batts, cause I should have a bigger bank, but it is not viable.

So therefor I made some adjustments to the inverter power based on time of the day, differing between winter and summer, whilst upping the SOC in 5% increments during the day to get to 100% SOC latish afternoon for specific evening usage.

In effect I’ve “spread” the usage over 24h.

All Automated off course. :wink:
(bar manual intervention when there are extended bad weather week or change of winter to summer … bugger the rest!

The way I see it: Batteries do not have a good ROI, it is purely a “I want it” thing. So it is a hard sell for me to get more batteries than that which I need to take me through the night and by extension, cover my loadshedding. I sized my bank for that.

My main problem is my geysers coming on around middag. If there’s not enough PV, it is raining or whatever, then it would pump my batteries. I really don’t want that.

So my inverter was sized for the loads I want it to be able to carry intermittently, like a kettle plus vacuum or something like that, on my critical loads. It is a nice plus that it can run my geyser off it, on my non-essentials. But my batteries aren’t sized to run my geyser and oven. It was sized to run my backup loads. Effectively if there were a setting to only use batteries for critical loads and not feed them back to the non-criticals, that would be perfect as well.

Ever considered to set the SOC at like 90%, or 80%, set inverter max wattage to what the geysers + house needs, and let it be?

Well I think that my current solution is a little more refined than that so I’m happy to keep it that way. I’m just more thinking along the lines that it can’t be too unique a case where batteries are sized according to the critical loads and not the total loads and therefore a system wouldn’t want to feed back battery power on the non-essentials?

I was there too, bank to small, wanting to us all the power from the array, without boiling the batts.

Being grid tied it does not matter much. The BIG saving, ROI on batts, is if you can shave the 24/7 loads off as far as possible, without shortening the life of the batteries.

It is a juggle, win some, lose some.

Yeah so that is what I do with my bats now. Run then down at max 400W during evenings from 100% after sunset to just a little over 40% (min SOC set at 40% because I need 10-20% for loadshedding to be safe) at sunrise (this time of year), then jump on PV again (albeit slowly at first) and charge batteries with excess.

With my automation, the max I can discharge the batteries at for more than 30 seconds during the day is about 500W (~10% more than PV generated because my inverter max is set at the DC generated by PV, not allowing for conversion loss), but this is fine.

I hope that managing my batteries this way will keep them viable for at least 15 years. Then I’ll be happy.

1 Like