# Flankenerkennung im Strukturierten Text mit Codesys 3



## SPS_15 (25 September 2020)

Hallo,
ich möchte eine steigende Flanke erkennen und somit einen Ausgang setzen, das ganze im strukturierten Text.

Kann mir hier jemand ein komplettes Beispiel darstellen? 

VAR

Taster1 : BOOL;

Lampe1 : BOOL;

END_VAR

Sofern der Taster1 betätigt wird, soll die Lampe1 eingeschaltet werden. 
Wie kann ich diese Flankenerkennnung im ST realisieren?


----------



## Blockmove (25 September 2020)

```
Taster1_FP := Taster1 and not Taster1_FHM;
Taster1_FHM := Taster1;

If Taster1_FP then
 Lampe1 := True;
endif
```


----------



## SPS_15 (25 September 2020)

In meinem PLC Designer von Lenze heißt der Baustein SF_R_TRIG.

VAR Input:
Name: CLK
Datentyp: Safebool 
Initialwert: FALSAE 

VAR_Output
Name: Q
Datentyp: Safebool
Initialwert: False

Meine Fragen sind:
1. Wie / Wo muss ich meine Eingangsvariable Taster1 und meines Ausgang Lampe1 deklarieren?
Wie sieht der Code für diese Flankenauswertung aus?


----------



## Heinileini (25 September 2020)

In Anlehnung an Dieters Vorschlag in #2 (ohne SF_R_TRIG):

```
VAR_INPUT    
    ibTaster :  BOOL ;
VAR_END

VAR_IN_OUT
    iobLampe :  BOOL ;
VAR_END

VAR_STATIC
    sbTaster :  BOOL := FALSE ;  // Init mit 0
VAR_END

VAR_TEMP
    tbImpuls :  BOOL ;
VAR_END

tbImpuls := ibTaster AND NOT sbTaster ;  // FlankenImpuls bilden
sbTaster := ibTaster ;  // Zustand von ibTaster in sbTaster speichern für Vergleich im nächsten Zyklus

// anschliessend 1 der folgenden 3 Alternativen:
iobLampe := iobLampe OR tbImpuls ;       // Alternative 1: OR  schaltet nur EIN
iobLampe := iobLampe XOR tbImpuls ;      // Alternative 2: XOR schaltet UM (AUS->EIN bzw. EIN->AUS)
iobLampe := iobLampe AND NOT tbImpuls ;  // Alternative 3: AND schaltet nur AUS
```

PS:
Alternative 1 entspricht Dieters Variante


----------



## SPS_15 (26 September 2020)

Vielen Dank für die Antwort! Leider meckert mein PLC Designer aber schon bei der Deklaration herum...
Die Befehle VAR_END, VAR_Static werden in meiner Deklartion gar nicht blau hinterlegt, wie es bei VAR_Input, VAR_In_OUT und VAR_Temp der Fall ist.

Gerne würde ich den Code von der Beckhoff - Seite umsetzten, weiß aber nicht wie er geschrieben wird:

VAR_INPUT
CLK : BOOL; (*Signal to detect*) // wo muss die Variable vom Signal hereingeschrieben werden?
END_VAR

VAR_OUTPUT
Q : BOOL; (*Edge detected*)
END_VAR

VAR
M : BOOL;
End_VAR

Kannst du mir den Code nochmal anhand diesem Beispiel erklären?


----------



## Blockmove (26 September 2020)

Die Variablendeklarationen bei VAR_STATIC kannst du auch bei VAR einfügen.
VAR_STATIC gibt es nicht bei jeder SPS.

Zum Thema Beckhoff:
Du hast hier nur eine Variablendeklaration und keine einzige Zeile Code.
Sieht aus wie die Schnittstelle zu zum Bautein R_TRIG


----------



## Heinileini (26 September 2020)

SPS_15 schrieb:


> Leider meckert mein PLC Designer aber schon bei der Deklaration herum...


Tschuldigung, VAR_END gibt's nicht, muss natürlich END_VAR heissen - da habe ich geschlampt. VAR_STATIC gibt's anscheinend auch nicht in CodeSys. Aber einen Beleg dafür, dass es VAR_TEMP gibt, habe ich auf die Schnelle auch nicht gefunden ... 
VAR gibt es aber für "lokale Variablen" und damit weiss ich immer noch nicht, ob und wie man zwischen temporär und statisch unterscheidet. RETAIN und PERSISTENT scheinen mir nicht das zu sein, was ich mit STATIC gemeint habe, nämlich, dass der Inhalt der Variable bis zum nächsten Aufruf des Bausteins (z.B. im nächsten PLC-Zyklus) erhalten bleiben muss. 
Bin totaler CodeSys-Laie und halte mich jetzt lieber raus und die Klappe. 

PS:
Wenn Deine CodeZeilen aus #5 tatsächlich Bestandteil von R_TRIG sind, dann hat Dieter Recht, dass VAR für statische Variablen funktioniert, denn M (der "FlankenMerker") muss statisch sein (temporär genügt nicht).


----------



## SPS_15 (26 September 2020)

Kein Problem, ich bin auch neu im St Bereich unterwegs.
Daher nochmal eine einfache Frage:
Dies ist meine Deklaration:
VAR_Input
Taster1 :BOOL;
Taster2 : BOOL;
End_VAR

VAR_OUTPUT
Lampe :BOOL;
END_VAR

Code:
If Taster1 And Taster2 Then
Lampe := True;
End_IF 

In meiner Online Simulation bekomme ich den Ausgang Lampe nicht gesetzt, obwohl ich den Taser1 und auch Taster2 auf True gesetzt habe?
Anschließend STRG + F7 für Werte schreiben, aber es passiert nichts am Ausgang Lampeß


----------



## Heinileini (26 September 2020)

Probier's mal mit VAR_IN_OUT statt VAR_OUTPUT, dann dürfte der Zustand von Lampe auch dann definiert sein und erhalten bleiben, wenn nicht beide Taster gedrückt werden.


----------



## Blockmove (26 September 2020)

Wo wird dein Baustein aufgerufen?
Je nach SPS gibt es da verschiedene Vorgaben.


----------



## Blockmove (26 September 2020)

Heinileini schrieb:


> Tschuldigung, VAR_END gibt's nicht, muss natürlich END_VAR heissen - da habe ich geschlampt. VAR_STATIC gibt's anscheinend auch nicht in CodeSys. Aber einen Beleg dafür, dass es VAR_TEMP gibt, habe ich auf die Schnelle auch nicht gefunden ...
> VAR gibt es aber für "lokale Variablen" und damit weiss ich immer noch nicht, ob und wie man zwischen temporär und statisch unterscheidet. RETAIN und PERSISTENT scheinen mir nicht das zu sein, was ich mit STATIC gemeint habe, nämlich, dass der Inhalt der Variable bis zum nächsten Aufruf des Bausteins (z.B. im nächsten PLC-Zyklus) erhalten bleiben muss.
> Bin totaler CodeSys-Laie und halte mich jetzt lieber raus und die Klappe.
> 
> ...



Heini,
VAR_STATIC ist in Codesys VAR
VAR_TEMP gibt es, wird aber oft anders gehandhabt als bei Siemens.
Es gibt dann auch noch VAR_INST bei Methoden
Persistent und Retain sind die Einstellungen für Remanzenz

VG
Dieter


----------



## SpeedyOOP (11 Oktober 2020)

VAR_Input
Taster1 :BOOL;
Taster2 : BOOL;
End_VAR

VAR_OUTPUT
Lampe :BOOL;
END_VAR

VAR
rtTaster1 : R_TRIG;
rtTaster2 : R_TRIG;
END_VAR

Code:
rtTaster1(CLK := Taster1);
rtTaster2(CLK := Taster2);

// Lampe Einschalten
If rtTaster1.Q OR rtTaster2.Q AND NOT Lampe Then
Lampe := True;
// Lampe Ausschalten
ELSIF rtTaster1.Q OR rtTaster2.Q AND Lampe Then
Lampe := false;
End_IF


----------



## LargoD (11 Oktober 2020)

SpeedyOOP schrieb:


> ...// Lampe Einschalten
> If rtTaster1.Q OR rtTaster2.Q AND NOT Lampe Then
> Lampe := True;
> // Lampe Ausschalten
> ...


Das geht übersichtlicher


```
// Lampe Ein- oder Ausschalten
[COLOR=#333333]If [/COLOR]rtTaster1.Q OR rtTaster2.Q [COLOR=#333333]Then[/COLOR]
[COLOR=#333333]Lampe := NOT Lampe;
End_If
[/COLOR]
```
Gruß
Erich


----------



## SpeedyOOP (11 Oktober 2020)

LargoD schrieb:


> Das geht übersichtlicher
> 
> 
> ```
> ...




Das ist natürlich eleganter!!!


----------



## Heinileini (11 Oktober 2020)

Helft mal bitte einem CodeSysLaien auf die Sprünge:
In den Zyklen, in denen keine Flanke detektiert wird, wer definiert dann den Zustand von Lampe? 
Für mein Verständnis sollte Lampe als VAR_IN_OUT deklariert sein!? Warum genügt VAR_OUTPUT?


----------



## SpeedyOOP (11 Oktober 2020)

Heinileini schrieb:


> Helft mal bitte einem CodeSysLaien auf die Sprünge:
> In den Zyklen, in denen keine Flanke detektiert wird, wer definiert dann den Zustand von Lampe?
> Für mein Verständnis sollte Lampe als VAR_IN_OUT deklariert sein!? Warum genügt VAR_OUTPUT?



Var_output reserviert einen Speicher.
Ergo behält die variable Lampe ihren letzten Zustand. 
Bei var_in_out wird kein Speicher reserviert. Der Speicher kommt dann von der Variablen die man bei var in out anlegt. Deswegen kann man var in out auch wie einen pointer betrachten.

Gruß


----------



## PN/DP (11 Oktober 2020)

Ich kenne Codesys auch nur theoretisch (ohne Praxis mit dem Codesys ES), daher habe auch ich Fragen:



SpeedyOOP schrieb:


> Heinileini schrieb:
> 
> 
> > Helft mal bitte einem CodeSysLaien auf die Sprünge:
> ...


Könnte es sein, daß die Aussage nur für FUNCTION_BLOCK gilt und nicht für FUNCTION?
(VAR_OUTPUT und VAR_IN_OUT sind doch in Codesys auch für FUNCTION möglich?)
Auch nach meinem Verständnis müsste Lampe als VAR_IN_OUT deklariert sein, auch wenn es im speziellen Fall auch mit VAR_OUTPUT funktioniert. 
Wenn ich sicher gehen will, daß Lampe unabhängig von der äußeren Beschaltung seinen Zustand in der Instanz speichert und behält, dann würde ich Lampe als Instanzvariable (VAR) deklarieren und am Ende auf den Output kopieren.



SpeedyOOP schrieb:


> // Lampe Einschalten
> If rtTaster1.Q OR rtTaster2.Q AND NOT Lampe Then
> Lampe := True;
> // Lampe Ausschalten
> ...


Könnte es sein, daß auch in Codesys das AND eine höhere Priorität hat als das OR? Dann wäre die Logik falsch formuliert und Taster1 könnte die Lampe nur einschalten aber nie ausschalten. Das müsste dann besser/richtig mit Klammern formuliert werden:

```
// Lampe Einschalten
If [COLOR="#0000FF"]([/COLOR]rtTaster1.Q OR rtTaster2.Q[COLOR="#0000FF"])[/COLOR] AND NOT Lampe Then
  Lampe := True;
// Lampe Ausschalten
ELSIF [COLOR="#0000FF"]([/COLOR]rtTaster1.Q OR rtTaster2.Q[COLOR="#0000FF"])[/COLOR] AND Lampe Then
  Lampe := false;
End_IF
```

Das Ganze geht aber noch eleganter ganz ohne IF..THEN..ELSIF:

```
Lampe := (rtTaster1.Q OR rtTaster2.Q) XOR Lampe;
```

Harald


----------



## SPS_15 (11 Oktober 2020)

Vielen Danke für die verschiedenen Lösungsansätze, ich konnte diese alle erfolgreich testen sowie umsetzten.
Was ich nicht verstehe ist, wofür steht hinter dem rtTaster1.Q und dem rtTaster2.Q das "Q"?


----------



## Heinileini (11 Oktober 2020)

SPS_15 schrieb:


> Was ich nicht verstehe ist, wofür steht hinter dem rtTaster1.Q und dem rtTaster2.Q das "Q"?


Wenn Du nur das nicht verstehst, dann erklär uns doch bitte die DeklarationsZeilen:

```
VAR
    rtTaster1 : R_TRIG;
    rtTaster2 : R_TRIG;
END_VAR
```
... und die CodeZeilen:

```
rtTaster1(CLK := Taster1);
rtTaster2(CLK := Taster2);
```


----------

