Regelung der Raumtemperatur

Hallo beisammen,

auch wenn der Winter noch in weiter Ferne ist habe ich mir mal das schicke Node Blue als Basis für meine neue Raumtemperaturregelung angeschaut und stelle meine derzeitige Lösung zur Diskussion.

Das zentrale Element ist der vorgefertigte Regler:

Er hat zwei Eingänge und einen Ausgang:

  • Eingang y: aktuelle Temperatur
  • Eingang w: Solltemperatur
  • Ausgang u: Stellgröße für das Heizungsventil in %

Für ganz simple Szenarien reicht das so bestimmt, aber ich habe zusätzlich folgende Anforderungen:

  1. Übermittlung der aktuellen Temperatur nach einem festen Intervall, da die Temperaturübermittlung sporadisch erfolgt.
    (Standardmäßig reagiert der Regler auf jede Mitteilung am Eingang für die aktuelle Temperatur)
  2. Berücksichtigung von offenen Fenstern/Türen.
  3. gezieltes An- und Ausschalten der Automatik.

Hier seht ihr das Ergebnis, die Erklärung folgt anschließend:

1. Durchlaufverzögerung
Das Ziel dieses Blocks ist es, die einlaufende Temperatur T_Küche in einem dedizierten Intervall weiterzureichen. Der Block Duchlaufverzögerung speichert den letzten Wert des Eingangs V. Sobald Eingang EN auf true gesetzt wird, wird der gespeicherte Wert an den Ausgang übergeben. EN steht auf false. Über clock kann das Intervall eingestellt werden, das unverzögert true an EN schickt und mit einer kurzen Verzögerung false hinterherschickt, so dass nur der gespeicherte Wert an den Regler übergeben wird.

2. Fenster und Türen
Bei offenem Fenster oder offener Türe soll nicht geheizt werden. Die Eingänge werden mit boolscher Logik verarbeitet und die Stellbefehle des Reglers blockiert oder durchgelassen. Im Falle der Blockierung wird der Stellantrieb auf 0 gesetzt.

3. Automatik, Stellantrieb offen, Stellantrieb geschlossen
Der dritte Block ermöglicht ein Umschalten zwischen den Zuständen automatischer Reglerbetrieb, Stellantrieb vollständig offen und Stellantrieb vollständig geschlossen. Dies erleichtert das Entlüften, die Vorbereitung auf den Schornsteinfeger und andere Revisionen.

Zu guter Letzt folgt hier noch der vollständige Flow:

[
    {
        "id": "300fbe7c.7d4432",
        "type": "tab",
        "namespace": "tab",
        "label": "Flow 2"
    },
    {
        "id": "efb52d0e.73936",
        "type": "function",
        "namespace": "function",
        "z": "300fbe7c.7d4432",
        "name": "Auto - Close - Open",
        "func": "$m1 = $message;\n$m2 = $message;\n\n//Falls Auto\nif ($message['payload'] == \"auto\") {\n    $m1['payload'] = true;\n    $m2 = null;\n}\nelseif ($message['payload'] == \"close\") {\n    $m1['payload'] = false;\n    $m2['payload'] = 0;\n}\nelseif ($message['payload'] == \"open\") {\n    $m1['payload'] = false;\n    $m2['payload'] = 99;\n}\nelse {\n    $m1 = null;\n    $m2 = null;\n}\nreturn [$m1,$m2];",
        "inputs": 1,
        "outputs": "2",
        "noerr": 0,
        "x": 815,
        "y": 650,
        "wires": [
            [
                {
                    "id": "d6bab6e8.13a5c8",
                    "port": 1
                }
            ],
            [
                {
                    "id": "5f6669dc.b4c448",
                    "port": 0
                }
            ]
        ]
    },
    {
        "id": "96669cfd.469cb",
        "type": "mqtt-in",
        "namespace": "mqtt",
        "z": "300fbe7c.7d4432",
        "name": "",
        "topic": "kueche/heizung/state",
        "broker": "",
        "x": 595,
        "y": 650,
        "wires": [
            [
                {
                    "id": "efb52d0e.73936",
                    "port": 0
                }
            ]
        ]
    },
    {
        "id": "f69544dd.385258",
        "type": "heating-controller",
        "namespace": "heating",
        "z": "300fbe7c.7d4432",
        "name": "",
        "heatingtype": "radiator",
        "kp": "50",
        "tn": "7200",
        "td": "900",
        "rcwlp": "1200",
        "ylprc": "180",
        "uvalvelprc": "180",
        "x": 755,
        "y": 330,
        "wires": [
            [
                {
                    "id": "9ac6c970.7a19a8",
                    "port": 0
                }
            ]
        ]
    },
    {
        "id": "d6bab6e8.13a5c8",
        "type": "passthrough",
        "namespace": "passthrough",
        "z": "300fbe7c.7d4432",
        "name": "Automatic",
        "onboolean": true,
        "x": 1055,
        "y": 590,
        "wires": [
            [
                {
                    "id": "5f6669dc.b4c448",
                    "port": 0
                }
            ]
        ]
    },
    {
        "id": "9ac6c970.7a19a8",
        "type": "passthrough",
        "namespace": "passthrough",
        "z": "300fbe7c.7d4432",
        "name": "Fenster & Türe",
        "onboolean": false,
        "x": 950,
        "y": 420,
        "wires": [
            [
                {
                    "id": "d6bab6e8.13a5c8",
                    "port": 0
                }
            ]
        ]
    },
    {
        "id": "501df89.2d95908",
        "type": "or",
        "namespace": "basic-logic",
        "z": "300fbe7c.7d4432",
        "name": "",
        "changes-only": false,
        "output-false": true,
        "inputs": 2,
        "x": 660,
        "y": 460,
        "wires": [
            [
                {
                    "id": "33a03a7a.2e0726",
                    "port": 0
                }
            ]
        ]
    },
    {
        "id": "33a03a7a.2e0726",
        "type": "not",
        "namespace": "basic-logic",
        "z": "300fbe7c.7d4432",
        "name": "",
        "x": 780,
        "y": 460,
        "wires": [
            [
                {
                    "id": "9ac6c970.7a19a8",
                    "port": 1
                },
                {
                    "id": "acf9911a.6f1dd",
                    "port": 0
                }
            ]
        ]
    },
    {
        "id": "acf9911a.6f1dd",
        "type": "function",
        "namespace": "function",
        "z": "300fbe7c.7d4432",
        "name": "false -> 0",
        "func": "if (!$message['payload']) $message['payload'] = 0;\nreturn $message;",
        "inputs": 1,
        "outputs": 1,
        "noerr": 0,
        "x": 935,
        "y": 480,
        "wires": [
            [
                {
                    "id": "d6bab6e8.13a5c8",
                    "port": 0
                }
            ]
        ]
    },
    {
        "id": "8b220c27.c1555",
        "type": "clock",
        "namespace": "timers",
        "z": "300fbe7c.7d4432",
        "name": "",
        "units": "m",
        "timestamp": true,
        "x": 140,
        "y": 250,
        "wires": [
            [
                {
                    "id": "292753f2.366f2c",
                    "port": 0
                }
            ]
        ]
    },
    {
        "id": "b45ed49d.8dc148",
        "type": "mqtt-in",
        "namespace": "mqtt",
        "z": "300fbe7c.7d4432",
        "name": "",
        "topic": "kueche/temp/soll",
        "broker": "",
        "x": 430,
        "y": 340,
        "wires": [
            [
                {
                    "id": "f68082b0.67349",
                    "port": 0
                }
            ]
        ]
    },
    {
        "id": "f68082b0.67349",
        "type": "function",
        "namespace": "function",
        "z": "300fbe7c.7d4432",
        "name": "to float",
        "func": "$message['payload'] = floatval($message['payload']);\nreturn $message;",
        "inputs": 1,
        "outputs": 1,
        "noerr": 0,
        "x": 580,
        "y": 340,
        "wires": [
            [
                {
                    "id": "f69544dd.385258",
                    "port": 1
                }
            ]
        ]
    },
    {
        "id": "10b97da1.49cf82",
        "type": "delay",
        "namespace": "timers",
        "z": "300fbe7c.7d4432",
        "delay": "1",
        "name": "",
        "x": 390,
        "y": 260,
        "wires": [
            [
                {
                    "id": "ad36dae9.7670b8",
                    "port": 1
                }
            ]
        ]
    },
    {
        "id": "292753f2.366f2c",
        "type": "switch",
        "namespace": "basic-logic",
        "z": "300fbe7c.7d4432",
        "name": "",
        "property": "payload",
        "changes-only": false,
        "output-true": true,
        "output-false": true,
        "rules": [
            {
                "t": "neq",
                "v": "abc",
                "vt": "string"
            },
            {
                "t": "eq",
                "v": "abc",
                "vt": "string"
            }
        ],
        "checkall": "true",
        "inputs": 1,
        "outputs": 2,
        "x": 260,
        "y": 250,
        "wires": [
            [
                {
                    "id": "ad36dae9.7670b8",
                    "port": 1
                }
            ],
            [
                {
                    "id": "10b97da1.49cf82",
                    "port": 0
                }
            ]
        ]
    },
    {
        "id": "ad36dae9.7670b8",
        "type": "passthrough",
        "namespace": "passthrough",
        "z": "300fbe7c.7d4432",
        "name": "Durchlaufverzögerung",
        "onboolean": true,
        "x": 570,
        "y": 230,
        "wires": [
            [
                {
                    "id": "f69544dd.385258",
                    "port": 0
                }
            ]
        ]
    },
    {
        "id": "3682b53a.dfaa6a",
        "type": "function",
        "namespace": "function",
        "z": "300fbe7c.7d4432",
        "name": "to float",
        "func": "$message['payload'] = floatval($message['payload']);\nreturn $message;",
        "inputs": 1,
        "outputs": 1,
        "noerr": 0,
        "x": 380,
        "y": 180,
        "wires": [
            [
                {
                    "id": "ad36dae9.7670b8",
                    "port": 0
                }
            ]
        ]
    },
    {
        "id": "341adb55.7ca904",
        "type": "variable-in",
        "namespace": "variable",
        "z": "300fbe7c.7d4432",
        "variabletype": "device",
        "family": "0",
        "peerid": "0",
        "channel": "0",
        "variable": "",
        "variabletext": "",
        "refractoryperiod": "200",
        "outputonstartup": false,
        "name": "T_Küche",
        "x": 230,
        "y": 180,
        "wires": [
            [
                {
                    "id": "3682b53a.dfaa6a",
                    "port": 0
                }
            ]
        ]
    },
    {
        "id": "9adc5530.1293b8",
        "type": "variable-in",
        "namespace": "variable",
        "z": "300fbe7c.7d4432",
        "variabletype": "device",
        "family": "0",
        "peerid": "0",
        "channel": "0",
        "variable": "",
        "variabletext": "",
        "refractoryperiod": "200",
        "outputonstartup": false,
        "name": "Fenster links",
        "x": 480,
        "y": 440,
        "wires": [
            [
                {
                    "id": "501df89.2d95908",
                    "port": 0
                }
            ]
        ]
    },
    {
        "id": "4f0b2e57.b4401",
        "type": "variable-in",
        "namespace": "variable",
        "z": "300fbe7c.7d4432",
        "variabletype": "device",
        "family": "0",
        "peerid": "0",
        "channel": "0",
        "variable": "",
        "variabletext": "",
        "refractoryperiod": "200",
        "outputonstartup": false,
        "name": "Fenster rechts",
        "x": 485,
        "y": 480,
        "wires": [
            [
                {
                    "id": "501df89.2d95908",
                    "port": 1
                }
            ]
        ]
    },
    {
        "id": "5f6669dc.b4c448",
        "type": "variable-out",
        "namespace": "variable",
        "z": "300fbe7c.7d4432",
        "variabletype": "device",
        "family": "0",
        "peerid": "0",
        "channel": "0",
        "variable": "",
        "variabletext": "",
        "name": "Stellantrieb",
        "x": 1250,
        "y": 660,
        "wires": []
    }
]

Ich hoffe, dass es jemandem hilft und freue mich auf eine Diskussion, wie man die einzelnen Bausteine geschickter bauen könnte!

Grüße,
Max

2 Likes

Hallo @max,

total cool und danke für den Flow :smiley:!

Der Regler läuft unabhängig von den Eingängen. Ein “Tick” ist eine Minute lang. Es müsste also eigentlich funktionieren, wenn du den Temperatureingang direkt an v hängst, auch, wenn dieser nur sporadisch gesetzt wird. v und w werden gespeichert, so dass nach einem Neustart der letzte eingegangene Wert weiterverwendet wird.

Viele Grüße

Sathya