Need help in finding PID solution for Energy Storage System (ESS)

Hi Folks,

I need to get my head around a problem for optimising my newly installed EnergyStorageSystem, to optimise Battery charging from dynamic PV intake, while consumption/loads are also dynamic during winter time - where in general the PV intake is not enough to charge the battery fully for some time.

This is what a current system state looks like:

This shows a situation, that I created manually now, but I want to achieve this programmatically with dynamic values via Node-Red.
I think, is is some kind of dynamically adjusted PID algorithm, but I am a little confused as on how to start.

This is what the picture above shows:

  • PV Inverter: the actual Power output from my solar array
  • Grid: the actual power consumption from the Grid
  • Battery (charging): the actual Power delivered from the inverter to the Battery,
    The battery is actually charging with a Power value (just) below the PV Power output.
  • AC Loads: the total actual Power consumed by the installation (house).

As you can see, the PV Output is lower that the actual AC-Loads. The Load from the Grid is also lower than the AC-Loads, as well as the Power charging the Battery.
In a "normal" ESS setup, PV power is first consumed directly and only when PV Power exceeds the AC-Loads, hence the Grid setpoint is configured to be zero Watts, the excess Power is either used to charge the batteries or even fed back into the grid (grid power being negative).
This is / would be the normal behaviour of the ESS System and the internal Controller will do that automatically. So normally, in that situation, the Batttery would not have started charging and PV power would be used directly, hence there is no excess power from PV left.

What I want, is to override/trick the ESS, as the PV Power available during winter allows not for much excess to charge the batteries fully (which is needed for re-balancing the cells and to keep them healthy), with a Node-Red by controlling the Grid setpoint.
This can be done via MQTT.
I manually created the situation above by setting the Grid setpoint to 1300W in this situation:

Now the question is, what controller "function" can be used or how a PID node could be used to control the value of the grid setpoint in a way, where available PV Power will be used to charge the Batteries instead.
The is one major constraint, though: Charging Power to the Batteries must always, at all times, be lower than the available PV-Power (or both zero) as my DSO does not allow charging the batteries from grid.

As a side note: The ESS does provide reading the values of Grid Power, PV Inverter Power, Battery Power (an charging/discharging state info) but NOT the value of the AC Loads via mqtt.

Many thanks in advance for your feedback and thoughts on how to tackle this.

The first thing to do is to try and tie the problem down.

  1. Try and write down in a list all the inputs that are available to the algorithm.

  2. Write down the output(s) that the algorithm can directly control.

  3. Write down any known relationships that are always true, if there are any (such as input_1 + input_2 = input_4, for example. That sort of thing.

  4. Write down the constraints and aims that need to be met.

So for example, the inputs might be
Grid Watts
AC Load Watts
and so on.

1 Like

Thank You @Colin ...should have started the list initially, before posting.
Here's my first try:

  • PV-Power (actual)
  • Grid Power (actual)
  • Battery Power (actual)
  • Battery state (actual - idle|charging|discharging)
  • AC Loads (Power) per phase (actual, L1, L2, L3 - total AC-Load =sum of all phases is not available directly) - these values are not from an accurate sensor, I'd rather not use them.
  • Edit: Battery SoC %
  • Grid setpoint (Power)
  • AC.Loads, total = sum of all 3 phases (AC.Load from L1+L2+L3)
  • Grid Power = AC.Loads (total) - (PV Power - Battery Power)
  • Grid Power = Grid-Setpoint if PV Power exceeds AC-Loads + Battery (Charge Power) (PID / ESS controller embedded in the system, does have some hysteresis, is slow and produces some headroom/offset from the maths given - but normally averages out over time).
    Edit: embedded rules of the underlying ESS
  • When Grid Power is above Grid Setpoint -> discharge the Battery, if minimum SOC is not reached.
  • When Grid Power is below Grid Setpoint -> charge Batteries if SOC 100% is not reached (this has to be avoided at all costs, as this will charge the batteries from grid, which is not allowed by my DSO). The Rule "PV-Power > Battery Power (chargeing) will take care of that).
  • Constraint: Battery Power (charging) < PV-Power
  • Constarint: Battery Power (chargeing) = 0 if PV-Power = 0
  • Aim: When PV-Power > 0 (i.e starting from >=100W) , change grid-setpoint to a value where not all PV-Power is consumed, hence resulting in some PV excess Power to start chargeing the battery.

Sorry, I haven't got much time to spend on this at the moment, so progress will probably be slow.

Is that just an indication of whether Battery Power is +ve, -ve, or zero?

Yes, that is indeed only an indicator....sign of Battery Power is also an indicator, like +500W (chargeing) or -2000W (discarging) or idle (0W).

No worries, I really appreciate your help, anytime. I added some more info to the list above...don't know if this is of value.

I'm familiar with the Victron ESS system and I think I understand what you're trying to do. You will have more luck getting responses here if your question is more generically about node-red.

From your list, do I understand correctly that only the last bullet point is what you want to accomplish with node-red?

You want to programmatically modify the setting of 'grid setpoint'. In relation to what?

Try to write down what you want, in terms of logical if / then statements.


IF "PV power" > 0 AND "PV power > "Grid power" THEN increase "Grid Setpoint" UNTIL "battery power" > 500

to help with the implementation we'll need to know if you are talking to your victron system over MQTT, over the API, or over modbus-TCP.

OK so the big issue you have is that you do not know what the AC load is - i find this very strange as you should have a Grid Meter that will report this information to you in realtime - the battery needs this otherwise it can not work out how much it can charge the battery by without drawing from the grid.

I have a system in place that does what you want - my IOTAWATTS do all the measurements for me and provide me with a rolling 3s average of the following

AC/Grid power flow
Battery in/out
Solar in/out

You do not need a PID algorithm just some basic maths - in my case the GoodWe inverters i use to charge my batteries do not allow me to specify an actual amount to charge by - but rather a % of the capacity of the inverter - which comes out to be very close to 1% = 50w

My flow is very specific to my iotawatts and my setup with my goodwes and batteries - but happy to provide any help or direction that you.

I do not think there is any way you can get an accurate number though without knowing all the variables.

Sorry just went back and read it more closely and it does look like you have enough information to do what you want.

Essentially you want to charge from Excess PV whilst keep the grid close to Zero (how do they know if you charge a battery from the grid - it just looks like any other load ? Seems a weird one that they do not want to sell excess power ?


Well, yes I would normally agree, but I am not trying to invent an alternative ESS algorithm . I want to control the existing ESS by external parameters to create a state, that it would normally not reach. Hence, I think, it is vital to understand that there is an external controller, the ESS running in parallel.

Yes, that is correct.
I want the ESS to use more of the PV-power for charging the batteries, than it normally a situation where the existing PV-power would not even supplement the existing loads (bad weather, winter) the batteries would not even start charging, as direct consumption is preferred, leading to no excess PV-energy to spare.
Normally the grid-setpoint is set to a low value, like 0W or even -10W (minimal feed-in) and the ESS would only start charging the batteries when there is PV-Power in excess of the actual loads, while the grid-setpoint is met (by consuming the existing PV-power first).

the algorithm needs to work both ways, as PV-Power and AC-Loads change/are non constant.
I think this could basically work:

  • IF (("PV-Power" > 0) AND ("Battery-Power" <= 0)) THEN increase "Grid Setpoint" UNTIL "Battery-Power" < = "PV-Power" * 0.9 // force Battery charging until Charging Power is max. of 90% of PV-Power

  • IF (("PV-Power" > 0) AND ("Battery-Power" > "PV-Power" * 0.9)) THEN decrease "Grid Setpoint" UNTIL "Battery-Power" < = "PV-Power" * 0.9 // Battery charging Power allowed is max. 90% of PV-Power...allow 90% of PV-Power only to avoid overshoot and charging from grid power

  • IF "PV-Power" =0 THEN set "grid setpoint" to "default" (i.e. 0W).

I'd prefer mqtt, as this is the most lightweight protocol for integrating with the Victron GX (Cerbo)

Well yes, ther is a grid meter, but the value does not represent the total loads, only what gets used-from/fed-into the grid. If there is already PV-Power available, it will be consumed by loads before the grid meter detects it.
The grid meters in my jurisdiction are required to sum-up all phases. And this is what the ESS will try to control, by minimizing consumption from the grid. by discharging the batteries until the grid setpoint s met or charging the batteries from excess PV-Power until the grid setpoint is met.

There is an extra 2way-meter from my DSO that meters the PV-Energy produced as well as energy going the other direction (to the battery inverters/chargers)....before I installed the battery system, that reading stayed at zero kWh.

feed-in to the grid is allowed, even from the batteries - if they have been previously charged with PV-Power only. Using power from the grid to charge the batteries and then feeding that Energy back into grid is not allowed, hence simply the rule that charging from the grid s not allowed.
The nature of that rule is based on the "good old days" where the tariff on consumption from the grid was sometimes lower than the tariff reward per kWh for the feed-in :wink:

Yep thats what we do with ours occsionally - arbitrage the grid

It would be a much easier equation for you to manage if you went down the same track as Bart and could monitor the total loads in your house using something as simple as a Shelly EM or some such

Our Solar is also metered seperately and our phases are also Zeroed out here in Australia so similar to you guys in SA.

What i currently do is use my iotawatt to take give me a rolling 3 sec average of my consumption, solar output and grid draw and then choose what i want the batteries to do (in terms of charging or discharging)

My main goal is to Zero out the Grid useage, but also do do arbitrage when we are with a different supplier.

I use a series of flows which set global flags and values and are then used in the calculation of what loads i want to turn on etc.

What specifically did you want - hapy to post any code so you can see how i have tackled it

Main thing i found was that i had a small tight loop that was responsible for battery charge and discharge nad it did not worry about loads in the house etc.

The loads instead run and check/set global variables

So for instance my pool filtering pump

In summer i want it to run for a minimum of 4 hours per day

  1. Midnight every nigth i run a trigger that determines the month and then sets a global variable to set the minimum run time

  2. From 9AM every day (every minute) i check if i have excess solar power (15 minute average greater than the loads in the house)

  3. If yes above i then check if the battery is over 60% SOC (which is enough to get me through the expensive peak hour later in the day)

  4. I then continue to run through this loop (which because i am working on a 15 minute average dampens out any other short term loads and clouds etc) - once i meet my minimum run time for the day - i then turn off the pump and go to a new branch

  5. This branch now waits for the battery to be over 90% SOC before it will then run the pool pump again for another period of time which is and additional 50% longer than the minimum - plus make up for any other days that have not met their minimum.

I do similar things with other loads such as our heat pump for our hydronic heating - obviously driven by different factors etc.


...interesting...arbitrage the Grid, I mean. That sort of thing is not allowed (based in DE, btw).
What I can do, however, is trying t shift battery discharge to times when different appliances that are on different tariffs are demanding load. I do have a different tariff for my heatpumps and EVs and one forr the rest of the home.

Yes, collecting the different power measures in global variables to have all vaues ready when a new calculation loop needs to be performed. also thought in that direction.

My first goal is to use PV to charge the batteries over direct consumption or feed it.
The basic goal is to zero out the grid, but having the batteries filled to 100% - in order to have the BMS performing cell balancing - is a vital thing during winter. Battery capacity is optimized for autumn and spring and too low during winter. challenge is, that I have the external control running in the victron ESS.
So with NR I need to override that, without disabling it.

First thing is to get my head around that alogrithm to prefer PV power for chargeing the batteries, even that means moore consumption from the grid for other loads. Once I have that, I will create other "loops" to control and steer battery discharge based on loads and SoC.

What happens when your battery is full and you have excess solar - can you feed this to the grid and do you get paid a reasonable amount for it ? Or do you have to throw it away ?

Do you have a reliable solar forecast source in your area - such as Solcast ?

You may want to have a look at Home Assistant - someone has written a load scheduling add-in for it that works quite well and he is very responsive to change requests etc

If you are able to get reasonable forecast data then a good amount of the work is done for you.


I can feed-in excess solar as well as Energy from the Battery...however using it for self consumption is commercially preferable...during Summer, I'd rather use Energy from the Battery to charge my EVs.

Yes, I am using solcast, which has proven to be quite rooftop install is from a time where PV-tuning was stll active.

I'll definitely have a look at that option....many thanks for your input...much appreciated.

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.