Step 7 Zähler in SCL

spirit

Level-1
Beiträge
961
Reaktionspunkte
23
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

mein Zähler in SCL funktioniert nur, wenn ich "TAKT" als Eingangsparameter deklariere. Sobald ich diesen als Statische Variable deklariere, zählt der Zähler nicht mehr! Warum ist das so; wo liegt mein Fehler?

Folgende Variablen habe ich deklariert:


VAR_INPUT
Eingang: BOOL;
SET : BOOL;
RESET : BOOL;
END_VAR

VAR_OUTPUT
Dual_Zaehlwert : WORD;
BCD_Zaehlwert : WORD;
Ausgang : BOOL;
END_VAR

VAR
TAKT : BOOL;
fm : BOOL;
END_VAR

Code:
// Neg. Flanke
 
IF NOT Eingang AND fm THEN
   TAKT := 1;
END_IF;
fm := Eingang;
 
// Aufwärtszähler
 
BCD_Zaehlwert:= S_CU (C_NO := Z1,
                      CU   := TAKT,
                      S    := SET,
                      PV   := 3,
                      R    := RESET,
                      CV   := Dual_Zaehlwert,
                      Q    := Ausgang);

Vielen Dank für eine Erklärung... ;)
 
Weil dein Takt keine Flanke ist, sondern du den fix auf "1" Schreibst, wenn die Bedingung "NOT Eingang AND fm" mal erfüllt wurde.
Wenn du Takt als IN-Parameter hast schreibst, dann wird "Takt" dadurch wieder "0".

a) Für eine Flanke brauchst du kein IF ... THEN sonder nur "Takt := NOT Eingang AND fm ;"
b) Für einen S5-Zähler wie du ihn hier verwendest, bräuchtest du überhaupt keine Flanke, das mach der Zähler schon selbst.

Mfg
Manuel
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Weil dein Takt keine Flanke ist, sondern du den fix auf "1" Schreibst, wenn die Bedingung "NOT Eingang AND fm" mal erfüllt wurde.
Wenn du Takt als IN-Parameter hast schreibst, dann wird "Takt" dadurch wieder "0".

Mfg
Manuel

Vielen Dank für deine Erklärungen Manuel!

1) Das heißt also, dass in diesem Fall TAKT nach einmaliger Erfüllung immer auf 1 bleiben würde, wenn er als Temp-Variable deklariert wurde?

2) Nur, warum wird TAKT dann wieder 0, wenn er als IN-Parameter deklariert ist - ist da das Speicherverahlten anders?
 
1) Das heißt also, dass in diesem Fall TAKT nach einmaliger Erfüllung immer auf 1 bleiben würde, wenn er als Temp-Variable deklariert wurde?

Code:
VAR 
TAKT : BOOL;
fm : BOOL; 
END_VAR

TAKT ist keine temporäre sondern eine (lokale) statische Variable.
Wenn TAKT temporär wäre (was keine gute Idee ist), wäre der Inhalt undefiniert wenn Du die Avriable nicht in jedem Bausteinaufruf vor der ersten Verwendung beschreiben würdest.

Gruß.
 
2) Nur, warum wird TAKT dann wieder 0, wenn er als IN-Parameter deklariert ist - ist da das Speicherverahlten anders?

MSB meint hier, dass du bei deiner S_CU-Beschaltung an Stelle deiner Variablen "Takt" auch gleich die IN-Variable "Eingang" verwenden kannst / solltest ...

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
TAKT ist keine temporäre sondern eine (lokale) statische Variable.
Gruß.

Ja Danke ducati... war ein Schreibfehler. In meinem Ausgangspost #1 hatte ich ja geschrieben, dass es eine Statische Variable ist.

Weil dein Takt keine Flanke ist, sondern du den fix auf "1" Schreibst, wenn die Bedingung "NOT Eingang AND fm" mal erfüllt wurde.
Wenn du Takt als IN-Parameter hast schreibst, dann wird "Takt" dadurch wieder "0".

Mfg
Manuel

1) Das heißt also, dass in diesem Fall TAKT nach einmaliger Erfüllung immer auf 1 bleibt, wenn er als Temp-Variable deklariert wurde?

2) Nur, warum wird TAKT dann wieder 0, wenn er als IN-Parameter deklariert ist - ist da das Speicherverahlten anders?
 
MSB meint hier, dass du bei deiner S_CU-Beschaltung an Stelle deiner Variablen "Takt" auch gleich die IN-Variable "Eingang" verwenden kannst / solltest ...

Gruß
Larry

Danke Larry,

mir ist halt nur nicht klar, warum es funktioniert, wenn ich TAKT als IN-Variable deklariere und es nicht funktioniert, wenn ich TAKT als Statische Variable deklariere.

Durch meinen Fehler, TAKT fest auf 1 zu schreiben, müssten doch die Auswirkungen bei beiden Variablen die gleichen sein, oder nicht?
 
Ähh ...

was wolltest du noch mit diesem Doppelpost bewirken ?

Warum legst du "Eingang" nicht auf den Zähler (an Stelle von Takt) ? Welchen Grund hat das ?

Wenn "Takt" die IN-variable wäre (das Speicherverhalten ist hier nicht anders wie bei einer STAT-Variablen), dann hättest du ja (vermutlich) einen Eingang (o.ä.) daran geschaltet - und der ändert seinen Zustand ja auch vielleicht wieder. Sonst wäre das Zählen eventuell Unsinn (wenn das zu zählende Signal permanent ist).

Schreib doch vielleicht mal etwas mehr zu deinem Vorhaben ...

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
1) Das heißt also, dass in diesem Fall TAKT nach einmaliger Erfüllung immer auf 1 bleibt, wenn er als Temp-Variable deklariert wurde?
Als Temp-Var ist Takt dann einfach völlig undefiniert. Er könnte immer auf 1 bleiben, wenn kein anderer Baustein deines Programmes zufällig Daten in diesem für Temp-Variablen genutzten Speicherbereich ablegt, kann aber auch sein, dass ab und an genau das passiert und Takt dann wieder mal 0 ist. Also so nicht.
2) Nur, warum wird TAKT dann wieder 0, wenn er als IN-Parameter deklariert ist - ist da das Speicherverahlten anders?
Immer wenn der Baustein im Zyklus durchlaufen wird, wird die Eingangsvariable wieder eingelesen, liegt also außen eine Variable an, die 0 ist, ist Takt auch wieder 0. Du kannst zwar intern Takt beschreiben, aber das wird natürlich nicht nach "außen" weitergereicht, denn darum ist es ja eine INPUT.

PS. Ich würde mir lieber mal die Zähler aus der IEC-Library ansehen, die fest eingebauten Zähler der SPS machen in einem FB eigentlich nicht wirklich Sinn. Besser eine Variable als IEC-Zähler, in STAT (VAR) deklarieren und damit arbeiten, dann kannnst du den FB später auch in mehrfachen Aufrufen nutzen, wenn nötig.
 
Zuletzt bearbeitet:
... ich hatte jetzt vorausgesetzt, dass die Prinzipien des Verhaltens der Schnittstelle (IN , IN_OUT , OUT) bekannt sind ...
 
Ja, der Doppelpost kam zustande, weil ich dir antworten wollte und gleichzeitig noch eine Frage an Manuel offen war... :p

Offensichtlich gibt es aber doch einen Unterschied, ob ich TAKT als IN- oder Statische- Variable deklariere. Denn als IN-Variable funktioniert es... sieht Post #1.

Den Eingang habe ich nicht direkt auf den Zähler gelegt, weil ich sowas (in SCL) konstruieren wollte:

U Eingang
FP M10.0
= TAKT

Und TAKT soll dann mehrmals im Programm Verwendung finden, um auf eine Flanke zu reagieren...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Du hast aber gelesen, dass das mit dem Flankenmerker bei einem Counter nicht wirklich Sinn machen würde ... ?

In SCL-Code sähe das dann z.B. so aus :
Code:
TAKT := Eingang and not FM ;
FM := Eingang ;
// TAKT kann hier ein TEMP sein
// FM muss hier ein STAT sein
Gruß
Larry
 
Immer wenn der Baustein im Zyklus durchlaufen wird, wird die Eingangsvariable wieder eingelesen, liegt also außen eine Variable an, die 0 ist, ist Takt auch wieder 0. Du kannst zwar intern Takt beschreiben, aber das wird natürlich nicht nach "außen" weitergereicht, denn darum ist es ja eine INPUT.

Lieben Dank Ralle,

ist echt etwas kompliziert das Ganze! Ich habe doch die Variable TAKT im Baustein (versehentlich) dauerhaft auf 1 gesetzt, wenn die Bedinung einmalig erfüllt war. Insofern ist TAKT doch auch beim nächsten Zyklusdurchlauf immer noch 1 oder nicht mehr?
 
Wenn TAKT allerdings eine INPUT-Variable ist, wird Sie im nächsten Zyklus wieder mit dem Wert der Eingangsvariable überschrieben. Wenn die Variable IN-OUT wäre würdest du Takt auserhalb des FB speichern und dann würde es nicht mehr funktionieren.

Gruß
FF
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Du hast aber gelesen, dass das mit dem Flankenmerker bei einem Counter nicht wirklich Sinn machen würde ... ?

In SCL-Code sähe das dann z.B. so aus :
Code:
TAKT := Eingang and not FM ;
FM := Eingang ;
// TAKT kann hier ein TEMP sein
// FM muss hier ein STAT sein
Gruß
Larry

Ja Larry, habe es gelesen; Manuel hat ja geschrieben: b) Für einen S5-Zähler wie du ihn hier verwendest, bräuchtest du überhaupt keine Flanke, das mach der Zähler schon selbst.

Aber ich wollte ja auf eine negative Flanke reagieren und das macht der Zähler ja nicht selbst.

Darf TAKT hier Temp sein, weil er den Zustand ja eh immer nur für einen Zyklus behält?

Vielen Dank und ich weiß, ich nerve... ;)
 
naja, Möglichkeiten gibt es viele... in nen FB in SCL nen externen Zählerbaustein zu verwenden macht m.M. nach wenig Sinn. Da kannst Du einfach eine Variable hochzählen und gut:

Code:
IF Eingang AND NOT Eingang_old THEN
    Zaehler:=Zaehler+1;
END_IF;
Eingang_old:= Eingang;

Gruß.
 
naja, Möglichkeiten gibt es viele... in nen FB in SCL nen externen Zählerbaustein zu verwenden macht m.M. nach wenig Sinn. Da kannst Du einfach eine Variable hochzählen und gut:

Code:
IF Eingang AND NOT Eingang_old THEN
    Zaehler:=Zaehler+1;
END_IF;
Eingang_old:= Eingang;

Gruß.

und hier noch für negative Flanke:

Code:
IF NOT Eingang AND Eingang_old THEN
    Zaehler:=Zaehler+1;
END_IF;
Eingang_old:= Eingang;

PS: Eingang ist ne Eingangsvariable BOOL
Eingang_old ist ne statische Variable BOOL
Zaehler ist ne statische Variable DINT
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn TAKT allerdings eine INPUT-Variable ist, wird Sie im nächsten Zyklus wieder mit dem Wert der Eingangsvariable überschrieben. Wenn die Variable IN-OUT wäre würdest du Takt auserhalb des FB speichern und dann würde es nicht mehr funktionieren.

Gruß
FF

Danke FF; nur was heißt... wird sie im nächsten Zyklus wieder mit dem Wert der Eingangsvariablen überschrieben? TAKT ist doch schon die Eingangsvaraible und sie wurde von mir versehentlich dauerhaft auf 1 gesetzt. Also ist sie doch im nächsten Zyklus automatisch wieder 1, oder nicht?
 
Danke FF; nur was heißt... wird sie im nächsten Zyklus wieder mit dem Wert der Eingangsvariablen überschrieben? TAKT ist doch schon die Eingangsvaraible und sie wurde von mir versehentlich dauerhaft auf 1 gesetzt. Also ist sie doch im nächsten Zyklus automatisch wieder 1, oder nicht?

Du kannst keine Eingangsvariable dauerhaft auf 1 setzen.
Eine SPS durchläuft ihr Programm zyklisch. Ist sie am Ende angekommen, beginnt sie wieder am Anfang.
Dein Baustein wird also abgearbeitet, der Eingang wird eingelesen (hier 0), du wertest ihn aus, setzt ihn auf 1, dein Baustein wird verlassen.
Das Programm arbeitet, falls vorhanden, weitere Bausteine ab, kommt an sein Ende und beginnt wieder vorn.
Wenn dein Baustein dran ist, wird der Eingang eingelesen, der ist immer noch 0, denn du hast ihn zwar intern auf 1 geschrieben, aber das wird nicht nach Außen an die wirkliche Eingangsvariable witergegeben, denn die Schnittstelle ist als INPUT definiert und die funktioniert nur in eine Richtung, REIN, nicht RAUS.
 
Und ausserdem ist die Diskussion "was passiert, wenn ich eine Eingangsvariable beschreibe" sinnlos, da man sowas besser bleiben lässt.

Gruß.

PS: Ausnahmen bestätigen die Regel :)
 
Zurück
Oben