Oké installing.
Confirmed
Before:
After:
I installed a custom peak shave logic that limits the sum of the 3 phases using a new virtual switch. Idea is to set a desired peak shave wattage, and the logic will convert this to amps and set this. By default it will set this for each phase. But if you surpass the set wattage it will lower the peak shave to spread the allowed wattage over all phases
[
{
"id": "60c13cd86d711ebe",
"type": "tab",
"label": "Peak Shave Optimize",
"disabled": false,
"info": "",
"env": []
},
{
"id": "16b31c57d1131c9f",
"type": "group",
"z": "60c13cd86d711ebe",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"1c5d0768146dc6c6",
"9bfafca68a2faa99",
"023d8e0145686e5b",
"81e78fc8734de095",
"37a1d098e1535fbf",
"9ff4c90b24da6bd7",
"2d84a0450fcb5637",
"337a3da64248bfe2",
"a0472456618f6478"
],
"x": 24,
"y": 39,
"w": 1242,
"h": 202
},
{
"id": "1c5d0768146dc6c6",
"type": "victron-input-gridmeter",
"z": "60c13cd86d711ebe",
"g": "16b31c57d1131c9f",
"service": "com.victronenergy.grid/0",
"path": "/Ac/Power",
"serviceObj": {
"service": "com.victronenergy.grid/0",
"name": "Fluvius GRID",
"communityTag": "gridmeter"
},
"pathObj": {
"path": "/Ac/Power",
"type": "float",
"name": "Power (W)"
},
"name": "Grid Power",
"onlyChanges": true,
"roundValues": "0",
"rateLimit": "2",
"outputs": 1,
"conditionalMode": false,
"outputTrue": "",
"outputFalse": "",
"debounce": "",
"x": 120,
"y": 80,
"wires": [
[
"9ff4c90b24da6bd7"
]
]
},
{
"id": "9bfafca68a2faa99",
"type": "change",
"z": "60c13cd86d711ebe",
"g": "16b31c57d1131c9f",
"name": "",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "notification",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 940,
"y": 140,
"wires": [
[
"2d84a0450fcb5637"
]
]
},
{
"id": "023d8e0145686e5b",
"type": "function",
"z": "60c13cd86d711ebe",
"g": "16b31c57d1131c9f",
"name": "PeakShave Controller",
"func": "// --- CONFIGURATIE ---\nconst MAX_SAMPLES = 20;\nconst MIN_HIGH_TIME_MS = 1*60*1000;\nconst MAX_VALUE = 25\nconst MIN_VALUE = 5\n\n// --- INPUT VERWERKING ---\nlet currentLimit = Number(msg.payload[\"AC input current limit\"]);\nlet inputPower = parseFloat(msg.payload[\"Grid Power\"]);\nlet lastSwitchTime = context.get('lastSwitchTime') || 0;\nlet now = Date.now();\n\nlet highThreshold = Number(msg.payload[\"PeakShave/value\"]) || 3000;\nlet lowThreshold = highThreshold - 200;\nlet highValue = Math.round(Math.min(MAX_VALUE,highThreshold/230));\nlet lowValue = Math.round(Math.max(MIN_VALUE,highThreshold/230/3));\n\nif (isNaN(inputPower) || isNaN(currentLimit)) return null; // Stop als input geen getal is\n\n// --- GEEN VERTRAGING VIRTUAL SWITCH ---\nif (msg.topic === \"PeakShave/value\") {\n lastSwitchTime = now - MIN_HIGH_TIME_MS;\n context.set('lastSwitchTime', lastSwitchTime);\n}\n\n// --- BUFFER LOGICA ---\nlet buffer = context.get('buffer') || [];\nbuffer.push(inputPower);\nif (buffer.length > MAX_SAMPLES) buffer.shift(); \n//if (buffer.length < 3) return null;\n\n// --- GEMIDDELDE BEREKENEN ---\nlet sum = buffer.reduce((a, b) => a + b, 0);\nlet avg = sum / buffer.length;\ncontext.set('buffer', buffer);\n\n// Deadband (optioneel, zet hele kleine waardes op 0)\nif (Math.abs(avg) < 50) avg = 0;\n\n// --- SCHAKEL LOGICA ---\nlet newPayload = null; \nlet notifyText = \"\";\n\nif (avg >= highThreshold ) {\n newPayload = lowValue;\n notifyText = `High load: ${avg.toFixed(0)}W. Switched to ${newPayload}A.`;\n} else if (avg <= lowThreshold) {\n let elapsed = now - lastSwitchTime;\n if (elapsed > MIN_HIGH_TIME_MS) {\n newPayload = highValue;\n notifyText = `Current load: ${avg.toFixed(0)}W. Restoring to ${newPayload}A.`;\n }\n}\n\n// --- OUTPUT BEPALEN ---\nif (newPayload === currentLimit || newPayload === null) return null;\n\n// Er is een actie nodig (schakelen naar 5A of 10A)\ncontext.set('lastSwitchTime', now);\nmsg.payload = newPayload;\nmsg.type = \"info\";\nmsg.notification = notifyText;\nreturn msg; \n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 700,
"y": 80,
"wires": [
[
"9bfafca68a2faa99",
"81e78fc8734de095"
]
]
},
{
"id": "81e78fc8734de095",
"type": "victron-output-settings",
"z": "60c13cd86d711ebe",
"g": "16b31c57d1131c9f",
"service": "com.victronenergy.settings",
"path": "/Settings/CGwacs/AcInputLimit",
"serviceObj": {
"service": "com.victronenergy.settings",
"name": "Venus settings",
"communityTag": "settings"
},
"pathObj": {
"path": "/Settings/CGwacs/AcInputLimit",
"type": "float",
"name": "AC input current limit (A)",
"mode": "both"
},
"name": "",
"onlyChanges": false,
"outputs": 0,
"x": 1080,
"y": 80,
"wires": []
},
{
"id": "37a1d098e1535fbf",
"type": "victron-input-settings",
"z": "60c13cd86d711ebe",
"g": "16b31c57d1131c9f",
"service": "com.victronenergy.settings",
"path": "/Settings/CGwacs/AcInputLimit",
"serviceObj": {
"service": "com.victronenergy.settings",
"name": "Venus settings"
},
"pathObj": {
"path": "/Settings/CGwacs/AcInputLimit",
"type": "float",
"name": "AC input current limit (A)",
"mode": "both"
},
"name": "AC input current limit",
"onlyChanges": true,
"roundValues": "0",
"outputs": 1,
"x": 150,
"y": 140,
"wires": [
[
"9ff4c90b24da6bd7"
]
]
},
{
"id": "9ff4c90b24da6bd7",
"type": "join",
"z": "60c13cd86d711ebe",
"g": "16b31c57d1131c9f",
"name": "Merge input",
"mode": "custom",
"build": "object",
"property": "payload",
"propertyType": "msg",
"key": "topic",
"joiner": "\\n",
"joinerType": "str",
"useparts": true,
"accumulate": true,
"timeout": "",
"count": "3",
"reduceRight": false,
"reduceExp": "",
"reduceInit": "",
"reduceInitType": "num",
"reduceFixup": "",
"x": 480,
"y": 80,
"wires": [
[
"023d8e0145686e5b"
]
]
},
{
"id": "2d84a0450fcb5637",
"type": "victron-inject",
"z": "60c13cd86d711ebe",
"g": "16b31c57d1131c9f",
"name": "",
"notificationType": 2,
"notificationTitle": "PeakShave Controller",
"x": 1150,
"y": 140,
"wires": [
[]
]
},
{
"id": "337a3da64248bfe2",
"type": "victron-virtual-switch",
"z": "60c13cd86d711ebe",
"g": "16b31c57d1131c9f",
"name": "PeakShave",
"outputs": 2,
"switch_1_type": 7,
"switch_1_min": "2500",
"switch_1_max": "9000",
"switch_1_initial": 0,
"switch_1_label": "",
"switch_1_unit": "W",
"switch_1_step": 250,
"switch_1_customname": "Dynamic Peak Shave",
"switch_1_group": "Logic",
"switch_1_include_measurement": false,
"switch_1_rgb_color_wheel": false,
"switch_1_cct_wheel": false,
"switch_1_rgb_white_dimmer": false,
"x": 310,
"y": 200,
"wires": [
[],
[
"9ff4c90b24da6bd7"
]
]
},
{
"id": "a0472456618f6478",
"type": "inject",
"z": "60c13cd86d711ebe",
"g": "16b31c57d1131c9f",
"name": "Button init",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": "0",
"topic": "",
"payload": "{\"/SwitchableOutput/output_1/Dimming\":3000}",
"payloadType": "json",
"x": 150,
"y": 200,
"wires": [
[
"337a3da64248bfe2"
]
]
},
{
"id": "0fbd43d364b7ba76",
"type": "global-config",
"env": [],
"modules": {
"@victronenergy/node-red-contrib-victron": "1.6.63"
}
}
]