TIA IEC Timer Verständnisproblem

Mindrover

Level-2
Beiträge
48
Reaktionspunkte
6
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo miteinander und ein gute neues Jahr,

ich habe gerade eine Denkblockade und vermutlich auch ein Verständnisproblem.

Folgendes möchte ich realisieren: Am Touch auf der "Handmode"-Seite meines "Öldosierers" möchte ich eine Anzahl Sprühstöße(HMI.EA.Amount) angeben und dann mit einem
Button aktivieren. Das Button Bit wird gesetzt. Das Ventil muss eine bestimmte Zeit geschaltet bleiben um die Mediummenge zu bestimmen.

Das wollte ich mit einer FOR-Schleife machen:

IF HMI.Button.Hand.Start then

tSpitAmount:=HMI.EA.Amount;

For tLoop:= 1 to "tSpitAmount" by 1 do

sTOFValveControlMan(IN:=8hz, PT:=10ms, Q=>QValve);

End_For;

HMI.Button.Hand.Start:=false;
END_IF;

Falls ich das mit der Schleife richtig verstehe würde das aber meine Zykluszeit extrem aufblähen, da es alle Durchläufe im gleichen Zyklus macht. Zum Beispiel bei Anzahl Sprühstöße=10, wären dass ja dann schon 100ms. (Vermutlich in Hand egal)
Zudem habe ich keine gute Idee wie ich den Eingang des Timers vernünftig toggeln kann.

Mir wäre alternativ noch eingefallen, das ganze so zu machen:

IF HMI.Button.Hand.Start then

tSpitAmount:= HMI.EA.Amount;

sTOFValveControlMan(IN:=8hz, PT:=10ms, Q=>QValve);

IF tSpitAmount > 0 then
tSpitAmount:=tSpitAmount-1;
END_IF;
IF tSpitAmount=0 then
HMI.Button.Hand.Start:=false;
END_IF;

Wo ich die 8Hz hernehmen soll oder generell einen Takt hernehmen soll, weiss ich aktuell auch nicht. Da gab es in meiner alten Firma einen Baustein der verschiedene Takte generiert hat.

An der Stelle komme ich gedanklich gerade nicht weiter.

Bitte um Ideen. Gerne auch Vorschläge wie man das schöner und einfacher programmieren kann.
Danke im Voraus
 
Kannst du nicht einfach einen Impulse erzeugen?

Code:
#IEC_TP_Sprühstöße(IN := HMI.Button.Hand.Start,
                   PT := tmpDauer,
                   Q  => Ausgang);

Der Ausgang würde dann bei einer Positiven Flanke von HMI.Button.Hand.Start die festgelegte Zeit tmpDauer anstehen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Kannst du nicht einfach einen Impulse erzeugen?

Code:
#IEC_TP_Sprühstöße(IN := HMI.Button.Hand.Start,
                   PT := tmpDauer,
                   Q  => Ausgang);

Der Ausgang würde dann bei einer Positiven Flanke von HMI.Button.Hand.Start die festgelegte Zeit tmpDauer anstehen.
Das würde nach meinem Verständnis einmalig einen Impuls erzeugen, beim zweiten Durchlauf aber nichtmehr, da HMI.Button.Hand.Start=true bis alle Sprühstöße getätigt sind.
🤔
 
Die Taktmerker findest du in der Gerätekonfiguration, wenn du auf deine CPU klickst und dann auf Eigenschaften - IO-Variablen.

sTOFValveControlMan(IN:=8hz, PT:=10ms, Q=>QValve);
Beim IN handelt es sich um einen BOOL-Eingang, klick am besten mal auf "sTOFValveControlMan" und drück dann F1. In der Hilfe dazu bekommst du eine schöne Beschreibung inklusive Diagramm.

alls ich das mit der Schleife richtig verstehe würde das aber meine Zykluszeit extrem aufblähen, da es alle Durchläufe im gleichen Zyklus macht.
Wie du richtig gesagt hast sollte man eine SPS nicht auf diese Weise mit der Schleife programmieren.

Wenn ich es richtig verstanden habe, würde ich es in etwa so umsetzen:
Mit dem "Button Bit" einen Impuls setzen wie @PEit gemeint hat, bei negativer Flanke mit einem Zähler eins runter zählen, wiederholen bis der Zähler unten ist und dann das "Button Bit" zurücksetzen. Für eine genauere Überlegung müsste ich es mir erst selbst aufbauen.
 
Zunächst:

Beim IN handelt es sich um einen BOOL-Eingang, klick am besten mal auf "sTOFValveControlMan" und drück dann F1. In der Hilfe dazu bekommst du eine schöne Beschreibung inklusive Diagramm.


Wie du richtig gesagt hast sollte man eine SPS nicht auf diese Weise mit der Schleife programmieren.

Wenn ich es richtig verstanden habe, würde ich es in etwa so umsetzen:
Mit dem "Button Bit" einen Impuls setzen wie @PEit gemeint hat, bei negativer Flanke mit einem Zähler eins runter zählen, wiederholen bis der Zähler unten ist und dann das "Button Bit" zurücksetzen. Für eine genauere Überlegung müsste ich es mir erst selbst aufbauen.
Ja stimmt, dass mit den 8hz war keine gute Idee und hätte eh nicht funktioniert.

Das mit der negativen Flanke verstehe ich nicht ganz. Der TP erzeugt doch nur einen Impuls bei Flankenwechsel bei IN von 0 auf 1. Damit würde dann, wenn der Knopf am Touch gedrückt wird auch nur einmalig ein Impuls erzeugt werden. Da das Button Bit ansteht, würde das ja bei z.B. 5 eingestellten Sprühstößen, nur einmal funktionieren.

Irgendwie stehe ich gerade auf der Leitung. Könntest du das möglicherweise in SCL darlegen, vielleicht verstehe ich es dann besser :)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Könnte denke ich etwa so aussehen.

Code:
#IEC_TP_Sprühstöße(IN := HMI.Button.Hand.Start and not #IEC_TOF_OffTime.Q,
                   PT := tmpDauer,
                   Q  => Ausgang);
                              
#IEC_TOF_OffTime(IN := #IEC_TP_Sprühstöße.Q,
                   PT := tmpOffTime);

Ich hab grad die Syntax vom Counter nicht im Kopf. Aber den wie @fabey geschrieben hat einfach bei negativer Flanke von #IEC_TP_Sprühstöße.Q runterzählen.
 
Könntest du das möglicherweise in SCL darlegen

Ich weiß nicht ob das die beste oder einfachste Variante ist, aber immerhin siehst du so wie ein Impuls und ein Zähler funktioniert:

C-ähnlich:
// Startimpuls
#R_TRIG_bButton(CLK := #bButton); // Positive Flanke Button

// Set Trigger
IF #bButton AND NOT #bTrigger THEN
    #bTrigger := TRUE;
END_IF;

// Output
#IEC_Timer_TP(IN:=#bTrigger, // Wenn positive Flanke bTrigger wird bQ für 10ms gesetzt
              PT:=T#10ms,
              Q=>#bQ);

// Reset Trigger
#F_TRIG_TP(CLK:=#IEC_Timer_TP.Q); // Negative Flanke Timer

IF #F_TRIG_TP.Q THEN
    #bTrigger := FALSE;
END_IF;

// Count down
#IEC_Counter_Down(CD:=#F_TRIG_TP.Q, // Reset des Trigger = 1 Zyklus fertig
                  LD:=#R_TRIG_bButton.Q, // Zählwert wird bei pos. Flanke am Button übernommen
                  PV:=#iAmount); // Anzahl Zyklen

// Done
#R_TRIG_CD(CLK:=#IEC_Counter_Down.QD); // Positive Flanke Counter fertig

IF #R_TRIG_CD.Q THEN
    #bButton := FALSE; // Rücksetzen des Buttons
END_IF;
 
Könnte denke ich etwa so aussehen.

Code:
#IEC_TP_Sprühstöße(IN := HMI.Button.Hand.Start and not #IEC_TOF_OffTime.Q,
                   PT := tmpDauer,
                   Q  => Ausgang);
                             
#IEC_TOF_OffTime(IN := #IEC_TP_Sprühstöße.Q,
                   PT := tmpOffTime);

Ich hab grad die Syntax vom Counter nicht im Kopf. Aber den wie @fabey geschrieben hat einfach bei negativer Flanke von #IEC_TP_Sprühstöße.Q runterzählen.
Auf die Idee einen zweiten Operanden bei IN herzunehmen bin ich irgendwie nicht gekommen😅

Habe mir dank euren Anregungen folgendes zurechtgemacht:
IF HMI.Button.Hand.Start then

tSpitAmount:= HMI.EA.Amount;

IF tSpitAmount>0 then sSpitMan:=true;
END_IF;

sTPValveMan(IN:=sSpitMan,PT=1ms,Q=>tSpitValve);

tSpitMan:=false;

sTOFValveControlMan(IN:=tSpitValve, PT:=9ms, Q=>QValve);

IF tSpitAmount > 0 then
tSpitAmount:=tSpitAmount-1;
END_IF;
IF tSpitAmount=0 then
HMI.Button.Hand.Start:=false;
END_IF;END_IF;

Bin scheinbar ein umstandskramer😆
 
Code:
IF HMI.Button.Hand.Start then

   tSpitAmount:= HMI.EA.Amount;

   IF tSpitAmount>0 then 
      sSpitMan:=true;
   END_IF;

   sTPValveMan(IN:=sSpitMan,PT=1ms,Q=>tSpitValve);

   tSpitMan:=false;

   sTOFValveControlMan(IN:=tSpitValve, PT:=9ms, Q=>QValve);

   IF tSpitAmount > 0 then
      tSpitAmount:=tSpitAmount-1;
   END_IF;
   IF tSpitAmount=0 then
      HMI.Button.Hand.Start:=false;
   END_IF;
END_IF;
Hast Du das mal laufen lassen?

tSpitAmount:= HMI.EA.Amount;
wird in jedem Zyklus gesetzt und
IF tSpitAmount > 0 then
tSpitAmount:=tSpitAmount-1;
END_IF;
in jedem Zyklus um 1 heruntergezählt.
Wann soll das nochmal enden? Nur in dem Fall in dem HMI.EA.Amount=1 ist, aber sonst nicht.

Ein paar mehr Fehler sind da noch drin, aber ich würde erstmal sicherstellen was ich überhaupt möchte:
Das Ventil soll ununterbrochen für Zeit X eingeschaltet bleiben
oder
Du willst das Ventil X mal schalten mit jeweils einer bestimmten Puls- und Pausenzeit?

Deine Aufgabenstellung widerspricht sich da ein wenig, denn eine Anzahl Sprühstöße wären eine Puls-Pause-Variante, Du aber schreibst oben das es eine bestimmte Zeit eingeschaltet bleiben muss und nutzt dennoch eine Anzahl.
 
Hast Du das mal laufen lassen?


tSpitAmount:= HMI.EA.Amount;
wird in jedem Zyklus gesetzt und

IF tSpitAmount > 0 then
tSpitAmount:=tSpitAmount-1;
END_IF;
in jedem Zyklus um 1 heruntergezählt.
Wann soll das nochmal enden? Nur in dem Fall in dem HMI.EA.Amount=1 ist, aber sonst nicht.

Ein paar mehr Fehler sind da noch drin, aber ich würde erstmal sicherstellen was ich überhaupt möchte:
Das Ventil soll ununterbrochen für Zeit X eingeschaltet bleiben
oder
Du willst das Ventil X mal schalten mit jeweils einer bestimmten Puls- und Pausenzeit?

Deine Aufgabenstellung widerspricht sich da ein wenig, denn eine Anzahl Sprühstöße wären eine Puls-Pause-Variante, Du aber schreibst oben das es eine bestimmte Zeit eingeschaltet bleiben muss und nutzt dennoch eine Anzahl.
Nein habe ich nicht laufen lassen. Dazu habe ich im Moment leider noch keine Möglichkeit.

Stimmt tSpitAmount:=HMI.EA.Amount; passiert jeden Zyklus. Das möchte ich aber eigentlich nur beim ersten mal, wenn der Button gedrückt wird.

Demnach müsste ich dann den HMI-Button gleich nach dem kopieren rücksetzen.

IF HMI.Button.Hand.Start then

tSpitAmount:= HMI.EA.Amount;
HMI.Button.Hand.Start:=false; // hier schon Rücksetzen
END_IF;
IF tSpitAmount>0 then
sSpitMan:=true;


sTPValveMan(IN:=sSpitMan,PT=1ms,Q=>tSpitValve);

tSpitMan:=false;

sTOFValveControlMan(IN:=tSpitValve, PT:=9ms, Q=>QValve); // Ventil soll z.B, 10 ms geschaltet bleiben: also 1ms solange der tSpitValve da ist // und dann 9ms vom TOF


tSpitAmount:=tSpitAmount-1; // Damit dürfte jeden Zyklus 1 abgezogen werden bis tSpitAmount 0 ist, also die erforderliche Anzahl // gesprüht wurde
END_IF;


END_IF;
END_IF;
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Nein habe ich nicht laufen lassen. Dazu habe ich im Moment leider noch keine Möglichkeit.

Stimmt tSpitAmount:=HMI.EA.Amount; passiert jeden Zyklus. Das möchte ich aber eigentlich nur beim ersten mal, wenn der Button gedrückt wird.

Demnach müsste ich dann den HMI-Button gleich nach dem kopieren rücksetzen.

IF HMI.Button.Hand.Start then

tSpitAmount:= HMI.EA.Amount;
HMI.Button.Hand.Start:=false; // hier schon Rücksetzen
END_IF;
IF tSpitAmount>0 then
sSpitMan:=true;


sTPValveMan(IN:=sSpitMan,PT=1ms,Q=>tSpitValve);

tSpitMan:=false;

sTOFValveControlMan(IN:=tSpitValve, PT:=9ms, Q=>QValve); // Ventil soll z.B, 10 ms geschaltet bleiben: also 1ms solange der tSpitValve da ist // und dann 9ms vom TOF


tSpitAmount:=tSpitAmount-1; // Damit dürfte jeden Zyklus 1 abgezogen werden bis tSpitAmount 0 ist, also die erforderliche Anzahl // gesprüht wurde
END_IF;


END_IF;
END_IF;
Nutze doch bitte mal den CODE-TAG für deine Programmzeilen ( hier im Forum ):
1642059605250.png
 
Code:
IF HMI.Button.Hand.Start then

tSpitAmount:= HMI.EA.Amount;
HMI.Button.Hand.Start:=false; // hier schon Rücksetzen
END_IF;
IF tSpitAmount>0 then
sSpitMan:=true;


sTPValveMan(IN:=sSpitMan,PT=1ms,Q=>tSpitValve);

sSpitMan:=false;

sTOFValveControlMan(IN:=tSpitValve, PT:=9ms, Q=>QValve); // Ventil soll z.B, 10 ms geschaltet bleiben: also 1ms solange der tSpitValve da ist // und dann 9ms vom TOF


tSpitAmount:=tSpitAmount-1; // Damit dürfte jeden Zyklus 1 abgezogen werden bis tSpitAmount 0 ist, also die erforderliche Anzahl // gesprüht wurde
END_IF;
 
Zuletzt bearbeitet:
Nein habe ich nicht laufen lassen. Dazu habe ich im Moment leider noch keine Möglichkeit.

Stimmt tSpitAmount:=HMI.EA.Amount; passiert jeden Zyklus. Das möchte ich aber eigentlich nur beim ersten mal, wenn der Button gedrückt wird.

Demnach müsste ich dann den HMI-Button gleich nach dem kopieren rücksetzen.

IF HMI.Button.Hand.Start then

tSpitAmount:= HMI.EA.Amount;
HMI.Button.Hand.Start:=false; // hier schon Rücksetzen
END_IF;
IF tSpitAmount>0 then
sSpitMan:=true;


sTPValveMan(IN:=sSpitMan,PT=1ms,Q=>tSpitValve);

tSpitMan:=false;

sTOFValveControlMan(IN:=tSpitValve, PT:=9ms, Q=>QValve); // Ventil soll z.B, 10 ms geschaltet bleiben: also 1ms solange der tSpitValve da ist // und dann 9ms vom TOF


tSpitAmount:=tSpitAmount-1; // Damit dürfte jeden Zyklus 1 abgezogen werden bis tSpitAmount 0 ist, also die erforderliche Anzahl // gesprüht wurde
END_IF;


END_IF;
END_IF;
Ja, im Prinzip hast Du Recht, man könnte ihn nach dem Kopieren rücksetzen, aber das wird dennoch ein Glücksspiel das es überhaupt wiederholbar zuverlässig läuft und wenn man es am Anfang gleich zurücksetzt, dann kann man im Falle einer Falschangabe oder Problems das gar nicht mehr anhalten.

Du solltest Dir nochmal Deine Zielsetzung anschauen. Was genau wird das?
Was ich sehe ist das Du ein Ventil für Zeit X eingeschaltet haben willst.
Dafür nimmst Du dann einfach nur ein TP und der HMI-Button wird SetzeBitWährendTasteAktiv oder so ähnlich.
Im HMI wird anstelle der Anzahl dann der Datentyp Time eingegeben und direkt am TP verlinkt.

Meine Vermutung aufgrund "Anzahl" und "Sprühstoß" ist, das Du ein Ventil X Male für X Sekunden mit einer Pause von X Sekunden eingeschaltet haben möchtest. Dann wäre das Vorgehen wirklich komplexer und man benötigt mehr als nur das TP, jedoch auch nicht so wie Du es geschrieben hast. Der Vorgang nennt sich dann Puls-Pause.

Du versuchst mit dem TOF und TP zusammen 10ms abzuarbeiten. Das funktioniert nicht weil die Zykluszeit zumeist nicht unter 1ms liegt.
Da tSpitAmount pro Zyklus nur einmal heruntergezählt wird dauert die Ausführung ebenfalls länger, also ca. 9ms + (Anzahl Zyklen * Zykluszeit).

Wenn ich nun verschiedene Zykluszeiten "mal eben" im Kopf durchrechne, so schaffe ich es sogar das das Ventil am Ende hängen bleibt und nicht mehr abschaltet weil das TOF noch aktiv ist jedoch tSpitAmount auf 0 fällt und somit nicht mehr größer 0 ist.
Dies liegt unter anderem daran das das TOF innerhalb der IF-Abfrage abgearbeitet wird. Das sollte vermieden werden. Wenn es nicht abgearbeitet wird so verbleibt der letzte Zustand und QValve bleibt aktiv.

Wenn Du nicht die Möglichkeit hast das zu testen, wie schreibst Du nun gerade das Programm? Falls Du das bereits im TIA-Portal erstellst, dann kannst Du das sehr wohl testen indem Du das Programm PLCSIM installierst und in TIA dann oben auf Simulation klickst. Dann siehst Du eventuell auch was passieren wird.

Also im Grunde genommen würde ich sagen das das Programm von Dir so überhaupt nicht laufen wird, zumindest nicht dauerhaft und sobald Änderungen am Programm vorgenommen werden oder aber die Zykluszeit steigt wird es nur noch Probleme geben.

Desweiteren stellt sich bei 10ms auch die Frage nach Deiner Hardware. Kann diese überhaupt 10ms im schnellsten verarbeiten?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Was ich sehe ist das Du ein Ventil für Zeit X eingeschaltet haben willst.
Dafür nimmst Du dann einfach nur ein TP und der HMI-Button wird SetzeBitWährendTasteAktiv oder so ähnlich.
Im HMI wird anstelle der Anzahl dann der Datentyp Time eingegeben und direkt am TP verlinkt.
Also der im Touch gebe ich eine Anzahl der Sprühstoße in ein EA-Feld ein und möchte dann mit Knopfdruck die Anzahl Sprühstöße abarbeiten.
Die Zeit habe ich am TP ja als 1 ms angegeben. Einfach weil es die kürzeste Zeit ist die ich mir vorstellen kann, da ich ja lediglich einen Flankenwechsel am IN vom TOF erreichen möchte.

Du versuchst mit dem TOF und TP zusammen 10ms abzuarbeiten. Das funktioniert nicht weil die Zykluszeit zumeist nicht unter 1ms liegt.
Da tSpitAmount pro Zyklus nur einmal heruntergezählt wird dauert die Ausführung ebenfalls länger, also ca. 9ms + (Anzahl Zyklen * Zykluszeit).
Die 10ms habe ich als Beispiel genommen, vermutlich wird es eher in Richtung >100ms gehen. Es wird eine Menge von 0,04g Dosiert werden, weshalb ich noch nicht abschätzen kann wie lange die Zeit im Endeffekt sein wird. Da wird man sich vermutlich bei Inbetriebnahme an einen Zeitwert rantasten müssen. Ich gehe davon aus das, ein paar ms mehr oder weniger durch Zykluszeit keinen Unterschied machen werden.

Wenn Du nicht die Möglichkeit hast das zu testen, wie schreibst Du nun gerade das Programm? Falls Du das bereits im TIA-Portal erstellst, dann kannst Du das sehr wohl testen indem Du das Programm PLCSIM installierst und in TIA dann oben auf Simulation klickst. Dann siehst Du eventuell auch was passieren wird.
Guter Punkt, ich sollte das PLCSIM mal testen.
Bisher habe ich noch keine Erfahrung mit Bausteinentwicklung und taste mich gerade ran.
Habe sonst nur Inbetriebnahme gemacht und von bereits vorhandenen Vorlagen weggearbeitet und diese evtl. angepasst.

Dies liegt unter anderem daran das das TOF innerhalb der IF-Abfrage abgearbeitet wird. Das sollte vermieden werden. Wenn es nicht abgearbeitet wird so verbleibt der letzte Zustand und QValve bleibt aktiv.
Das ist natürlich schlecht und zeigt ganz klar meine Wissens- bzw. Erfahrungslücken auf.


Code:
IF HMI.Button.Hand.Start then

tSpitAmount:= HMI.EA.Amount;
HMI.Button.Hand.Start:=false; // hier schon Rücksetzen
END_IF;
IF tSpitAmount>0 then
sSpitMan:=true;
END_IF;

sTPValveMan(IN:=sSpitMan,PT=1ms,Q=>tSpitValve);

sSpitMan:=false;

sTOFValveControlMan(IN:=tSpitValve, PT:=100ms, Q=>QValve); 

IF QValve then
tSpitAmount:=tSpitAmount-1; // Damit dürfte jeden Zyklus 1 abgezogen werden bis tSpitAmount 0 ist, also die erforderliche Anzahl // gesprüht wurde
END_IF;

Wenn ich dich richtig verstanden habe, dann sollte der Code in etwa so aussehen und ich werde diesen demnächst mit PLC Sim testen.

Danke für deine Hilfe
 
Es wird eine Menge von 0,04g Dosiert werden, ...
Ich weiß jetzt nicht wie groß die Toleranzen bei deiner Ausbringmenge sind und wie hoch deine Zykluszeit sein wird, aber ich würde im Hinterkopf behalten, das falls deine Zykluszeit schwankt, auch deine Ausbringmenge schwanken wird.

Ich würde mal darüber nachdenken die Ausgänge über einen Interrupt anzusteuern, und mit SET_CINT die Zeittakt bzw. die Sprühstöße pro Sekunde einzustellen. Da aber immer aufpassen, das der Interrupt nicht zu häufig aufgerufen wird.
Könnte so aussehen:

Code:
   VAR_INPUT 
      StartAuto : Bool;
      StartHand : Bool;
      "Pulse/Sek" : Real;
      OV : UDInt;
   END_VAR

   VAR_OUTPUT 
      Dosieren : Bool;
      Dosiertakt : Time;
   END_VAR

   VAR_TEMP 
      RET_VAL : Int;
      us : Real;
   END_VAR

IF #Dosieren THEN // Wenn Dosieren Aktiv
    IF #"Punkt/Sek" <> 0 THEN
        IF #AutomatikAktiv THEN
            IF #OV <> 0 THEN
                // Punkte/Sekunde mit OV verrechnen
                #"tmpPunkt/Sek" := #"Punkt/Sek" * #OV / 100;
                // Ausrechnen vom Aufruf Cycle: 1 Sekunde in us / Punkte/Sekunde
                #tmpCylcle := ROUND(1000000 / #"tmpPunkt/Sek");
                #tmpFreigabe := True;
            END_IF;
        ELSE
            // Ausrechnen vom Aufruf Cycle: 1 Sekunde in us / Punkte/Sekunde
            #tmpCylcle := ROUND(1000000 / #"Punkt/Sek");
            #tmpFreigabe := True;
        END_IF;
    END_IF;
ELSE // Sonst Cycle hochsetzten zur Entlastung des Zyklus.
    #tmpCylcle := 50000;
END_IF;

IF #tmpCylcle > 60000000 THEN
    #tmpCylcle := 60000000;
ELSIF #tmpCylcle < 70000 THEN
    #tmpCylcle := 70000;
END_IF;

#FreigabeDüse := #tmpFreigabe;
#Dosiergeschw_Einst := SET_CINT(OB_NR := #OBNr, CYCLE := #tmpCylcle, PHASE := 0);
#Dosiergeschw_Einst := SET_CINT(OB_NR := #ResetOBNr, CYCLE := #tmpCylcle, PHASE := 35000);
 
Ich weiß jetzt nicht wie groß die Toleranzen bei deiner Ausbringmenge sind und wie hoch deine Zykluszeit sein wird, aber ich würde im Hinterkopf behalten, das falls deine Zykluszeit schwankt, auch deine Ausbringmenge schwanken wird.
Die Ausbringmenge muss jedes Mal gleich sein.

Da bedeutet das ich dann die Timer wegwerfen muss und mit Interrupt arbeiten um Schwankungen bei der Ausbringmenge zu vermeiden.

Bin sehr froh hier gepostet zu haben. Da hätte ich mich andernfalls ganz schön blamiert :).
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich bin mir nicht ganz sicher was Du mit Anzahl Sprühstöße erreichen willst? Du hast doch gar keine Sprühstöße sondern einen einzigen durchgehenden Sprühstoß von 100ms, vielleicht auch 80ms oder 120ms, das wird bei der Inbetriebnahme noch herauszufinden sein.
Mit Deiner Anzahl Sprühstöße erreichst Du nur eine variable Zeitlänge die stark von der Zykluszeit abhängt. Der Ausgang ist in der Zeit durchgehend aktiv.

Warum also schreibst Du nicht einfach:
Code:
sTPValveMan(IN:=HMI.Button.Hand.Start, PT:=tSpitTime, Q=>Qvalve);
IF sTPValveMan.Q then
   HMI.Button.Hand.Start:=FALSE;
END_IF;

Es wird in der HMI ein EA-Feld erstellt das mit tSpitTime verlinkt ist.
tSpitTime ist innerhalb Deines FBs am IN eine Variable von Datentyp Time.
Mit dem Code muss man also in der HMI nur angeben wieviele ms das Ventil schalten soll und mit HMI.Button.Hand.Start wird das ganze aktiviert.
Der ganze andere Klimbim drum rum ist gar nicht nötig.

Womit wir dann übrigens bei Beitrag #2 von @PEit wären.

Das ganze setzt natürlich voraus das der Sprühstoss größer ist als Deine Zykluszeit. Sollte er darunter liegen, dann hat Dir PEit in Beitrag #16 gerade eine Möglichkeit mittels Weckalarm-OBs benannt.

PS: Mit Zykluszeiten irgendwelche zeitbasierten Funktionen zu versuchen ist nicht gut, das kann schnell nach hinten losgehen. Kann man aber machen, aber nicht so sondern dann mit tatsächlichen Zykluszeiten und die müssen Zyklus für Zyklus neu ermittelt werden.
Wenn man allerdings nur für Zeit X was schalten will, dann einfach nur ein TON, TOF oder TP nutzen.
 
Ok ich fange jetzt nochmal ganz von vorne an.

Ich möchte fürs erste eine Hand Seite für eine Öldosiereinheit erstellen.
Diese wird benutzt um einfach mal das Sprühen zu testen.

Nun soll man mit einem Knopf einen oder mehrere Sprühstöße auslösen können.

Die Anzahl der Sprühstöße soll man über ein EA-Feld Int bestimmen können.

Ich möchte also eine Zahl z.B. 3 eingeben und dann mit einem Knopfdruck 3 Sprühstöße in Folge auslösen können.

Ein Sprühstoß wir mit dem Ansteuern eines Ventils ausgelöst.

Da ich eine bestimmte Ölmenge dosieren möchte, steure ich das Ventil eine bestimmte Zeit an.
Deswegen der Tp und der Tof.

Da der Tof eine fallende Flanke benötigt um die eingeschaltete Zeit abzulaufen, benutze ich einen Tp für den IN des TOF.
Indem ich den Wert vom HMI-EA auf einen temp kopiere und diesen bei jedem Zyklus um 1 reduziere, stelle ich mir vor das
der Tp und somit der Tof 3 mal ausgelöst und somit das Ventil 3x 100ms angesteuert wird.

Wobei mir auffält, dass der Eingang des Tof ja wahrscheinlich schon wieder true ist bevor die Zeit abgelaufen ist, also schon wieder ein Fehler von mir. Vermutlich habe ich dadurch Verwirrung geschaffen.

Code:
IF HMI.Button.Hand.Start then

tSpitAmount:= HMI.EA.Amount;
HMI.Button.Hand.Start:=false; // hier schon Rücksetzen
END_IF;
IF tSpitAmount>0 AND NOT sTOFValveControlMan.Q then     // hier muss ich verhindern, dass sSpitMan true wird solange der tof noch läuft       
sSpitMan:=true;
END_IF;

sTPValveMan(IN:=sSpitMan,PT=1ms,Q=>tSpitValve);

sSpitMan:=false;

sTOFValveControlMan(IN:=tSpitValve, PT:=100ms, Q=>QValve);

IF QValve then
tSpitAmount:=tSpitAmount-1; // Damit dürfte jeden Zyklus 1 abgezogen werden bis tSpitAmount 0 ist, also die erforderliche Anzahl // gesprüht wurde
END_IF;


Erreichen will ich also das das Ventil Xmal gleich lange angesteuert wird, wenn der Knopf am Touch gedrückt wird.
Wichtig ist dabei, dass egal wie oft, die Dauer der Ventilansteuerung immer gleich ist.
 
Zuletzt bearbeitet:
So wie du das geschrieben hast würdest du wahrscheinlich keine einzelnen Sprühstöße sondern einen lagen haben.
Außerdem kannst du nicht jeden Zyklus deinen Zähler runterzählen. Da musst du schon darauf warten das der Sprühstoß fertig ist.

C-ähnlich:
IF HMI.Button.Hand.Start THEN
  
    tSpitAmount := HMI.EA.Amount;
    HMI.Button.Hand.Start := false; // hier schon Rücksetzen
END_IF;

IF tSpitAmount > 0 AND NOT #sTOFValveControlMan.Q THEN     // hier muss ich verhindern, dass sSpitMan true wird solange der tof noch läuft     
  
    sSpitMan := true;
END_IF;

// Der TP Schaltet deinen Ausgang
#sTPValveMan(IN:=sSpitMan,
            PT=100ms,
            Q=>QValve); 

sSpitMan := false;

// Der TOF ist die Wartezeit zwischen den Sprühstößen.
// Sobald also der TP abfällt läuft der TOF noch 20ms nach.
#sTOFValveControlMan(IN:=#sTPValveMan.Q,
            PT:=20ms);


#F_TRIG_TP(CLK := sTPValveMan.Q); // Negative Flanke vom Sprühstoß

IF #F_TRIG_TP.Q THEN // Sobald ein Sprühstoß Fertig ist kannst du tSpitAmount um einen Verringern
  
    tSpitAmount -= 1;
END_IF;
 
Zurück
Oben