ESS Mode 3 timeout behaviour does not match documentation (10s vs 60s)

Hi,

I was able to reproduce this behaviour very easily with a simple Node-RED test setup with Firmware 3.72.

[
    {
        "id": "4ce31719083f99a9",
        "type": "tab",
        "label": "Testflow Victron Speichersteuerung",
        "disabled": true,
        "info": "",
        "env": []
    },
    {
        "id": "39370198213c14f8",
        "type": "inject",
        "z": "4ce31719083f99a9",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "30",
        "crontab": "",
        "once": false,
        "onceDelay": "10",
        "topic": "",
        "payload": "2000",
        "payloadType": "num",
        "x": 170,
        "y": 780,
        "wires": [
            [
                "31a09e8db3cc382f"
            ]
        ]
    },
    {
        "id": "d66e472f0cb07fe2",
        "type": "inject",
        "z": "4ce31719083f99a9",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "-2000",
        "payloadType": "num",
        "x": 170,
        "y": 840,
        "wires": [
            [
                "31a09e8db3cc382f"
            ]
        ]
    },
    {
        "id": "a1442086e512d7b5",
        "type": "inject",
        "z": "4ce31719083f99a9",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "5100",
        "payloadType": "num",
        "x": 170,
        "y": 900,
        "wires": [
            [
                "31a09e8db3cc382f"
            ]
        ]
    },
    {
        "id": "4311b79256c40230",
        "type": "inject",
        "z": "4ce31719083f99a9",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "0",
        "payloadType": "num",
        "x": 210,
        "y": 320,
        "wires": [
            [
                "f1f518c95e78a489"
            ]
        ]
    },
    {
        "id": "6d43590038a9dd98",
        "type": "inject",
        "z": "4ce31719083f99a9",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "1",
        "payloadType": "num",
        "x": 210,
        "y": 380,
        "wires": [
            [
                "f1f518c95e78a489"
            ]
        ]
    },
    {
        "id": "12afccc565c78ac0",
        "type": "modbus-write",
        "z": "4ce31719083f99a9",
        "name": "",
        "showStatusActivities": false,
        "showErrors": false,
        "showWarnings": true,
        "unitid": "228",
        "dataType": "HoldingRegister",
        "adr": "37",
        "quantity": "1",
        "server": "c7e96e5c482c85ce",
        "emptyMsgOnFail": false,
        "keepMsgProperties": false,
        "delayOnStart": false,
        "startDelayTime": "",
        "x": 840,
        "y": 780,
        "wires": [
            [],
            []
        ]
    },
    {
        "id": "c20b333c668ba51b",
        "type": "inject",
        "z": "4ce31719083f99a9",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "1",
        "payloadType": "num",
        "x": 210,
        "y": 120,
        "wires": [
            [
                "6bab990d6227a654"
            ]
        ]
    },
    {
        "id": "08ea6a8fc791f82f",
        "type": "inject",
        "z": "4ce31719083f99a9",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "30",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "3",
        "payloadType": "num",
        "x": 210,
        "y": 180,
        "wires": [
            [
                "6bab990d6227a654"
            ]
        ]
    },
    {
        "id": "6bab990d6227a654",
        "type": "modbus-write",
        "z": "4ce31719083f99a9",
        "name": "",
        "showStatusActivities": false,
        "showErrors": false,
        "showWarnings": true,
        "unitid": "100",
        "dataType": "HoldingRegister",
        "adr": "2902",
        "quantity": "1",
        "server": "c7e96e5c482c85ce",
        "emptyMsgOnFail": false,
        "keepMsgProperties": false,
        "delayOnStart": false,
        "startDelayTime": "",
        "x": 520,
        "y": 140,
        "wires": [
            [],
            []
        ]
    },
    {
        "id": "2d952a3183417773",
        "type": "comment",
        "z": "4ce31719083f99a9",
        "name": "EMS Mode 2902",
        "info": "",
        "x": 160,
        "y": 60,
        "wires": []
    },
    {
        "id": "dbe1ac563a132db8",
        "type": "comment",
        "z": "4ce31719083f99a9",
        "name": "Register 37/40/41",
        "info": "",
        "x": 170,
        "y": 660,
        "wires": []
    },
    {
        "id": "b4472608f07c19a5",
        "type": "comment",
        "z": "4ce31719083f99a9",
        "name": "Register 38",
        "info": "",
        "x": 150,
        "y": 260,
        "wires": []
    },
    {
        "id": "f1f518c95e78a489",
        "type": "modbus-write",
        "z": "4ce31719083f99a9",
        "name": "",
        "showStatusActivities": false,
        "showErrors": false,
        "showWarnings": true,
        "unitid": "228",
        "dataType": "HoldingRegister",
        "adr": "38",
        "quantity": "1",
        "server": "c7e96e5c482c85ce",
        "emptyMsgOnFail": false,
        "keepMsgProperties": false,
        "delayOnStart": false,
        "startDelayTime": "",
        "x": 520,
        "y": 340,
        "wires": [
            [],
            []
        ]
    },
    {
        "id": "4cedfb7f43a26c7e",
        "type": "function",
        "z": "4ce31719083f99a9",
        "name": "Signed 16bit",
        "func": "// Convert payload to signed 16-bit integer\nmsg.payload = (msg.payload << 16) >> 16;\nreturn msg;\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 570,
        "y": 780,
        "wires": [
            [
                "12afccc565c78ac0",
                "dac9307c1c5053aa",
                "63f25d54520175ae",
                "ff3105e89ffd3fc5"
            ]
        ]
    },
    {
        "id": "d72f20790b6aed1e",
        "type": "debug",
        "z": "4ce31719083f99a9",
        "name": "debug 57",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 660,
        "y": 1380,
        "wires": []
    },
    {
        "id": "7d2374826a72c9da",
        "type": "inject",
        "z": "4ce31719083f99a9",
        "name": "-2700 senden",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "-2700",
        "payloadType": "num",
        "x": 230,
        "y": 1400,
        "wires": [
            [
                "0d1b9a1c5de47601"
            ]
        ]
    },
    {
        "id": "9ba6d365a0fde656",
        "type": "modbus-write",
        "z": "4ce31719083f99a9",
        "name": "",
        "showStatusActivities": false,
        "showErrors": false,
        "showWarnings": true,
        "unitid": "228",
        "dataType": "HoldingRegister",
        "adr": "37",
        "quantity": "1",
        "server": "c7e96e5c482c85ce",
        "emptyMsgOnFail": false,
        "keepMsgProperties": false,
        "delayOnStart": false,
        "startDelayTime": "",
        "x": 640,
        "y": 1480,
        "wires": [
            [],
            []
        ]
    },
    {
        "id": "0d1b9a1c5de47601",
        "type": "function",
        "z": "4ce31719083f99a9",
        "name": "Nur int16 wandeln",
        "func": "// Nur Wert in int16 (Zweierkomplement) umwandeln\nlet value = msg.payload;\n\nlet buf = Buffer.alloc(2);\nbuf.writeInt16BE(value);\n\nlet modbusValue = buf.readUInt16BE();\n\nmsg.payload = [modbusValue];  // Array fĂĽr modbus-write\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 430,
        "y": 1400,
        "wires": [
            [
                "d72f20790b6aed1e",
                "9ba6d365a0fde656"
            ]
        ]
    },
    {
        "id": "93574ca382583f9c",
        "type": "inject",
        "z": "4ce31719083f99a9",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "0",
        "payloadType": "num",
        "x": 210,
        "y": 520,
        "wires": [
            [
                "c5366f47f17668c3"
            ]
        ]
    },
    {
        "id": "1835f3485e8323b4",
        "type": "inject",
        "z": "4ce31719083f99a9",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "1",
        "payloadType": "num",
        "x": 210,
        "y": 580,
        "wires": [
            [
                "c5366f47f17668c3"
            ]
        ]
    },
    {
        "id": "cbfdb334d6777edb",
        "type": "comment",
        "z": "4ce31719083f99a9",
        "name": "Register 39",
        "info": "",
        "x": 150,
        "y": 460,
        "wires": []
    },
    {
        "id": "c5366f47f17668c3",
        "type": "modbus-write",
        "z": "4ce31719083f99a9",
        "name": "",
        "showStatusActivities": false,
        "showErrors": false,
        "showWarnings": true,
        "unitid": "228",
        "dataType": "HoldingRegister",
        "adr": "39",
        "quantity": "1",
        "server": "c7e96e5c482c85ce",
        "emptyMsgOnFail": false,
        "keepMsgProperties": false,
        "delayOnStart": false,
        "startDelayTime": "",
        "x": 520,
        "y": 540,
        "wires": [
            [],
            []
        ]
    },
    {
        "id": "dac9307c1c5053aa",
        "type": "modbus-write",
        "z": "4ce31719083f99a9",
        "name": "",
        "showStatusActivities": false,
        "showErrors": false,
        "showWarnings": true,
        "unitid": "228",
        "dataType": "HoldingRegister",
        "adr": "40",
        "quantity": "1",
        "server": "c7e96e5c482c85ce",
        "emptyMsgOnFail": false,
        "keepMsgProperties": false,
        "delayOnStart": false,
        "startDelayTime": "",
        "x": 840,
        "y": 840,
        "wires": [
            [],
            []
        ]
    },
    {
        "id": "63f25d54520175ae",
        "type": "modbus-write",
        "z": "4ce31719083f99a9",
        "name": "",
        "showStatusActivities": false,
        "showErrors": false,
        "showWarnings": true,
        "unitid": "228",
        "dataType": "HoldingRegister",
        "adr": "41",
        "quantity": "1",
        "server": "c7e96e5c482c85ce",
        "emptyMsgOnFail": false,
        "keepMsgProperties": false,
        "delayOnStart": false,
        "startDelayTime": "",
        "x": 840,
        "y": 900,
        "wires": [
            [],
            []
        ]
    },
    {
        "id": "31a09e8db3cc382f",
        "type": "function",
        "z": "4ce31719083f99a9",
        "name": "/3",
        "func": "msg.payload = msg.payload / 3;\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 370,
        "y": 780,
        "wires": [
            [
                "4cedfb7f43a26c7e"
            ]
        ]
    },
    {
        "id": "ff3105e89ffd3fc5",
        "type": "debug",
        "z": "4ce31719083f99a9",
        "name": "debug 1",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 820,
        "y": 720,
        "wires": []
    },
    {
        "id": "c7e96e5c482c85ce",
        "type": "modbus-client",
        "name": "Victron",
        "clienttype": "tcp",
        "bufferCommands": true,
        "stateLogEnabled": false,
        "queueLogEnabled": false,
        "failureLogEnabled": true,
        "tcpHost": "127.0.0.1",
        "tcpPort": "502",
        "tcpType": "DEFAULT",
        "serialPort": "/dev/ttyUSB",
        "serialType": "RTU-BUFFERD",
        "serialBaudrate": "9600",
        "serialDatabits": "8",
        "serialStopbits": "1",
        "serialParity": "none",
        "serialConnectionDelay": "100",
        "serialAsciiResponseStartDelimiter": "0x3A",
        "unit_id": 1,
        "commandDelay": 1,
        "clientTimeout": 1000,
        "reconnectOnTimeout": true,
        "reconnectTimeout": 2000,
        "parallelUnitIdsAllowed": true,
        "showErrors": false,
        "showWarnings": true,
        "showLogs": true
    },
    {
        "id": "b997eca12ce71629",
        "type": "global-config",
        "env": [],
        "modules": {
            "node-red-contrib-modbus": "5.44.1"
        }
    }
]

According to the documentation, ESS Mode 3 should stay active as long as register 37/40 and 41 is updated at least every 60 seconds:

But in reality, Victron already seems to fall back to its internal regulation after roughly 10 seconds without updates.

This is currently becoming a problem for openWB.
We want to implement external battery control for Victron systems and openWB normally works with a control interval of 10 seconds. According to the documentation, this should work fine with ESS Mode 3.

Unfortunately, Victron already takes over regulation again within these 10 seconds, so stable external control is not really possible.

I also found older reports describing the same behaviour:

Could you please check this behaviour?

From my perspective this looks like a bug, and I would appreciate a fix so Mode 3 really behaves with the documented 60 second timeout.

Kai

I found another simpler method to control the AC net setpoints.

I started this topic as Victron described this method in their Mode 3 and I did not want the high controller and modbus load in our Loxone system.

Studying the modbus register map there is as well register 2700. That controls the AC setpoint for 3 phases together and does not need refreshing.

This register is documented to work with Mode 2 (Timeshift) but turns out to work ALWAYS. Even during DESS you can use this to influence the AC net setpoint.

I very much like the Victron system. But it takes a lot of time to figure the real behaviour and meaning of all the modbus registers

I made a post on my blog: Loxone Loxberry to document the basics of the loxone-Victron connection we use to run our own DESS from Loxone on days wher Victron DESS is not the best option for us.

Hi,

have a look at the assistant changelog:

Although I must admit that updating documents after significant changes is not on top of Victron’s priority list.
Sometimes I get the feeling that things in firmware and assistants are changed without properly thinking it through for (almost) all use cases.

You could downgrade to a previous assistant version to revert to the old behavior.

Hope that helps.

CU, Frank

Thank you for the feedback, I also looked into that register.

According to Victron documentation, it is only intended to work with Mode 2. If it actually works in Mode 3 as well, that is of course good news.

However, this unfortunately cannot be used as the foundation for programming an external battery control system for thousands of energy management systems running live at customer sites.

The functionality is not officially documented by Victron. That makes it potentially a useful workaround for individual users, but not something reliable enough for production systems.

Victron could remove or change this unintended behaviour at any time, and then everyone actively relying on it would suddenly run into problems.

There is also official documentation from Victron describing how external control of the system is supposed to work. Either the documentation is wrong, or the actual implementation contains a bug.

I really like the Victron ecosystem, but I honestly find it surprising that this issue has already been discussed in the Victron forum for years without being addressed properly. That does not feel very reassuring for developers trying to build reliable integrations on top of the officially documented interfaces.

I agree with your view. For individual solutions my suggestions is valid, not for wide use. I fully understand your view.

But actually there are more deviations and even undocumented functions.

So I see two solutions here:

  • Either Victron confirms for this one a a few other crucial functions they will NOT to change anything on short term. And provide a kind of roadmap for possible changes.
  • Or Victron to creates a small working group of key-users for various application fields to work on a minimal set of registers including more focussed documentation. For example start updating and expanding the document with the operating modes.

I get the impression that the long history of Victron applications has evolved without a clear roadmap. So I would not say that the spreadsheet with registers is chaotic, but at least the documentation is lagging behind while the system grew and got more fucntionality.

As a suggestion; Maybe it would be good to hear from Victron if they would appreciate any help from the users community directly. Maybe they do have something like this already. But then it would be good to read something of the activities.

Those are all great suggestions. But how can this actually be brought to Victron’s attention?

Who has a good connection to Victron?
Does Victron actively read and follow discussions here in the forum?

No idea. Sorry no direct contact to Victrom other then my supplier who directs me to the forum.

Some topics seem to be actively followed. Others like this one are ignored as it seems, by Victron.

Could you please send me the link to the changelog? I tried to find it myself on the internet, but without success. Thx Kai

The changelog is only available on the Victron Professional platform which is intended for installers since those are the (only) ones supposed to mess with firmware and assistant updates.
However you might still be able to register on Victron Professional as a non-installer.

Anyone can access the site, it is not restricted.
It is a good idea to register for their news updates.