ESS limit (dis)charge power in watts

Hi everyone,

I have an ESS setup with a MultiPlus-II 48/5000 GX with a single 16kWh battery on a single phase, connected to a 3-phase grid supply. To protect my main fuses from overloading, I would like to manage my charge and discharge wattage using Node-Red.

For grid metering i am using a VM3P75CT, and a second one for PV metering.

For discharging, I am currently using the “Max Inverter Power (W)” setting. I can see this reflected in my menu, and it works perfectly.

For charging, I would like to control the inverter in the same manner, but I cannot find a corresponding setting in the menu. However, in Node-Red, I see a setting called “Max Charge Power (W)”, but it currently shows a value of -1.

My questions are:

  • Can I use this “Max Charge Power (W)” value to set a charging limit for the inverter?

  • Will the system ignore this value, or could it cause unexpected behavior?

  • Alternatively, is there anyone else managing charge/discharge power in a different way who would be willing to share their method?

Thanks in advance!

You can set a AC input current limit in ve configure for the multiplus

will it also affect output?

It will limit current from grid, not inverter output

So the multi can still invert 4000w cont and will add that to whatever max AC input limit you set

Charging will be whatever you set it and will not exceed AC input limit

You can use DVCC to reduce the charge current, and adjust it up or down depending on the available AC input current. A 16 kWh battery is relatively small for the MultiPlus 70 A charge capability. Charging at around 30–40 A would be more comfortable, allowing the battery to recharge from 20% SOC over roughly 8 hours.

Charging at 70 A would reduce the charge time to approximately 3.5–4 hours, but this higher rate is more likely to cause unnecessary battery heating.

If you need any help let me know.

Hi Owen, thanks for your support.

Charging a 314ah battery at 70A is on the high side?
The manual states it can be charged at 157A continuous (0,5C), 70A sounds to me like being kind to it.

Most of the time it will be charged with less power, as most of charging will be excess solar power out of a AC coupled 3750wp solar system, but DESS will also charge from the grid and i assume that will be at max power?

But do you know if i can set de Max Charge Power (W) parameter with a Red Node flow without causing unexpected behaviour?
That would be the easiest way to control the charging power by setting a maximum grid L1 wattage and lower that with de L1 loads.

Hi Marc,

Thanks for helping.

I don’t think it will limit current from grid metered by de VM3P75CT but only what is going in tot de MP.
Will it limit the inverter both ways?

In that case it would do the job by setting it to 25 lowered by the AC Loads current, possibly maximized to lets say 15-16A for ~3500 watts.

I have three battery packs and a 450/100 MPPT. They normally charge at around 30 A each, but they can peak at up to 60 A when they get close to full and one battery stops accepting charge. When the batteries are fully charged, battery temperature can reach close to 40 °C.

I use an air conditioner to cool the battery space when it gets too hot, which I control using Node-RED. Once heat builds up, it tends to stay there for hours. The batteries also generate heat while discharging, not just during charging. Being able to monitor battery temperature makes it much easier to choose a safe maximum charge current.

You can also do some simple maths in Node-RED to manage DVCC. For example, at the maximum charge current of 70 A on a 48 V system:

70 A × 48 V = 3360 W of charging power

If the AC output load is 5000 W, the total power required is:

5000 W (load) + 3360 W (charging) = 8360 W

At 230 V AC, that equates to:

8360 W ÷ 230 V ≈ 36 A AC input

This exceeds a 32 A AC input limit, so in this case DVCC needs to be reduced to prevent overloading the AC supply. By dynamically lowering the charge current based on AC load (and battery temperature), you can ensure the loads are fully supplied while only using the remaining AC capacity for battery charging.

Step 1: Define the limits

AC input limit: 32 A @ 230 V

Max AC input power:
32 A × 230 V ≈ 7360 W

Step 2: Account for the load

AC output load: 5000 W

Remaining power available for charging:

7360 W − 5000 W = 2360 W

Step 3: Convert remaining power to DVCC charge current

At 48 V battery:

2360 W ÷ 48 V ≈ 49 A

Allowing for inverter/charger losses, a safe DVCC limit would be:

~45 A

To get everything accurate you can use actual AC voltage and battery voltage.

I have a pic of my battery charging with current temps.

Exactly, it will limit grid input in multiplus

For feeding back to grid you can set a pv feed in limit

@owenb79 @DuivertNL
Hi Marc and Owen, Thanks for the help.

I’ve decided to limit my ESS charge and discharge power via the AC Input Current Limit.

I will share my flow below for the community. I’m open to suggestions for improvement, and if anyone wants to use this for their own system, feel free to do so!

In short: the flow monitors the DC current to determine whether the battery is charging, discharging, or in an idle state.

  • Idle: The limit is set to 10 amps.
  • Charging: The flow ensures the phase load does not exceed 23 amps by setting the input current limit to 23 minus the AC load current on that phase.
  • Discharging: To prevent backfeeding more than 15 amps into the phase, the PV generation on that phase is subtracted from the discharge current.

The final value is capped at a maximum of 16 (16 * 230 = 3680 watts) and a minimum of 2 (2 * 230 = 460 watts).

The calculation is made every 5 seconds.

Inputs:

  • Venus System AC Consumption L1 (W)
  • Grid Meter L1 Voltage (V) (for calculation AC Consumption amps W/V=A)
  • VE Bus Battery current (A)
  • PV System L1 Current (A)

Output:

  • VE Bus Active input current limit (A)

The inject node is for simulation purpose.

[
    {
        "id": "58d39409c2a6a6ca",
        "type": "tab",
        "label": "Dynamic AC Current Limit",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "60d587c92f4da21b",
        "type": "victron-input-vebus",
        "z": "58d39409c2a6a6ca",
        "service": "com.victronenergy.vebus/275",
        "path": "/Dc/0/Current",
        "serviceObj": {
            "service": "com.victronenergy.vebus/275",
            "name": "Omvormer"
        },
        "pathObj": {
            "path": "/Dc/0/Current",
            "type": "float",
            "name": "Battery current (A)"
        },
        "name": "",
        "onlyChanges": false,
        "roundValues": "1",
        "x": 150,
        "y": 120,
        "wires": [
            [
                "37b84e68de93f20c"
            ]
        ]
    },
    {
        "id": "c81532203f154cc1",
        "type": "victron-input-pvinverter",
        "z": "58d39409c2a6a6ca",
        "service": "com.victronenergy.pvinverter/40",
        "path": "/Ac/L1/Current",
        "serviceObj": {
            "service": "com.victronenergy.pvinverter/40",
            "name": "PV meter"
        },
        "pathObj": {
            "path": "/Ac/L1/Current",
            "type": "float",
            "name": "L1 Current (A)"
        },
        "name": "",
        "onlyChanges": false,
        "roundValues": "0",
        "x": 130,
        "y": 180,
        "wires": [
            [
                "37b84e68de93f20c"
            ]
        ]
    },
    {
        "id": "6ac9493f2ba19699",
        "type": "victron-input-gridmeter",
        "z": "58d39409c2a6a6ca",
        "service": "com.victronenergy.grid/41",
        "path": "/Ac/L1/Voltage",
        "serviceObj": {
            "service": "com.victronenergy.grid/41",
            "name": "Grid meter"
        },
        "pathObj": {
            "path": "/Ac/L1/Voltage",
            "type": "float",
            "name": "L1 Voltage (V)"
        },
        "name": "",
        "onlyChanges": false,
        "roundValues": "0",
        "x": 130,
        "y": 240,
        "wires": [
            [
                "37b84e68de93f20c"
            ]
        ]
    },
    {
        "id": "6550d2fa210262a7",
        "type": "victron-input-system",
        "z": "58d39409c2a6a6ca",
        "service": "com.victronenergy.system/0",
        "path": "/Ac/Consumption/L1/Power",
        "serviceObj": {
            "service": "com.victronenergy.system/0",
            "name": "Venus system"
        },
        "pathObj": {
            "path": "/Ac/Consumption/L1/Power",
            "type": "float",
            "name": "AC Consumption L1 (W)"
        },
        "name": "",
        "onlyChanges": false,
        "x": 170,
        "y": 60,
        "wires": [
            [
                "37b84e68de93f20c"
            ]
        ]
    },
    {
        "id": "37b84e68de93f20c",
        "type": "join",
        "z": "58d39409c2a6a6ca",
        "name": "",
        "mode": "custom",
        "build": "object",
        "property": "payload",
        "propertyType": "msg",
        "key": "topic",
        "joiner": "\\n",
        "joinerType": "str",
        "accumulate": true,
        "timeout": "",
        "count": "4",
        "reduceRight": false,
        "reduceExp": "",
        "reduceInit": "",
        "reduceInitType": "num",
        "reduceFixup": "",
        "x": 430,
        "y": 60,
        "wires": [
            [
                "cafb7e1810614f21"
            ]
        ]
    },
    {
        "id": "cafb7e1810614f21",
        "type": "delay",
        "z": "58d39409c2a6a6ca",
        "name": "",
        "pauseType": "rate",
        "timeout": "5",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "5",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": true,
        "allowrate": false,
        "outputs": 1,
        "x": 600,
        "y": 60,
        "wires": [
            [
                "f7d8d8fc9052fb8b",
                "4c282319399309d4"
            ]
        ]
    },
    {
        "id": "f7d8d8fc9052fb8b",
        "type": "debug",
        "z": "58d39409c2a6a6ca",
        "name": "debug data",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 810,
        "y": 60,
        "wires": []
    },
    {
        "id": "80486658c1238500",
        "type": "victron-output-vebus",
        "z": "58d39409c2a6a6ca",
        "service": "com.victronenergy.vebus/275",
        "path": "/Ac/ActiveIn/CurrentLimit",
        "serviceObj": {
            "service": "com.victronenergy.vebus/275",
            "name": "Omvormer"
        },
        "pathObj": {
            "path": "/Ac/ActiveIn/CurrentLimit",
            "type": "float",
            "name": "Active input current limit (A)",
            "mode": "both"
        },
        "name": "",
        "onlyChanges": false,
        "x": 820,
        "y": 160,
        "wires": []
    },
    {
        "id": "4c282319399309d4",
        "type": "function",
        "z": "58d39409c2a6a6ca",
        "name": "function 2",
        "func": "// 1. Waarden ophalen\nconst pvCurrent = msg.payload[\"PV meter - L1 Current (A)\"] || 0;\nconst acConsumptionW = msg.payload[\"Venus system - AC Consumption L1 (W)\"] || 0;\nconst gridVoltage = msg.payload[\"Grid meter - L1 Voltage (V)\"] || 235;\nconst batteryCurrent = msg.payload[\"Omvormer - Battery current (A)\"] || 0;\n\n// Onthoud de vorige status in het geheugen van de node\nlet lastStatus = context.get('lastStatus') || \"rust\"; \nlet currentStatus = lastStatus;\n\n// 2. Hysteresis logica voor statusbepaling\nif (batteryCurrent < -0.5) {\n    currentStatus = \"ontladen\";\n} else if (batteryCurrent > 0.5) {\n    currentStatus = \"laden\";\n} else if (batteryCurrent >= -0.3 && batteryCurrent <= 0.3) {\n    // Keer pas echt terug naar rust als hij heel dicht bij 0 is\n    currentStatus = \"rust\";\n}\n\ncontext.set('lastStatus', currentStatus);\n\n// 3. Berekening op basis van de vastgestelde status\nconst L1LoadsAmpere = acConsumptionW / gridVoltage;\nlet result;\n\nif (currentStatus === \"ontladen\") {\n    result = 15 - pvCurrent + L1LoadsAmpere;\n} else if (currentStatus === \"laden\") {\n    result = 23 - L1LoadsAmpere;\n} else {\n    // Rust status\n    result = 10;\n}\n\n// 4. Begrenzen en afronden\nif (result > 16) result = 16;\nif (result < 2) result = 2;\n\nmsg.payload = Number(result.toFixed(1));\n\n// Extra: voeg status toe aan msg voor debuggen\nmsg.status_debug = currentStatus;\n\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 560,
        "y": 160,
        "wires": [
            [
                "9ab3f85a79e84ba6",
                "80486658c1238500"
            ]
        ]
    },
    {
        "id": "9ab3f85a79e84ba6",
        "type": "debug",
        "z": "58d39409c2a6a6ca",
        "name": "debug output",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 810,
        "y": 100,
        "wires": []
    },
    {
        "id": "b7da306fc992d212",
        "type": "inject",
        "z": "58d39409c2a6a6ca",
        "name": "Inject data",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "{\"Venus system - AC Consumption L1 (W)\":200,\"Grid meter - L1 Voltage (V)\":240,\"PV meter - L1 Current (A)\":10,\"Omvormer - Battery current (A)\":100}",
        "payloadType": "json",
        "x": 400,
        "y": 160,
        "wires": [
            [
                "4c282319399309d4"
            ]
        ]
    }
]