question

tailele avatar image
tailele asked

Node red relay configuration support

Sorry for the question definitely in a forum of red node experts, maybe it's not the best thing.

In any case I try anyway, I would have a goal, which would be to use the surplus energy from my photovoltaic system to heat a water storage tank.

Currently my system consists of a multiplus GX, a 450/200 and two home-built Daly BMS batteries. I have set the CAN communication correctly, so through the GX system, you can correctly see the battery soc, the charging current, the discharging current, the cell with the highest, lowest voltage etc.

Currently I would like to enable the two auxiliary relays so that when the battery is 100% charged the Aux 1 relay closes, and when there is no absorption from the battery the aux 2 relay closes. As soon as the system notices an energy withdrawal, the aux 2 relay must open just as if the battery drops to 98%, the aux 1 relay must open.

I would need this because I would like to combine a Raspberry which, when it sees the two relays closed, injects the surplus power gradually to a resistor, then starts with a 500W ramp, with 200W steps increasing, up to a maximum of 3kW (which corresponds to the total power of the resistor), as soon as relay 2 opens, the Raspberry understands that the solar power is not sufficient and decreases the power in steps of 500W until the relay closes again.

I would ask you if anyone could kindly help me understand:

1- if it is possible to do it without node red

2- if not, could you guide me in configuring the workflow


I thank you infinitely

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.

4 Answers
tailele avatar image
tailele answered ·

Good morning, as I said I'm new to the red node mod, I tried to write a quick code to close the relays depending on the conditions I had thought of. I'd like to share it and get your opinion. Let me start by saying, I don't know if it works, I'm monitoring the status of the relays to see if when the set conditions are reached, they work as I think

1712821214685.png

Function for activation relay 1 code:

// Function node to control relay 1 based on SOC status


// Read the SOC status from the received message

var soc = msg.payload;


// Check if the SOC status is 100%

if (soc === 100) {

// If the SOC status is 100% and relay 1 is open (assuming relay 1 is represented by a boolean variable relay1_open)

if (context.get('relay1_open') === true) {

// Send a command to close relay 1 (assuming the command to close relay 1 is sent via a boolean variable relay1_command)

context.set('relay1_command', false);

msg.payload = "Closing relay 1";

return msg;

}

} else if (soc < 95) {

// If the SOC status has dropped below 95%, send a command to open relay 1

// Make sure to set relay1_command to true to open relay 1

context.set('relay1_command', true);

msg.payload = "Opening relay 1";

return msg;

}


// If none of the above conditions are met, do nothing

return null;


Function for activation relay 2 code:

// Function node to control relay 2 based on the state of relay 1 and battery discharge


// Read the state of relay 1 from context

var relay1_closed = context.get('relay1_closed');


// Read the battery discharge state from the received message

var battery_discharging = msg.payload;


// Check if relay 1 is closed and there is no battery discharge

if (relay1_closed === true && battery_discharging === false) {

// If relay 1 is closed and there is no battery discharge, send a command to close relay 2

// Make sure to set relay2_command to true to close relay 2

context.set('relay2_command', true);

msg.payload = "Closing relay 2";

return msg;

} else {

// If relay 1 is open or there is battery discharge, send a command to open relay 2

// Make sure to set relay2_command to false to open relay 2

context.set('relay2_command', false);

msg.payload = "Opening relay 2";

return msg;

}


Thanks for support


1712821214685.png (29.3 KiB)
2 |3000

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

tailele avatar image
tailele answered ·

sorry, the initialization of the variables was missing. I added it. In any case, the state of the relay does not change. Obviously I'm getting the truth wrong....


context.set('relay_state', 0); // Set the initial state of the relay to 0 (open)

context.set('relay1_closed', false); // Set the initial state of relay 1 to open

context.set('relay2_command', false); // Set the initial state of the command for relay 2 to false

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.

matt1309 avatar image
matt1309 answered ·

Looks cool. I prefer using shelly smart switches with http node for the same task so then i dont need to have my water heater close to the relays (as shelly switches are activated via via lan/wifi), but your code would have been the same if you did that anyway

2 |3000

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

tailele avatar image
tailele answered ·

Ees it will be cool, but at the moment it doesn't work.... and i don't understand why!!!

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 @Tailele


You could simplify and do if (absorption phase) then relay 1 on

if float phase then relay 2 on?

Using SoC might not be perfect if you're battery isnt 100% synced. Therefore checking what phase you're in might be better.


I did try read through to try spot errors.

You already spotted the one where you are trying to context.get varibales that you havent yet set. However could you not combine relay1_open, relay_command and relay1_closed all into the one variable? Why have you got seperate ones? Might make code simpler to combine.



The other one i spotted was:

var battery_discharging = msg.payload;

isnt the msg.payload in this case current in amps.

but you've done:

if( battery_discharging === false)


isnt battery_discharging going to be a float not a bool?

so you've want (battery_discharging < x amps)


Just out of curiosity is there a reason you went with using context vars to "send command" rather than returning messages and that flowing into a node that enables/disables relays?

0 Likes 0 ·
tailele avatar image tailele matt1309 commented ·

Hi Matt, I actually had the SOC set to 100% because in some cases, if the battery is low, I have no absorption, so I wanted to remove this possibility of misunderstanding. For the rest I'm honest, I used some gpt chat suggestions, trying independently to find the variables to insert into the program. But there is something that doesn't add up as the states of the relays always remain at 1, they don't switch to 0. I don't understand why.

0 Likes 0 ·
matt1309 avatar image matt1309 tailele commented ·

HI @Tailele


When you say the relay stays at 1 what are you looking at when you say that? As in what variable, is it relay1_open, relay1_closed, or relay1_command? I can have a look through and check if i can spot why the variable you're looking at isnt swapping to 0.

0 Likes 0 ·
matt1309 avatar image matt1309 matt1309 commented ·

I would do something like this:



var soc = msg.payload;
// Check if the SOC status is 100%

if (soc === 100 && global.get('relay1') === 1) {
// If the SOC status is 100% and relay 1 is open

//setting context var for relay 1 to 1 and returning msg 1 to close relay. 
global.set('relay1', 1);
msg.payload = 1;
return msg

} else if (soc < 95 && global.get('relay1') != 0 ) {
// If the SOC status has dropped below 95% and relay1 isn't already open. 

//setting context var for relay 1 and returning msg to open relay1
global.set('relay1', 0);
msg.payload = 0;

return msg;

}else{

//put some code here to take care of the case between 95 and 100%

}


//no need to return anything otherwise.


Output of function 1 goes into a node that activates relay if it receives 1 and deactivates (open relay if receives 0).



Function 2:

var relay1 = global.get('relay1');



// Read the battery discharge state from the received message

var battery_discharging = msg.payload;



// Check if relay 1 is closed and there is no battery discharge

if (relay1 === 1 && battery_discharging < 0){

global.set('relay2', 1);
msg.payload = 1;
return msg;

} else {
// If relay 1 is open or there is battery discharge, send a command to open relay 2

// Make sure to set relay2_command to false to open relay 2

global.set('relay2', 0);
msg.payload = 0
return msg;

}



Output of function 2 goes into a node that activates relay2 if it receives 1 and deactivates (open relay if receives 0).

0 Likes 0 ·