question

larsea-dk avatar image
larsea-dk asked

Help with "not always working" NodeRed code

Hi

to control my feedin to the battery, I have a code tweaking the Setpoint made by help from some guys from Germany a while ago.

Due to sometimes we need to pay for delivering to the net at full battery, I have tried to make a code that reset this tweak simply by setting the setpoint to 0 if the price is too low.

Id to though not always work and the input to the code from Nordpool gives the corrct input for the code to work.

Any inputs why it seems not always to work?

1714304153042.png

Thank you very much :-)

battery chargingNode-REDfeed-in limit
1714304153042.png (11.6 KiB)
4 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.

matt1309 avatar image matt1309 commented ·
HI @larsea-dk


Do you mind sharing how you're defining the variables? Is there a chance that sometimes one of the var's is undefined when the code is running. Which is causing the inconsistent outcome.

0 Likes 0 ·
larsea-dk avatar image larsea-dk matt1309 commented ·

Yes it can be the case and I'm not that good in Node Red, so might be doe wrong. I keep it very basic and do not keep it that compact, so I have a chance of editing it later.

1714422437076.png

0 Likes 0 ·
1714422437076.png (43.3 KiB)
matt1309 avatar image matt1309 larsea-dk commented ·

Hi @larsea-dk


Here's my guess. So your setup is you have multiple data nodes populating msg and you use change nodes to assign them a key?

That should work fine however what happens if the data node for BAT isnt populated at the same time as Shunt v for example.


If Shunt V node sends data, this then flows into the function, however BAT node hasn't send data yet but the function is running as soon as it receives a message from SHunt V? So BAT is undefined and SHunt V isn't. This is my guess for why you're code is running inconsistently, sometimes the variables are undefined.


The fix I'd use is something like this but for all variables:

Essentially if variable is undefined you have to get the contents from somewhere. ie the last value that's available so i store in global context.

and write to global context when updating it.

var soc = global.get('soc');
var acSolar = global.get('acSolar');

 
//setting soc variable depending on inputs from flows
if (msg.payload['soc'] !== undefined) {
  soc = msg.payload['soc']; // Extract payload from input 1
  global.set('soc', soc);
}
 
if (msg.payload['acSolar'] !== undefined) {
  acSolar = msg.payload['acSolar']; // Extract payload from input 2
  global.set('acSolar', acSolar);
}
 


However if you're using newer version of venus of you dont need to use msg at all as victron node data is stored in global context. More on that approach here:

Node-RED - update for Victron users - Victron Energy




0 Likes 0 ·
larsea-dk avatar image larsea-dk matt1309 commented ·
Thank you for fast feedback. I have checked a bit during the day today and it seems like it work as intended in case the battery is full. I'm not sure if this makes sense.

I also think the value might be lost...I have a Debug running and here the value for infeed activated or not activated to not always show. So I think you have a point!

1 Like 1 ·
1 Answer
matt1309 avatar image
matt1309 answered ·

In addition to my comment I thought it might be useful to share some code i wrote for someone awhile back doing something similar but using time criteria as well as ac and dc solar: My guess is the reading last available value from global is the bit that's causing your issues as this prevents vars being undefined.


As noted in comment you can read victron data directly from global context in more recently versions of venus os (I've put link for more details on that in the comment reply above)


//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;
}
2 |3000

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