Seite 6 von 11

Re: Automatische Bewässerungssteuerung

Verfasst: Do Apr 28, 2022 10:51 pm
von Robert_Mini
Hier nun der Letztstand.
Im wesentlichen ist noch der globale Zeitfaktor hinzugekommen, über den die Bewässerungsdauer zusätzlich skaliert werden kann.

Im Screenshot sieht man auch die Sperrobjekte (bei mir Kreis und Freigabe-gesamt).
TriggerStart1/2 sind im Screenshot auskommentiert, da nicht in Verwendung (ich mag kein Ein, das nicht automatisch beendet wird).

lg
Robert
Screenshot 2022-04-28 224526.png

Code: Alles auswählen

/**
 * File: Irrigation_CircuitControl.twl V1.0 BETA 1
 * Logic for Garden irrigation. This module is the Circuit Control which controls one single irrigation circuit 
 * Author: Hans Martin
 * Der Schöpfer dieser Custom Logik überträgt die Nutzungsrechte gemäß der TOLL ("Timberwolf Open Logikblock License") die unter https://wrgt.news/TOLL zum Download zur Verfügung steht.
 */

{
  "Input": [
        ["Trigger Automatic 1", "(RISING) Trigger to start an automatic irrigation cycle", "$TriggerInpAutomaticIn1", "c"],
        ["Trigger Automatic 2", "(RISING) Trigger to start an automatic irrigation cycle", "$TriggerInpAutomaticIn2", "c"],
        ["Trigger Start 1", "(RISING) Activation of irrigation circuit", "$TriggerInpStartIn1", "c"],
        ["Trigger Start 2", "(RISING) Activation of irrigation circuit", "$TriggerInpStartIn2", "c"],
        ["Trigger Stop 1", "(RISING) Stops any active cycle", "$TriggerInpStopIn1", "c"],
        ["Trigger Stop 2", "(RISING) Stops any active cycle", "$TriggerInpStopIn2", "c"],
// *MR*: Change to $autotime_min
        ["Automatic Time [min]", "(T_s) Time of one irrigation cycle", "$AutoTime_min", "u"],
        ["Global Factor", "Factor to scale circuit timer", "$GlobalFactor", "u"],
        
//
        ["System OK Feedback", "(0/1) Loopback of SystemControl", "$SystemOk", "a"],
        ["Send interval on [s]", "Send outputs with ct periodically during circuit on", "$SendIntervalOn", "u"],
        ["Send interval off [s]", "Send outputs with ct periodically during circuit off", "$SendIntervalOff", "u"],
        ["Inhibit", "", "$VAR<Inhibit?>", "c"]
  ],
  "Output": [
        ["Valve", "(0/1) Output for the valve", "$ValveOut", "c"],
        ["System Request", "(0/1) Request for the SystemControl", "$SystemRequest", "c"],
        ["Circuit State", "(0/1) State indicating whether the circuit is running", "$CircuitState", "c"],
        ["Circuit finished", "(0/1) Flag indicating that the circuit is finished", "$CircuitFinished", "c"],
        ["Runtime [s]", "Time passed since valve opened", "$Time_sec_actual?", "ct"],
        ["Runtime [min]", "Time passed since valve opened", "$Time_min_actual?", "a"],
        ["Time left [s]", "Time left for this cycle", "$Time_sec_remaining?", "ct"],
        ["Time left [min]", "Time left for this cycle", "$Time_min_remaining?", "ct"],
        ["State", "Current state 0=off/1=request systemOK/2=circuit on/3=finishing", "$State?", "c"]
  ],
  "Level": [
        // Inputs
        ["$VAR<Inhibit?>","bool",false],
        ["$TriggerInpAutomaticIn1", "bool", false],
        ["$TriggerInpAutomaticIn2", "bool", false],
        ["$TriggerInpStartIn1", "bool", false],
        ["$TriggerInpStartIn2", "bool", false],
        ["$TriggerInpStopIn1", "bool", false],
        ["$TriggerInpStopIn2", "bool", false],
        ["$AutoTime", "float", 0],
        ["$SystemOk", "bool", false],

        // Output
        ["$ValveOut", "bool", false],
        ["$SystemRequest", "bool", false],
        ["$CircuitState", "bool", false],
        ["$CircuitFinished", "bool", false],

        // Constants
        ["$Konst1", "int", 1],
        ["$Konst2", "int", 2],
        ["$KonstFalse", "bool", false],
        ["$KonstTrue", "bool", true],

        // Internals
        ["$State","integer",0],
        ["$Inhibit","bool",false],
        ["$Cancel","bool",false],
        ["$ShouldRun", "bool", false],
        ["$LastShouldRun", "bool", false],
        ["$LastShouldRunOrAutoRising", "bool", false],
        ["$ShouldRunAndSysOk", "bool", false],
        ["$TimerActive", "bool", false],
// *MR*: new variables
        ["$AutoTime_min", "float", 0.0],
        ["$AutoTime_sec", "float", 0.0],
        ["$AutoTime_global", "float", 0.0],
        ["$LastTimerActive", "bool", false],
        ["$Timeout", "float", 5.0],
        ["$Time_sec_actual", "float", 0.0],
        ["$Time_min_actual", "float", 0.0],
        ["$Time_sec_remaining", "float", 0.0],
        ["$Time_min_remaining", "float", 0.0],
        ["$Konst0", "float", 0.0],
        ["$Konst60", "float", 60.0],
        ["$Konst005", "float", 0.05],
        ["$SendIntervalOn", "float", 5.0],
        ["$SendIntervalOff", "float", 60.0],
        ["$SendInterval", "float", 5.0],
        ["$Clk", "bool", false],
        ["$GlobalFactor", "float", 1.0],   // Global factor on circuit time, used if triggered manually or by auto2
        ["$GlobalFactorLim", "float", 1.0],   // Global factor on circuit time, used if triggered manually or by auto2
        ["$TriggerNoFactor", "bool", false],
        ["$TriggerWithFactor", "bool", false],
//        
        ["$TriggerAutomaticSaved", "bool", false],
        ["$TimerShouldRun", "bool", false],
        ["$CancelFinished", "bool", false],
        ["$TriggerInpStartRising","bool",false],
        ["$TriggerInpStopRising","bool",false],
        ["$TriggerInpAutomaticRising","bool",false],
        ["$ManualOn","bool",false],
        ["$SetOutputs","bool",false],
        ["$AutomaticModeActive","bool",false],
        ["$AutomaticModeActiveOrRequested","bool",false],
        ["$CancelAndAutoActive","bool",false]
  ],
  "Module": [
// *MR*:
        // calculate time in seconds
        ["Polynomial", "$Konst60", "$AutoTime_sec",["$Konst0", "$AutoTime_min"]],
        // Limit factor
        ["Limiter","$GlobalFactor","$GlobalFactorLim",0,["$Konst005", "$Konst2"]],
        // calculate time with global factor
        ["Polynomial", "$GlobalFactorLim", "$AutoTime_global",["$Konst0", "$AutoTime_sec"]],
        
        // take over current circuit time
        ["Or", ["$TriggerInpStartIn1","$TriggerInpStartIn2","$TriggerInpAutomaticIn2"], "$TriggerNoFactor"],
        ["And", ["$TriggerNoFactor","-$State"], "$TriggerNoFactor"],
        ["Latch","$AutoTime_sec","$AutoTime","$TriggerNoFactor",1],
        ["And", ["$TriggerInpAutomaticIn1","-$State"], "$TriggerWithFactor"],
        ["Latch","$AutoTime_global","$AutoTime","$TriggerWithFactor",1],
//
        // calculate inputs
        ["Or", ["$TriggerInpAutomaticIn1","$TriggerInpAutomaticIn2"], "$TriggerInpAutomaticRising"],
        ["Or", ["$TriggerInpStartIn1","$TriggerInpStartIn2"], "$TriggerInpStartRising"],
        ["Or", ["$TriggerInpStopIn1","$TriggerInpStopIn2"], "$TriggerInpStopRising"],
      
        // calculate cancel state
        ["Or", ["$VAR<Inhibit?>"], "$Inhibit"],
        ["Or", ["$Inhibit", "$TriggerInpStopRising"], "$Cancel"],

        // calculate manual state
        ["Or",["$TriggerInpStartRising", "$ManualOn"],"$ManualOn"],
        ["And", ["$ManualOn", "-$TimerActive", "-$Cancel"], "$ManualOn"], // if automatic mode was triggered, cancel manual mode

        // calculate start of system
        ["Or", ["$TriggerAutomaticSaved", "$TriggerInpAutomaticRising"], "$TriggerAutomaticSaved"], // save trigger
        ["And", ["$TriggerAutomaticSaved", "-$TimerActive", "-$Cancel"], "$TriggerAutomaticSaved"], // reset trigger if timer has taken over control or cancel was issued
 
// *MR*: Store last status of timer to detect 
        ["And", ["$TimerActive"], "$LastTimerActive"],
//
        // Set timer if automatic mode was triggered
        ["And", ["$TriggerAutomaticSaved", "$SystemOk"], "$TimerShouldRun"], // start timer only if also system ok was announced
        ["Monoflop", "$TimerShouldRun", "$Cancel", "$TimerActive", "$AutoTime", 2], // not retriggerable, rising-edge controlled, reset on cancel

// *MR*: Start stopwatch to provide runtime and remaining time of circuit     
        ["Stopwatch", "$TimerActive", "$Time_sec_actual"],
        ["Polynomial", "$Konst1", "$Time_sec_remaining",["$AutoTime", "-$Time_sec_actual"]],
        // convert to minutes
        ["Ratio", "$Time_sec_actual", "$Time_min_actual", "$Konst60"],
        ["Ratio", "$Time_sec_remaining", "$Time_min_remaining", "$Konst60"],
//        
        // build target state (run or not)
        ["Or", ["$TriggerAutomaticSaved", "$TimerActive"], "$AutomaticModeActive"],
// *MR*: $LastTimerActive added to detect cancel properly
        ["Or", ["$AutomaticModeActive", "$TriggerInpAutomaticRising", "$LastTimerActive"], "$AutomaticModeActiveOrRequested"],
        ["Or", ["$ManualOn", "$AutomaticModeActive"], "$ShouldRun"],

        // build state
        ["And", ["$ShouldRun", "$SystemOk"], "$ShouldRunAndSysOk"], //bypass to skip state 1
        ["And", ["$AutomaticModeActiveOrRequested", "$Cancel"], "$CancelAndAutoActive"], // bypass to only announce finished on cancel from state 0, 1 or 2 when automatic mode was active

        ["Statemachine",
            // 0: Circuit Off
            // 1: Requesting for SystemOK
            // 2: Circuit On
            // 3: Finishing
            [
                // [condition , current state, next state, timeout]
                // cancel state transitions
// *MR*: $Timeout instead of Konst1 => can be used as input, ensures that system request is keep active while switching to next circuit                
                ["$CancelAndAutoActive", 0, 3, "$Timeout"],
                ["$CancelAndAutoActive", 1, 3, "$Timeout"],
                ["$CancelAndAutoActive", 2, 3, "$Timeout"],

// *MR*: state 1 calls state 3 with timeout when cancel in manual mode is called to handle inhibit during request properly
                ["$Cancel", 1, 3, "$Timeout"],
// *MR*: state 2 calls state 3 with timeout when cancel in manual mode is called.
                ["$Cancel", 2, 3, "$Timeout"],        

                // normal operation state transitions
                ["$ShouldRunAndSysOk", 0, 2, 0], // bypass to skip state 1
                ["$ShouldRun", 0, 1, 0], // new request
                ["-$ShouldRun", 1, 0, 0], // cancel request
                ["$SystemOk", 1, 2, 0], // system reported ok
                ["$ShouldRun", 2, 2, 0], // running
                ["-$ShouldRun", 2, 3, "$Timeout"], // finishing
                [0, 3, 0, 0] // end
            ],
            "$State"
        ],

        // set some outputs only if system should run now or was running in last tick
        ["Or", ["$ShouldRun", "$LastShouldRun"], "$SetOutputs"],

        // Map state to outputs
        ["Comparator", "$State", "$CircuitFinished", "$Konst2"], // Finished (only 1 when state > 2)
        ["Comparator", "$State", "$CircuitState", 0], // Circuit State (only 1 when state > 0)
        ["Comparator", "$State", "$SystemRequest", 0], // SystemRequest (only 1 when state > 0)
        ["Multiplexer", [0, 0, "$Konst1", 0], "$ValveOut", "$State"], // Valve (1 only in state 2)

        ["And", ["$SetOutputs", "$CircuitState"], "$CircuitState"],
        ["And", ["$SetOutputs", "$SystemRequest"], "$SystemRequest"],
      
        // announce finished when canceld or automatic finished
        ["Or", ["$LastShouldRun",  "$TriggerInpAutomaticRising"], "$LastShouldRunOrAutoRising"], // announce also when auto was triggered
        ["And", ["$Cancel", "$LastShouldRunOrAutoRising"], "$CancelFinished"],
        ["Or", ["$CancelFinished", "$CircuitFinished"], "$CircuitFinished"],

// *MR*: Cyclic trigger with different intervall for on/off-phase
        ["Multiplexer", ["$SendIntervalOff", "$SendIntervalOn"], "$SendInterval", "$ValveOut"],    // Select Interval
        ["Clocksignal","$KonstTrue","$Clk","$SendInterval"],
// *MR*: Set remaining time zero, when off. 
        ["Latch","$Konst0","$Time_sec_remaining","-$CircuitState",0],
        ["Latch","$Konst0","$Time_min_remaining","-$CircuitState",0],
//
        // Reset Trigger
        ["Multiplexer", [0, "$TriggerAutomaticSaved", "$TriggerAutomaticSaved", "$TriggerAutomaticSaved"], "$TriggerAutomaticSaved", "$State"],

        // set last variables
        ["And", ["$ShouldRun"], "$LastShouldRun"],

        // Reset Inputs
        ["Latch", "$KonstFalse", "$TriggerInpAutomaticIn1", "$KonstTrue", 0],
        ["Latch", "$KonstFalse", "$TriggerInpAutomaticIn2", "$KonstTrue", 0],
        ["Latch", "$KonstFalse", "$TriggerInpStartIn1", "$KonstTrue", 0],
        ["Latch", "$KonstFalse", "$TriggerInpStartIn2", "$KonstTrue", 0],
        ["Latch", "$KonstFalse", "$TriggerInpStopIn1", "$KonstTrue", 0],
        ["Latch", "$KonstFalse", "$TriggerInpStopIn2", "$KonstTrue", 0]
  ]
}

Re: Automatische Bewässerungssteuerung

Verfasst: Di Mai 03, 2022 7:17 am
von ztjuu
Wenn ich inhibit verwende, wird dann circuit finished ausgelöst?

Bei inhibit wird der baustein ja nicht berechnet. Wenn jetzt circuit finish nicht ausgelöst wird, bleibt die Zentralsteuerung stehen weil diese die Sequenc nicht weiterzählt.

Deshalb hätte ich gerne minimax gefragt wie er einzelne Kreise deaktiviert und die gesamte Sequenz trotzdem weiterläuft.

Re: Automatische Bewässerungssteuerung

Verfasst: Di Mai 03, 2022 10:26 am
von Robert_Mini
Hallo ztjuu!

Doch, ich habe das im obigen Code so erweitert, dass auch das finish 1 sendet und wieder auf 0 gesetzt wird.
Die Sequenz läuft damit ich mit gesperrten Kreisen sauber durch.

Inhibit steht zumeist für den Baustein break. In Standardmodulen wird damit der baustein unmittelbar gestoppt und damit auch nichts mehr gesendet, deshalb vermutlich deine Frage.
In der Bewässerungslogik wurde nur der Name inhibit verwendet, die Abarbeitung der Logik wird aber nicht gestoppt (break wird nicht verwendet) sondern als "Stop" abgearbeitet.

@MiniMaxV2: Eventuell sollten wir den Eingang auf "lock circuit" umbenennen, um diese Verwechselung zu vermeiden?

lg
Robert

Re: Automatische Bewässerungssteuerung

Verfasst: Mi Mai 04, 2022 8:58 am
von ztjuu
Hallo Robert

Danke für die Erläuterung. Dachte schon ich bin zu doof weil es mit einem Inhibit nicht funktioniert hat.

Mann muss beide Inhibit Eingänge setzen!

Re: Automatische Bewässerungssteuerung

Verfasst: Mi Mai 04, 2022 1:03 pm
von Robert_Mini
Hallo!

Eigentlich nein. Wenn mehrere Eingänge aktiviert werden, sollten diese eigentlich per ODER wirken.
["Or", ["$VAR<Inhibit?>"], "$Inhibit"],

lg
Robert

Re: Automatische Bewässerungssteuerung

Verfasst: Do Mai 05, 2022 7:19 am
von ztjuu
Das ist komisch, bei mir funktioniert es nicht? In Grafana kann ich sehr wohl den Impuls von Circuit finished erkennen jedoch funktioniert meine Weiterschaltung nicht. Nur beim ersten Kreis?

Dürfte irgendwo ein Timeing problem sein.

Ich hab die Ausgänge circuit finished auf ein ODER gelegt und diesen Ausgang dann bei der Ablaufsteuerung auf die Weiterschaltung. Wie macht ihr dass?

Re: Automatische Bewässerungssteuerung

Verfasst: Do Mai 05, 2022 9:13 pm
von MiniMaxV2
Hi, Zusammen,
sorry für die sporadischen antworten - hier ist einiges los.
@Robert - den Vorschlag find ich gut. So könnte es eindeutiger werden.

@Ztjuu schau mal auf deine sendeflags. Es wird immer eine 1 gesendet was nur beim ersten mal ein change auslößt. Die müssen auf Always stehen.
Ich hab bei mir die alle direkt an der Ablaufsteuerung dran, also alle Circuit finished ohne eigenes or.

Re: Automatische Bewässerungssteuerung

Verfasst: Do Mai 05, 2022 10:12 pm
von Robert_Mini
Hallo ztjuu!

Anbei ein Screenshot, beschreibt Hans-Martins Kommentare:
- Next Circuit steht auf "a"
- Mit Next Circuit sind alle "Circuit Finished" verbunden

lg
Robert
Screenshot 2022-05-05 220900.png

Re: Automatische Bewässerungssteuerung

Verfasst: Fr Mai 06, 2022 7:20 am
von ztjuu
Ihr seit die besten! :bow-yellow: Funktioniert
MiniMaxV2 hat geschrieben: Do Mai 05, 2022 9:13 pm @Ztjuu schau mal auf deine sendeflags. Es wird immer eine 1 gesendet was nur beim ersten mal ein change auslößt. Die müssen auf Always stehen.
Ich hab bei mir die alle direkt an der Ablaufsteuerung dran, also alle Circuit finished ohne eigenes or.
Durch das Oder, welches nur auf Change war hat es nicht funktiniert.

Wusste auch nicht, dass ich mehrere Variablen(Ausgänge) an einen Eingang hängen kann.

Re: Automatische Bewässerungssteuerung

Verfasst: So Mai 08, 2022 7:26 pm
von MiniMaxV2
Moin @Robert_Mini ,
eine Woche verspätet, aber ich hab heute mal deine Anpassungen in meine DEV Umgebung geworfen. Schauen gut aus und ich mag den Timer schon jetzt ;)
Bevor ich das jetzt "aufnehme", hab ich noch ne Rückfrage:
  • Ich hab da den Edgecase gefunden, dass der Globalfactor von 0 zu einem undefinierten Verhalten führt. Vielleicht sollten wir das abfangen und direkt in circuit finished übergehen in diesem Fall
  • Runtime gibt es in s und min als Ausgabe. Time left nur als min. Auch hier sollten wir mmn. noch die Zeit als s ausgeben. So kann jeder den Wert nehmen den er braucht
  • Time Left ist im inaktiven Zustand auf 0. Ich würde hier bevorzugen, dass hier Automatic Time * Global Factor angezeigt wird (und auch updated). So kann man dann einen Baustein bauen, der alle Zeiten aufaddiert - Ausgang dann Automatic Time left und Automatic Time passed
Was meinst du ? :whistle: