question

zed-must avatar image
zed-must asked

Schedule grid feed back using Node red

Example below of how to achieve this:

what i want it to do is control whether to export to grid or charge the batteries based on time of day and battery SOC - and i want to be able to modify these 2 parameters easily

e.g.

If SOC > 50% and time is after 7pm send PV to grid.

Node-RED
2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

3 Answers
matt1309 avatar image
matt1309 answered ·

Hi @zed must

Not sure I'll have time but thought I'd ask a few questions (that I imagine anyone willing to help might want to ask anyway which might give people the extra info they need to offer their services).

1. What is your plan for how to adjust the parameters? Do you need/want a dashboard created in node red to adjust these, or do you have another system ie homeassistant/openhab that you'd want to utilise to update the SoC, time and i assume charge/discharge.

2. How is the system currently configured, is the solar connected via charge controller (DC coupled) or via Grid tied inverter (AC coupled) or do you have both. (If it's just AC coupled there's a faster way to code it up I believe)

3. When you say export to grid which of the below do you mean (or do you mean a mix in which case another few parameters might be needed to select which one).

  • Export any excess solar only
  • Export all solar (so loads will be powered from battery)
  • Export a fixed number of amps/watts so solar + battery
  • Export so that grid setpoint = a specific negative number


4. In terms of turning off this feature. (less applicable if your answer to 3 is excess solar only)

ie feature turned on if SoC > 50% after 7pm.

do you want off to occur only when SoC < 50% or at 5am or after x hours.



2 comments
2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

zed-must avatar image zed-must commented ·

HI Matt, thanks for your interest.

1. Ideally we would be able to adjust the parameter in node red. Not sure i need a dashboard - i can just about get my way around node red so im sure if you tell me which nodes to edit i can do that myself.

2.We have both DC coupled solar and AC coupled wind through a Quattro. See screenshot below.screenshot-2024-04-12-at-120504.png

3. we would want to:

  • Export all solar (so loads will be powered from battery)

During certain hours when battery SOC meets a set value.

4. ideally we would be able to have multiple conditions/time slots, but not the end of the world if there is only a couple. So that the feature would turn on and off automatically when conditions are not met, ie

from 8am-10am, if SOC>90%, send all generated power to grid (so that when SOC drops <90%, power goes back to batteries

from 10am-2pm, if SOC>70%, send all generated power to grid

from 2pm-7pm, if SOC>50%, send all generated power to grid

from 7pm-11pm, if SOC>30%, send all generated power to grid

Where i can change the hours and the SOC for each rule. But they should all work the same i.e. on when conditions are met (i.e. send to grid) and off when conditions are not med (i.e. charge the batteries).

And one final complication - we aren't allowed to export more than 6kw, which is currently set up as a limit in the ESS settings. However if using a node red setup instead, we would need to make sure that if we are in 'send all generated power to grid mode', that any power generated over 6kw doesnt get wasted and instead goes to the batteries i.e. 6kw to grid, balance to batteries.

Hope all that makes sense and isn't too difficult to set up.

Thx


0 Likes 0 ·
matt1309 avatar image matt1309 zed-must commented ·

Making a fully polished system with dashboards (ie an interface where you just fill in a text box to adjust parameters) is time consuming. If however you just want this:


from 10am-2pm, if SOC>70%, send all generated power to grid

from 2pm-7pm, if SOC>50%, send all generated power to grid

from 7pm-11pm, if SOC>30%, send all generated power to grid


Written in code. I can send you that and you can implement it for free.

In terms of the 6kw limit, id leave that in ESS, feels safer there in native very well tested code.

0 Likes 0 ·
matt1309 avatar image
matt1309 answered ·

Here's some code:


I know the below is instructions rather than an easy install but it's free....


EDIT: You might have to change this is you ever want to manually make grid setpoint greater than 0. As this code will override it back to 0.


You need to do a few things first:

1. Get the data from victron nodes:

So you need to find the node that outputs the AC Solar data (PV Inverter node, then select measurement of power) as well as the DC solar data (likely Solar charger node and select measurement of PV Power). If you've got multiple MPPTs let me know i can edit the code to have multiple dcSolar variables.

And finally you do the same with State of charge data (likely from battery monitor node selecting measurement state of charge %).



2. These data nodes need to be passed into their own change nodes so you can set the topic of the message (this tells the function what type of info it's received.


It'll look like this:

1712949505205.png

With the inside of the change node looking like this:

1712949521569.png


You repeat this process for the DC solar but change the topic name in the change node to dcSolar and soc for battery monitor


You string them together like this:


1712949539491.png


Function 2:

//setting up time variables
var currentTime = new Date();
var hours = currentTime.getHours();
var minutes = currentTime.getMinutes();

//setting up data variables. If using up to date venus os you could get these directly via global context. 
var soc = global.get('soc');
var acSolar = global.get('acSolar');
var dcSolar = global.get('dcSolar');
var gridSetpoint = global.get('gridSetpoint');

//setting soc variable depending on inputs from flows
if (msg.topic === "soc") {
  soc = msg.payload; // Extract payload from input 1
  global.set('soc', soc);
}

if (msg.topic === "acSolar") {
  acSolar = msg.payload; // Extract payload from input 2
  global.set('acSolar', acSolar);
}

if (msg.topic === "dcSolar") {
  dcSolar = msg.payload; // Extract payload from input 3
  global.set('dcSolar', dcSolar);
}

//this is used to check if gridsetpoint is already 0, if it is then we won't bother updating it.
if (msg.topic === "gridSetpoint") {
  gridSetpoint = msg.payload;
  global.set('gridSetpoint', gridSetpoint);
}

if (msg.topic === "acLoad") {

  acLoad = msg.payload; // Extract payload from input 2

  global.set('acLoad ', acLoad);

}

//two examples of times
if (hours >= 10 && hours < 14) { //if time is between 10am-1.59pm
  if (soc > 70 && acLoads < 10000) { //if state of charge is above 70%
    //return the new grid setpoint
    gridSetpoint = -Math.min(acSolar + dcSolar, 6000);
  } else {
    gridSetpoint = 0;
  }
} else if (hours >= 14 && hours < 19) { //if time is between 2pm and 6.59pm
  if (soc > 50 && acLoads < 10000) { //if state of charge is above 50%
    //return the new grid setpoint
    gridSetpoint = -Math.min(acSolar + dcSolar, 6000);
  } else {
    gridSetpoint = 0;
  }
} else if (hours >= 19 && hours < 23) { //if time is between 7pm and 10.59pm
  if (soc > 30 && acLoads < 10000) { //if state of charge is above 30%
    //return the new grid setpoint
    gridSetpoint = -Math.min(acSolar + dcSolar, 6000);
  } else {
    gridSetpoint = 0;
  }
} else {
  gridSetpoint = 0;
}

if (gridSetpoint !== global.get('gridSetpoint')) { // Check if gridSetpoint is going to change
  global.set('gridSetpoint', Math.min(gridSetpoint, 0));
  msg.payload = Math.min(gridSetpoint, 0);
  return msg;
}




At this stage the function will output a message of what to set the gridsetpoint to. However before you pass this function into the ESS gridsetpoint node (to set the grid setpoint). You should test the code works as expected on your system/there aren't any bugs in it. To do this you should pass function into a debug node like below. And watch the outputs at various times of the day. Once you're happy that the function is outputing the correct negative number at all points in the day then you can pass the function into the ESS grid setpoint node.


I've hopefully written the code so you can see what hours you need to change and SoC to get the desired times.

1712949401118.png


As i said the debug would be replaced with grid set point node once you've confirmed function 2 is outputing what you expect.


1712949401118.png (41.0 KiB)
1712949505205.png (8.9 KiB)
1712949521569.png (14.3 KiB)
1712949539491.png (36.5 KiB)
12 comments
2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

zed-must avatar image zed-must commented ·

wow, thanks so much Matt! i appreciate you doing this for free but still happy to pay you something, or if you want to nominate a charity i would be happy to make a donation on your behalf. thx again

Update: so ive got wind, pv and soc all coming through, but when you said the system would give a msg - im not sure if i have done something wrong? I put all your code into the OnStart tab of node 2 is that correct?


screenshot-2024-04-13-at-095730.png


0 Likes 0 ·
matt1309 avatar image matt1309 zed-must commented ·

Hi @zed must


Use on message not on start in function node

Msg is the message received. So you need a message to be received for msg to be defined


Let me know if you need any tweaks. But if you do as I suggest and just check it's working using debug node there's literally no harm in you playing/editing the function code to get it more features/tweaks yourself. Hopefully the layout is such that you can somewhat guess how to add extra bits if needed.


You can also go way more in depth and make graphical interfaces (dashboards) so you could make it so the time schedules and soc limits are just text boxes on a dashboard for easier input. But the above function is hopefully a good jumping off point.


This code might have issues if your solar goes offline before issuing a 0w output. the code will think it's still outputting it's last provided value.


If you have that happen regularly let me know and I can write in a timeout ie if acSolar hasnt provided a value in x seconds then assume it's off and set to 0

0 Likes 0 ·
zed-must avatar image zed-must matt1309 commented ·

hi thx again.

Working now, but when you said 'the function will output a message of what to set the gridsetpoint to', i dont see this - i only see the values for L1, PV and SOC in the debug, nothing for gridsetpoint.

screenshot-2024-04-13-at-141546.png

One tweak which would be great (which i forgot about) is to measure AC loads, and when AC loads is above a certain value e.g. 10000W then skip the whole flow, and just let the ESS manage itself normally. This is because we have one item with a very large load that is only used rarely, but when it is used we wouldnt want to send power to the grid but instead let it go to batteries.

Finally when it comes to deploying this live, im struggling to find a victron node that has grid setpoint as a measurement which i can select.

0 Likes 0 ·
matt1309 avatar image matt1309 zed-must commented ·

Hi @zed must


I suspect this is because you've added a return msg; at the top of the function, remove that and you should be good.


In regards to the 10000w scenario how long do you want the code to be disabled for. For the full time period or only when load is above 10kw?


If it's only when the load is above 10kw then you just need to repeat the steps for getting acSolar, dcSolar and soc data into the function but instead use the System node and select measurement AC Consumption and set topic in change node to something like acLoad and again pass that into function like so:


1713052949103.png


1713052966947.png



Then add this to function to near top of function:

if (msg.topic === "acLoad") {

  acLoad = msg.payload; // Extract payload from input 2

  global.set('acLoad ', acLoad);

}



And edit each of the soc if statements from this:

 if (soc > 70)

to this:

 if (soc > 70 && acLoads < 10000)


In regards to the grid setpoint node it's in ESS control node if you select Venus Settings under ESS drop down, and measurement type set to Grid set-point (W)



I've edited my original answer so you can see the full function with the 10kw change implemented in case it's easier to copy paste the full thing rather than following additions of adding the code like i describe above. Shout if it's not what you wanted.



0 Likes 0 ·
1713052949103.png (27.8 KiB)
zed-must avatar image zed-must matt1309 commented ·

absolutely super, thanks!

small issue - the grid set point node only has an output connector, not any for input - so how can i pass function 2 into it?


screenshot-2024-04-14-at-070724.png


0 Likes 0 ·
matt1309 avatar image matt1309 zed-must commented ·
There's an input node and an output node. Ess control is what in one that accepts inputs is called (at least on my version of node red)
0 Likes 0 ·
zed-must avatar image zed-must matt1309 commented ·
thx Matt, running now, so far seems to be working perfectly ) I think others would benefit from this, might be worth you posting somewhere. I have changed the post title to make it easier for others to find.
0 Likes 0 ·
matt1309 avatar image matt1309 zed-must commented ·

Hi @zed must


Glad it's working for you. Have to shout if there's any other useful features. Happy to tweak further if need.


One thing to flag is this code will have issues if any of the devices go offline and don't issue a 0 value first. ie say wind data stops being received before 0w is sent. The code won't know this has happened and still think wind is at the last value it sent. I can maybe write in a timer to reset to 0 if this is needed.

0 Likes 0 ·
zed-must avatar image zed-must matt1309 commented ·

Thanks Matt,


Once i saw it working i realised i didnt need to tell you to export only 'excess' wind and solar. All i needed was to export during the set times whenever the battery was above the set value. So i have now removed the 'math.min ac+dc' part of the code temporarily and just set the gridsetpoint = -6000 and i will see how that works. So i dont think what you say above will matter - if there is no wind or no solar or a fault there it shouldnt matter - in that scenario the batteries will drop to the low limit quicker and stop feeding back, which is exactly what i need. So all good! Thanks so much again for your help!!!

1 Like 1 ·
matt1309 avatar image matt1309 zed-must commented ·
No worries, yeh hopefully it's set out clear enough that tweaking/adding/removing bits is guessable but if not just shout.
1 Like 1 ·
Dirk-Jan Faber (Victron Energy) avatar image Dirk-Jan Faber (Victron Energy) ♦ matt1309 commented ·

FYI there is no need to explicitly store the retrieved data in the global context. You can just check the box in the configuration.

1713365046943.png

0 Likes 0 ·
1713365046943.png (59.7 KiB)
matt1309 avatar image matt1309 Dirk-Jan Faber (Victron Energy) ♦ commented ·

Thanks @Dirk-Jan Faber (Victron Energy)


I did think about using this but wasn't sure what version of venus os @zed must was using so thought writing the above was safer as would work on older versions.


I did have a question regarding the Global context. What happens in the event the data providing node goes offline? Is there a timeout implemented where global context vars go to zero of null if data isn't provided after a certain timeframe?


That was the other reason i didnt concider going the global context route, as the above code i provided could be edited to implement a timeout feature. ie a map to record when each piece of data was last received which is checked every call to see if it's been longer than 6seconds (or whatever default data send is). Is that the best way to go about solving the situation where a device goes offline before issuing 0.


Or should I be using another method to protect against that. ie if PV Inverter stops providing data. Should i build in timeout checker or is there another way to monitor node health and maybe use that instead?

0 Likes 0 ·
markus-001 avatar image
markus-001 answered ·

@zed must

Clarity needed, Your example of

If SOC > 50% and time is after 7pm send PV to grid.

Do you have PV after 7pm?

1) Are you only feeding in PV or are you wanting to feed-in stored battery energy during peak periods where the feed-in tariff is at its highest then recharge the batteries during off peak at the lowest tariff.

2) do you want to limit the maximum feed-in power.

Settting the minimum SOC through the node red dashboard is easy and you can set as many set points as you wish, I change the minimum SOC every hour to crate a slow discharge through the night to make sure I don’t deplete the battery in the first 3 hours. I then bring up the minimum SOC hourly during the day which usually lags the actual SOC on sunny days how ever on over cast days the internal battery charger initializes to charge from the grid if there is insufficient Solar on overcast mornings, after mid day when the sun is up high the actual SOC overtakes the hourly minimum SOC again, so no charging from the grid takes place.

Setting PV Feed-in at different times as well as the feed-in amount in watts is also quite easy, Discharging the batteries into the grid is also easy to do by just setting a negative grid set point which will deactivate when the minimum SOC is reached.

The problem comes in when you have to limit the maximum feed-in power from the batteries. It can be done, I have done it but the amount of writes to the GX flash memory is quite a lot, every 2 or 3 seconds you need to write a new grid set point taking into account your current load on the AC-out of the inverter, AC-in to calculate internal loses as well as include any grid loads before the inverter if you have an external energy meter who’s roll is set as grid meter



1 comment
2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

zed-must avatar image zed-must commented ·
Thanks Markus but i think i have got a solution now from Matt above
0 Likes 0 ·