Ankündigung

Einklappen
Keine Ankündigung bisher.

Logik zur Steuerung der Vorlauftemperatur älterer Heizungen via Schaltaktor

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

    Logik zur Steuerung der Vorlauftemperatur älterer Heizungen via Schaltaktor

    Hallo,
    ich werde meine ältere Ölheizung in smarthomeNG einbinden. Grundlage ist dieser Thread aus dem homematic-forum.

    Im Grunde wird mittels Widerstanden eine Fernbedienung simuliert. Mit der Schaltung der Widerstände kann der Fußpunkt der Heizkurve verändert werden. Mit einem 4-fach Schaltaktor lassen sich über die Zuschaltung von Widerständen 5 Zustände einstellen.

    Zwischenablage01.jpg

    Die Schaltzustände:
    - Tag_max
    - Tag_med
    - Tag_low
    - Nacht
    - Frostschutz

    Je nach Fußpunkt sollen die Schaltzustände aktiviert werden. Damit im Grenzbereich zwischen 2 Temperaturschwellen die Schaltzustände nicht ständig wechseln, soll das "Abschalten" immer ca. 1°C unterhalb des Einschaltschwelle erfolgen.

    Das Ganze habe ich in einer Logik umgesetzt, die durch Veränderung des errechneten Fußpunktes und der Außentemperatur ausgelöst wird.
    Die Logik sieht so aus:

    Code:
    #!/usr/bin/env python3
    # heizung_vorlauf.py
    
    # 4-Stufen-Steuerung des Vorlaufes in Abhängigkeit vom berechneten Fusspunkt
    # Ausgelöst durch "Fusspunkt" und Außentemperatur
    
    logger.info("Logik HeizungVorlauf ausglöst durch:" + trigger['by'] )
    
    # Aussentemperaturen einlesen
    aussentemp_aktuell = sh.rpi1wire.temp_1()
    aussentep_tagesmittel = sh.rpi1wire.temp_1.tagesmittel_gleitend()
    fusspunkt = sh.heizung.vorlauf.fusspunkt()
    
    
    # Prüfung ob Heizung aufgrund Aussentemperatur gebraucht wird
    if (aussentemp_aktuell < 20.0) or (aussentep_tagesmittel < 11.0):
    heizung = true
    
    # Prüfung, ob persistente Variablen vorhanden, wenn nicht setzen dieser
    if not hasattr(logic, 'fusspunkt_alt'):
    logic.fusspunkt_alt = fusspunkt
    
    # Prüfung, ob neuer Fußpunkt größer oder kleiner ist, um die Verlaufsrichtung des Fußpunkts festzustellen
    richtung = round(fusspunkt - logic.fusspunkt_alt, 1)
    
    logger.info("Richtung " + str(richtung))
    
    #Konstanten (Schaltschwellen)
    nachtaus = 15.0
    tagminaus = 18.5
    tagnormaus = 20.5
    tagmaxaus = 22.5
    
    nachtein = 16.5
    tagminein = 19.5
    tagnormein = 21.5
    tagmaxein = 23.5
    
    #Stufen
    if (heizung == 'true') and ((richtung >= 0) and (fusspunkt >= tagmaxein)) or ((richtung < 0) and (fusspunkt > tagmaxaus)):
        zustand = 'tag_max'
    elif (heizung == 'true') and ((richtung >= 0) and (fusspunkt >= tagnormein)) or ((richtung < 0) and (fusspunkt > tagnormaus)):
        zustand = 'tag_med'
    elif (heizung == 'true') and ((richtung >= 0) and (fusspunkt >= tagminein)) or ((richtung < 0) and (fusspunkt > tagminaus)):
        zustand = 'tag_min'
    elif (heizung == 'true') and ((richtung >= 0) and (fusspunkt >= nachtein)) or ((richtung < 0) and (fusspunkt > nachtaus)):
        zustand = 'nacht'
    else:
        zustand = 'frost'
    
    logger.info("Zustand gesetzt auf " + str(zustand))
    
    #Aktionen
    if zustand == 'tag_max':
        sh.heizung.vorlauf.widerstand1(1)
        sh.heizung.vorlauf.widerstand1(1)
        sh.heizung.vorlauf.widerstand1(1)
        sh.heizung.vorlauf.widerstand1(1)
        logger.info("Tag_Max aktiviert")
    elif zustand == 'tag_med':
        sh.heizung.vorlauf.widerstand1(1)
        sh.heizung.vorlauf.widerstand1(1)
        sh.heizung.vorlauf.widerstand1(1)
        sh.heizung.vorlauf.widerstand1(0)
        logger.info("Tag_Med aktiviert")
    elif zustand == 'tag_min':
        sh.heizung.vorlauf.widerstand1(1)
        sh.heizung.vorlauf.widerstand1(1)
        sh.heizung.vorlauf.widerstand1(0)
        sh.heizung.vorlauf.widerstand1(0)
        logger.info("Tag_Min aktiviert")
    elif zustand == 'nacht':
        sh.heizung.vorlauf.widerstand1(1)
        sh.heizung.vorlauf.widerstand1(0)
        sh.heizung.vorlauf.widerstand1(0)
        sh.heizung.vorlauf.widerstand1(0)
        logger.info("Nacht aktiviert")
    elif zustand == 'frost':
        sh.heizung.vorlauf.widerstand1(0)
        sh.heizung.vorlauf.widerstand1(0)
        sh.heizung.vorlauf.widerstand1(0)
        sh.heizung.vorlauf.widerstand1(0)
        logger.info("Frostschutz aktiviert")
    
    logic.fp_alt = fp
    logger.info("Fußpunkt_alt gesetzt auf " + str(logic.fp_alt))
    Geht die Logik auch eleganter?
    Dankeschön
    Zuletzt geändert von bmx; 18.11.2018, 07:13. Grund: Bitte [ CODE ] nutzen statt [ QUOTE ]

    #2
    Du kannst z.B. ein dictionary verwenden um die ganze Tirade von if unten zu verkleinern.
    Code:
    #Aktionen
    preset = { 'tag_max': (1,1,1,1,"Tag_Max aktiviert"), 
        'tag_med': (1,1,1,0,"Tag_Med aktiviert"),
        'tag_min': (1,1,0,0,"Tag_Min aktiviert"),
        'nacht':(1,0,0,0,"Nacht aktiviert"),
        'frost':(0,0,0,0,"Frostschutz aktiviert") }
    
    settings = preset[zustand]
    sh.heizung.vorlauf.widerstand1(settings[0])
    sh.heizung.vorlauf.widerstand1(settings[1])
    sh.heizung.vorlauf.widerstand1(settings[2])
    sh.heizung.vorlauf.widerstand1(settings[3])
    logger.info(settings[4])
    Du könntest das heizung = true "ausklammern" und das 'frost' als default wert nehmen

    Code:
    #Stufen
    
    zustand = 'frost'
    
    if (heizung == 'true'):
        if ((richtung >= 0) and (fusspunkt >= tagmaxein)) or ((richtung < 0) and (fusspunkt > tagmaxaus)):
            zustand = 'tag_max'
        elif ((richtung >= 0) and (fusspunkt >= tagnormein)) or ((richtung < 0) and (fusspunkt > tagnormaus)):
            zustand = 'tag_med'
        elif ((richtung >= 0) and (fusspunkt >= tagminein)) or ((richtung < 0) and (fusspunkt > tagminaus)):
            zustand = 'tag_min'
        elif ((richtung >= 0) and (fusspunkt >= nachtein)) or ((richtung < 0) and (fusspunkt > nachtaus)):
            zustand = 'nacht'

    Kommentar


      #3
      bmx

      Dankeschön.
      den zweiten Teil des Kommentares habe ich verstanden und umgesetzt.

      Beim ersten Teil war noch von mir ein Fehler drin. Dieser Teil setzt die Item des Schaltaktores, der wiederum dann die Widerstände schaltet. Kann man das auch mit einem dict umsetzen?

      So sieht die Logik jetzt aus.
      Code:
      #!/usr/bin/env python3
      # heizung_vorlauf.py
      
      # 4-Stufen-Steuerung des Vorlaufes in Abhängigkeit vom berechneten Fusspunkt
      # Ausgelöst durch "Fusspunkt" und Außentemperatur
      
      logger.info("Logik HeizungVorlauf ausglöst durch:" + trigger['by'] )
      
      # Werte einlesen
      fusspunkt = sh.heizung.vorlauf.fusspunkt()
      logger.info("Fußpunkt " + str(fusspunkt))
      waermebedarf = bool(sh.heizung.waermebedarf())
      #logger.info("Wärmebedarf " + str(waermebedarf))
      
      # Prüfung, ob persistente Variablen vorhanden, wenn nicht setzen dieser 
      if not hasattr(logic, 'fusspunkt_alt'):
          logic.fusspunkt_alt = fusspunkt
      
      if not hasattr(logic, 'zustand'):
          logic.zustand = None
          
      # Prüfung, ob neuer Fußpunkt größer oder kleiner ist, um die Verlaufsrichtung des Fußpunkts festzustellen
      richtung = round(fusspunkt - logic.fusspunkt_alt, 1)
      
      logger.info("Richtung " + str(richtung))
      
      #Konstanten (Schaltschwellen)
      tagmaxein = 23.5
      tagnormein = 21.5
      tagminein = 19.5
      nachtein = 16.5
      
      tagmaxaus = 22.5
      tagnormaus = 20.5
      tagminaus = 18.5
      nachtaus = 15.0
      
      if (richtung != 0):
          logic.zustand = 'frost'
      
          if (waermebedarf == 1):
              if ((richtung > 0) and (fusspunkt >= tagmaxein)) or ((richtung < 0) and (fusspunkt > tagmaxaus)):
                  logic.zustand = 'tag_max'
              elif ((richtung > 0) and (fusspunkt >= tagnormein)) or ((richtung < 0) and (fusspunkt > tagnormaus)):
                  logic.zustand = 'tag_med'
              elif ((richtung > 0) and (fusspunkt >= tagminein)) or ((richtung < 0) and (fusspunkt > tagminaus)):
                  logic.zustand = 'tag_min'
              elif ((richtung > 0) and (fusspunkt >= nachtein)) or ((richtung < 0) and (fusspunkt > nachtaus)):
                  logic.zustand = 'nacht'
              else:
                  logger.info("keine Zustandsänderung") 
      
          logger.info("Zustand gesetzt auf " + str(logic.zustand))
      
          #Aktionen
          if logic.zustand == 'tag_max':
              sh.heizung.vorlauf.widerstand1(1)
              sh.heizung.vorlauf.widerstand2(1)
              sh.heizung.vorlauf.widerstand3(1)
              sh.heizung.vorlauf.widerstand4(1)
              logger.info("SA 1-4 an")
          elif logic.zustand == 'tag_med':
              sh.heizung.vorlauf.widerstand1(1)
              sh.heizung.vorlauf.widerstand2(1)
              sh.heizung.vorlauf.widerstand3(1)
              sh.heizung.vorlauf.widerstand4(0)
              logger.info("SA 1-3 an")
          elif logic.zustand == 'tag_min':
              sh.heizung.vorlauf.widerstand1(1)
              sh.heizung.vorlauf.widerstand2(1)
              sh.heizung.vorlauf.widerstand3(0)
              sh.heizung.vorlauf.widerstand4(0)
              logger.info("SA 1-2 an")
          elif logic.zustand == 'nacht':
              sh.heizung.vorlauf.widerstand1(1)
              sh.heizung.vorlauf.widerstand2(0)
              sh.heizung.vorlauf.widerstand3(0)
              sh.heizung.vorlauf.widerstand4(0)
              logger.info("SA 1 an")
          elif logic.zustand == 'frost':
              sh.heizung.vorlauf.widerstand1(0)
              sh.heizung.vorlauf.widerstand2(0)
              sh.heizung.vorlauf.widerstand3(0)
              sh.heizung.vorlauf.widerstand4(0)
              logger.info("kein SA an")
      else:
          logger.info("keine Wertänderung") 
          
      logic.fusspunkt_alt = fusspunkt
      logger.info("Fußpunkt_alt gesetzt auf " + str(logic.fusspunkt_alt))

      Kommentar


        #4
        Hm Du mußt doch bloß das dict bei preset ändern und die Items der Widerstände korrekt mit 1...4 benennen...?

        Ansonsten kannst Du IMHO
        Code:
        if not hasattr(logic, 'fusspunkt_alt'):
            logic.fusspunkt_alt = fusspunkt
        schreiben als
        Code:
        logic.fusspunkt_alt = getattr(logic, 'fusspunkt_alt', fusspunkt )
        und
        Code:
        logic.zustand = getattr(logic, 'zustand', None)

        Kommentar


          #5
          bmx
          Danke das klappt soweit.

          Zur Errechnung des max. Fußpunktes aller Räume habe ich auch eine Logik erstellt. Gibt es auch dafür eine einfachere Möglichkeit?

          Code:
          #!/usr/bin/env python3
          # heizung_fusspunkt.py
          
          # maximalen Fusspunkt für alle Räume ermitteln
          
          # lokale Variablen
          #    x;              jeweiliger Istwert in °C
          #    w;              jeweiligerSollwert in °C
          #    fusspunkt;      jeweiliger, errechnerter Fusspunkt in °C
          #    fusspunkt_max   maximaler Fusspunkt in °C
          
          logic.fusspunkt_max = getattr(logic, 'fusspunkt_max', -20 )
          logic.fusspunkt_max_old = getattr(logic, 'fusspunkt_max_old', logic.fusspunkt_max )
          
          
          # EG_wohnen
          x = sh.raumtemp.eg.wohnen.ist.wz_tvwand_ist()
          w = sh.raumtemp.eg.wohnen.rtr_automatik.soll()
          fusspunkt = (2.0 * w) - x
          if fusspunkt > logic.fusspunkt_max:
              logic.fusspunkt_max = fusspunkt
              
          # EG_flur
          x = sh.raumtemp.eg.diele.ist()
          w = sh.raumtemp.eg.diele.soll()
          fusspunkt = (2.0 * w) - x
          if fusspunkt > logic.fusspunkt_max:
              logic.fusspunkt_max = fusspunkt
          
          # OG_buero
          x = sh.raumtemp.og.buero.ist()
          w = sh.raumtemp.og.buero.soll()
          fusspunkt = (2.0 * w) - x
          if fusspunkt > logic.fusspunkt_max:
              logic.fusspunkt_max = fusspunkt
          
          # OG_bad
          x = sh.raumtemp.og.bad.ist()
          w = sh.raumtemp.og.bad.soll()
          fusspunkt = (2.0 * w) - x
          if fusspunkt > logic.fusspunkt_max:
              logic.fusspunkt_max = fusspunkt
              
          # OG_kind
          x = sh.raumtemp.og.kind.ist()
          w = sh.raumtemp.og.kind.soll()
          fusspunkt = (2.0 * w) - x
          if fusspunkt > logic.fusspunkt_max:
              logic.fusspunkt_max = fusspunkt
          
          # OG_schlafen
          x = sh.raumtemp.og.schlafzimmer.ist()
          w = sh.raumtemp.og.schlafzimmer.soll()
          fusspunkt = (2.0 * w) - x
          if fusspunkt > logic.fusspunkt_max:
              logic.fusspunkt_max = fusspunkt
          
          # OG_gaeste
          x = sh.raumtemp.og.gaestezimmer.ist()
          w = sh.raumtemp.og.gaestezimmer.soll()
          fusspunkt = (2.0 * w) - x
          if fusspunkt > logic.fusspunkt_max:
              logic.fusspunkt_max = fusspunkt
          
          logic.fusspunkt_max = round(logic.fusspunkt_max, 1)
          
          if logic.fusspunkt_max != logic.fusspunkt_max_old:
              sh.heizung.vorlauf.fusspunkt(logic.fusspunkt_max)
              logic.fusspunkt_max_old = logic.fusspunkt_max
              logger.info("Fußpunktes berechnet zu " + str(logic.fusspunkt_max))
          else:
              logger.info("keine Änderung des Fußpunktes")

          Die Anfrage hat sich in sofern erledigt, dass ich umgestellt habe und den Fußpunkt im jeweilgen Raum mit einem eval errechne und den maximalen Fußpunkt ebenfalls mit einem eval auf einem separatem Item ermittle. Somit ist keine Logik mehr nötig.
          Zuletzt geändert von Sisamiwe; 18.11.2018, 13:53. Grund: Ich habe umgestellt und errechne des Fußpunkt im jeweilgen Raum mit einem eval und ermittle den maximalen Fußpunkt ebenfalls mit einem eval auf einem separatem Item.

          Kommentar

          Lädt...
          X