Heizungssteuerung mit Raspberry

  • Hallo zusammen,
    hier will ich mein Projekt vorstellen.
    Es geht um eine automatische Heizungssteuerung in einem Einfamilienhaus. Zu 90% Fußbodenheizung ohne Thermostate. Das Haus ist innen mehr oder weniger offen, auch über die beiden Etagen. Installiert ist eine Junkers Gastherme. Diese wurde gesteuert von einem zentral angebrachten Innenthermometer mit dem ganzen üblichen Kauderwelsch wie Heizkurven und dergleichen. Hat nie richtig gut funktioniert. Dann bin ich auf das Produkt "Netatmo Thermostat" aufmerksam geworden. Hab es bestellt, die komplette Elektronik der Therme lahmgelegt (CAN Bus Außenthermometer, Mischer, Innenthermometer, die Pumpe ist eine autarke Grundfoss), und Netatmo angeschlossen. Die Außentemperatur bekommt der Netatmo Thermostat über die Netatmo Wetterstation oder über die Wettervorhersage. Innthermometer ist dabei. Durch zwei Kontakte an der Junkers-Therme, kann diese beliebig ein- und ausgeschaltete werden (hat wohl jede Heizung solche Anschlüsse). Der Netatmo Thermostat lernt nach ein paar Tagen die Eigenheiten der Heizung. Und was soll ich sagen, es funktioniert wesentlich besser als die originale Steuerung. Nach über einem Jahr Nutzung bin ich aber doch noch nicht 100%ig zufrieden und Schabe ich den Netatmo Thermostat durch eine eigene Raspberry Lösung ersetzt. Ist bis jetzt 2 Wochen im Einsatz und es sieht sehr vielversprechend aus.


    - Raspberry Pi 2 B
    - PiFace Digital 2
    - USB-WLAN
    - Raspbian


    Das Programm habe ich in C geschrieben.
    Vom PiFace verwende ich eines der beiden Relais, welches mit der Heizung an den beiden An/Aus Pins verbunden ist (Niedrigspannung).
    Das C Programm ruft zwei Python Scripts zum Aktiviert bzw Deaktivieren des Relais auf und damit zum An- und Ausschalten der Therme.
    Das Programm verarbeitet die Innen- und Außentemperatur. Da ich eine Netatmo Wetterstation habe, nutze ich diese und das Programm ruft ein entsprechendes PHP Script auf, um die Temperaturen zu bekommen.


    Datum, Zeit, Innentemperatur, Außentemperatur und wie lange die Therme an war, werden alle 30 Minuten in einer Datei gespeichert.


    Das Kniffligste an solch einer Steuerung ist, einen Algorithmus oder eine Formel zu finden, wann und wie lange die Heizung eingeschaltet sein muß, um zu einer bestimmten Zeit, eine gewünschte Innentemperatur zu haben. Das ganze ist unglaublich träge und sehr viele Faktoren spielen da eine Rolle. Die Lösung war ein künstliches neuronales Netz. Ich hatte es erst selbst programmiert, bin dann aber auf die quell-offene Lösung FANN umgeschwenkt ( FANN ).


    Das Programm lernt so an Hand der bisherigen Messwerte, die Heizung immer besser zu regeln. Alle halbe Stunde werden neue Messwerte erfaßt, gespeichert, das neuronale Netzt mit diesen Werten abgefragt und die optimale neue Brenndauer der Therme bestimmt. Sie bleibt dann die nächsten 30 Minuten entweder aus oder wird eingeschaltet und nach der berechneten Zeit wieder per Timer ausgeschaltet. Die Zwischenzeit verwendet das Programm zum Training des neuronalen Netzes. Einer der 4 CPU Kerne des Raspis ist dabei natürlich ausgelastet. Die RAM Auslastung braucht kaum mehr als 1 MByte.


    Wenn Interesse besteht, werde ich hier nach und nach den Sourcecode und Anleitungen hier hinterlegen.


    Gruß, Matthias

  • Ich habe das etwas anders gelöst als Du. Ich habe auch eine autarke elektronische Pumpe, die je nach Abnahme reagiert. Ich habe an jedem Heizkreis einen elektrischen Thermostaten dran. Zudem in jedem Bereich 2 DS18B20 zur Temperaturmessung. Einen direkt am Fußboden einen in "Sitzhöhe". Der RasPi steuert bei mir nun die Heizungskreise nach der für den Bereich eingestellten Temperatur. Mit den "Fußbodensensoren" steuere ich die Flussgeschwindigkeit der Fussbodenheizungen damit der Boden nicht zu heiß wird (ich habe 40°C Vorlauf, weil noch andere Heizkörper dran hängen) mit dem "Raumsensoren" die Raumtemperatur. Also ist in einem Bereich die Wunschtemperatur noch nicht erreicht, wird der Thermostat so weit aufgedreht, dass die Fußbodentemperatur einen eingestellten Wert (bei mir 22°C) nicht überschreitet. Das läuft solange, bis der Raumsensor die Wunschtemperatur hat, dann dreht der Thermostat ganz ab. Ich hatte erst bedenken wegen der Hysterese, aber die Fussbodenheizung ist so träge, dass das gut läuft. Sind alle Thermostaten, auch die der normalen Heizkörper zu, schalte ich auch den Brenner ab. Der geht erst wider an, sobald der Speicher zu kalt wird und ein Thermostat offen ist bzw. zu viel warmes Wasser entnommen wurde. Außensensor habe ich deaktiviert, weil ich den überhaupt nicht benötige.

  • Hallo Jörg,
    danke für deine Antwort.
    Ich vermute, deine Lösung funktioniert sehr gut, wenn man permanent die gleiche Solltemperatur haben möchte. Problematisch wird es sicher, wenn nachts tiefere Temperaturen erlaubt werden (17 Grad), und ab 7:00 20 Grad und dann abends 22 Grad. Ohne Beachtung der Hysterese (die sich auch stetig ändert) erreicht man nie die Solltemperatur zum Wunschzeitpunkt. Auch muss das Annähern an die Solltemperatur "vorsichtig" passieren, sonst passiert es durch die Trägheit des Systems, dass die Solltemperatur weit überschritten wird und man unnötig Energie verschwendet.


    Gruß, Matthias

  • Ich fahre auch mit Nachtabsenkung, das ist überhaupt kein Problem. Ich lasse dabei die Fussbodentemperatur auf 22°C. Durch die Absenkung der Raumtemperatur, bleibt die Heizung bei mir beinahe die ganze Nacht aus. Das ist natürlich eine Frage der Programmierung.

  • Hallo Zusammen,


    beide Lösungen hören sich ziemlich gut an, wobei Matthias Lösung den Regler mittels FANN zu implementieren wirklich sehr elegant ist. Ich bin gerade auch dabei ohne Fußbodenheizungsregelung ein wenig zu optimieren, hatte es erst mit einem PI-Regler versucht war aber nicht besser als das Standardheinzungszeug.


    Ich bin deshalb wirklich sehr an dem Code von Matthias interessiert, steht dein Vorschlag den zu verteilen noch?


    Schon mal danke für die Schilderung eurer tollen Ideen und liebe Grüße,
    Fritz

  • Hallo Airrud,


    Deine Lösung ist sehr interessant!!! Was mich interessieren würde ist, wie Du die einzelnen Regelstrecken/~kreise in Deinem neuronalen Netzwerk abgebildet hast. Betrachtet man den Kesseltemperaturregler und den Thermostaten am Heizkörper, dann hat man bereits zwei Regelstrecken. Optimiert man über beide und ggf. über verschiedene Regelkreise (EG, UG, OG...), dann kommen diverse weitere Regelkreise hinzu. Ebenfalls, wenn man die Wärmeabstrahlung des Hauses berücksichtigt. Regelkreise müssen dabei ein Stabilitätskriterium erfüllen, um nicht in's Schwingen zu gelangen. Auch Neuronen können übertrainiert werden und neigen dann zu Oszillation. Kannst Du ein wenig darüber berichten, wie Du DIe neuronalen Netze organisiert hast, sie trainierts etc., um dem allen Rechnung zu tragen? Ich habe mich selbst nur rudimentär mit neuronalen Netzen beschäftigt, mit dem Thema der Heizungssteuerung schon etwas mehr (siehe >>> hier <<<). Daher würde mich das sehr interessieren (wenngleich ich mit meiner konvetionellen Steuerung zunächst auch ganz gut leben kann :-)).


    Schöne Grüße


    schnasseldag



  • Hallo,
    im Anhang ist der Kram.



    Die Dateien vom angehängten zip nach /opt/Boiler kopieren und die Rechte auf den User pi anpassen.



    Kompilieren:


    $ cd /opt/Boiler
    $ gcc -O3 -pthread -std=c99 -o boiler main.c brain.c -lm


    In boiler.cfg steht die Konfiguration des Programms:


    1. Zeile: Dateipfad für das neuronale Netzwerk. Wenn es noch keines gibt, wird es hier angelegt.
    2. Zeile: Dateipfad für die Messungen. Wenn es noch keines gibt, wird es hier angelegt. Per Semikolon getrennt: Datum/Zeit; Innentemperatur; Sekunden Laufzeit Heizung; Außentemperatur; Zieltemperatur
    3. Zeile: Dateipfad wo das Programm vermerkt, wie lange die Heizung zuletzt an war. Wird benötigt, wenn man das Programm stoppt und wieder startet. Datei wird angelegt.
    4. Zeile: CLI Command, welches die Innentemperatur ausgibt. Bei mir ein DS Sensor.
    5. Zeile: CLI Command welches die Außentemperatur ausgibt. Bei mir eine Netatmo Wetterstation. Wird nicht verrechnet, aber in der Maßdatei gespeichert. Ist kein Außensensor vorhanden, kann man auch echo "0.0" hier eintragen.
    6. Zeile: CLI Command um die Heizung einzuschalten. Bei mir ein Relais auf dem Raspi PiFace Digital 2
    7. Zeile: CLI Command um die Heizung auszuschalten. Gleiches Relais auf dem Raspi PiFace Digital 2
    8. Zeile: YES wenn permanent das neuronale Netzt trainiert werden soll. NO: kein permanentes Training
    9. Zeile: Für jede Stunde die Wunschtemperatur beginnen 0:00 Uhr


    Das Programm einfach durch ./boiler starten. Besser ist natürlich ein Eintrag als Deamon in /etc/init.d. Script ist im zip mit drin.


    Das Programm mißt alle 30 Minuten die Innentemperatur, die Außentemperatur (optional) und hängt diese Messwerte plus die Laufzeit der Heizung der letzten halben Stunde an die Maßdatei. Dann nimmt es die letzen 24 Messwerte von Innentemperatur und Laufzeit der Heizung (also die letzten 12 Stunden) und fragt damit das neuronale Netzwerk ab, was die optimale Laufzeit der Heizung für die nächste halbe Stunde ist, um die Zieltemperaturen der nächsten 4 Stunden zu erreichen. Dann setzt es entsprechend die Command ab, um die Heizung an bzw. auszuschalten. In der Zwischenzeit wird das neuronale Netz trainiert. Dann get es wieder von vorne los.


    Die FANN Lib habe ich mittlerweile durch eigenen Code ersetzt (brain.c). Das Netz hat hier 48 Input Neuronen, 12 versteckte (hidden) Neuronen und nur ein Output Neuron. Das Netz soll lernen, die Innentemperatur vorauszusagen. Als Input dienen ihm dazu die letzten 24 Messwerte von Innentemperatur und Heizung An (Sekunden wie lange die Heizung im Zeitintervall von 30 Minuten eingeschaltet war). Also 24 Messwerte multipliziert mit 2 Sensoren = 48 Input Neuronen. Das eine Outputneuron gibt die voraussichtliche Innentemperatur in 30 Minuten aus. Und damit wird das Netz auch trainiert.


    Die 30 Minuten Voraussage reichen natürlich nicht wegen der Hysterese der Heizung. Für meine Heizung brauche ich 8h Voraussagen (Predictions), also 16 zukünftige Innentemperaturen. Der Trick ist, dass ich an Hand der letzten 24 Messwerte die Temperaturvoraussage für die nächste halbe Stunde vom Netzwerk ausgeben lasse. Dann nehme ich die letzten 23 Messwerte, füge die vorausgesagte Temperatur an und frage damit das Netz ab. So bekomme ich die Voraussage für die nächste Stunde. Und so weiter bis 8h vorausgesagt sind. Es muß als Input natürlich auch die Heizung An Zeit angegeben werden. Das mache ich dann in einer Schleife von 0-30 Minuten an. Und wenn die Temperaturvoraussage meine Wunschtemperatur am besten erreicht, habe ich die einzustellende Zeit für die Heizung An gefunden.


    Es lassen sich natürlich beliebig viele Eingabesensoren im Netz trainieren. Ich hatte auch zuerst mit der Außentemperatur als zusätzlichen Input experimentiert. War aber unnötig.


    Das FANN Netz ist zwar sehr schnell zu trainieren, aber es neigt zum over-fitting. Das heißt, es kategorisiert nicht, sondern lernt sozusagen den Output auswendig.


    Um das Netz zu trainieren, braucht man natürlich erstmal eine möglichst große Anzahl von Datensätzen. Ich habe deswegen meine Messwerte mit angehängt. Auch das trainierte Netz.


    Anfangs hatte ich den Pi permanent das Netz trainieren lassen. Ist aber unnötig. Mit ./boiler -teach wird nur das Netz trainiert. Das Programm habe ich am Mac in Xcode entwickelt (da C und Posix läuft es unter OS X und Linux ohne eine einzige Codezeile zu ändern). Da der Mac wesentlich schneller ist als der Pi, trainiere ich ihn hier und kopiere dann das trainierte Netzwerk auf den Pi. Der Output beim Training sieht so aus:


    Training is running...


    06.03.2016 10:33:59 - Training Results: Runs: 00000000 Avg: 0.042912 Max: 0.243999
    06.03.2016 10:34:04 - Training Results: Runs: 00000336 Avg: 0.042914 Max: 0.243910
    06.03.2016 10:34:09 - Training Results: Runs: 00000422 Avg: 0.042914 Max: 0.243910


    "Runs" zeigt die Anzahl der Trainingsdurchläufe durch die Messdatei.
    "Avg." zeigt die durchschnittliche Trefferquote in Grad Celsius der Innentemperatur. Das Netz schätzt die Innentemperatur im Durchschnitt für die nächste halbe Stunde mit einer Genauigkeit von beachtlichen 0,04 Grad!
    "Max." Ist die maximale Abweichung in Grad vom Soll.


    Hier der Output am Pi, wenn es die Heizung steuert (ohne permanentes Training):


    [font="Courier New"]06.03.2016 06:11:33 - Current Temperatures: 20.74 02.40
    [/font]
    [font="Courier New"]06.03.2016 06:11:33 - Target Temperatures: 20.00 21.00 21.00 21.00 21.00 21.00 21.00 21.00[/font]


    [font="Courier New"]06.03.2016 06:11:33 - Predicted Temperatures: 20.76 20.84 20.96 21.03 21.01 21.01 20.96 21.00[/font]


    [font="Courier New"]06.03.2016 06:11:33 - Optimal Boiler On: 960 / 300[/font]


    [font="Courier New"]06.03.2016 06:11:33 - Boiler Command: Switched ON[/font]


    [font="Courier New"]06.03.2016 06:27:33 - Boiler Command: Switched OFF[/font]




    [font="Courier New"]06.03.2016 06:41:46 - Current Temperatures: 20.74 02.20[/font]


    [font="Courier New"]06.03.2016 06:41:46 - Target Temperatures: 21.00 21.00 21.00 21.00 21.00 21.00 21.00 21.00[/font]


    [font="Courier New"]06.03.2016 06:41:46 - Predicted Temperatures: 20.81 20.93 20.96 21.01 21.03 20.99 21.00 20.99[/font]


    [font="Courier New"]06.03.2016 06:41:46 - Optimal Boiler On: 780 / 360[/font]


    [font="Courier New"]06.03.2016 06:41:46 - Boiler Command: Switched ON[/font]


    [font="Courier New"]06.03.2016 06:54:46 - Boiler Command: Switched OFF[/font]




    [font="Courier New"]06.03.2016 07:11:34 - Current Temperatures: 20.80 01.90[/font]


    [font="Courier New"]06.03.2016 07:11:34 - Target Temperatures: 21.00 21.00 21.00 21.00 21.00 21.00 21.00 21.00[/font]


    [font="Courier New"]06.03.2016 07:11:34 - Predicted Temperatures: 20.91 20.93 20.96 21.01 20.99 21.02 21.02 20.94[/font]


    [font="Courier New"]06.03.2016 07:11:34 - Optimal Boiler On: 600 / 360[/font]


    [font="Courier New"]06.03.2016 07:11:34 - Boiler Command: Switched ON[/font]


    [font="Courier New"]06.03.2016 07:21:34 - Boiler Command: Switched OFF[/font]




    [font="Courier New"]06.03.2016 07:41:36 - Current Temperatures: 20.86 01.70[/font]


    [font="Courier New"]06.03.2016 07:41:36 - Target Temperatures: 21.00 21.00 21.00 21.00 21.00 21.00 21.00 21.00[/font]


    [font="Courier New"]06.03.2016 07:41:36 - Predicted Temperatures: 20.88 20.89 20.92 20.94 21.00 21.06 21.03 20.99[/font]


    [font="Courier New"]06.03.2016 07:41:36 - Optimal Boiler On: 540 / 600[/font]


    [font="Courier New"]06.03.2016 07:41:36 - Boiler Command: Switched ON[/font]


    [font="Courier New"]06.03.2016 07:50:36 - Boiler Command: Switched OFF[/font]




    [font="Courier New"]06.03.2016 08:11:34 - Current Temperatures: 20.93 01.70[/font]


    [font="Courier New"]06.03.2016 08:11:34 - Target Temperatures: 21.00 21.00 21.00 21.00 21.00 21.00 21.00 21.00[/font]


    [font="Courier New"]06.03.2016 08:11:34 - Predicted Temperatures: 20.95 20.98 20.96 20.98 21.05 21.03 21.00 20.94[/font]


    [font="Courier New"]06.03.2016 08:11:34 - Optimal Boiler On: 300 / 660[/font]


    [font="Courier New"]06.03.2016 08:11:34 - Boiler Command: Switched ON[/font]


    [font="Courier New"]06.03.2016 08:16:34 - Boiler Command: Switched OFF[/font]




    [font="Courier New"]06.03.2016 08:41:34 - Current Temperatures: 20.93 02.80[/font]


    [font="Courier New"]06.03.2016 08:41:34 - Target Temperatures: 21.00 21.00 21.00 21.00 21.00 21.00 21.00 21.00[/font]


    [font="Courier New"]06.03.2016 08:41:34 - Predicted Temperatures: 20.95 20.94 20.98 20.99 21.01 21.00 21.00 21.02[/font]


    [font="Courier New"]06.03.2016 08:41:34 - Optimal Boiler On: 480 / 780[/font]


    [font="Courier New"]06.03.2016 08:41:34 - Boiler Command: Switched ON[/font]


    [font="Courier New"]06.03.2016 08:49:34 - Boiler Command: Switched OFF[/font]




    [font="Courier New"]06.03.2016 09:11:34 - Current Temperatures: 20.99 03.80[/font]


    [font="Courier New"]06.03.2016 09:11:34 - Target Temperatures: 21.00 21.00 21.00 21.00 21.00 21.00 21.00 21.00[/font]


    [font="Courier New"]06.03.2016 09:11:35 - Predicted Temperatures: 20.98 21.03 21.04 21.00 21.00 20.99 21.01 21.01[/font]


    [font="Courier New"]06.03.2016 09:11:35 - Optimal Boiler On: 480 / 840[/font]


    [font="Courier New"]06.03.2016 09:11:35 - Boiler Command: Switched ON[/font]
    [font="Courier New"]06.03.2016 09:19:35 - Boiler Command: Switched OFF[/font]



    Gruß, Matthias