Kellerluft Steuerung

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
MadTrinity
User
Beiträge: 5
Registriert: Mittwoch 5. April 2017, 18:06

Hallo,

ich habe seit kurzer Zeit mir auch mal einen PI zugelegt ohne zu ahnen das Linux und die Programmiersprachen Python PHP so kompliziert sind mag wohl daran liegen das ich zuvor nur mit Windows gearbeitet habe und ein wenig in C# programmiert habe.
Das Auslesen von Gaszähler, Stromzähler, Wasserzähler funktionier wunderbar auch Daten aus der Heizung auslesen und in die MySQLdb schreiben geht einwandfrei.
Mein neuestes Projekt ist die Luft im Keller zu steuern bzw das Fenster und den Lüfter.
Wie gesagt da ich Blutiger Anfänger bin mir die Syntax schwer fällt ich nicht unbedingt Python studieren möchte hoffe ich hier ein paar Tipps zubekommen was an meinem Code alles so falsch ist.
Ich habe einen Sensor im Keller und eine Außen die Werte schreibe ich Minütlich in eine MySQLdb das funktioniert. Jetzt möchte ich anhand der Werte gucken wo die Luft besser bzw. trockner ist um das Fenster und den Lüfter dementsprechend zu schalten.
Ich habe einen Ketten Motor am Fenster montiert der leider von alleine sehr spät abschaltet so das er mir den Rahmen am Fenster verzieht deswegen darf der nur 8 Sekunden laufen. Also 8 Sekunden für auf und 8 Sekunden für zu.
Leider hat Python manchmal das Problem obwohl in der Datenbank der Wert AUF steht trotzdem das Fenster versucht zu öffnen somit sich wieder mein Rahmen am Fenster verzieht.
Leider hat Python nicht so eine schöne IDE wie Visual Studio und somit kann ich nicht wirklich sehen wo es da hakt???
Dann habe ich noch eine Frage wie könnte ich noch einbauen das der Lüfter nicht immer an ist sondern z.B. 30min an 30min aus???
Kann mir vielleicht einer Helfen.
Vielen Dank vorab
Gruß

Code: Alles auswählen

#-*- coding: utf-8 -*-

import RPi.GPIO as GPIO
import time
import datetime
import MySQLdb
import math

TempK="20"
TempA="20"
HydroK="0.0"
HydroA="0.0"
bedingung = "Status"
fensterstatus = 0
luefterstatus = 0
entfeuchterstatus = 0
fensterbewegung = 0
luft=0

#GPIO fuer Steuerung
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(True)

#GPIO definieren
RELAI_FensterAuf = 33 
RELAI_FensterZu = 35
RELAI_Luefter = 22
RELAI_Entfeuchter = 29

#GPIO als Ausgang
GPIO.setup(RELAI_FensterAuf, GPIO.OUT)
GPIO.setup(RELAI_FensterZu, GPIO.OUT)
GPIO.setup(RELAI_Luefter, GPIO.OUT)
GPIO.setup(RELAI_Entfeuchter, GPIO.OUT)

#GPIO als Eingang für Kellerfensterschalter (11) GPIO17
GPIO.setup(11,GPIO.IN,pull_up_down = GPIO.PUD_DOWN)

#Status aus Datenbank lesen
def getStatus():
    global fensterstatus
    global luefterstatus
    global entfeuchterstatus
    db = MySQLdb.connect(host="localhost", user="root", passwd="2012", db="Haus")
    cursor = db.cursor()
    cursor.execute("""SELECT Fenster, Luefter, Luftentfeuchter FROM Kellerstatus ORDER BY zeitstempel DESC LIMIT 1""")
    result2 = cursor.fetchall()
    for data in result2:
        fensterstatus=data[0]
        luefterstatus=data[1]
        entfeuchterstatus=data[2]
    cursor.close()
    print("Status aus Datenbank eingelesen " + str(fensterstatus)+str(luefterstatus)+str(entfeuchterstatus))
    return fensterstatus, luefterstatus, entfeuchterstatus

#Temperatur und Luftfeuchte einlenen aus Kellerdatenbank
def getWerte():
    global TempK
    global TempA
    global HydroA
    global HydroK
    db = MySQLdb.connect(host="localhost", user="root", passwd="2012", db="Haus")
    cursor = db.cursor()
    cursor.execute("""SELECT temperatur, hydro, temperaturauss, hydroauss FROM keller ORDER BY zeitstempel DESC LIMIT 1""")
    AB = cursor.fetchall()
    for data in AB:
        TempK=data[0]
        TempA=data[2]
        HydroK=data[1]
        HydroA=data[3]
    cursor.close()
    print("Werte aus Kellerdatenbank eingelesen " + str(TempK) + str(TempA)+ str(HydroA) + str(HydroK))
    return TempK, TempA, HydroK, HydroA

#Status in Datenbank schreiben
def setStatus(fs,ls,es,bd):
    global fensterstatus
    global luefterstatus
    global entfeuchterstatus
    db = MySQLdb.connect(host="localhost", user="root", passwd="2012", db="Haus")
    cursor = db.cursor()
    cursor.execute("UPDATE Kellerstatus SET Fenster=%s, Luefter=%s, Luftentfeuchter=%s, bedingung=%s, zeitstempel=CURRENT_TIMESTAMP",(fs,ls,es,bd))
    db.commit()
    cursor.close()
    fensterstatus=fs
    luefterstatus=ls
    entfeuchterstatus=es
    print("Werte in Datenbank geschrieben " + str(fensterstatus) + str(luefterstatus) + str(entfeuchterstatus))
    return fensterstatus, luefterstatus, entfeuchterstatus, bedingung

#Taupunktberechnung
def Taupunkt(t, h):
    a1 = 7.45
    b1 = 235
    dp = float(t)
    fw = float(h)
    x1=(a1*dp)/(b1+dp)
    e1=6.1*math.exp(x1*2.3025851)
    e2=e1*fw/100
    x2=e2/6.1
    x3=0.434292289*math.log(x2)
    dew=(235*x3)/(7.45-x3)*100
    dew=math.floor(dew)/100
    hum=(216.7*e2)/(273.15+dp)*100
    hum=round(hum)/100
    dew =  "%02.2f" % (dew)
    hum =  "%02.2f" % (hum)
    dew = '{: >5}'.format(dew)
    hum = '{: >5}'.format(hum)
    #print("dewpoint: "+dew+" °C (condensing)")
    #print("feu:      "+hum+" (g water per 1m³ air)")
    return dew,hum

#Fennstermotor steuern
def fenster(x):
    print("Fenster " + str(x))
    global fensterbewegung
    global RELAI_FensterAuf
    global RELAI_FensterZu
    global fensterstatus
    if x == 1:
        if fensterbewegung == 0:
            if fensterstatus == 0:
                fensterbewegung = 1
                GPIO.output(RELAI_FensterAuf, GPIO.HIGH)
                time.sleep(8)
                GPIO.output(RELAI_FensterAuf,GPIO.LOW)
                fensterbewegung = 0
                setStatus(1,luefterstatus,entfeuchterstatus,bedingung)
                print("Fenster ist AUF")
    elif x == 0:
        if fensterbewegung == 0:
            fensterbewegung = 1
            GPIO.output(RELAI_FensterZu, GPIO.HIGH)
            time.sleep(8)
            GPIO.output(RELAI_FensterZu, GPIO.LOW)
            fensterbewegung = 0
            setStatus(0,luefterstatus, entfeuchterstatus, bedingung)
            print("Fenster ist ZU")
    return fensterstatus

def luefter(z):
    global luefterstatus
    print("Lüfter " + str(z))
    if z == 1:
        GPIO.output(RELAI_Luefter, GPIO.HIGH)
        setStatus(fensterstatus,1,entfeuchterstatus,bedingung)
    elif z == 0:
        GPIO.output(RELAI_Luefter,GPIO.LOW)
        setStatus(fensterstatus,0,entfeuchterstatus,bedingung)
    return z

def entfeuchter(y):
    global entfeuchterstatus
    print("entfeuchter " + str(y))
    if y == 1:
        GPIO.output(RELAI_Entfeuchter, GPIO.HIGH)
        setStatus(fensterstatus,luefterstatus,1,bedingung)
    elif y == 0:
        GPIO.output(RELAI_Entfeuchter, GPIO.LOW)
        setStatus(fensterstatus,luefterstatus,0,bedingung)
    return y

def lueften(x):
    global fensterstatus
    global luefterstatus
    if x == 1:
        if fensterstatus == 0 and luefterstatus == 0:
            luft=1
            print("Lüfter = AUS und Fenster = ZU")
            luefter(1)
            print("Lüfter eingeschaltet")
            fenster(1)
            print("Fenster geöffnet")
            print("Lüften")
            for i in range(0,60):
                print(str(60 - i) + " Sekunden")
                time.sleep(1)
            print("Lüften beenden")
            luefter(0)
            print("Lüfter ausgeschaltet")
            fenster(0)
            print("Fenster geschlossen")
            luft = 0
        elif fensterstatus == 1 and luefterstatus == 0:
            luft = 1
            print("Fenster = AUF und Lüfter = AUS")
            luefter(1)
            print("Lüfter eingeschaltet")
            print("Lüften")
            for i in range(0,60):
                print(str(60 - i) + " Sekunden")
                time.sleep(1)
            print("Lüften beenden")
            luefter(0)
            print("Lüfter ausgeschaltet")
            luft = 0
        elif fensterstatus == 0 and luefterstatus == 1:
            luft = 1
            print("Fenster = ZU und Lüfter = AN")
            fenster(1)
            print("Fenster geöffnet")
            print("Lüften")
            for i in range(0,60):
                print(str(60 - i) + " Sekunden")
                time.sleep(1)
            print("Lüften beenden")
            fenster(0)
            print("Fenster geschlossen")
            luft = 0
        elif fensterstatus == 1 and luefterstatus == 1:
            print("Alles AN bzw AUF")

    elif x == 0:
        if fensterstatus == 1:
            print("Fenster ist AUF und wird geschlossen")
            fenster(0)
            print("Fenster geschlossen")
        if luefterstatus == 1:
            print("Lüfter ist AN und wird ausgeschaltet")
            luefter(0)
            print("Lüfter ist AUS")
        luft = 0
    return x

def doIfHigh(channel):
        
    if GPIO.input(channel) == GPIO.HIGH:
        getStatus()
        print("Taster gedrückt == HIGH")
        #if luft == 0:
            #lueften(1)
            #print("Lüften EIN gedrückt")
        #elif luft == 1:
            #print("Lüften AUS gedrückt")
            #lueften(0)

getStatus()
GPIO.output(RELAI_FensterZu,0)
GPIO.output(RELAI_FensterAuf,0)
GPIO.output(RELAI_Luefter, luefterstatus)
GPIO.output(RELAI_Entfeuchter, entfeuchterstatus)

#Taster 
GPIO.add_event_detect(11,GPIO.BOTH,callback=doIfHigh,bouncetime =200)

try:
    print("Fensterstatus " + str(fensterstatus))
    print("Lüfterstatus " + str(luefterstatus))
    print("entfeuchterstatus " + str(entfeuchterstatus))
    
    while True:
        getWerte()
        getStatus()
        #wertA_Alt = wertA_Neu
        #wertK_Alt = wertK_Neu
        wertA_Neu = Taupunkt(TempA,HydroA)
        wertK_Neu = Taupunkt(TempK,HydroK)
        
        if HydroK >= 55 and HydroK <=68:
            bedingung = "Luft Keller >= 55 und <= 68"
            if HydroA < (HydroK - 10):
                bedingung = "Aussenfeuchte min 10 % besser"
                if wertA_Neu[1] < wertK_Neu[1]:
                    bedingung = "Wassergehalt Außen auch besser"
                    if TempK >= 8 and TempK <= 25:
                        bedingung = "Kellertemperatur zwischen 8 und 25 Grad"
                        if luefterstatus == 0 and fensterstatus == 0:
                            bedingung = "Luft Außen ist besser 0 0"
                            luefter(1)
                            fenster(1)
                            entfeuchter(0)
                        elif luefterstatus == 1 and fensterstatus == 0:
                            bedingung = "Luft Außen ist besser 1 0"
                            fenster(1)
                            entfeuchter(0)
                        elif luefterstatus == 0 and fensterstatus == 1:
                            bedingung = "Luft Außen ist besser 0 1"
                            luefter(1)
                            entfeuchter(0)
                    else:
                        bedingung = "Temperatur Keller nicht zwischen 8 und 25 Grad"
                        if fensterstatus == 1:
                            fenster(0)
                        if luefterstatus == 1:
                            luefter(0)
                        if entfeuchterstatus == 0:
                            entfeuchter(1)
                else:
                    bedingung ="Wassergehalt Außen höher"
                    if fensterstatus == 1:
                        fenster(0)
                    if luefterstatus == 1:
                        luefter(0)
                    if entfeuchterstatus == 0:
                        entfeuchter(1)
            else:
                bedingung ="Luftfeuchte Außen ist höher"
                if fensterstatus == 1:
                    fenster(0)
                if luefterstatus == 1:
                    luefter(0)
                if entfeuchterstatus == 1:
                    entfeuchter(0)
        elif HydroK > 68:
            bedingung = "Luftfeuchte über 68"
            if fensterstatus == 1:
                fenster(0)
            if luefterstatus == 1:
                luefter(0)
            if entfeuchterstatus == 0:
                entfeuchter(1)
        elif HydroK <= 52:
            if HydroA < HydroK - 15:
                bedingung = "Luft Außen Super"
                if entfeuchterstatus == 1:
                    entfeuchter(0)
                if luefterstatus == 1:
                   luefter(0)
                elif luefterstatus == 0:
                   luefter(1)
                if fensterstatus == 0:
                    fenster(1)
        time.sleep(600)
        print("Schleife 10 Minuten")
        print(time.strftime("%H:%M:%S"))
                    

except KeyboardInterrupt:
    GPIO.cleanup()

    
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

@MadTrinity: im Gegensatz zu C# sollte die Syntax von Python deutlich einfacher sein. Zudem gelten allgemeine Regeln für quasi alle Programmiersprachen: keine globalen Variablen, aussagekräftige Namen (Was soll Temp oder K bei TempK heißen und was ist dann A bei TempA?)

Zudem sollten Variablen keine Dummywerte erhalten. Die ganzen Initalisierungen (Zeile 9-18) sind überflüssig und ein String keine Zahl. In getStatus ist das global unnötig, weil Du die Werte ja als Rückgabewerte hast. Wenn Du einen Wert aus der Datenbank liest, dann ist fetchall und eine for-Schleife falsch, dafür gibt es fetchone. In jeder Funktion wieder die Datenbankverbindung mit allen Parametern zu haben, ist umständlich, wenn Du z.B. das Passwort ändern willst. Dafür schreibt man Funktionen, die das EINMAL machen. Und sind das wirklich Tabellen mit nur einer Zeile?
In der Funktion fenster steht zweimal das gleiche, das sollte man zusammenfassen und die Unterschiede in Variablen packen. luefter und entfeuchter ebenso. Wenn sich Teile des Status nicht ändern, sollte man sie auch nicht angeben müssen; das spart einem auch die globalen Variablen.
In lueften steht sogar 3mal das selbe.
Zeile 253/254: wenn man Funktionen mit Rückgabewerten hat, sollte man die auch nutzen.
Die Bedingungen wann welches Fenster zu öffnen und welcher Lüfter anzuschalten ist, ist mir zu kompliziert, als dass ich das als Code ausgeschrieben lesen möchte.
BlackJack

@MadTrinity: C# könntest Du auch auf dem Raspi verwenden. Oder Windows 10 Embedded darauf installieren.
MadTrinity
User
Beiträge: 5
Registriert: Mittwoch 5. April 2017, 18:06

BlackJack Danke schon mal für die Antwort,
für mich sind die Namen aussagekräftig TempK = Temperatur Keller, TempA = Temperatur Außen ob ich den Code in Jahren noch lesen könnte lasse ich mal dahin gestellt.
Den Variablen habe ich die Dummywerte zugewiesen weil Python irgendwas zu meckern hatte das gleiche Gilt auch für die Global Sache.
Fetchall habe ich nur aus meinen anderen Programmen übernommen werde jetzt mal fetchone einsetzten, die Tabelle hat jeweils nur eine Zeile Fenster Luefter Luftentfeuchter zeitstempel bedingung die ich alle paar Minuten per update aktualisiere
Die ganzen Print Zeilen habe ich nur eingebaut um den Fehler zu finden hat aber noch nicht wirklich was gebracht.
Im Moment ist gerade wenig Zeit habe Nachwuchs bekommen da wird es nicht gerne gesehen wenn ich in der wenigen Zeit auch noch vor dem Laptop sitze.
Versuche mir mal das mit dem C# für den PI anzugucken aber Windows bleibt erst mal vom PI weg habe mich da jetzt so durchgekämpft das soweit alles läuft.
BlackJack

@MadTrinity: `kellertemperatur` und `aussentemperatur` wären also verständlicher. Bei `TempK` besteht die Gefahr, dass die Abkürzung falsch verstanden wird und jemand denkt das K steht für Kelvin.

Das mit den globalen Variablen, den Dummywerten, und ``global`` ist absolut übel. Das Python das „irgendwas zu meckern hatte“ solltest Du ernst nehmen und verstehen *was* da angemeckert wurde. Denn das Programm ist nur sehr schwer nachvollziehbar mit dem ganzen globalen Zustand und Du machst an einigen Stellen sehr komische Sachen, wenn es nicht sogar Fehler sind. Zum Beispiel werden in `setStatus()` die Argumente sowohl in die Datenbank geschrieben, als auch den globalen Variablen zugewiesen, als auch die Werte als Rückgabewerte der Funktion an den Aufrufer zurückgegeben. Nun ja, fast! Das Muster wird nicht für alle Argumente/globale Variablen durchgezogen. Ist das jetzt gewollt oder nicht? Kann das *irgendwo* im *gesamten* Quelltext zu einem Fehler führen? Dazu muss man das *alles* auf einmal im Blick haben und verstehen. Was deutlich zu viel ist um es komplett im Kopf zu haben. Globaler Zustand halt. Weg damit! ``global`` hat nichts in sauberen, nachvollziehbaren Programmen zu suchen, und auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Keine Variablen. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

`datetime` wird importiert aber nirgends verwendet.

Die Kommentare *vor* den Funktionen wären besser DocStrings.

Bei `RELAI_*` fehlt ein `S`. Zudem werden Konstanten per Konvention komplett in Grossbuchstaben geschrieben und da macht ``global`` nicht einmal Sinn.

Python hat für Wahrheitswerte `True` und `False`, da sollte man nicht 1 und 0 für missbrauchen.

Die Datenbanktabelle ist komisch. Du speicherst dort auch wenn sich nur ein Wert des Zustands geändert hat immer alle Werte in einer neuen Zeile ab. Das macht nicht wirklich Sinn und es fallen dadurch deutlich mehr Daten an als notwendig wären. Wenn sich ein Wert nicht ändert, kann man auch gar nicht mehr feststellen wegen welchem der Gesamtzustand eigentlich gespeichert wurde.
MadTrinity
User
Beiträge: 5
Registriert: Mittwoch 5. April 2017, 18:06

Hallo BlackJack,
leider bin ich erst jetzt dazu gekommen zu antworten, Danke noch mal für die aufklärung was ich bisher alles falsch gemacht habe.
Habe mich entschlossen den alten Code zu löschen und noch mal neu aufzusetzen.

Code: Alles auswählen

from RPi import GPIO
import time
import MySQLdb
import math

LOCALHOST = "localhost"
USER = "root"
PASSWORD = "2012"
DB = "Haus"
TASTER = 11
AUSGANG_Luefter = 22
AUSGANG_Entfeuchter = 29
AUSGANG_Fenster_Zu = 35
AUSGANG_Fenster_Auf = 33

#Wenn sich ein Status ändert
def setStatus(fensterstatus,luefterstatus,entfeuchterstatus,warum):
    db = MySQLdb.connect(host=LOCALHOST, user=USER, passwd=PASSWORD, db=DB)
    cursor = db.cursor()
    #cursor.execute("UPDATE Kellerstatus SET Luftentfeuchter = 1 WHERE Luftentfeuchter = 0")
    cursor.execute("UPDATE Kellerstatus SET Fenster=%s, Luefter=%s, Luftentfeuchter=%s, bedingung=%s, zeitstempel=CURRENT_TIMESTAMP",(fensterstatus,luefterstatus,entfeuchterstatus,warum))
    db.commit()
    cursor.close()
    db.close()
    return fensterstatus,luefterstatus,entfeuchterstatus,warum

#Status der Geräte einlesen
def getStatus():
    db = MySQLdb.connect(host=LOCALHOST, user=USER, passwd=PASSWORD, db=DB)
    cursor = db.cursor()
    cursor.execute("""SELECT Fenster, Luefter, Luftentfeuchter FROM Kellerstatus ORDER BY zeitstempel DESC LIMIT 1""")
    row = cursor.fetchone()
    while row is not None:
        fensterstatus=row[0]
        luefterstatus=row[1]
        entfeuchterstatus=data[2]
        cursor.close()
        db.close()
    return fensterstatus,luefterstatus,entfeuchterstatus
	
#Temperatur und Luftfeuchte Werte auslesen
def getWerte():
    db = MySQLdb.connect(host=LOCALHOST, user=USER, passwd=PASSWORD, db=DB)
    cursor = db.cursor()
    cursor.execute("""SELECT temperatur, hydro, temperaturauss, hydroauss FROM keller ORDER BY zeitstempel DESC LIMIT 1""")
    row = cursor.fetchone()
    while row is not None:
        TemperaturKeller=row[0]
        TemperaturAussen=row[2]
        HydroKeller=row[1]
        HydroAussen=row[3]
        row = cursor.fetchone()
    cursor.close()
    db.close()
    return TemperaturKeller, TemperaturAussen, HydroKeller, HydroAussen


#Lüfter Ein-Ausschalten
def luefter(state):
    if state == True:
        GPIO.output(AUSGANG_Luefter, GPIO.HIGH)
	#status ändern
    else:
        GPIO.output(AUSGANG_Luefter, GPIO.LOW)
	#status ändern

#Fenster Öffnen-Schließen
def fenster(state):
    if state == True:
        GPIO.output(AUSGANG_Fenster_Auf, GPIO.HIGH)
        time.sleep(8)
        GPIO.output(AUSGANG_Fenster_Auf, GPIO.LOW)
	#status ändern
    else:
        GPIO.output(AUSGANG_Fenster_Zu, GPIO.HIGH)
        time.sleep(8)
        GPIO.output(AUSGANG_Fenster_Zu, GPIO.LOW)
	#status ändern

#Entfeuchter Ein-Ausschalten
def entfeuchter(state):
    if state == True:
        GPIO.output(AUSGANG_Entfeuchter, GPIO.HIGH)
	#status ändern
    else:
        GPIO.output(AUSGANG_Entfeuchter,GPIO.LOW)
	#status ändern

#Taupunktberechnung
def taupunkt(t, h):
    a1 = 7.45
    b1 = 235
    dp = float(t)
    fw = float(h)
    x1=(a1*dp)/(b1+dp)
    e1=6.1*math.exp(x1*2.3025851)
    e2=e1*fw/100
    x2=e2/6.1
    x3=0.434292289*math.log(x2)
    dew=(235*x3)/(7.45-x3)*100
    dew=math.floor(dew)/100
    hum=(216.7*e2)/(273.15+dp)*100
    hum=round(hum)/100
    dew =  "%02.2f" % (dew)
    hum =  "%02.2f" % (hum)
    dew = '{: >5}'.format(dew)
    hum = '{: >5}'.format(hum)
    #print("dewpoint: "+dew+" °C (condensing)")
    #print("feu:      "+hum+" (g water per 1m³ air)")
    return dew,hum

#GPIO zuweisung	
def setup_gpio():
    GPIO.setmode(GPIO.BOARD)
    GPIO.setwarnings(True)
    GPIO.setup(TASTER, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    GPIO.setup(AUSGANG_Luefter, GPIO.OUT)
    GPIO.setup(AUSGANG_Entfeuchter,GPIO.OUT)
    GPIO.setup(AUSGANG_Fenster_Auf, GPIO.OUT)
    GPIO.setup(AUSGANG_Fenster_Zu, GPIO.OUT)
 
 
#Keller Lüften für x Minuten
def do_lueften(channel):
    print('Taster wurde gedrueckt')
     
     
def main():
    #setup_gpio()
    
    try:
        #GPIO.add_event_detect(TASTER, GPIO.FALLING, callback=do_lueften, bouncetime=200)
        print("OK")
		#Prüfen wie ist die Luft Fenster und Lüfter Steuern
    except KeyboardInterrupt:
        pass
    finally:
        GPIO.cleanup()
     
if __name__ == '__main__':
    main()

Also Ziel ist es einen Lüfter, das Fenster und den Luftentfeuchter zu steuern, anhand der Werte die mir die Sensoren liefern einer INNEN und einer ist AUSSEN.
Grob gesagt wenn die Luftfeuchte draußen kleiner als Innen ist soll sich das Fenster öffnen der Lüfter 30 Minuten mitlaufen dann für 30 Minuten pausieren und so weiter bis entweder die Luftfeuchte ok ist oder aber draußen es feuchter wird der Luftentfeuchter soll nur angehen wenn ein gewisser wert überschritten wird.
Die Werte werden alle 2 Minuten in eine Tabelle geschrieben.
Die KellerLuftSteuerung wie ich sie nenne zeige ich dann auf meiner Intranet Seite an Lüfter ist AN oder AUS … deswegen muss ich auch die Werte in die Kellerstatus Tabelle schreiben um an die Aktuellen Zustände zu kommen.
Letztendlich möchte ich noch einen Taster benutzen um Manuell mal zu lüften z.B. 30 Minuten Fenster auf und Lüfter an.
Nur mal eine kleine Erklärung was ich machen möchte.
Mein Ansatz ich wollte die Variablen fensterstatus, luefterstatus, entfeuchterstatus, warum nutzen um den Status einzulesen damit zu arbeiten und dann bei änderung wieder in die Tabelle zu schreiben.
Was wäre den eine Alternative oder wie kann man das Besser machen du meintest ja das sei Komisch
Gruß
MadTrinity
__deets__
User
Beiträge: 14480
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ein paar Anmerkungen:

Statt "wert == True" reicht ein simples "wert". Statt "if wert == True: GPIO.output(AUSGANG_Luefter, GPIO.HIGH)" reicht "GPIO.output(AUSGANG_Luefter, wert)".

Zusammen also so:

Code: Alles auswählen

def luefter(state):
        GPIO.output(AUSGANG_Luefter, state)
Eine etwas kuerzere Fassung der Fenstersteuerung:

Code: Alles auswählen

def fenster(state):
    ausgang = AUSGANG_Fenster_Auf if state else AUSGANG_Fenster_Zu
    GPIO.output(ausgang, GPIO.HIGH)
    time.sleep(8)
    GPIO.output(ausgang, GPIO.LOW)
Generell halte ich deine Fenster-Geschichte fuer fragwuerdig. Du solltest dringend einen Endabschalter einbauen, statt dieses Zeit-basierte Vorgehen. Denn wenn dir dein System im unguenstigen Moment abschmiert, weisst du nicht mehr, wo du bist, und machst deine Anlage kaputt. Generell wuerde ich das ganze in eine eigene Klasse kapseln, die eine Vorstellung davon hat, ob das Fenster jetzt auf oder zu ist, und entsprechend vor wiederholtem oeffnen/schliessen schuetzt. Mit einem solchen Endabschalter wuerde zB das Fenster immer erstmal in eine definierte Position gefahren werden, und danach kann es sicher benutzt werden.

Die Berechnung des Taupunktes macht in meinen Augen den Fehler, diese Werte gleich zu Strings zu konvertieren. Damit sind die spaeter nicht mehr gut verwendbar. Konvertiere sie stattdessen erst, wenn das notwendig ist.

Deine gewuenschte Steuerungslogik ist in meinen Augen etwas sehr kompliziert. Ich bin kein Experte fuer Lueftungssteurung, aber mir kommt es seltsam vor, dass du so ein Intervallueften anpeilst. Oder gibt es dafuer einen Grund?

Denn wenn du davon absiehst, dann wird die Steuerung deutlich einfacher. Kann der Luefter laufen? Dann laeuft er.
MadTrinity
User
Beiträge: 5
Registriert: Mittwoch 5. April 2017, 18:06

@__deets__
Hi das verkürzt den Code Natürlich ungemein.
Kompliziert ist das Ganze in meinen Augen nicht, der kleine Raum hat ein Fenster und fast gegenüberliegend hat die Wand einen Durchbruch in dem sich ein Lüfter befindet.
Durch den Lüfter wird Natürlich die Luft schneller getauscht, hat aber den Nachteil das der Lüfter Strom verbraucht und auch zu hören ist.
Deswegen wollte ich den Lüfter nicht so lange laufen lassen.
Das zwangslüften möchte ich mit einem Taster realisieren das heißt auch wenn die Werte gerade gegen das Öffnen des Fensters sprechen muss man trotzdem mal Lüften.
Ich könnte wenn unbedingt Nötig einen Reedkontakt schalter einbauen und daran erkennen ob das Fenster auf und zu ist.
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

@MadTrinity: von einer Funktion, die setStatus heißt, erwartet man eigentlich nicht, dass sie etwas zurückgibt, zumal der Rückgabewert ja identisch zu den Parametern ist. Die while-Schleife in getStatus ist quatsch. row ändert sich ja nie, das ist also eine Endlosschleife, wenn row nicht None ist, andernfalls ist fensterstatus, luefterstatus und entfeuchterstatus nicht definiert und es gibt einen UnboundLocalError. Zusätzlich ist data nicht definiert. In getWerte hast Du vorherige for-Schleife nur komplizierter als while-Schleife geschrieben, obwohl die auch nur maximal einmal durchlaufen wird.
__deets__
User
Beiträge: 14480
Registriert: Mittwoch 14. Oktober 2015, 14:29

Aus langjähriger Erfahrung mit Robotern und anderen elektromechanischen Gerätschaften rate ich dir wirklich nachdrücklich dazu, einen endabschalter einzubauen. Du selbst sagst, das sich dein Fensterrahmen verzieht, wenn du dir der Stellung nicht bewusst bist. Und ein Absturz im falschen Moment kann genau das nach sich ziehen.

Und wenn die Steuerung so simpel ist, dann schreib sie doch einfach ;)

Ich finde sie sehr kompliziert & auch am Bedarf vorbei gedacht: wieso nervt die Lüft erst nach 30 Minuten? Wenn der nervt, nervt der sofort. Eine in meinen Augen viel sinnvollere Steuerung (die auch noch einfacher zu implementieren ist) sieht so aus:

- Lüfter an, wenn lüften gut ist (nach deinen oben beschriebenen Taupunkt
- wahschalter mit 3 Stellungen: Automatik, an, aus.

Damit bestimmt der Schalter klar, was Sache ist, statt das sich der Benutzer fragen muss, wie lange der denn jetzt noch läuft.
MadTrinity
User
Beiträge: 5
Registriert: Mittwoch 5. April 2017, 18:06

Hi,

ich besorge mir jetzt mal 2 Reed Kontaktschalter dann weiß genau wann das Fenster Auf bzw. Zu ist.

Ich möchte halt so wenig wie möglich Energie verwenden deswegen wollte ich den Lüfter Ein und Ausschalten, die schleife hat ein Intervall von 30 Minuten wenn der Lüfter An ist wird er dann ausgeschaltet und im nächsten durchgang wieder angeschaltet.
Ursprünglich wollte ich die Werte vergleichen sprich Neuer Wert und Alter Wert um festzustellen in wie weit der Lüfter das ganze verbessert oder auch nicht, leider habe ich noch keine lösung gefunden.

Gruß
__deets__
User
Beiträge: 14480
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn es mechanisch gut möglich ist, sind zwei Schalter fein. Aber für vernünftige Funktion reicht auch nur einer. Wann immer das Programm startet, fährt es das Fenster zu, um so in einen definierten Zustand zu kommen. Das reicht dann. Der zweite ist interessanter, um auch beim Fenster die zeitabhängige Steuerung loswerden zunkönnen - aber das ist nicht so wichtig.
Antworten