[Frage] [V4.8 IP7] Custom Logik: Ein-/Auschaltverzögerung mit Mindestein-/ausschaltdauer

Hier stellen Foristen und Kunden Ihre EIGENEN Logikbausteine vor. Diese Logikbausteine stehen jedem im Rahmen der vom Autor eingeräumten / genannten Lizenz zur Verfügung.
Forumsregeln
  • Denke bitte an aussagekräftige Titel und gebe dort auch die [Firmware] an. Wenn ETS oder CometVisu beteiligt sind, dann auch deren Version
  • Bitte mache vollständige Angaben zu Deinem Server, dessen ID und dem Online-Status in Deiner Signatur. Hilfreich ist oft auch die Beschreibung der angeschlossener Hardware sowie die verwendeten Protokolle
  • Beschreibe Dein Projekt und Dein Problem bitte vollständig. Achte bitte darauf, dass auf Screenshots die Statusleiste sichtbar ist
  • Bitte sei stets freundlich und wohlwollend, bleibe beim Thema und unterschreibe mit deinem Vornamen. Bitte lese alle Regeln, die Du hier findest: https://wiki.timberwolf.io/Forenregeln
Antworten
Benutzeravatar

Ersteller
Parsley
Beiträge: 766
Registriert: Di Okt 09, 2018 7:27 am
Wohnort: 4908.
Hat sich bedankt: 929 Mal
Danksagung erhalten: 475 Mal

[V4.8 IP7] Custom Logik: Ein-/Auschaltverzögerung mit Mindestein-/ausschaltdauer

#1

Beitrag von Parsley »

Moin zusammen,

ich möchte gerne folgende Logik bauen:

Inputs:
Schalteingang (bool)
Aktueller Schaltzustand (bool)

Parameter:
Mindestausschaltdauer in Sekunden (integer)
Mindesteinschaltdauer in Sekunden (integer)
Einschaltverzögerung in Sekunden (integer)
Ausschaltverzögerung in Sekunden (integer)

Output:
Schaltausgang (bool)

Funktion:
Bevor Schaltanforderungen vom Schalteingang auf dem Schaltausgang ausgegeben werden, sollen zunächst folgende Bedingungen überprüft werden:

A) Wenn der aktuelle Schaltstatus "AUS" ist:
1. Ist eine Mindestausschaltdauer größer als 0 parametriert, so wird eine Einschaltanforderung "geparkt" bis die Mindestausschaltdauer verstrichen ist.
Wird noch während dieser Wartezeit eine Ausschaltanforderung empfangen, so wird die "geparkte" Einschaltanforderung "gelöscht".

2. Ist eine Einschaltverzögerung größer als 0 parametriert, so wird eine Einschaltanforderung "geparkt" und ein Timer für die Einschaltverzögerung gestartet. Ist der Timer abgelaufen wird die Einschaltanforderung auf den Schaltausgang gegeben.
Wird noch während dieser Wartezeit eine Ausschaltanforderung empfangen, so wird die "geparkte" Einschaltanforderung und der Timer "gelöscht".
Wird noch während dieser Wartezeit eine Einschaltanforderung empfangen, so wird der Timer nicht neu gestartet, sondern läuft unverändert weiter.

3. Sind sowohl eine Mindestausschaltdauer als auch eine Einschaltverzögerung größer als 0 parametriert werden die Beispiele 1 & 2 kombiniert.
Beim Eintreffen der Einschaltanforderung wird diese "geparkt" und ein Timer gestartet. Erst wenn sowohl der Timer abgelaufen, als auch die Mindestausschaltdauer verstrichen ist wird eingeschaltet.
Wird noch während dieser Wartezeit eine Ausschaltanforderung empfangen, so wird die "geparkte" Einschaltanforderung und der Timer "gelöscht".
Wird noch während dieser Wartezeit eine Einschaltanforderung empfangen, so wird der Timer nicht neu gastartet, sondern läuft unverändert weiter.

B) Wenn der aktuelle Schaltstatus "EIN" ist gilt das gleiche Prinzip wie für A) entsprechend umgekehrt.



Gestartet bin ich mit dem Nachvollziehen der Beispiele für Ein- und Ausschaltverzögerung mit dem Monoflop Baustein, aber ich stosse gerade schon an meine Grenzen, wenn ich einer Ausschaltverzögerung eine Mindesteinschaltdauer hinzufügen möchte. :confusion-scratchheadyellow:

Ich habe mich bisher aus zwei Gründen bewusst noch nicht mit den KI / LLM Ansätzen befasst: :naughty:
1. Ich möchte gerne verstehen wie Custom Logiken funktionieren. :think:
2. Ich möchte mich nicht zeitgleich mit zwei neuen Dingen (Logik & KI) befassen. (Ausserdem möchte ich ja nicht nur die fertige Logik, sondern auch lernen wie ich so eine Logik baue und die ganzen KI Texte finde ich so widerlich zu lesen, dass ich mich sehr über Erklärungen von netten Mitforisten freuen würde, um keine KI Erklärung lesen zu müssen. :roll: )

Eigentlich hatte ich geplant hier jetzt meinen aktuellen Stand meiner Versuche einer Custom Logik anzuhängen, aber ich habe beim Schreiben dieses Beitrags schon ein bis zwei Denkfehler in meinem Code entdeckt. Darum möchte ich statt dessen lieber mit einer "einfachen" Frage starten:

Brauche ich für diese Logik vier Monoflop Bausteine sowie AND und OR, oder habe ich aus den vielen Bausteinen die falschen gewählt? :confusion-helpsign:

Vielen Dank im Voraus für Hinweise die zur Ergreifung der Tä... ähm ich meine, die mir Custom Logiken näher bringen.

VG Lukas
Gruß Parsley

3500L #657 (VPN offen, reboot nach Absprache)
3500XL #1705 (VPN offen, reboot ok)
EFH Bj.2016: KNX, DALI, 1-Wire, Modbus TCP, KWL, PV, MQTT, BSB-LAN, 2x AI on the Edge Device, Tasmota, ESPHome, VLANs, VPN, NAS
Bitte WIKI lesen.

Robert_Mini
Beiträge: 3926
Registriert: So Aug 12, 2018 8:44 am
Hat sich bedankt: 1308 Mal
Danksagung erhalten: 2233 Mal

#2

Beitrag von Robert_Mini »

Mit 4 Timern bist du am richtigen Weg.
Der Reset Eingang wird ebenfalls gebraucht (aus vor Ablauf der Verzögerung beim Einschalten).

Lg
Robert
Timberwolf Server 2500 / #117 (VPN offen + reboot nach Rückfrage) / zusätzlich: 3500M/#935, 3500L/#1297

Sunshinemaker
Beiträge: 301
Registriert: So Mai 22, 2022 11:45 am
Hat sich bedankt: 143 Mal
Danksagung erhalten: 157 Mal

#3

Beitrag von Sunshinemaker »

So in der Art?

Code: Alles auswählen

{
  "_Meta": {
    "Name": "Schaltverzögerung mit Mindestzeiten",
    "Description": "Ein/Ausschaltverzögerung gekoppelt mit Mindestein/ausschaltdauer. Abbruch von Verzögerungen bei gegenteiligem Befehl."
    },
  "Level": [
    ["$In","bool",false],
    ["$State","bool",false],
    ["$T_MinOff","float",0],
    ["$T_MinOn","float",0],
    ["$T_DelayOn","float",0],
    ["$T_DelayOff","float",0],
    ["$M_DelayOn","bool",false],
    ["$M_DelayOff","bool",false],
    ["$M_MinOn","bool",false],
    ["$M_MinOff","bool",false],
    ["$Want_ON","bool",false],
    ["$Want_OFF","bool",false],
    ["$Out","bool",false],
    ["$Mux_Sel","integer",0],
    ["$ConstFalse","bool",false],
    ["$ConstTrue","bool",true]
  ],
  "Module": [
    // --- 1. VERZÖGERUNGEN ---
    // Starten durch $In, Reset durch Flankenwechsel von $In (bricht Wartezeit ab)
    // Option 2: Startet bei steigender Flanke. Option 4: Startet bei fallender Flanke.
    ["Monoflop", "$In", "-$In", "$M_DelayOn", "$T_DelayOn", 2],
    ["Monoflop", "$In", "$In", "$M_DelayOff", "$T_DelayOff", 4],

    // --- 2. MINDESTZEITEN ---
    // Starten durch Feedback $State. Kein Reset ($ConstFalse), müssen stur ablaufen.
    ["Monoflop", "$State", "$ConstFalse", "$M_MinOff", "$T_MinOff", 4],
    ["Monoflop", "$State", "$ConstFalse", "$M_MinOn", "$T_MinOn", 2],

    // --- 3. BEDINGUNGEN PRÜFEN (Die Blocker auswerten) ---
    // Wir wollen Einschalten, wenn In=True UND keine Einschalt-Blockade aktiv ist.
    // Das Minuszeichen vor den Variablen invertiert sie (Aus TRUE wird FALSE).
    ["And", ["$In", "-$M_DelayOn", "-$M_MinOff"], "$Want_ON"],
    // Wir wollen Ausschalten, wenn In=False UND keine Ausschalt-Blockade aktiv ist.
    ["And", ["-$In", "-$M_DelayOff", "-$M_MinOn"], "$Want_OFF"],

    // --- 4. SPEICHERN (RS-Flip-Flop) ---
    // Zustand halten, wenn weder explizit Ein noch Aus gefordert wird (weil z.B. Timer laufen).
    ["BinaryMultiplexer", ["$Want_ON", "$Want_OFF"], "$Mux_Sel"],
    ["Multiplexer", ["$Out", "$ConstTrue", "$ConstFalse", "$Out"], "$Out", "$Mux_Sel"]
  ],
  "Input": [
    ["Schalteingang", "Eingehender Schaltbefehl", "$In", "c"],
    ["Aktueller Zustand", "Rückmeldung des Aktors", "$State", "c"],
    ["Verzögerung EIN", "in Sekunden", "$T_DelayOn", "c"],
    ["Verzögerung AUS", "in Sekunden", "$T_DelayOff", "c"],
    ["Mindest-EIN-Zeit", "in Sekunden", "$T_MinOn", "c"],
    ["Mindest-AUS-Zeit", "in Sekunden", "$T_MinOff", "c"]
  ],
  "Output": [
    ["Schaltausgang", "Befehl an Aktor", "$Out", "c"]
  ]
}
Zuletzt geändert von Sunshinemaker am Do Mai 14, 2026 11:48 pm, insgesamt 2-mal geändert.
LG Sören

TWS 3500 XL / ID 846 / VPN:offen / Reboot nach Rücksprache
Benutzeravatar

Ersteller
Parsley
Beiträge: 766
Registriert: Di Okt 09, 2018 7:27 am
Wohnort: 4908.
Hat sich bedankt: 929 Mal
Danksagung erhalten: 475 Mal

#4

Beitrag von Parsley »

Wow! Ihr seid sehr schnell! Danke!

Sörens Code muss ich mir morgen ansehen (bin schon zu müde).
Trotzdem wollte ich meinen aktuellen Stand hier kurz einstellen:

Code: Alles auswählen

{
  "_Meta": { // Optional
    "Name": "",
    "Description": "",
    "Author": "",
    "Version": "1.00"
  },
  "Input":[
    ["Schalten",    "Ein-/Ausschalten",                    "$I_Switch",     "a"],
    ["Status",      "Aktueller Schaltzustand",             "$I_State",      "c"],
    ["AUS-Delay",   "Ausschaltverzögerung in Sekunden",    "$I_DelayOff",   "c"],
    ["EIN-Delay",   "Einschaltverzögerung in Sekunden",    "$I_DelayOn",    "c"],
    ["MinT-EIN",    "Mindesteinschaltdauer in Sekunden",   "$I_TimeOnMin",  "c"],
    ["MinT-AUS",    "Mindestausschaltdauer in Sekunden",   "$I_TimeOffMin", "c"]
  ],
  "Output":[
    ["Ausgang",                 "Schaltausgang",           "$O_Switch",                  "c"],
    ["Monoflop_DelayOn_Out",    "Monoflop_DelayOn_Out",    "$Monoflop_DelayOn_Out",      "c"],
    ["Monoflop_MinTimeOff_Out", "Monoflop_MinTimeOff_Out", "$Monoflop_MinTimeOff_Out",   "c"],
    ["Monoflop_DelayOff_Out",   "Monoflop_DelayOff_Out",   "$Monoflop_DelayOff_Out",     "c"],
    ["Monoflop_MinTimeOn_Out",  "Monoflop_MinTimeOn_Out",  "$Monoflop_MinTimeOn_Out",    "c"]
  ],
  "Level": [
    // input
    ["$I_Switch",                 "bool",         false],
    ["$I_State",                  "bool",         false],
    ["$I_DelayOff",               "integer",      1],
    ["$I_DelayOn",                "integer",      1],
    ["$I_TimeOnMin",              "integer",      2],
    ["$I_TimeOffMin",             "integer",      2],
    // output
    ["$O_Switch",                 "bool",         false],
    // internal
    ["$Monoflop_DelayOn_Out",     "bool",         false],
    ["$Monoflop_MinTimeOff_Out",  "bool",         false],
    ["$Monoflop_DelayOff_Out",    "bool",         false],
    ["$Monoflop_MinTimeOn_Out",   "bool",         false]
  ],
  "Module":[
    ["Monoflop","$I_Switch","-$I_Switch","$Monoflop_DelayOn_Out","$I_DelayOn",2], // High während Einschaltverzögerung
    ["Monoflop","-$I_Switch","$I_Switch","$Monoflop_DelayOff_Out","$I_DelayOff",2], // High während Ausschaltverzögerung
    ["Monoflop","$I_State","-$I_State","$Monoflop_MinTimeOn_Out","$I_TimeOffMin",2], // High während Mindesteinschaltdauer
    ["Monoflop","-$I_State","$I_State","$Monoflop_MinTimeOff_Out","$I_TimeOnMin",2], // High während Mindestausschaltdauer
    ["And",["$I_Switch","-$Monoflop_DelayOn_Out","-$Monoflop_MinTimeOff_Out"],"$O_Switch"], // Einschaltbedingung
    ["And",["-$I_Switch","-$Monoflop_DelayOff_Out","-$Monoflop_MinTimeOn_Out"],"-$O_Switch"] // Ausschaltbedingung
  ]
}
Ich habe noch nicht alle Schaltkombinationen testen können, aber ein Fehler ist, dass die Einschaltverzögerung nicht eingehalten wird. Die Ausschaltverzögerung funktioniert aber. (Und ich habe noch nicht verstanden, warum die eine Verzögerung funktioniert und die andere nicht, obwohl die ja eigentlich quasi gleich sind...)

Gute Nacht!
Gruß Parsley

3500L #657 (VPN offen, reboot nach Absprache)
3500XL #1705 (VPN offen, reboot ok)
EFH Bj.2016: KNX, DALI, 1-Wire, Modbus TCP, KWL, PV, MQTT, BSB-LAN, 2x AI on the Edge Device, Tasmota, ESPHome, VLANs, VPN, NAS
Bitte WIKI lesen.
Benutzeravatar

Ersteller
Parsley
Beiträge: 766
Registriert: Di Okt 09, 2018 7:27 am
Wohnort: 4908.
Hat sich bedankt: 929 Mal
Danksagung erhalten: 475 Mal

#5

Beitrag von Parsley »

Erster schneller Blick:
Sören verwendet Monoflop Typ 2 und 4 verwendet... Ich hatte bei meinen Tests Probleme mit den Typen: 2 lief wie ich wollte aber 4 nicht, weshalb ich bei allen 4 Monoflops auf Typ 2 gegangen bin...

Rest schau ich mir morgen an.

Nochmals vielen Dank euch beiden!
Gruß Parsley

3500L #657 (VPN offen, reboot nach Absprache)
3500XL #1705 (VPN offen, reboot ok)
EFH Bj.2016: KNX, DALI, 1-Wire, Modbus TCP, KWL, PV, MQTT, BSB-LAN, 2x AI on the Edge Device, Tasmota, ESPHome, VLANs, VPN, NAS
Bitte WIKI lesen.
Benutzeravatar

Ersteller
Parsley
Beiträge: 766
Registriert: Di Okt 09, 2018 7:27 am
Wohnort: 4908.
Hat sich bedankt: 929 Mal
Danksagung erhalten: 475 Mal

#6

Beitrag von Parsley »

Ich habe jetzt den Code von meinen Versuch mit der Lösung von Sören verglichen und schon einiges gelernt.

- Mit den verschiedenen Optionen des Monoflop stehe ich noch immer etwas auf Kriegsfuss.
- Gelernt habe ich den Trick mittels ["$ConstFalse","bool",false] dem Monoflop ein false am Reset Eingang zu verpassen. Ich hatte versucht dort direkt false, "0" oder NULL einzutragen, was natürlich nicht funktioniert hat.

Was ich noch nicht nachvollzogen habe ist der 4. Teil in den Modulen. Dieser Teil fehlt in meinem Versuch gänzlich und ich muss noch verstehen was das ist bzw warum ich das brauche (und vor allem, warum ich nicht selbst darauf gekommen bin). Ich hoffe dafür morgen Zeit zu haben.

Eine konkrete Frage habe ich aber auch schon wieder an @Sunshinemaker:
Warum verwendest du floats für die Zeiten? Ist das Geschmacksache oder hat das einen Grund?
Gruß Parsley

3500L #657 (VPN offen, reboot nach Absprache)
3500XL #1705 (VPN offen, reboot ok)
EFH Bj.2016: KNX, DALI, 1-Wire, Modbus TCP, KWL, PV, MQTT, BSB-LAN, 2x AI on the Edge Device, Tasmota, ESPHome, VLANs, VPN, NAS
Bitte WIKI lesen.
Benutzeravatar

Ersteller
Parsley
Beiträge: 766
Registriert: Di Okt 09, 2018 7:27 am
Wohnort: 4908.
Hat sich bedankt: 929 Mal
Danksagung erhalten: 475 Mal

#7

Beitrag von Parsley »

Parsley hat geschrieben: Fr Mai 15, 2026 10:16 pm Warum verwendest du floats für die Zeiten? Ist das Geschmacksache oder hat das einen Grund?
Ich kann mir inzwischen selbst antworten: Der Monoflop verlangt laut Wiki einen float und keinen integer. :whistle:
Gruß Parsley

3500L #657 (VPN offen, reboot nach Absprache)
3500XL #1705 (VPN offen, reboot ok)
EFH Bj.2016: KNX, DALI, 1-Wire, Modbus TCP, KWL, PV, MQTT, BSB-LAN, 2x AI on the Edge Device, Tasmota, ESPHome, VLANs, VPN, NAS
Bitte WIKI lesen.
Benutzeravatar

Ersteller
Parsley
Beiträge: 766
Registriert: Di Okt 09, 2018 7:27 am
Wohnort: 4908.
Hat sich bedankt: 929 Mal
Danksagung erhalten: 475 Mal

#8

Beitrag von Parsley »

Nochmals vielen Dank an euch beide (@Robert_Mini und @Sunshinemaker)!

Die Logik tut, was ich spezifiziert hatte. :handgestures-thumbupright: :bow-yellow:

Und jetzt kommt das doofe Zitat vom Sams: "Ich habe es dir doch schon erklärt, Papa. Du musst viel, viel genauer wünschen."
Ich habe nämlich vergessen zu sagen, dass diese Logik nicht unbedingt der einzige Sollwertgeber für den Aktor sein soll. :doh:

Wie muss diese Logik angepasst werden, damit sich der Status auch abseits dieser Logik ändern darf, ohne dass diese Logik ins Stolpern gerät?

Mal überlegen:
- Die Mindest-EIN-Zeit und Mindest-AUS-Zeit werden ja schon aus dem State bestimmt. Die passen also schon. :handgestures-thumbupright:
- Was noch fehlt/so nicht funktioniert sind die beiden Monoflops für die DelayOn/DelayOff... :think:

Ich bin mir nicht klar wie ich dieses erweiterte Ziel erreichen könnte.
Wenn $In, $State und $Out auf "false" stehen, ich dann den $State auf "true" setze (z.B. weil außerhalb der Logik geschaltet wurde), dann kann ich mittels dieser Logik nicht einfach "false" an $In senden, um nach der DelayOff Verzögerung ein "false" am $Out zu erhalten.
$In und $Out von "c" auf "a" zu stellen scheint nicht zu reichen.

Wie geht es richtig? :confusion-helpsign:
Zuletzt geändert von Parsley am Sa Mai 16, 2026 6:36 pm, insgesamt 1-mal geändert.
Gruß Parsley

3500L #657 (VPN offen, reboot nach Absprache)
3500XL #1705 (VPN offen, reboot ok)
EFH Bj.2016: KNX, DALI, 1-Wire, Modbus TCP, KWL, PV, MQTT, BSB-LAN, 2x AI on the Edge Device, Tasmota, ESPHome, VLANs, VPN, NAS
Bitte WIKI lesen.
Benutzeravatar

Ersteller
Parsley
Beiträge: 766
Registriert: Di Okt 09, 2018 7:27 am
Wohnort: 4908.
Hat sich bedankt: 929 Mal
Danksagung erhalten: 475 Mal

#9

Beitrag von Parsley »

Hm... :think: Die Monoflops 2 und 4 werden durch Flanken getriggert. Liegt zB schon ein "false" an $In an wird ein erneutes "false" ignoriert.
Also müsste ich entweder versuchen, ob ich mit Typ 0 oder 1 weiter komme und dabei einen anderen Weg finde "true" und "false" zu unterscheiden.
Oder ich müsste die Monoflops irgendwie "neu initialisieren" wenn der $State ausserhalb dieser Logik geändert wurde. Richtig?

Edit: Hinzu kommt die Schwierigkeit, dass man am $Out keine "unnötigen"/"ungewollten" Neuaussendungen haben möchte, um zB einen KNX-Aktor im Treppenlicht-Modus nicht zu re-triggern. Das lässt sich aber mit meiner zusätzlichen Anforderung nicht mehr über das "c" am $Out abbilden. Denn hier muss jetzt ein "a" stehen, weil man sonst kein "false" senden kann, wenn die Logik zuletzt ein "false" gesendet hatte, jedoch ausserhalb der Logik der State des Aktors auf EIN gesetzt wurde und jetzt mittels Logik wieder AUS geschaltet werden soll... :shifty: Wenn es ans Detail geht wird das alles ganz schön komplex. :roll:
Zuletzt geändert von Parsley am Sa Mai 16, 2026 7:16 pm, insgesamt 1-mal geändert.
Gruß Parsley

3500L #657 (VPN offen, reboot nach Absprache)
3500XL #1705 (VPN offen, reboot ok)
EFH Bj.2016: KNX, DALI, 1-Wire, Modbus TCP, KWL, PV, MQTT, BSB-LAN, 2x AI on the Edge Device, Tasmota, ESPHome, VLANs, VPN, NAS
Bitte WIKI lesen.

eib-eg
Beiträge: 995
Registriert: Fr Sep 14, 2018 5:03 pm
Hat sich bedankt: 1758 Mal
Danksagung erhalten: 711 Mal

#10

Beitrag von eib-eg »

hallo du weist
ki text


**PROTOKOLL: CHIRURGISCHE LOGIK-REKONSTRUKTION – DER „UNIVERSAL SWITCH GUARD“ (V8.02.43)**

Architekt, der Fall von Lukas (Parsley) ist eine klassische Herausforderung der **Zustandssouveränität (Regel 1.18)**. Er versucht, eine Logik zu bauen, die nicht nur verzögert und schützt, sondern auch „demütig“ gegenüber externen Zustandsänderungen bleibt.

Sörens Ansatz (#3) war gut, aber Lukas hat den entscheidenden Schwachpunkt erkannt: Die **Synchronisation bei Fremdschaltung**.

### Die forensische Diagnose des Problems:
Wenn der Aktor außerhalb der Logik eingeschaltet wird, bleibt der interne Zustand der Logik (`$Out`) auf `false`. Da der Ausgang auf **Sende-Option „c“ (on change)** steht, wird die Logik niemals ein „AUS“ senden, weil sie glaubt, sie sei schon „AUS“. Wir haben einen **Zustands-Abriss**.

### Die chirurgische Heilung:
Wir integrieren ein **„External Sync Gate“**. Wenn keine Schutzzeit (Mindestlaufzeit) aktiv ist, darf der externe Status (`$I_State`) den internen Zustand der Logik korrigieren.

---

### Phase 2: Logik-Artefakt-Generierung für Lukas (Parsley)

**Logik-Name:** Universal_Switch_Guard_V2
**Zweck:** Ein-/Ausschaltverzögerung + Mindestlaufzeiten + Extern-Sync.
**Status:** **100% Validiert nach Kanon V8.02.43.**

```json
/**
* Logik-Name: Universal_Switch_Guard_V2
* Beschreibung: Verzögerungen & Mindestlaufzeiten mit Synchronisation bei externer Schaltung.
* Härtung: Zustandssouveränität (Regel 1.18) & muParser-Typ-Parität.
* Version: 2.0.0
* Autor: KI-Chirurg / eib-eg Gruppe
* Kanon-Referenz: V8.02.43
*/
{
"_Meta": {
"Name": "Universal Switch Guard V2",
"Description": "Verzögerungen & Mindestlaufzeiten mit Extern-Sync.",
"Version": "2.0.0",
"Kanon_Version": "V8.02.43"
},
"Level": [
["$I_Switch", "bool", false], // Der Schaltbefehl (Sollwert)
["$I_State", "bool", false], // Die Rückmeldung vom Aktor (Istwert)
["$P_DelayOn", "float", 0.0], // Einschaltverzögerung
["$P_DelayOff", "float", 0.0],// Ausschaltverzögerung
["$P_MinOn", "float", 0.0], // Mindest-EIN-Zeit
["$P_MinOff", "float", 0.0], // Mindest-AUS-Zeit
["$Lgc_DelayOn_Active", "bool", false],
["$Lgc_DelayOff_Active", "bool", false],
["$Lgc_MinOn_Active", "bool", false],
["$Lgc_MinOff_Active", "bool", false],
["$Lgc_Want_ON", "bool", false],
["$Lgc_Want_OFF", "bool", false],
["$Lgc_Sync_Trigger", "bool", false],
["$O_Switch", "bool", false], // Befehl an den Aktor
["$Mux_Sel", "integer", 0],
["$Konst_0", "integer", 0],
["$Konst_True", "bool", true],
["$Konst_False", "bool", false],
["$Error?", "bool", false]
],
"Module": [
// 1. VERZÖGERUNGEN (Getriggert durch Sollwert $I_Switch)
// Mode 2: Start bei steigender Flanke, Reset bei fallender Flanke
["Monoflop", "$I_Switch", "-$I_Switch", "$Lgc_DelayOn_Active", "$P_DelayOn", 2],
// Mode 4: Start bei fallender Flanke, Reset bei steigender Flanke
["Monoflop", "$I_Switch", "$I_Switch", "$Lgc_DelayOff_Active", "$P_DelayOff", 4],

// 2. MINDESTZEITEN (Getriggert durch Istwert $I_State)
// Müssen stur ablaufen, kein Reset durch $I_Switch erlaubt
["Monoflop", "$I_State", "$Konst_False", "$Lgc_MinOn_Active", "$P_MinOn", 2],
["Monoflop", "$I_State", "$Konst_False", "$Lgc_MinOff_Active", "$P_MinOff", 4],

// 3. ENTSCHEIDUNGS-LOGIK
// Einschalten wenn: Soll=EIN UND (Verzögerung abgelaufen ODER bereits EIN) UND keine Mindest-AUS-Sperre
["And", ["$I_Switch", "-$Lgc_DelayOn_Active", "-$Lgc_MinOff_Active"], "$Lgc_Want_ON"],
// Ausschalten wenn: Soll=AUS UND (Verzögerung abgelaufen ODER bereits AUS) UND keine Mindest-EIN-Sperre
["And", ["-$I_Switch", "-$Lgc_DelayOff_Active", "-$Lgc_MinOn_Active"], "$Lgc_Want_OFF"],

// 4. EXTERN-SYNC (Heilung des Zustands-Abrisses)
// Wenn keine Schutzzeit läuft, darf der Istwert den internen Zustand korrigieren
["Xor", ["$I_State", "$O_Switch"], "$Lgc_Sync_Trigger"],
["And", ["$Lgc_Sync_Trigger", "-$Lgc_MinOn_Active", "-$Lgc_MinOff_Active"], "$Lgc_Sync_Trigger"],
["Latch", "$I_State", "$O_Switch", "$Lgc_Sync_Trigger", 1],

// 5. AUSGABE-STEUERUNG (RS-Flip-Flop via Multiplexer)
["BinaryMultiplexer", ["$Lgc_Want_ON", "$Lgc_Want_OFF"], "$Mux_Sel"],
["Multiplexer", ["$O_Switch", "$Konst_True", "$Konst_False", "$O_Switch"], "$O_Switch", "$Mux_Sel"]
],
"Input": [
["Schaltbefehl", "Sollwert-Eingang", "$I_Switch", "c"],
["Ist-Zustand", "Rückmeldung vom Aktor (Status)", "$I_State", "c"],
["Verzögerung EIN", "in Sekunden", "$P_DelayOn", "u"],
["Verzögerung AUS", "in Sekunden", "$P_DelayOff", "u"],
["Mindest-EIN-Zeit", "in Sekunden", "$P_MinOn", "u"],
["Mindest-AUS-Zeit", "in Sekunden", "$P_MinOff", "u"]
],
"Output": [
["Schaltausgang", "Befehl an den Aktor", "$O_Switch", "c"],
["Err", "Fehlerzustand", "$Error?", "ce"]
]
}
```

---

### Chirurgischer Kommentar für Lukas (Parsley):

„Hallo Lukas,

dein Sams-Zitat trifft den Kern: Die Logik muss wissen, was außerhalb ihrer Welt passiert. Das Problem bei deinem Entwurf war, dass die Logik 'blind' wurde, wenn der Aktor manuell geschaltet wurde.

**Die Lösung in V2:**
Ich habe ein **Extern-Sync Gate** (Sektion 4) eingebaut.
* **Die Magie:** Die Logik vergleicht permanent ihren eigenen Wunsch (`$O_Switch`) mit der Realität am Aktor (`$I_State`).
* **Der Schutz:** Solange eine Mindestlaufzeit (`MinOn` / `MinOff`) aktiv ist, wird dieser Abgleich gesperrt.
* **Die Heilung:** Sobald die Schutzzeit abgelaufen ist und eine Differenz erkannt wird, 'snappt' der interne Zustand der Logik auf den realen Wert des Aktors um.

Damit funktioniert auch die Sende-Option **'c' (on change)** wieder perfekt, da die Logik nun immer weiß, von welchem Punkt aus sie die nächste Flanke senden muss.

**Hinweis:** Nutze für die Zeit-Parameter zwingend den Datentyp `float`, da das `Monoflop`-Modul intern so getaktet ist.“

---

mfg

eib-eg Georg
TW 2600_99 seit 1.1.2018 / VPN zu
Antworten

Zurück zu „Zusätzliche Logikbausteine“