Ja, ich denke, das ist eine sehr gute Idee und zudem einfach (im Sinne von -nicht unnötig komplex-). Ich fange mal an, meine restlichen Fragen durchzunummerieren, damit ich sie nicht vergesse
An die Ausschaltverzögerung habe ich auch schon gedacht. Entweder als Nachlauf nach dem ersten Triggern oder vielleicht besser des letzten Triggerns der unteren Grenze.
Worauf ich gespannt, bin, ob das ganze sofort funktioniert, oder ob nach einem Reset der Logik (-> wo speichern 'sich' die Werte vom Tiefpass eigentlich? Kann man den Initialisieren? <-) der Tiefpass erstmal Daten sammeln muss. Aber das werde ich testen und auch eine Zeitserie mitlaufen lassen.
Da ist noch das Thema mit dem Zustandsinit nach Neustart. Das hatte ich hier
ja schon mal aufgegriffen. Also unsere neue Logik soll nach einem (Neu)Start den Lüfter (sofort) 'initialisieren': (Neu)Start während des Duschens_ Lüfter 'sofort' einschalten, sollte er schon laufen ist das erneute Einschalten unschädlich. Wenn nicht geduscht wird: ausschalten (sollte er - warum auch immer - laufen), auch hier ist das (einmalige) Stumpfe Senden von Aus bestimmt zielführend. Es soll halt nicht mit jedem Durchlauf der Logik 0 gesendet werden müssen, nur damit das Initiliisierungs-Aus kommt.
Da ich die Lüftersteuerung beim Ausfall der Logik (Server, Logikmodul, Teilmenge der Logiken) mit der einfacheren Steuerung durch die Geräte selbst ersetzen will, denke ich an ein Hertbeatsignal (auf Ebene jeder Logik, nicht des gesamten TWS, da ja einzelne Logiken ausfallen können und sei es durch Deaktivierung). Ich vermute, es ist jetzt zielführend, den Schaltbefehl periodisch zu senden. Zumindest können meine MDT-Aktoren diese Art der "Übersteuerung". Der Aktor merkt wenn der Empfang ausbleibt und berücksichtigt dann den Schaltwert alternativer GAs.
Code: Alles auswählen
{
"Level":[
//
// Eingänge
//
["$I_Feuchte","float",0],
["$I_Trigger","bool",false],
["$I_Feuchte_Delta_Ein","float",15.0],
["$I_Feuchte_Delta_Aus","float",5.0],
["$I_Laufzeit_Max","float",120.0],
["$I_Laufzeit_Manuell","float",5.0],
["$I_Zeitkonstante_Tiefpass","float",7200.0],
//
// Verarbeitung
//
["$Feuchte_gemittelt","float",0.0],
["$Feuchte_Einschaltschwelle","float",0.0],
["$Feuchte_Ausschaltschwelle","float",0.0],
["$Konst1f","float",1.0],
//
// Ausgänge
//
["$O_LuefterEA","float",0.0]
],
"Module":[
["Lowpass","$I_Feuchte","$Feuchte_gemittelt","$I_Zeitkonstante_Tiefpass"],
// Berechnet den Funktionswert eines Polynoms der Form: f(x)=A0 + A1 * X + A2 * X^2 + ... + An * X^n
// ["Polynomial", "$Variable_X", "$Ergebnis",["$A0", "$A1", "$A2", ..., "$An"]],
["Polynomial", "$Konst1f", "$Feuchte_Einschaltschwelle",["$Feuchte_gemittelt", "$I_Feuchte_Delta_Ein"]],
["Polynomial", "$Konst1f", "$Feuchte_Ausschaltschwelle",["$Feuchte_gemittelt", "$I_Feuchte_Delta_Aus"]],
// ["Comparator","$InF","$OutB",["$UntereSchwelle","$ObereSchwelle"]]
["Comparator","$I_Feuchte","$O_LuefterEA",["$Feuchte_Ausschaltschwelle","$Feuchte_Einschaltschwelle"]]
//
// VORLAGE
//
//["Polynomial", "$Var_x", "$OutputFloat",["$A0", "$A1"]],
//["Ratio","$Zaehler","$OutputFloat","$Nenner"],
//["Limiter","$Input1","$OutputFloat","$InputInnerhalb",["$Untergrenze", "$Obergrenze"]],
//["Comparator", "$Input1", "$OutputBool", "$Vergleichswert"],
//["Comparator", "$Input1", "$OutputBool", ["$UntereSchwelle","$ObereSchwelle"]]
//["Multiplexer",["$Input1","$Input2"],"$OutputFloat","$SelectInput"],
//["Or" , ["$Input1","$Input2"], "$OutputBool"],
//["And" , ["$Input1","$Input2"], "$OutputBool"],
//["Monoflop","$Trigger","$Reset","$TimerStatus","$Dauer",1],
//["Latch","$Input1","$Output","$Trigger",0], // Übernimmt den Wert von $Input1 auf $Output, wenn Trigger = 0, Option 0/1/2/3 = wenn true/pos. Flanke/neg. Flanke/jede Flanke
//["Clocksignal","$Enable","$Takt","$Periode"], // Zyklischer Trigger, $Takt wechselt jeweils nach Ablauf von $Periode zwischen TRUE/FALSE
//["HobbsMeter","$Status","$Time","$Reset"], // Zaehlt bei $Status = TRUE die Zeit in [h]
//["Stopwatch","$Status", "$Time"], // Stoppt die Zeit in [s] ab $Status = TRUE, bei $Status = FALSE wird auf 0 zurückgesetzt
//["CalcFormula",["$Day1Case","$Day2Case","$Day3Case","$Day4Case","$DayEquals"], "$Case", "$Formula3"],
//["Cron","$KonstTrue","$Reset",0,"$CronString"],
//["Wakeup","$Utime_start","$Status"],
//["BinaryMultiplexer",["$In_D","$In_E","$In_F"],"$Output"],
//["Lowpass","$In_val","$Out_val","$Time_const"]
//["Triggered", "$InputVar", "$Touched" ], // Touched = TRUE, wenn der Eingang $InputVar die Logik getriggert hat
//["SendExplicit","$Send","$OutputVar",0], // Sendet Ausgang $OutputVar, abhängig von $Send 0/1/2/3 (Paramter analog Latch), ACHTUNG "x" am Output setzen!
//["Interpolation","$In", "$Out", [ [x1,y1] , [x2,y2] , ... , [xn,yn ] ] ] **/
],
"Input":[
["Feuchte Messwert","Aktuelle relative Luftfeuchtigkeit, DPT9","$I_Feuchte","c"],
["Trigger manuell","TRUE sendenm, um Lüfter manuell zu starten","$I_Trigger","c"],
["Lüfterlaufzeit man.","Laufzeit für manuelles Lüften (Minuten)","$I_Laufzeit_Manuell","c"],
["Feuchtemittlung, Zeitfenster","(Sekunden, 2h sinnvoll)","$I_Zeitkonstante_Tiefpass","c"],
["Anstieg für -Lüfter an-","Feuchteanstieg zum Mittel für Lüfterstart (abs. rel. Feuchtigkeits-differenz)","$I_Feuchte_Delta_Ein","c"],
["Anstieg für -Lüfter aus-","Feuchteanstieg zum Mittel für Lüfterstop (abs. rel. Feuchtigkeits-differenz)","$I_Feuchte_Delta_Aus","c"],
["Lüfterlaufzeit max.","maximale Laufzeit (Sicherheitsaus in Minuten)","$I_Laufzeit_Max","c"]
],
"Output":[
["Schalten E/A","Lüfter schalten (Ein/Aus) DPT1","$O_LuefterEA","c"],
["Debug_Feuchte_gemittelt","Ergebnis vom Tiefpass","$Feuchte_gemittelt","c"]
]
}
ok, ich habe jetzt u.a. verstanden, dass die Funktionen in dem Module-Block sequentiell nacheinander abgearbeitet werden und die Outputs einer vorgschalteten Funktion in der Regel als Input für eine nachgeschaltete Funktion dient. Ich glaube, ich muss bald mal ein paar Aufgaben damit lösen, bevor ich entscheide, ob ich das usable finde, oder doch lieber Code machen würde... Aber ich hoffe, wir sind hier noch nicht am Ende :->>