Ankündigung

Einklappen
Keine Ankündigung bisher.

Taupunktberechnung für Lüftungssteuerung

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    [Codebeispiel] Taupunktberechnung für Lüftungssteuerung

    Moin Zusammen,

    meine letzte Frage ging in Richtung Lambdas zur Nutzung als Funktion. Dieses Thema habe ich nun geknackt und daraus ist etwas entstanden, was sich meine Frau gewünscht hat. Vielleicht hab ihr ja dafür Verwendung.

    Das Lüften von Kellern ist nicht so einfach, da man bei falschem Lüften Feuchtigkeit in den Keller holt, die man in der Regel loswerden möchte. Rein technisch muss man also prüfen, ob die Luft draußen in der Lage ist aus dem Keller Feuchtigkeit aufzunehmen. Je nach Temperatur und Luftfeuchtigkeit ist die Luft in der Lage mehr oder weniger Feuchtigkeit aufzunehmen oder abzugeben. Um dieses zu bewerten kann man den Taupunkt der Luft berechnen und hieraus ableiten, ob sich das Lüften lohnt. Im Internet habe ich den Hinweis gefunden, dass der Taupunkt der Außenluft um 5°c niedriger liegen sollte, als der Taupunkt der Kellerluft. Ist das der Fall sendet openHAB meine Frau nun den Hinweis, das es ein optimaler Zeitpunkt zum lüften im Keller ist und wenn das Lüftungsfenster vorbei ist bekommt sie auch einen Hinweis.

    Hierzu habe ich jetzt die passenden Item und Regeln gebaut. Wer automatische Fensteröffner hat kann diese damit ebenfalls steuern.

    Jetzt aber zum eingemachten.

    Sitemap:
    In der Sitemap habe ich eine Gruppe implementiert, die angezeigt wird, wenn ein virtueller Kontakt anzeigt, dass Lüften angesagt ist. Hierdurch kann man das Thema auf mehrere Räume ausdehnen.

    Code:
            Group item=gStatusVentilation visibility=[gStatusVentilation==CLOSED]
    Items:
    In dem Items habe ich die Gruppe definiert und den virtuellen Kontakt. Closed heisst hier Lüften und Open ist nicht Lüften.

    Code:
            Group:Contact:OR(CLOSED, OPEN) gStatusVentilation "Lüftung optimal" <myVentilation>
            Contact VCBSSupplyCellarVentilation "Vorratskeller: Lüftung [MAP(ventilation.map):%s]" <myVentilation> (gStatusVentilation)
    Rule:
    Die Regeln stellen einemal die Funktion zur Berechnung des Taupunktes zur Verfügung und auch die Regel für die Auswertung.

    Code:
    import org.openhab.core.library.*
    import org.openhab.core.items.*
    import org.openhab.core.library.types.*
    import org.openhab.model.script.actions.*
    import org.joda.time.*
    import java.lang.Math.*
    
    /* ------------------------------------------------------------------------------------------------------ 
     * 
     * Berechnung des Taupunktes für eine gegebene Temperatur und Luftfeuchtigkeit
     * 
     * Beschreibung:
     * Die Luft ist ein Gemisch verschiedener Gase. Eines dieser Gase ist der Wasserdampf. Die Menge an 
     * Wasserdampf, die in der Luft enthalten sein kann, ist allerdings begrenzt. Je wärmer die Luft ist, 
     * desto mehr Wasserdampf kann in ihr enthalten sein.
     * 
     * Die relative Luftfeuchtigkeit gibt an, wie viel Prozent des maximalen Wasserdampfgehaltes die Luft 
     * im Augenblick enthält. Da der maximale Wasserdampfgehalt mit steigender Temperatur ansteigt, 
     * fällt die relative Luftfeuchtigkeit mit steigender Temperatur (und umgekehrt).
     * 
     * Die Taupunkttemperatur ist definiert als die Temperatur, bei der der aktuelle Wasserdampfgehalt in 
     * der Luft der maximale (100% relative Luftfeuchtigkeit) ist. Die Taupunkttemperatur ist damit eine von 
     * der aktuellen Temperatur unabhängige Größe. Eine Möglichkeit die Taupunkttemperatur zu messen 
     * ist das Abkühlen von Metall bis sich die Oberfläche mit Wasserdampf beschlägt. Dann ist die 
     * Temperatur des Metalls die Taupunkttemperatur.
     * 
     * Es gibt keine exakte Formel zur Umrechnung der Taupunkttemperatur in die relative Luftfeuchtigkeit. 
     * Zur Erstellung des Taupunktrechners habe ich eine einfache Näherungsformel benutzt. Eine exakte 
     * Umrechnung ist nur mit experimentell ermittelten Tabellen möglich.
     * 
     * Aus Temperatur und relativer Luftfeuchte bzw. Temperatur und Taupunkt lässt sich auch der 
     * absolute Feuchtegehalt der Luft in Gramm Wasserdampf pro Kubikmeter ausrechnen.
     * 
     * Formeln:
     * Die Grundlage der Berechnungen ist die Näherungsformel für den Sättigungsdampfdruck ( Gleichung 1 ), 
     * die sogenannte Magnusformel. Die relative Luftfeuchtigkeit ist definiert als das Verhältnis vom 
     * augenblicklichen Dampfdruck zum Sättigungsdampfdruck (umgeformte Gleichung 2). Bei der 
     * Taupunkttemperatur ist definitionsgemäß der Sättigungsdampfdruck gleich dem aktuellen Dampfdruck. 
     * Aus diesen beiden Definitionen folgt unmittelbar Gleichung 3, die Formel zur Berechnung der 
     * relativen Luftfeuchtigkeit aus der Taupunkttemperatur. Die 4. Gleichung beschreibt umgekehrt die 
     * Berechnung der Taupunkttemperatur aus der relativen Luftfeuchtigkeit und der aktuellen Temperatur. 
     * Diese 4. Gleichung ist im Grunde nichts anderes als die nach T aufgelöste 1. Gleichung , wobei für 
     * den Sättigungsdampfdruck der aktuelle Dampfdruck (und nicht der aktuelle Sättigungsdampfdruck) 
     * eingesetzt wird, so dass die Taupunkttemperatur und nicht die normale Temperatur als Ergebnis 
     * herauskommt. Aus der allgemeinen Gasgleichung ergibt sich die 5. Gleichung .
     * 
     * Bezeichnungen:
     * r = relative Luftfeuchte
     * T = Temperatur in °C
     * TK = Temperatur in Kelvin (TK = T + 273.15)
     * TD = Taupunkttemperatur in °C
     * DD = Dampfdruck in hPa
     * SDD = Sättigungsdampfdruck in hPa
     * 
     * Parameter:
     * a = 7.5, b = 237.3 für T >= 0
     * a = 7.6, b = 240.7 für T < 0 über Wasser (Taupunkt)
     * a = 9.5, b = 265.5 für T < 0 über Eis (Frostpunkt)
     * 
     * R* = 8314.3 J/(kmol*K) (universelle Gaskonstante)
     * mw = 18.016 kg/kmol (Molekulargewicht des Wasserdampfes)
     * AF = absolute Feuchte in g Wasserdampf pro m3 Luft
     * 
     * Formeln:
     * SDD(T) = 6.1078 * 10^((a*T)/(b+T))
     * DD(r,T) = r/100 * SDD(T)
     * r(T,TD) = 100 * SDD(TD) / SDD(T)
     * TD(r,T) = b*v/(a-v) mit v(r,T) = log10(DD(r,T)/6.1078)
     * AF(r,TK) = 10^5 * mw/R* * DD(r,T)/TK; AF(TD,TK) = 10^5 * mw/R* * SDD(TD)/TK
     * 
     * Quelle: http://www.wetterochs.de/wetter/feuchte.html
     * 
     * Danke an Stefan Ochs von www.wetterochs.de
     * 
     * ------------------------------------------------------------------------------------------------------ */
    val org.eclipse.xtext.xbase.lib.Functions$Function2 calculateDewPoint = [
        double temperature, double humidity 
        |
        var double a
        var double b
        var double SDD
        var double DD
        var double v
        var double TD
        
        if (temperature >= 0.0){ // T >= 0 °C
            a = 7.5
            b = 237.3
        } else { // T < 0 °C über Wasser
            a = 7.6
            b = 240.7
        }
        SDD=(6.1078 * Math::pow(10.0, ((a*temperature)/(b+temperature)).doubleValue)).doubleValue
        DD = (humidity/100*SDD).doubleValue
        v = Math::log10((DD/6.107).doubleValue)
        TD = ((b*v)/(a-v)).doubleValue
    
        // Return Value is TD
        TD
    ]
    
    rule "Lüftung Vorratskeller"
    when 
        Item CSBSSupplyCellarTemperature changed or
        Item CSBSSupplyCellarHumidity changed or
        Item CSGDOutsideTemperature changed or
        Item CSGDOutsideHumidity changed or
        System started
    then
        var double TDi
        var double TDo
        
        TDo = calculateDewPoint.apply((CSGDOutsideTemperature.state as DecimalType).doubleValue, (CSGDOutsideHumidity.state as DecimalType).doubleValue) as Double
        TDi = calculateDewPoint.apply((CSBSSupplyCellarTemperature.state as DecimalType).doubleValue, (CSBSSupplyCellarHumidity.state as DecimalType).doubleValue) as Double
        
        if ((TDo+5.0 <= TDi)&& (VCBSSupplyCellarVentilation.state == OPEN)) {
            sendCommand(VCBSSupplyCellarVentilation, CLOSED)
            // Hier den Code für die Benachrichtigung einbauen -> Lüften
        } else if ((TDo+5.0 > TDi)&& (VCBSSupplyCellarVentilation.state == CLOSED)){
            sendCommand(VCBSSupplyCellarVentilation, OPEN)
            // Hier den Code für die Benachrichtigung einbauen -> Nicht lüften
        } else {
            sendCommand(VCBSSupplyCellarVentilation, OPEN)
        }    
    end
    So das war es schon. Für Verbesserungsvorschläge bin ich jederzeit offen. Nächste Theme sind Humidex, Hitzeindex und Summer Simmer Index.

    Gruß
    Thomas

    #2
    Extrem cool! Leider haben wir keinen Keller

    Kommentar


      #3
      Moin Zusammen,

      eine kleine Optimierung habe ich bereits umgesetzt. Die Regel für den Lüftunghinweis sollte eine Hysterese enthalten. Folgend die angepasste Rule.

      Code:
       rule "Lüftung Vorratskeller"
          when
           Item CSBSSupplyCellarTemperature changed or
           Item CSBSSupplyCellarHumidity changed or
           Item CSGDOutsideTemperature changed or
           Item CSGDOutsideHumidity changed or
           System started
      then
          var double TDi
          var double TDo
      
          TDo = calculateDewPoint.apply((CSGDOutsideTemperature.state as DecimalType).doubleValue, (CSGDOutsideHumidity.state as DecimalType).doubleValue) as Double
          TDi = calculateDewPoint.apply((CSBSSupplyCellarTemperature.state as DecimalType).doubleValue, (CSBSSupplyCellarHumidity.state as DecimalType).doubleValue) as Double
               if ((TDo+5.0 <= TDi)&& (VCBSSupplyCellarVentilation.state == OPEN)) {
                  sendCommand(VCBSSupplyCellarVentilation, CLOSED)
                  // Hier den Code für die Benachrichtigung einbauen -> Lüften
              } else if ((TDo+3.0 > TDi)&& (VCBSSupplyCellarVentilation.state == CLOSED)) {
                  sendCommand(VCBSSupplyCellarVentilation, OPEN)
                  // Hier den Code für die Benachrichtigung einbauen -> Nicht lüften
             } else {
                 sendCommand(VCBSSupplyCellarVentilation, OPEN)
             }     end
      Gruß
      Thomas
      Zuletzt geändert von dibbler42; 26.05.2015, 06:59.

      Kommentar


        #4
        Danke für das Code-Beispiel, genau so etwas habe ich noch gesucht :-) Kurze Fragen hierzu:

        - Wird zur Berechnung lediglich ein Innen- und Aussenthermostat benötigt? Gibt es bestimmte Voraussetzungen wo diese plaziert sein müssen/sollten?
        - Eignet sich die obige Berechnung auch für Wohnräume (Bäder usw.) oder sollten zwecks besserer Genauigkeit hierbei einige Parameter angepasst werden?

        Grüsse,

        Michael

        Kommentar


          #5
          Moin Michael,

          schön, dass Du den Code gebrauchen kannst. Nun zu deinen Fragen, die ich sogut wie möglich versuche zu beantworten.

          1.) Du musst Temperatur und Luftfeuchtigkeit messen. Da sich Feuchtigkeit an den Wänden niederschlägt, sollte die Messung dicht an einer Wand erfolgen
          2.) Parameter kannst du in der Formel keine anpassen. Für Wohnräume habe das Thema nicht implementiert, sollte aber genauso funktionieren, Besonders im Bad. (Check: Noch nen Thermometer bestellen und Bad ausprobieren :-))

          Kannst ja mal Feedback geben, wie das ganze funktioniert. Welche Thermostate hast Du im Einsatz?

          Gruß
          Thomas

          Kommentar


            #6
            Du kennst diesen Thread?
            Ich hatte mal vor einiger Zeit die gleiche Idee

            Kommentar


              #7
              Nein, den kannte ich nicht. Danke dafür, sieht ja fast so aus wie meine Lösung, nur das die Auswertung etwas anders funktioniert.

              Thomas

              Kommentar


                #8
                Hallo zusammen,

                darf ich das hier nochmal aufgreifen? Ich stecke fest: Ich versuche, mir die 2 ausgerechneten Taupunkte in Openhab anzeigen zu lassen. Das klappt irgendwie nicht. Ich habe 2 Number items (Taupunkt1 und Taupunkt2) angelegt und die Rule oben so abgeändert, dass beide Werte TDi & TDo mittels "postupdate(Taupunkt1, TDi)" aktualisiert werden sollen. Leider passiert das nicht ;(

                Jemand einen Tipp, oder gar ein funktionierendes Beispiel für mich? Ich bin noch nicht ganz so "sattelfest" mit Rules - insbesondere was das debuggen angeht...
                Würde mich über Hilfe freuen.

                Grüße

                Andreas

                Kommentar


                  #9
                  Probier mal
                  Code:
                  Taupunkt1.postUpdate(TDi as DecimalType)

                  Kommentar


                    #10
                    Funktioniert nicht.

                    Meine Items sehen so aus:

                    Code:
                    Number DewpointOutside "Dewpoint Outside [%d]"
                    Number DewpointInside "Dewpoint Inside [%.1f ]"
                    
                    Number TempOutside "Außentemperatur: [%.1f °C]" { homematic="address=MEQ0832840,channel=1,parameter=TEMPERATURE"}
                    Number HumOutside "Luftfeuchtigkeit: [%d %%]" {homematic="address=MEQ0832840, channel=1, parameter=HUMIDITY"}
                    Number TempSchuppen "Temperatur: [%.1f °C]" {homematic="address=LEQ1461286, channel=1, parameter=TEMPERATURE"}
                    Number HumSchuppen "Luftfeuchtigkeit: [%d %%]" {homematic="address=LEQ1461286, channel=1, parameter=HUMIDITY"}
                    Meine Sitemap so:

                    Code:
                    Text item=DewpointOutside
                    Text item=DewpointInside
                    und die Rule als ganzes:

                    Code:
                    import org.openhab.core.library.*
                    import org.openhab.core.items.*
                    import org.openhab.core.library.types.*
                    import org.openhab.model.script.actions.*
                    import org.joda.time.*
                    import java.lang.Math.*
                    
                    val org.eclipse.xtext.xbase.lib.Functions$Function2 calculateDewPoint = [
                        double temperature, double humidity
                        |
                        var double a
                        var double b
                        var double SDD
                        var double DD
                        var double v
                        var double TD
                    
                        if (temperature >= 0.0){ // T >= 0 °C
                            a = 7.5
                            b = 237.3
                        } else { // T < 0 °C über Wasser
                            a = 7.6
                            b = 240.7
                        }
                        SDD=(6.1078 * Math::pow(10.0, ((a*temperature)/(b+temperature)).doubleValue)).doubleValue
                        DD = (humidity/100*SDD).doubleValue
                        v = Math::log10((DD/6.107).doubleValue)
                        TD = ((b*v)/(a-v)).doubleValue
                    
                        // Return Value is TD
                        TD
                    ]
                    
                    rule "Lueftung"
                    when
                        Item TempOutside received update or
                        Item HumOutside received update or
                        Item TempSchuppen received update or
                        Item HumSchuppen received update or
                        System started or
                    
                    then
                        var double TDi
                        var double TDo
                    
                        TDo = calculateDewPoint.apply((TempOutside.state as DecimalType).doubleValue, (HumOutside.state as DecimalType).doubleValue) as Double
                        TDi = calculateDewPoint.apply((TempSchuppen.state as DecimalType).doubleValue, (HumSchuppen.state as DecimalType).doubleValue) as Double
                    
                            DewpointInside.postUpdate(TDi as DecimalType)
                            DewpointOutside.postUpdate(TDo as DecimalType)
                    end
                    Anzeigen tut er mir nur: Taupunkt.JPG

                    Ich find einfach nicht den Fehler
                    Zuletzt geändert von ahhk; 04.09.2016, 22:20.

                    Kommentar


                      #11
                      Hast Du schon mal ein logInfo() eingebaut (einfach, um zu sehen, ob das Lamba das tut, was es soll?
                      Code:
                      logInfo("rules","Dewpoints: inside {} - outside {} ",TDi,TDo)
                      natürlich hinter die Funktionsaufrufe
                      Wenn die Rule getriggert wurde, findest Du eine entsprechende Zeile in logs/openhab.log

                      Kommentar


                        #12
                        Hi,

                        hab ich eingebaut und dabei einen ganz peinlichen Fehler entdeckt. Mein Rule-File hatte die Endung. rule - nicht .rules.

                        Nun bekomme ich folgende Fehlermeldung:

                        Error during the execution of startup rule 'Lueftung': Cannot cast java.lang.Double to org.openhab.core.library.types.DecimalType

                        Kommentar


                          #13
                          Du könntest versuchen, das as DecimalType wieder wegzulassen.

                          Kommentar


                            #14
                            Hi,

                            genau das war es Jetzt klappt es! Super klasse! Vielen Dank für die Tipps...Wenn man nicht so der Programmierer ist, ist es manchmal etwas fummelig. Ich werde mich in jedem Fall weiter darum bemühen, mehr zu lernen und noch besser damit zu werden!
                            Grüße

                            Andreas

                            Kommentar

                            Lädt...
                            X