Solar battery control via Node-RED - Gladys

You are an expert? You have been using Gladys for a long time? In that case, do not hesitate: move along, there is nothing to see here, thank you for your visit :wink:

You are a beginner? Terms like « energy », « power », « watt », etc. mean nothing to you? Then come closer, enter, take a look. Thank you very much for coming :slight_smile:

Prerequisites:

1. Controllable battery

2. Updated information on your electricity consumption recorded on the meter

3. Node-RED

4. Gladys

The flow described below consists of three parts. The first part allows you to determine the current electricity consumption at your meter. This data is then used to force a discharge of the battery of a balcony power plant. The third part then generates additional information for the loop or flow. Note: here we only use the battery, without solar panels or cabling… Ideal for a rented apartment or if you don’t want to install cable ducts or dig.

Part 1:

To query the electricity meter, a product from the company Wattwächter is used. This IR head is attached to the electricity provider’s meter and provides the current consumption on the network at any time. One of the advantages is the possibility to query the meter via MQTT or Modbus.

What matters to you is simply that at the end of this first part, you get the current consumption of your meter in watts. The product you use for this is of no importance. The battery manufacturer indicates the approved products, but if you already have another product, you are in the right place.

So replace this part, if necessary, with your own technical solutions.

Structure:

Injection node: start of the flow. Debug output in the form of date and time to check which time is used.

Modbus query of the IR head from the company Wattwächter: Unit ID: 1, FC3 read holding register at address 40088, quantity 1

Value processing function:

// ********************************************

let payload = msg.payload;

let wert = 0;

if (payload && payload.data && Array.isArray(payload.data) && payload.data.length > 0) {

wert = payload.data\[0\];

}

// int16 correction for negative values (feed-in)

if (wert > 32767) {

wert = wert - 65536;

}

// Save value in flow context

flow.set(« Hausuebergabepunkt », wert);

// IMPORTANT: We trigger the calculation here directly as soon as a new meter value comes in

msg.payload = wert;

return msg;

// *******************************************************

The line « flow.set("Point de transfert domestique", value) » is crucial: the value in watts currently obtained is stored in the flow for later use.

At the end of the first part of the flow, the current battery level is also queried in percentage. This value is important to avoid deep discharge of the battery:

Modbus query of the battery: Unit ID: 1, FC3 Reading holding register, register 37612, quantity 1

Then the flow goes through a switch. This allows you to determine whether the processing continues or stops.

Variant A:

The battery is already discharged. The switch node then returns the remote control to the smartphone app of the manufacturer Solakon using the following function:

// ********************************************

// msg.payload to return control to the smartphone app

msg.payload = {

    value:\[0\],       // 0 deactivates the remote mode

    fc: 16,            // Describe holding registers

    unitid: 1,         // Modbus ID of your Solakon ONE

    address: 46001,    // Starting address

    quantity: 1        // Only describe this one register

};

// 4. Forward message to the Modbus node

return msg;

// *********************************************************

The value of msg.payload is then simply passed on using a modbus-flex-write node.

Variant B:

The process continues: if the battery still has more than 12%, for example, the flow moves on to the next step.

We generate the necessary information using a function.

// *************************************************************

// 1. Get values from memory

let netzBezug = flow.get(« Hausuebergabepunkt ») || 0;

// Gets the value that your updated battery function stores

let aktuelleEntladung = flow.get(« AktuelleBatterieEntladung »);

// If Node-RED just starts and the memory is empty,

// we take 100W as a safe starting value

if (aktuelleEntladung === undefined || aktuelleEntladung === null) {

aktuelleEntladung = 100;

}

// 2. Calculate the REAL house consumption (meter reading + current discharge power)

let echterHausverbrauch = netzBezug + aktuelleEntladung;

// 3. Set target value for the battery (corresponds to the real consumption)

let targetPower = echterHausverbrauch;

// 4. Observe safety limits (0 to a maximum of 800 watts)

targetPower = Math.round(targetPower);

if (targetPower < 0) {

targetPower = 0;

}

if (targetPower > 800) {

targetPower = 800;

}

// 5. 32-bit split for the Solakon Modbus register (I32 Big Endian)

const powerHigh = (targetPower >> 16) & 0xFFFF;

const powerLow = targetPower & 0xFFFF;

// Prepare msg.payload for the Modbus Flex-Write Node

msg.payload = {

value: \[5, 240, powerHigh, powerLow\], // 5 = Discharge mode

fc: 16,                        

unitid: 1,                    

address: 46001,                

quantity: 4                    

};

return msg;

// ******************************************************************

We simply send this information to the battery via a Modbus Flex-Write command.

That’s it…

We queried the product from the company Wattwächter for the current electricity consumption, retrieved the current state of the battery, calculated the necessary discharge from this data and sent this calculation to the battery.

But:

It is a cycle, i.e. the flow is actually only finished when we end it or the battery is empty, so:

We wait 5 seconds using a « delay » node so that the battery can record the values.

Then we query the battery again via Modbus:

Unit ID: 1, FC3 Reading Holding Register, register 39134, quantity 2

Then we use another function to integrate the new values into the loop.

Name on the image: « Battery status »

Function:

//****************************************************

if (!msg.payload || !msg.payload.buffer) {

node.error("Error: No buffer found in msg.payload.");

return null;

}

const buf = msg.payload.buffer;

const rawValue = buf.readInt32BE(0);

// Conversion exactly like the working « anlage »-node

let wert = rawValue / 1000;

wert = Math.round(wert * 1000);

wert = wert * -1; // Makes the value negative for display (e.g. -239)

// For display in the dashboard / debug (now correctly displayed!)

msg.payload = wert;

msg.topic = « solakon/status/batterie »;

// IMPORTANT: For our control calculation we need the value POSITIVE in memory

// Math.abs(-239) makes it +239 watts

flow.set(« AktuelleBatterieEntladung », Math.abs(wert));

return msg;

// ********************************************************

We then wait for 2 minutes, after which the cycle starts again from the beginning.

In other words, after two minutes, the power controller is queried again and the new data is finally recalculated in the « Forced Discharge » function, then sent to the battery.

Here is the complete cycle with the corresponding debug outputs:

This is the first part of the tutorial. In the next part, we will discuss the automatic recharging of the battery at times we have defined (for example, within the context of dynamic electricity rates or similar; another photovoltaic installation could also be considered); we will also explain how, based on the wattage information from the battery or the home connection point, to set up an accurate energy monitoring system for Gladys.

Until then,

Happy exploring

Best regards

Thomas

3 Likes