TIA Beschalten EN-Schnittstelle FC und FUP Bausteine

Beiträge
2.630
Reaktionspunkte
766
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Alle,

Wenn Mann die EN-Schnittstelle eines FC's oder z.b. im FUP eine MOVE Funktion nicht beschaltet werden die FC's und Funktion immer bearbeitet.

So weit so gut.

Wenn Mann jetzt der EN-Schnittstelle mit wert "Falsche" werden die nicht bearbeitet.

Auch so weit so gut.

Aber jetzt meine frage dazu:

Hat es in die Programmbearbeitung (meine Einfluss auf Zycluszeit ) das gleiche Effekt als würde ich eine JUMP Funktion einsetzen um die FC's zu überspringen.
bei der FUP Funktionen kommt in meinen fall auch etwas beisammen.

Mir ist für Testzwecke online aufgefallen dass ich bei Beschaltung mit "falsch" die Bausteine als strich dargestellt sehe und bei JUMP seht man nichts (Als ob offline).

Denke selbst ich muss zum JUMP Funktionen über gehen.

Grund ist ein durch mir selbst geschriebene FB Zycluszeitmäßig zu optimieren.
Zur Info : Natürlich ist das ein FB für alles wobei man jedes mal nur einzelne teilen braucht.

Hat jemand von euch da Erfahrungen ?

Bram
 
Bei einer S7300/400 kann man in der AWL sehen dass der Baustein ganz einfach übersprungen wird. Das Programm wird also um den Anteil des Bausteins schneller wenn dieser nicht aufgerufen wird.

Bei der 1200/1500 sieht das ähnlich aus. Wobei man da nicht weiß wie die CPU die Anweisungen umsetzt.
Bzw. konnte ich nur bei der 1200er den generierten Zwischencode entschlüsseln. Zumindest bei der 1200 wird die EN-/ENO-Mechanik nicht schon im Zwischencode mit Sprüngen umgesetzt, sondern die Anweisungen die im Zwischencode aufgerufen werden (z.B. MOVE) bekommen mitgeteilt ob EN/ENO beachtet werden soll. Was die CPU damit macht wird wohl für immer unklar bleiben, aber letztenendes wird es auch auf ein Überspringen der Anweisungen hinauslaufen, d.h. das Programm sollte schneller werden wenn Teile nicht bearbeitet werden.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Tatsächlich,

Man seht im AWL das das Programm ein Sprung darein macht wenn man de EN Schnittstelle beschaltet.

Dann brauch ich mir um einige Netzwerke nicht zu kümmern.

Mein FB wird in ein S7 414 CPU laufen später. Projektiert wird es mit TIA V13

Bram
 
Ich hab eben weiter geprüft und fest gestellt wen man ein FC 3 mal aufruft im FUP das dann auch 3 Sprüngen entstehen. Nicht 1 Sprung so wie ich erwartet hab.

Anhang anzeigen 24154
FUP

Anhang anzeigen 24155
AWL

Dann wäre es doch schneller für die CPU mit 1 Sprung zu schaffen ?

Wobei das in der FUP ein riesen Darstellung und Netzwerkorgie wird

Dann wäre de beste Wahl um zu schreiben im AWL. Oder natürlich gleich in der AWL.

Bram
 
Hätte da noch mal eine frage die mir so bei der FUP zu AWL Umschaltung aufgefallen ist

Anhang anzeigen 24207

Das mittlere Netzwerk ist der FC763 im Darstellung FUP
Das rechter Netzwerk ist der FC763 in eine von FUP nach AWL umgeschaltete Darstellung
Das linker Netzwerk ist der FC763 als reine AWL Aufruf.

Jetzt sehe ich das er erst die Variablen auf lokal Daten schiebt , und dann die Lokal Daten auf der Baustein schaltet

Wie seht dann die spätere Machinencode aus die aus dem FC generiert wird ?
Die ist im FUP um 49 Zeilen länger als reine AWL Aufruf, so das es aus endlich (Denke ich) auch Einfluss hat auf der cycluszeit.

Ist der Machinencode später gleich ??
Es interessiert mir wirklich ob das schlecht ist für die Cycluszeit.

Wen ich Quelle generier aus ein FC Aufruf. 1 mal als rein AWL andermal als reine FUP sehe ich das die 49 zeilen mitgenommen werden.

Bram
 
Hallo Bram

es ist egal in welcher Sprache du den Call programmierst. Auf die Zykluszeit hat das keinen Einfluss.

Aber du musst vorsichtig sein, dass du nicht Äpfel mit Birnen vergleichst. In deinem AWL verwendest du nur Merker. Während du in FUP auf DB zugreifst, manchen Eingang negierst und einmal sogar einen Vergleich an den Eingang legst. Das kostet alles zusätzliche AWL Befehle, die du in AWL je auch programmieren müsstest. Also wenn du die Sprachen miteinander vergleichst, dann müssen es auch wirklich semantisch gleich und von den Adressierungsarten her gleich sein. Wenn du das hast, dann gibt es zwischen KOP, FUP und AWL keinen Unterschied.

Bei 300/400 wird letztendlich sowie so alles über AWL nach MC7 abgebildet. AWL kann etwas mehr als MC7. In AWL schreibst du L DB10.DBW12. Das kann MC7 gar nicht! MC7 kann nur AUF DB10; L DBW12, das sind zwei Befehle. Bei den CALL ist das ähnlich. MC7 kennt nur einen UC FCx. Dabei werden alle Parameter als 32Bit Pointer per Referenz übergeben. Deswegen muss du auch alles was nicht direkt adressiert werden kann, also die Negationen, die DB-Zugriffe und das Vergelichsergebnis zuerst nach L kopiert werden, damit im Hintergrund ein Zeiger auf L an den FC übergeben wird. Fazit: Es gibt keinen Geschwindigkeitsunterschied zwischen den Sprachen. Es gibt jedoch sehr wohl einen Unterschied im Komfort. Je komfortabler eine Sprache ist, desto schneller schreibt man langsame Programme :cool:
SCL fällt ein wenig aus dem Rahmen, weil die andere Wege bei der Parameterübergabe gehen. Hier kann man in einer Zeile FC3( a + b ) schreiben. Letztendlich wird aber genau so wie bei FUP zuerst die Addition ausgeführt, das Ergebnis in einem LW abgelegt und ein Zeiger auf LW an den FC übergeben. Alles landet im MC7.

Bei 1200 (und vermutlich auch bei 1500) wird alles nach MC7+ abgebildet. Aber wie in einem schönen Thread von Thomas_v2.1 erklärt wird, gehen hier die Compiler andere Wege. KOP/FUP wird nicht über den AWL Umweg abgebildet. Die 1200 hat kein AWL! Eher im Gegenteil, der KOP/FUP Code ist oft (aber nicht immer) kürzer als der AWL Code. Wir wissen zwar nicht wie der aussieht, aber allein an der Codegröße erkennt man, dass es AWL Konstrukte gibt, die die 1500 nicht mag. U >0 oder SPN mag sie überhaupt nicht. Bei meinen Laufzeitmessungen fallen solche Konstruktionen und das Gehampel mit Adressregistern total aus dem Rahmen. Der symbolische Zugriff auf ein Element eines DB geht rasend schnell. Ein AWL Programm, welches sich ein ANY Pointer zerlegt und über AUF DB und L W[AR1,p#0.0] auf das gleiche Element zugreift, braucht ungefähr 30 mal so lange. Das ist bei der AS400 nicht so.

Fazit: Jede Sprache hat ihre Berechtigung. Keine ist im Prinzip schneller als die andere.

'n schön' Tach auch
HB
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Hellebarde,

Danke für die Antwort

Ich hab es mir gewünscht das es kein unterschied gibt :icon_smile:.
Bin so im Zweifel gekommen.
Ja klar ist es 1000 mal angenehmer wenn noch Logik verschaltet wird um das im FUP zu machen.

Hätte gleich noch mal eine frage an dir?

http://www.sps-forum.de/simatic/708...tualparameter-in_out-einem-fb-uebergeben.html

In diese Tread hast du einige Cyclus Zeiten gemessen.

Hat du dann der OB1 Cycluszeit dann jedes mal ausgelesen mit eine systemfunction ?

Bram
 
Hallo Bram

ich habe keine Zykluszeiten vermessen, ich habe Befehlslaufzeiten (versucht) zu messen. Das klingt jetzt rechthaberisch (vermutlich ist es das auch) und ist ein pingeliger aber (für mich) extrem wichtiger Unterschied.

So ein Zyklus besteht aus:
Peripherie lesen und Abbild der Eingänge erstellen
Programm aus dem freien Zyklus ausführen
Unterbrochen werden und was anderes tun
weiter Programm aus dem freien Zyklus ausführen
nochmal Unterbrochen werden
weiter Programm aus dem freien Zyklus ausführen
...
Abbild der Ausgänge auf die Peripherie schreiben
Kommunikation mit dem ES und anderen Baugruppen durchführen


Also man sieht, dass die Zykluszeit sehr viel mehr enthält als nur dein Programm. Das wird um so schlimmer je kürzer dein Programm ist. Aber wenn man nun messen will ob der eine Befehl oder der andere Befehl schneller ist, dann schreibt man ja ein kurzes Programm das eben nur den einen oder den anderen Befehl enthält. Und so lange da die Zykluszeit unter 1ms bleibt, hast du überhaupt keine Aussage.

Weil man bei der Sache ja Information aus der CPU braucht, macht man eine Beobachtungstabelle und beobachtet Werte. Das schlägt sich als Kommunikation ebenfalls auf den Zyklus. Und Bausteinstatus kostet beim Beobachten von Schleifen richtig böse viel Zeit.

Seit einiger Zeit gibt es für 1200/1500 einen Befehl RUNTIME, mit dem kann man Befehlsfolgen vermessen. Aber so richtig glücklich macht mich der auch nicht. Die Auflösung ist CPU abhängig und auch nicht so richtig toll.

Inzwischen habe ich mir folgenden Trick ausgedacht. Geht in KOP/FUP/SCL (und AWL) und geht mit jeder CPU. (auch wenn die nicht von Siemens ist, z.B. von Beckhof)

Man definiere ein oneloop : REAL im MD0 und erzeuge einen OB.
Dort definiere ein cnt : DINT in der TEMP
und setze diesen cnt auf 0
dann starte einen TP für 100ms
While-Schleife solange der TP true
rufe einen Baustein ohne Parameter auf
inkrementiere cnt
while_end
oneloop := 1e9 * ( 0.1 / DINT_TO_REAL( cnt ))

Damit bekommst du in oneloop die Zeit für einen Schleifendurchgang in Nanosekunden.
Für die 1200 kannst du auch 1e6 verwenden, dann sind das eben Mikrosekunden.
Den onelopp kann man schön ein einer Beobachtungstabelle verfolgen (weil ja im MD0)

Zuerst mal lässt du den aufgerufenen Baustein leer. Das ist sozusagen der Grundaufwand, die Basiszeit.
Dann schreibst du in den aufgerufenen Baustein rein was dich gerade interessiert. Wenn du nun vom zweiten Versuch die Basiszeit abziehst, dann bleibt dir das was durch die zusätzlichen Zeilen, Boxen, Kontakte an Aufwand hinzugekommen ist.

Die Zykluszeit ist dabei immer 100ms. Du musst also nie Angst haben, dass die CPU in Stop geht.

Wenn du das im OB1 machst, wird du feststellen, dass die Zeiten sehr schwanken. Das liegt wie ich schon vermutet hatte an den Unterbrechungen. Also verwende am besten nicht den OB1 sondern einen zyklischen OB (bei der As400 einen 30er) und setze diesen auf höchste Priorität (findet sich in den Bausteineigenschaften des OB).

Damit beruhigen sich die Werte, denn es gibt jetzt nicht mehr soviel, was die Messung unterbricht. Da der Baustein aber 100ms läuft, scheint die Kommunikation immer noch dazwischen zu funken. Also völlig stabil wird es nie. Aber man kann schon viel bessere Aussagen treffen als im OB1.


viel Spaß beim Messen
HB
 
Zuletzt bearbeitet:
Vor allem ist bei der Messerei bei der 1200/1500 zu beachten, dass der Compiler den Code mehr oder weniger gut optimiert. Das heißt, es wird nicht mehr alles genau so wie man es im Quellcode schreibt auch in der SPS abgearbeitet. Da wir noch nicht so weit sind uns den generierten Code komplett anzuschauen, kann man die realisierten Optimierungsschritte nur an Stichworten im TIA-Portal mutmaßen. Was es auf jeden Fall gibt ist, dass arithmetische Operationen mit Konstanten schon vorher ausgerechnet werden. Das beherrschte sogar der leidige Step7-SCL Compiler.

Dann könnte es sein, dass man in seinem Testprogramm Berechnungen mit Temp-Variablen vornimmt deren Ergebnis aber nicht weiter verarbeitet oder gespeichert werden. Theoretisch könnte der Compiler den kompletten Codeblock entfernen weil er ihn als sinnlos erkennt. Sicherer ist hingegen (bezüglich Laufzeittests) wenn die Daten auf denen gearbeitet wird im Merker- oder Datenbausteinbereich abgelegt werden. Da diese Daten global sind kann der Compiler den Code nicht einfach entfernen, denn es könnte ja sein dass ein Zeitinterrupt oder eine Visualisierung auf diese Daten zugreift.

Ich würde vermuten dass bei der 1200/1500 DB-Zugriffe weiterhin langsamer sind als Merkerzugriffe oder Zugriffe auf Temp-Variablen. Zumindest wenn man Operationen mit Variablen aus unterschiedlichen DBs vornimmt.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi Thomas

Nein, da liegst du falsch. Optimierte DB sind schneller als Standard DB, Merker, Eingänge und Ausgänge.
Es ist aber auch vom Datentyp abhängig. Dint zeigt größere Unterschiede als Int, Byte keine, und Bool die Größten.

Nehmen wir eine REAL Addition:

Am schnellsten gehen Zugriffe auf optimierte DB wenn die DB-Nummer bekannt ist.

Auf Platz zwei liegen Zugriffe auf TEMP und STATIC wenn der Baustein optimiert ist.

Dann kommen Zugriffe auf optimierte Daten die als Referenz rein kommen. Also auf die eigene Schnittstelle oder Elemente in UDT die im INOUT deklariert sind.

Dann folgen Zugriffe auf optimierte Daten die per Value rein/raus kommen. Das liegt aber am kopieren, das durch meine Methode mit gemessen wird, was durchaus realistisch ist. Greift man auf einfache Typen in der In und Out eines FB zu, welche im Aufruf aber gar nicht versorgt sind, dann hast du den nackten Zugriff und der landet auf Platz zwei. Aber was soll ein unversorgter Input? Das ist ja dann STATIC :rolleyes:

Auf Platz fünf kommt E A M und Standard DB wenn die DB Nummer bekannt ist.

Dann TEMP und STATIC wenn der Baustein nicht optimiert ist.

Dann nicht optimierte Daten per Referenz.

Den vorletzten Platz haben nicht optimierte Daten die per Value übergeben werden.

Und einsam weit abgeschlagen liegen ungünstig versorgte UDT Parameter. Also an einen optimierten FC einen Standard DB verschalten, das kostet richtig böse viel Laufzeit. Der wird vermutlich erst kopiert und dann referenziert.


Du hast recht, mit dem optimierenden Compiler kann man sehr irritierende Messwerte bekommen. Also einfach irgendwelchen Code verdoppeln führt total in die Irre. Aber wenn du.
Code:
t1 := i1 + i2;
t2 := i3 + i4;
o1 := t1 * t2;
rechnen lässt, dann gibt es auch für den besten Optimierer der Welt wenig Potential.


Seit neuestem kann man ja auch mit VariantPut und VariantGet indirekt ... aber das liegt auch nicht besser als Standard Speicher. Andererseits schein MOVE_BLK_VARIANT wieder einigermaßen schnell zu werden, wenn die Datenmenge größer wird. Das ist eine von den Ecken, wo ich noch nicht wirklich durch blicke. Die paar Messwerte die habe sind sehr unlogisch.

'n schön' Tach auch
HB
 
Zuletzt bearbeitet:
Hier hab ich 2 PDF's mit die verarbeitungszeit einzelne aufrufen. Ist aber für die 300 und 400.

Jetzt ist das für mir o.k. weil wir der 1200 und 1500 nicht im Einsatz haben.
.
Anhang anzeigen 24213

Anhang anzeigen 24212

Hab gerade ein erste versuch gemacht der Messmethode um zu setzen .
Hänge gerade an der While schleife und ob der Weck OB eine feste 100ms cyclus hat.
Sehe im Moment nur das ich der aufruf auf 100ms setzen kann.

Morgen auf der Arbeit das Berger Buch mal dazu nehmen.

Bram
 
es ist egal in welcher Sprache du den Call programmierst. Auf die Zykluszeit hat das keinen Einfluss.

Aber du musst vorsichtig sein, dass du nicht Äpfel mit Birnen vergleichst. In deinem AWL verwendest du nur Merker. Während du in FUP auf DB zugreifst, manchen Eingang negierst und einmal sogar einen Vergleich an den Eingang legst. Das kostet alles zusätzliche AWL Befehle, die du in AWL je auch programmieren müsstest. Also wenn du die Sprachen miteinander vergleichst, dann müssen es auch wirklich semantisch gleich und von den Adressierungsarten her gleich sein. Wenn du das hast, dann gibt es zwischen KOP, FUP und AWL keinen Unterschied.
Also ich sehe da schon einen Unterschied ob der CALL in AWL oder FUP/KOP programmiert wird.
Ausführungszeiten habe ich nicht gemessen, denke aber, daß der längere Code auch länger braucht.

AWL, benötigt 46 Byte
Code:
      CALL  FC10
       IN_1:=M0.0
       IN_2:=M0.1
       IN_3:=M0.2
       IN_4:=M0.3
       IN_5:=M0.4
       IN_6:=M0.5
       IN_7:=M0.6
       IN_8:=M0.7

KOP, benötigt 112 Byte, 66 Byte mehr als AWL
Code:
            +----------+
            |   FC10   |
------------|EN     ENO|-
            |          |
       M0.0-|IN_1      |
            |          |
       M0.1-|IN_2      |
            |          |
       M0.2-|IN_3      |
            |          |
       M0.3-|IN_4      |
            |          |
       M0.4-|IN_5      |
            |          |
       M0.5-|IN_6      |
            |          |
       M0.6-|IN_7      |
            |          |
       M0.7-|IN_8      |
            +----------+

AWL, benötigt 126 Byte
Code:
      CALL  FC10
       IN_1:=DB1.DBX0.0
       IN_2:=DB1.DBX0.1
       IN_3:=DB1.DBX0.2
       IN_4:=DB1.DBX0.3
       IN_5:=DB1.DBX0.4
       IN_6:=DB1.DBX0.5
       IN_7:=DB1.DBX0.6
       IN_8:=DB1.DBX0.7

KOP, benötigt 144 Byte, 18 Byte mehr als AWL
Code:
            +----------+
            |   FC10   |
------------|EN     ENO|-
            |          |
 DB1.DBX0.0-|IN_1      |
            |          |
 DB1.DBX0.1-|IN_2      |
            |          |
 DB1.DBX0.2-|IN_3      |
            |          |
 DB1.DBX0.3-|IN_4      |
            |          |
 DB1.DBX0.4-|IN_5      |
            |          |
 DB1.DBX0.5-|IN_6      |
            |          |
 DB1.DBX0.6-|IN_7      |
            |          |
 DB1.DBX0.7-|IN_8      |
            +----------+

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das mit optimierte und nicht optimierte Baustein muss ich mir auch mal anschauen.

Ich hab viele FB's die (denke ich Standard sein)also nicht optimiert.
Und auch eine menge an UDT's , aber nur im OUT Schnittstelle.
Die UDT's werden dann OUT Schnittstelle wieder weiter gegeben an eine global (nicht optimierte ?) DB.

Bram
 
HB könnte ja mal sein Messprogramm einstellen. Am Besten vielleich in SCL, dann kann man das mal mit verschiedenen Steuerungen und TIA-Portal Versionen vergleichen.
 
Hallo Bram

wenn du den TP auf 100ms stellst, dann solltest du den Zyklus auf 200ms stellen.
Den TP auf 100ms und den Zyklus auf 100ms zu stellen muss schief gehen.
Schließlich braucht der OB etwas mehr als 100ms, denn da kommen ja noch eine handvoll Befehle außen rum. Und damit verpasst der Zyklus sein Fenster und beim dritten mal bleibt die PLC stehen.

Zyklus auf 200ms hat außerdem den Vorteil, dass dann noch reichlich Zeit für die Kommunikation bleibt, die durch die Beobachtungstabelle ausgelöst wird.

HB
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@ PN/DP

Ist der länge in BYTE der Machinencode MC7 die ich im Eigenschaften des Bausteins sehe ?

Um bei mein Beispiel zu bleibenvon FC763 (nur mit merker beschaltet ohne Logik)

AWL Aufruf MC7 code 86 BYTE

FUP Aufruf MC7 code 216 BYTE

Bram
 
Zuletzt bearbeitet:
Nach lange Zeit mal daran zugekommen.

Erste Resultaten sind nicht schlecht mit diese Code

Code:
 "Meettijdpuls".TP(IN:="START_IEC_Testtijd",
                    PT:=t#100ms,
                    Q=>#Testimpuls,
                    ET=>#Aktuele_Tijdwaarde);

WHILE (#Testimpuls = true) DO
    // Te testen FB voor Cyclustijd
"Berechnung_Sattdampf_DB"(P_Ist:=20.0,
                          Bara:="High",
                          T_Sattdampf=>#REAL);

"TELWAARDE" := "TELWAARDE" + 1;
RETURN;
END_WHILE;

Bram
 
Zurück
Oben