Großen FB in 2 Teile splitten - knifflig.

Zuviel Werbung?
-> Hier kostenlos registrieren
Habe nun mal folgendes gemacht:

Neuen FB angelegt, Schnittstelle exakt übernommen, eine Portion Netzwerke vom einen in den anderen verschoben und im ersten Netzwerk die DB-Nummer Zuweisung von aussen noch mal reingesetzt.

Habe nun mal im OB1 den ersten FB ganz normal aufgerufen (er hätte jetzt übrigens schon weniger als 16kB!) und gleich danach mit UC den zweiten.

Das dumme ist jetzt nur daß ich das jetzt hier nicht simulieren kann - aber noch mal konkret gefragt:

Wird die Schnittstelle des zweiten FB wenn er mit UC aufgerufen wird exakt gleich versorgt wie die des ersten - bzw. erhält er dann schon automatisch die im ersten veränderten Parameter an gleicher stelle?

Wenn dem so wäre dann wäre ich jetzt schon am Ziel !
 
Theoretisch gesehen müsste ja so wie ich das mit einem Übergeordneten FB gelöst habe die Werte in den Lokaldaten erhalten bleiben wenn du zwischen den 2 Bausteinaufrufen nicht auf den Lokaldatenbereich zugreifst. Also müsste bei gleicher Bausteindeklaration Variable 1 im FB11 gleich der Variable 1 im FB12 sein.

Ich weiß jetzt nicht genau wie das mit den Prozessalarmen usw ist aber die werden glaube ich auch nur aktiviert wenn ein Bausten der im OB1 aufgerufen wird zu ende geht.
Also die können dir auch nicht dreinpfuschen.

godi
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@Godi: Unsere letzten Antworten haben sich überschnitten...

In deinem Beispiel bettest du aber doch den zweiten FB im ersten ein - was dessen Größe ja noch ansteigen ließe - oder nicht ?
 
Habe nun mal folgendes gemacht:

Neuen FB angelegt, Schnittstelle exakt übernommen, eine Portion Netzwerke vom einen in den anderen verschoben und im ersten Netzwerk die DB-Nummer Zuweisung von aussen noch mal reingesetzt.

Habe nun mal im OB1 den ersten FB ganz normal aufgerufen (er hätte jetzt übrigens schon weniger als 16kB!) und gleich danach mit UC den zweiten.

Das dumme ist jetzt nur daß ich das jetzt hier nicht simulieren kann - aber noch mal konkret gefragt:

Wird die Schnittstelle des zweiten FB wenn er mit UC aufgerufen wird exakt gleich versorgt wie die des ersten - bzw. erhält er dann schon automatisch die im ersten veränderten Parameter an gleicher stelle?

Wenn dem so wäre dann wäre ich jetzt schon am Ziel !

Nein du musst das über einen Übergeordneten FB machen sonst kannst ja nicht auf den selben InstanzDB zugreifen bzw wenn du auf den selben Instanz db zugreifst indem du vorher den Db mit AUF DIxy öffnest dann kannst du ja die Ausgänge nach dem zweiten FB nicht auslesen!
 
@Godi: Unsere letzten Antworten haben sich überschnitten...

In deinem Beispiel bettest du aber doch den zweiten FB im ersten ein - was dessen Größe ja noch ansteigen ließe - oder nicht ?


Warum sollte der Code ansteigen?
Wegen dem wird ja im Übergeordneten fall der FB10 nicht größer!
Also nochmal:
Habe den großen FB in den FB11 (erster Teil) und den FB 12 (zweiter Teil) geteilt. Diese 2 FB's rufe ich im FB 10 auf.
Also vom FB 10 wird der Code nicht mehr viel größer als jetzt! Und der code vom großen ist ja aufgeteilt.

Probiere es einfach mal aus.
Zersplittere deinen FB und rufe sie in meinem FB10 auf.


godi
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das Problem mit den Ausgängen habe ich schon mal umgangen in dem ich einfach keine verwende - nur IN_OUT, da die meisten eh in gemeinsam benutzten (global-) DB Bereichen liegen.

Aja und deine IN_OUT Variablen musst du trozdem nach dem zweiten FB aufruf wie Ausgänge behandeln so wie ich es in dem Musterbeispiel gemacht habe sonst hast du immer nur die werte von dem ersten FB aufruf drinnen!
 
So langsam dämmerts...

Das habe ich in dem Beispiel nicht gleich erkannt was da genau passiert.

Ich versuche mal es in die Richtung zu lösen, melde mich dann wenn noch Fragen sind.

Danke!
 
So langsam dämmerts...

Das habe ich in dem Beispiel nicht gleich erkannt was da genau passiert.

Ich versuche mal es in die Richtung zu lösen, melde mich dann wenn noch Fragen sind.

Danke!

Ja für weitere Fragen bin ich erst morgen wieder Online!
Ich gehe jetzt :s10: :sm24: :s10: :sm24:

godi
 
... da Godi jetzt anscheinend auf Zwutsch ist ...

Wenn du den FB11 und den FB12 in den FB10 packst, dann kennt nur der FB10 alle deine Variablen.
Legst du FB12 in FB11, dann kennt FB11 alle Variablen von FB12 auch - leider aber nicht umgekehrt ...
Ich weiss also nicht so 100%ig, ob dass dann wirklich das geschilderte Problem lösst.

Ich bin auf jeden Fall gespannt, wie es weiter geht - schliesslich kann mich das Ganze ja auch ganz schnell mal erwischen ...

Gruß
LL
 
... und wie ich erst gespannt bin.

Ich habe das Beispiel mal mit meinen Bausteinen so weit vorbereitet.

Momentan steht für mich noch offen:

Der FB10 wird ja im OB1 aufgerufen (und dort auch der tatsächliche IDB zugewiesen), da nehme ich an daß hier die vollständige Schnittstelle versorgt werden sollte/muss.

Kann ich davon ausgehen dass wenn der FB10 dann fertig ist (also FB11 und 12 durch sind) ich die an der Schnittstelle definierten Parameter ganz normal weiterverarbeiten kann, oder müssen diese am Ende vom FB10 dann irgendwie noch "von Hand" zurückgeschrieben werden (da godi ja schrieb daß die Ausgänge intern nicht belegt werden dürfen) - hier komme ich noch nicht ganz mit...

Auf jeden fall muss immer noch gewährleistet sein daß ich den FB10 mehrfach mit verschiedenen IDB starten kann.

Eine für mich verständlichere Lösung wäre vielleicht auch folgende:

(Ich verwende jetzt mal die Nummern 10,11 und 12 analog zu godis Beispiel daß hier alle was damit anfangen können)

Im OB1 rufe ich den FB11 auf und kopiere anschließend mit BLKMOV den DI in den DI vom FB12. Dann rufe ich den FB12 auf und kopiere anschließend wiederum dessen DI in den DI des FB11. Somit müsste dann der FB10 überflüssig sein und trotzdem bei jedem Aufruf die aktuell gültigen Daten zur Verfügung stehen. Das wären halt je ein IDB aber zumindest übersichtich weil man es im OB1 auf den ersten Blick sieht was gemacht wird...

Na ja mal abwarten.


@LL: was/wo ist "auf Zwutsch" ???
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo RS,

auf Zwutsch gehen ist : :s10: :sm24: :s10: :sm24: - also "Party machen" !!!

was den Rest angeht ...
Ein in etwa verwandtest Thema hatte ich hier auch einmal hereingestellt (2 FB's - 1 DB). Ich meine, du hättest damals da auch mit mit gepostet ...
Die Grund-Aufgabenstellung war da war etwas anders aber eben auch "verwandt".

Ich hatte das so gelösst, dass ich per Any-Pointer das gemeinsame Daten-ARRAY vom "Master"-FB an den "Slave"-FB übergeben habe. Das hat dann auch soweit ganz gut funktioniert, aber du weisst ja vielleicht wie das ist - wenn man nicht 100% von dem bekommen hat, was man haben wollte, dann bohrt man im Hintergrund immer weiter rum. Schluss-endlich ist es jetzt nun so, dass ich aus den 2 FB's einen gemacht habe (also das Gegenteil von dem was du vorhast) und ihn Aufgaben-bezogen mit den entsprechenden Parametern, die sich wieder gegeneinander verriegeln, aufrufe. Aber das nur so nebenbei - hat ja mit deinem Problem eigentlich nichts zu tun.

Die Frage bei dir ist ja, ob du eventuell aus deinem "Super"-FB Sub-Funktionen auslagern kannst, die erstmal in sich geschlossen sind, viel Speicherplatz verbrauchen (also vielleicht eine FOR-TO-Geschichte) und die man als klar definierten Block übergeben könnte. Das wäre dann ein Fall für "FB10 ruft FB11 und FB12 auf" und gemeinsame Daten werden werden ge"Share"d.

Geht das nicht, so geht es nur wie von Godi beschrieben, wobei ich keine Ahnung habe (noch nie probiert) ob das mit den gleichen Aufruf-Parametern funktioniert - also FB11 übernimmt automatisch die Aufrufdaten von FB10 und FB12 tut das auch. Hast du das schon ausprobiert und wird die Schnittstelle der aufgerufenen FB's korrekt versorgt ?

Trotz alledem, so interessant wie ich das finde und das Ergebnis möchte ich auch auf jeden Fall wissen - du siehst keine Möglichkeit, deinen FB auf "konventionelle" Weise zu schrumpfen ...?

Gruß
LL
 
Hallo RS,

...
Ich hatte das so gelösst, dass ich per Any-Pointer das gemeinsame Daten-ARRAY vom "Master"-FB an den "Slave"-FB übergeben habe. Das hat dann auch soweit ganz gut funktioniert, aber du weisst ja vielleicht wie das ist - wenn man nicht 100% von dem bekommen hat, was man haben wollte, dann bohrt man im Hintergrund immer weiter rum. Schluss-endlich ist es jetzt nun so, dass ich aus den 2 FB's einen gemacht habe (also das Gegenteil von dem was du vorhast) und ihn Aufgaben-bezogen mit den entsprechenden Parametern, die sich wieder gegeneinander verriegeln, aufrufe. Aber das nur so nebenbei - hat ja mit deinem Problem eigentlich nichts zu tun.

Das ist wiederum meine Ausgangssituation...

Die Frage bei dir ist ja, ob du eventuell aus deinem "Super"-FB Sub-Funktionen auslagern kannst, die erstmal in sich geschlossen sind, viel Speicherplatz verbrauchen (also vielleicht eine FOR-TO-Geschichte) und die man als klar definierten Block übergeben könnte. Das wäre dann ein Fall für "FB10 ruft FB11 und FB12 auf" und gemeinsame Daten werden werden ge"Share"d.

Geht das nicht, so geht es nur wie von Godi beschrieben, wobei ich keine Ahnung habe (noch nie probiert) ob das mit den gleichen Aufruf-Parametern funktioniert - also FB11 übernimmt automatisch die Aufrufdaten von FB10 und FB12 tut das auch. Hast du das schon ausprobiert und wird die Schnittstelle der aufgerufenen FB's korrekt versorgt ?

Nein - als realen Test bisher nicht, wollte da noch o.g. Sachen vorher in der Theorie durchgehen.

Trotz alledem, so interessant wie ich das finde und das Ergebnis möchte ich auch auf jeden Fall wissen - du siehst keine Möglichkeit, deinen FB auf "konventionelle" Weise zu schrumpfen ...?

Gruß
LL

Ein bissl was geht immer aber ob es genug sein wird ist halt die Frage - zu dem kommt eben auch jedes Mal ein klein wenig hinzu deswegen will ich jetzt mal richtig "Luft" machen...

An sich bin ich jetzt schon überzeugt daß Godis Vorschlag der am leichtesten zu realisierende sein wird - nur ich kann eben erst was damit anfangen wenn ich zu 100% kapiert habe was da genau passiert...
 
...
für jede deiner Bedenken habe ich vollstes Verständnis - das würde bei mir auch nicht anders laufen ...
Dennoch kommst du ums ausprobieren (und ggf. wieder verwerfen) nicht drum herum.

Aber vielleicht doch noch einmal von vorne :
Was genau macht dein Baby ganz konkret ?
Ich denke, das Ding hier ins Forum zu stellen bringt nicht viel, denn wenn du da > 16k Anweisungen drin hast, dann können sich Vorschläge sowieso nicht auf das Konzept beziehen sondern nur auf Details. Da wird dann sicher auch schon einiges an Gehirnschmalz drin stecken.

Noch einmal zu dem "Abspecken" :
Es ist ja möglich das viele Kleinigkeiten in der Summe dann doch etwas bringen.
Wenn das Ding noch wächst (weiter wachsen könnte), dann ist es nach meiner Meinung umso wichtiger ggf. Teilfunktionen sinnvoll auszulagern.
Da wären wir dann wieder eher bei deinem eigenen Ansatz - oder vielleicht einer Mischung - wobei mir die Sache mit der Daten-"Vererbung" schon ein bißchen Gänsehaut bereitet.

Hast du den FB in AWL geschrieben ?
Würde es sich von der Aufgabenstellung her vielleicht für SCL eignen ?
Ggf. ergäben sich hier vielleicht im Detail zusätzliche Möglichkeiten ...

:???: Es ist ziemlich schwierig pauschal etwas zu sagen ...

Gruß
LL
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das mit dem Auslagern ist schon so ne Sache aber wie?

Das Verhältnis "normaler" Code der immer bearbeitet wird (Bausteinbeginn) und Schrittkette liegt vielleicht bei 5/90 %

Mal kurz die Eckdaten:

Ich schreibe alles in AWL (kann auch nix anderes).

Beispiel ein Netzwerk ohne eigene Schrittnummer
(Schrittnummer nenne ich IZ = innerer Zustand...):

Code:
// Beginn Netzwerk
 
// Wenn bereits gesperrt ist, dann nichts machen.
      L     #IZ_FB
      L     900
      ==I   
      SPB   ue99
 
// Wenn der IZ kleiner 10 ist braucht nur gesperrt zu werden.
      L     #IZ_FB
      L     10
      <I    
      UN    #Notaus_IO
      UN    #Gesperrt_Aktiv
      S     #Merker_Sperren
      SPBN  ue01
      L     900
      T     #IZ_FB
      SPA   ue99
ue01: NOP   0
// Wenn der IZ zwischen 10 und 64 ist kann NormalAus_S angewandt werden...
      L     #IZ_FB
      L     10
      <I    
      SPB   ue02
      L     #IZ_FB
      L     64
      >I    
      SPB   ue02
      UN    #Notaus_IO
      UN    #NormalAus_S_Aktiv
      UN    #Abbruch_Aktiv
      S     #Merker_NormalAus_S
      SPBN  ue02
      U     #Option_XY // wenn True anderen IZ nehmen!
      SPBN  sd03
      L     450
      T     #IZ_FB
      SPA   ue99
sd03: L     750
      T     #IZ_FB
      SPA   ue99
ue02: NOP   0
// Wenn der IZ größer als 64 ist muß NotAus angewandt werden...
      L     #IZ_FB
      L     64
      >I    
      UN    #Notaus_IO
      UN    #NotAus_Aktiv
      UN    #Abbruch_Aktiv
      S     #Merker_NotAus
      SPBN  ue03
      U     #Option_XY  // wenn True anderen IZ nehmen!
      SPBN  sd04
      L     450
      T     #IZ_FB
      SPA   ue99
sd04: L     800
      T     #IZ_FB
ue03: NOP   0
ue99: NOP   0
// Ende Netzwerk

Solche Netzwerke stehen alle am Beginn des FB. Grund ist der um sicherzustellen daß sie immer durchlaufen werden.

Das andere ist wie eine sehr umfangreiche Schrittkette zu sehen die u.A. in abhängigkeit von Optionsflags (IN Parametrer TRUE/FALSE) verzweigt.

Es sind Schritte vorhanden die niemals in einer Anlage vorhanden sein können jedoch aber auf Grund der gemeinsamen restlichen Basis im selben Baustein sitzen weil das nächste mal sie und dafür die anderen nicht verwendet werden.

So gesehen ist es für mich dann relativ einfach eine neue Teilkette nachträglich einzufügen da es immer definierte Abzweigungen gibt (also bis dahin ist alles gleich und wenn wir hier angekommen sind gehen wir abhängig von der Option weiter...) und es ist sichergestellt daß die vorletzte Anlage immer noch damit laufen würde wenn sie gleich parametriert ist (Wichtig!)

Schon aus diesem Grund eignet sich die Sprungleiste nicht so gut für mich weil ich es so handhabe eine Interger als Zustandkennung zu verwenden und am Netzwerkbeginn auf ==I vergleichnederweise abfrage (natürlich nur in den Netzwerken die einem Schritt zugeordnet sind). Das hat zwar den Nachteil daß weit unten liegende Netzwerke erst durch abklappern der vorigen erreicht werden - also etwas zu lasten der zykluszeit, aber den riesen Vorteil daß sich das beliebig Strukturieren und Gruppieren lässt.

Wenn also im Schritt angekommen (==I TRUE) wird das Netzwerk bearbeitet und am ende festgelegt wohin es als nächstes geht. Entweder gleicher Schritt (z.B. bei Verzögerungszeiten) oder Nächster bzw. Alternativschritt. Dies geschieht dann durch Schreiben der neuen Nummer und anschließend BE (ende FB)

Beispiel ein Netzwerk (IZ=401) mit einer Verzögerungszeit:

Code:
// Beginn Netzwerk
      L     401
      L     #IZ_FB
      ==I   
      =     #HB_FB
      SPBN  z401
 
// Wenn eine Abwahl durch den Bediener am Schalter entweder auf "AUS" oder
// auf "Bereit" erfolgt, ODER wenn eine Abwahl vom Master erfolgt dann:
      U     #Notaus_IO
      UN    #BA_Hand
      UN    #Modul_EIN_ZS
      SPBN  e401
 
// Zum Beenden - IZ wechseln...
      SET   
      CALL  #t_SFB4_EVerz
       IN:=FALSE
       PT:=T#5MS
       Q :=#t_M_SFB4_EVerz
       ET:=
      L     450
      T     #IZ_FB
      BE    
e401: NOP   0
 
// Verzoegerungszeit abwarten
      SET   
      CALL  #t_SFB4_EVerz
       IN:=TRUE
       PT:=T#10S
       Q :=#t_M_SFB4_EVerz
       ET:=#t_Status_SFB4_EVerz
 
      U     #t_M_SFB4_EVerz
      SPBN  z401
 
// abgelaufen -> Zeit ruecksetzen, naechster IZ...
      CALL  #t_SFB4_EVerz
       IN:=FALSE
       PT:=T#5MS
       Q :=#t_M_SFB4_EVerz
       ET:=
      L     402
      T     #IZ_FB
      BE    
z401: NOP   0
// Ende Netzwerk

Ich gruppiere z.B. die Schrittnummern so sinnvoll daß sogar andere Bausteine davon profitieren können in dem ich die Schrittnummer zur verfügung stelle (sogar im HMI anzeige) und durch simple Vergleiche >I / <I einer bestimmten Zahl weiss welcher globale Zustand (Stillstand, Betrieb, Gestört...) dort gerade herrscht...

Ich darf natürlich nicht über Netzwerkgrenzen hinweg springen.

Was ich mir jetzt vorstellen kann Platz zu sparen wäre wie schon gesagt ähnliche Teilketten zusammenzufassen und per Hilfsbits einen Grund für dessen Ausführung mitzugeben. So würde der Teil gleich gut erledigt, aber am HMI eine andere Meldung angezeigt sowie am Ende des Teils abhängig vom Hilfsbit hier oder dort weitergemacht - z.B. bei einer Störung der automatische Wiederanlauf blockiert werden und warten bis ein "Finger" den Taster an der Schranktüre betätigt hat (nachdem er hoffentlich die Fehlermelung am Panel gelesen und richtig interpretiert hat...).

Nur komme ich so auf keinen Fall unter die 16kB, leider...


Zu Godis Vorschlag noch mal was:

Wenn das so funktioniert wie ich jetzt denke daß es funktionieren müsste dann hätte ich die wenigste Arbeit damit - weil dann automatisch sichergestellt ist daß immer nur ein Schritt aktiv ist, egal in welchem der beiden (oder vielleicht später im fünften ?) FBs er liegt. Spätestens hier wäre die Sprungleiste gar nicht mehr einsetzbar...

Von der "Aufteilung" her bin ich ja flexibel weil es gar nicht so eine Rolle spielt welcher Schritt in welchem FB nachher liegt -> Ablauftechnisch zumindest wäre es trotzdem besser zu organisieren, ganz klar. Aber das geht ja wiederum spielend leicht in dem ich die Netzwerke nach belieben in Ihrer Reihenfolge sortiere. Trotzdem liegt dann immer nur in einem der FBs ein aktiver Schritt pro Zyklus.
 
OK werde es versuchen nochmals genauer zu erklären
aber Testen musst du es selbst

Code:
FUNCTION_BLOCK FB 11
TITLE =
//Hier fängt der erste Teil deines Aufgesplitterten FB's an
//Bei mir steht nur ein Versuchscode drinn
VERSION : 0.1
 
VAR_INPUT
  Ein : BOOL ; 
  Ein_Word : WORD ; 
END_VAR
VAR_OUTPUT
  Aus : BOOL ; 
  Aus_Word : WORD ; 
END_VAR
VAR
  STAT_WORD : WORD ; 
  HM_FP_EIN : BOOL ; 
  FP_EIN : BOOL ; 
  STAT_AUS : BOOL ; 
END_VAR
BEGIN
NETWORK
TITLE =
      U     #Ein; 
      FP    #HM_FP_EIN; 
      =     #FP_EIN; 
NETWORK
TITLE =
      U     #FP_EIN; 
      X     #STAT_AUS; 
      =     #STAT_AUS; 
NETWORK
TITLE =
      U     #STAT_AUS; 
      SPBN  next; 
      L     #Ein_Word; 
      T     #STAT_WORD; 
next: NOP   0; 
END_FUNCTION_BLOCK
 
 
FUNCTION_BLOCK FB 12
TITLE =
//Hier fängt der zweite Teil deines Aufgesplitterten FB's an
//Bei mir steht nur ein Versuchscode drinn
VERSION : 0.1
 
VAR_INPUT
  Ein : BOOL ; 
  Ein_Word : WORD ; 
END_VAR
VAR_OUTPUT
  Aus : BOOL ; 
  Aus_Word : WORD ; 
END_VAR
VAR
  STAT_WORD : WORD ; 
  HM_FP_EIN : BOOL ; 
  FP_EIN : BOOL ; 
  STAT_AUS : BOOL ; 
END_VAR
BEGIN
NETWORK
TITLE =
      U     #STAT_AUS; 
      =     #Aus; 
 
NETWORK
TITLE =
      U     #Aus; 
      SPBN  next; 
      L     #STAT_WORD; 
      T     #Aus_Word; 
next: NOP   0; 
END_FUNCTION_BLOCK
FUNCTION_BLOCK FB 10
TITLE =
//Von Aussen kann der Zusammengesetzte Baustein wie ein ganzer Betrachtet werden
//also du kannst den ganz normal im OB 1 Aufrufen und wie deinen originalen Baustein mit Parametern versehen
VERSION : 0.1
 
VAR_INPUT
  Ein : BOOL ;                //Hier legst du deine Inputvariablen an wie du sie im Original FB verwendest
  Ein_Word : WORD ; 
END_VAR
VAR_OUTPUT
  Aus : BOOL ;             //Hier legst du deine Outputvariablen an wie du sie im Original FB verwendest
  Aus_Word : WORD ; 
END_VAR
VAR
  FB_Test : FB 11;   //Anlegen des ersten Teiles deines FB's als Statische Variable (Multiinstanz)
END_VAR
VAR_TEMP
  Rette_AR2 : DINT ; //Zum Retten deines Adressregister 2
END_VAR
BEGIN
NETWORK
TITLE =
      CALL #FB_Test (//Die Ausgänge von diesem Baustein nicht verwenden weil es nur eine Teilaktualisierung ist wenn du den FB als ganzes siehst IN_OUT Variablen schon anlegen
           Ein                      := #Ein,
           Ein_Word                 := #Ein_Word);
//Sichere Adressregister 2 weil eine Multiinstanz arbeitet mit dem Adressregister 2 und du brauchst es wieder zum zurücksichern
      TAR2  ; 
      T     #Rette_AR2; 
//Erzeuge Bausteinaufruf
      L     P##FB_Test; //Lade Pointer von Variable wo sich dein Multiinstanz FB befindet
      L     2#111111111111111111111111; 
      UD    ; //Maskiere Byte 0 von Pointer aus
      L     2#10000100; 
      SLD   24; 
      XOD   ; //Maskiere Pointer auf DB
      LAR2  ; //Pointer muss an das AR2 übergeben werden weil dann der FB 12 damit arbeitet und auf die selben Daten wie dein Multiinstanz FB zugreift
      UC    FB    12; //Bausteinaufruf ohne Bausteinparameter
//Schreibe AR2 zurück damit die nachfolgenden Variablen wieder auf den richtigen Speicherbereich zugreifen
      L     #Rette_AR2; 
      LAR2  ; 
// Hier können jetzt die Ausgänge von dem Baustein Abgefragt werden da ja jetzt dein ganzer FB abgearbeitet ist und die Ausgänge vom zweiten Teil des FB's auch aktualisiert wurden und du die Ausgänge von der Multiinstanz in den Übergeordneten FB als Ausgänge schreiben kannst. Das selbe gilt natürlich für die IN_OUT auch.
      U     #FB_Test.Aus;    //Lese die Ausgänge von der Multiinstanz
      =     #Aus;                //und schreibe sie auf die Ausgänge des FB10
      L     #FB_Test.Aus_Word; 
      T     #Aus_Word; 
 
 
 
END_FUNCTION_BLOCK
DATA_BLOCK DB 10
TITLE =
VERSION : 0.0
 FB 10
BEGIN
   Ein := FALSE; 
   Ein_Word := W#16#0; 
   Aus := FALSE; 
   Aus_Word := W#16#0; 
   FB_Test.Ein := FALSE; 
   FB_Test.Ein_Word := W#16#0; 
   FB_Test.Aus := FALSE; 
   FB_Test.Aus_Word := W#16#0; 
   FB_Test.STAT_WORD := W#16#0; 
   FB_Test.HM_FP_EIN := FALSE; 
   FB_Test.FP_EIN := FALSE; 
   FB_Test.STAT_AUS := FALSE; 
END_DATA_BLOCK
ORGANIZATION_BLOCK OB 1
TITLE = "Main Program Sweep (Cycle)"
VERSION : 0.1
 
VAR_TEMP
  OB1_EV_CLASS : BYTE ; //Bits 0-3 = 1 (Coming event), Bits 4-7 = 1 (Event class 1)
  OB1_SCAN_1 : BYTE ; //1 (Cold restart scan 1 of OB 1), 3 (Scan 2-n of OB 1)
  OB1_PRIORITY : BYTE ; //Priority of OB Execution
  OB1_OB_NUMBR : BYTE ; //1 (Organization block 1, OB1)
  OB1_RESERVED_1 : BYTE ; //Reserved for system
  OB1_RESERVED_2 : BYTE ; //Reserved for system
  OB1_PREV_CYCLE : INT ; //Cycle time of previous OB1 scan (milliseconds)
  OB1_MIN_CYCLE : INT ; //Minimum cycle time of OB1 (milliseconds)
  OB1_MAX_CYCLE : INT ; //Maximum cycle time of OB1 (milliseconds)
  OB1_DATE_TIME : DATE_AND_TIME ; //Date and time OB1 started
END_VAR
BEGIN
NETWORK
TITLE =
      CALL FB    10 , DB    10 (
           Ein                      := M      1.0,
           Ein_Word                 := MW    12,
           Aus                      := M      1.1,
           Aus_Word                 := MW    14);
 
END_ORGANIZATION_BLOCK

Was mir noch eingefallen ist du könntest ja auch im FB11 das AR2 auslesen und als Outputvariable ausgeben und dann vor dem UC aufruf des FB 12 ins AR2 zurückschreiben.
Dann brauchst du nicht mehr den für dich undverstänlichen code vor dem UC aufruf durchführen!

Das war jetzt mein 600 Beitrag! :) :s10: :s10: :s10:

godi
 
Zuletzt bearbeitet:
...
ich hatte es mir nach deiner Beschreibung mit deiner Schrittkette in etwa so vorgestellt, wie du es hier nun auch veröffentlicht hast.
Dir ist schon klar, dass die "Schritt-Vergleiche" und "Schritt-Zuordnungen" ganz schön Speicher fressen können ...?
Ich selber favourisiere da :
Code:
U -Schrittmerker 100
U -Bedingung_1
S -Schrittmerker 200
R -Schrittmerker 100
 
U -Schrittmerker 100
U -Bedingung_2
S -Schrittmerker 230
R -Schrittmerker 100
 
usw.
 
Die Schrittmerker könnten im STAT-Bereich deines FB's deklariert sein ...
Der reine binäre Vergleich müsste schon Resourcen sparen. Für die Visualisierung der Schrittkette ist er allerdings nicht so sehr geeignet. Du kannst ja aktuell in deiner Visu anzeigen "Stehe in Schrittkette 1 im Schritt 740" ohne da größere Klimmzüge machen zu müssen.
Bei mir müsste das entsprechende Bit erst einmal in eine Schrittnummer umgerechnet werden - ginge aber auch ...

Da ich mir von deiner Schrittketten-Struktur noch kein klares Bild machen kann ...
Du hast eine Gesamt-Schrittkette für die ganze Anlage ?
Aus dieser SK werden benötigte / freigegebene Bereiche simultan abgearbeitet ?
Wie wäre es, wenn du die Teil-SK's wie ein Unterprogramm behandelst ?
Hier würde jede UP-SK erstmal in sich geschlossen laufen und ihre Freigabe von der Haupt-SK erhalten und sich nach getaner Arbeit bei dieser auch wieder zurück melden. Falls du das nicht schon so hast, dann wäre es u.A. eine Möglichkeit, deinen "Super"-FB in Teilbereiche zu zergliedern, die trotzdem vom Master-FB überwacht werden können ...

Während ich hier so schreibe, habe ich gesehen, das Godi auch wieder mit an Bord ist. Der Beitrag von ihm ist sehr interessant. Das muss ich unbedingt bei Gelegenheit mal testen - zwar ohne konkrete Aufgabenstellung aber einfach des Wissens wegen ...

Bis dahin
Gruß
LL
 
Zuviel Werbung?
-> Hier kostenlos registrieren
...
ich hatte es mir nach deiner Beschreibung mit deiner Schrittkette in etwa so vorgestellt, wie du es hier nun auch veröffentlicht hast.

Dir ist schon klar, dass die "Schritt-Vergleiche" und "Schritt-Zuordnungen" ganz schön Speicher fressen können ...?
Das hat auch mal ganz klein angefangen und jetzt gilt es eben die besagten Vor- und Nachteile abzuwägen.
Ich selber favourisiere da :
Code:
U -Schrittmerker 100
U -Bedingung_1
S -Schrittmerker 200
R -Schrittmerker 100
 
U -Schrittmerker 100
U -Bedingung_2
S -Schrittmerker 230
R -Schrittmerker 100
 
usw.
 
Die Schrittmerker könnten im STAT-Bereich deines FB's deklariert sein ...
Der reine binäre Vergleich müsste schon Resourcen sparen. Für die Visualisierung der Schrittkette ist er allerdings nicht so sehr geeignet. Du kannst ja aktuell in deiner Visu anzeigen "Stehe in Schrittkette 1 im Schritt 740" ohne da größere Klimmzüge machen zu müssen.
Bei mir müsste das entsprechende Bit erst einmal in eine Schrittnummer umgerechnet werden - ginge aber auch ...
Das wäre sogar nicht mal das schlimmste, aber die Gruppierung der Bereiche wäre mit Bits schon sehr schwierig.
Es müsste eine Lösung gefunden werden die die IZ Nummer erhält aber den Vergleichsmechanismus überflüssig macht --> doch etwa eine SPL ? (aber das müsste dann so viel bringen das der zweite FB überflüssig wird)

Ach so das habe ich glaub auch noch nicht erwähnt: Der FB hat aktuell etwa 22kB...

Da ich mir von deiner Schrittketten-Struktur noch kein klares Bild machen kann ...
Du hast eine Gesamt-Schrittkette für die ganze Anlage ?
Nein, pro Maschine eine Instanz des von dir so liebevoll genannten "Super-FB"
Aus dieser SK werden benötigte / freigegebene Bereiche simultan abgearbeitet ?
Es geht eher in die Richtung eine Maschine mit allem Zubehör und 2-3 Ausführungen zu definieren - welche rein über die Schnittstelle im OB1 Aufruf parametriert wird. Das heisst in der Schrittkette existieren eher viele "blinde" Schritte die in der jeweiligen Konfiguration nicht benötigt werden weil die Maschine das gar nicht kann. Weil aber sein kann daß die die daneben steht es kann und was anderes dafür nicht muss alles drin sein. Ich rufe dann die nächste Instanz eben anders konfiguriert auf...
Wie wäre es, wenn du die Teil-SK's wie ein Unterprogramm behandelst ?
Hier würde jede UP-SK erstmal in sich geschlossen laufen und ihre Freigabe von der Haupt-SK erhalten und sich nach getaner Arbeit bei dieser auch wieder zurück melden. Falls du das nicht schon so hast, dann wäre es u.A. eine Möglichkeit, deinen "Super"-FB in Teilbereiche zu zergliedern, die trotzdem vom Master-FB überwacht werden können ...
Das wird halt sehr sehr schwierig weil im Prinzip immer die volle Schnittstelle in jedem Bereich zur Verfügung stehen müsste - und diese ist ziemlich umfangreich. Die Abschnitte (Start / Bertrieb / Stop / Fehler /... z.B.) wären eigentlich gut zu unterteilen nur jedes davon in ein Unterprogramm?
Meinst du vielleicht eine FC die vom FB aus aufgerufen wird ?
Während ich hier so schreibe, habe ich gesehen, das Godi auch wieder mit an Bord ist. Der Beitrag von ihm ist sehr interessant. Das muss ich unbedingt bei Gelegenheit mal testen - zwar ohne konkrete Aufgabenstellung aber einfach des Wissens wegen ...

Bis dahin
Gruß
LL

Ja - ich komm auch vor lauter schreiben nicht zum Testen... :)
 
Das wäre sogar nicht mal das schlimmste, aber die Gruppierung der Bereiche wäre mit Bits schon sehr schwierig.
Es müsste eine Lösung gefunden werden die die IZ Nummer erhält aber den Vergleichsmechanismus überflüssig macht --> doch etwa eine SPL ? (aber das müsste dann so viel bringen das der zweite FB überflüssig wird)

Ach so das habe ich glaub auch noch nicht erwähnt: Der FB hat aktuell etwa 22kB...

Hallo RS,
der SPL-Befehl würde da meines Erachtens keinen Speicher-Vorteil erbringen. Wenn überhaupt (das müßte man vielleicht im Kleinen mal testen) dann der Bit-Vorschlag. Hier könntest du auch ein ARRAY of BOOL nehmen. Das käme deiner Satz-Nummern-Geschichte ja auch wieder näher. Dein Problem ist ja nicht die Größe des I-DB sondern des Codes darin. 22k ist natürlich schon eine Haunummer ...! Ich selber habe auch ein paar "Brummer"-FB's. Die haben zum Teil auch einiges drauf, beschränken sich aber auf max. 5 - 6 k ... also ganz andere Liga ...

... des von dir so liebevoll genannten "Super-FB"
was Recht ist muss doch auch Recht bleiben - bei der Größe liege ich mit dem Namen doch auch nicht falsch ...

Spass beiseite. Ich denke, durch das Folgende musst du selbst durch, da es letztendlich deine Entscheidung ist, die du dann auch (vor dir selbst) vertreten können musst. Ein paar Anregungen hast du nun ja bekommen - so wie ich es aus meiner Sicht sehe war der Knaller nicht mit dabei. Vielleicht versuchst du mal meinen Vorschlag mit einem ARRAY of BOOL in einem beschränkten Bereich um zu sehen, was (und ob überhaupt) es bringt. Sonst fällt mir nichts Tolles mehr ein ...

Resumierend würde ich aber sagen, dass du ums Umstrukturieren und Erstellen eines neuen Standard-FB's nicht auf Dauer herum kommst. Manchmal muss man eben in den sauren Apfel beissen. Wenn du es richtig anstellst, dann wirst du allerdings dann trotzdem kaum Kompatiblitäts-Probleme bekommen (höchstens bei der Visu).

Ich bin auf jeden Fall auf deine Ergebnisse gespannt - ich hoffe du schreibst darüber.

Gruß
LL
 
Schritt FB mit Stepnr und Stepbits

Hier ein FB mit Schritt nr und mit Schritt bits
Max schritte = 255
Code:
FUNCTION_BLOCK FB 50
TITLE =
VERSION : 0.1
 
VAR_INPUT
  Reset : BOOL ; //Reset Steps
  MaxStep : INT ; //Max nr of steps
END_VAR
VAR
  StepNr : INT ; //Nr of act step
  Step : ARRAY  [0 .. 254 ] OF //Step bits
  BOOL ; 
END_VAR
VAR_TEMP
  adress : DWORD ; 
  RetVal : INT ; 
  RESET_BYTE : BYTE ; 
END_VAR
BEGIN
NETWORK
TITLE =Reset + control max steps
      U     #Reset; 
      SPBN  m1; 
      L     0; 
      SPA   end; 
m1:   L     #StepNr; 
      L     #MaxStep; 
      >=I   ; 
      SPBN  List; 
      L     0; 
      SPA   end; 
NETWORK
TITLE =
//Sprung liste max steps 254 
List: L     #StepNr; 
      SPL   fout; 
      SPA   S000; 
      SPA   S001; 
      SPA   S002; 
      SPA   S003; 
      SPA   S004; 
      SPA   S005; 
      SPA   S006; 
      SPA   S007; 
      SPA   S008; 
      SPA   S009; 
      SPA   S010; 
      SPA   S011; 
      SPA   S012; 
      SPA   S013; 
      SPA   S014; 
      SPA   S015; 
      SPA   S016; 
      SPA   S017; 
      SPA   S018; 
      SPA   S019; 
      SPA   S020; 
// UZW  bis SPA 254
fout: SPA   S254; 
NETWORK
TITLE =Step 0
S000: NOP   0; 
//     u start
      SPBN  ende; 
      L     1; 
//= Nr next step
      SPA   end; 
NETWORK
TITLE =Step 1
S001: NOP   0; 
//     u xxx  for next step
      SPBN  ende; 
      L     2; 
      SPA   end; 
NETWORK
TITLE =Step 2
S002: NOP   0; 
//     u xxx
      SPBN  ende; 
      L     3; 
      SPA   end; 
NETWORK
TITLE =Step 3
S003: NOP   0; 
//     u xxx
      SPBN  ende; 
      L     4; 
      SPA   end; 
NETWORK
TITLE =Step 4
S004: NOP   0; 
//     u xxx
      SPBN  ende; 
      L     5; 
      SPA   end; 
NETWORK
TITLE =Step 5
S005: NOP   0; 
//     u xxx
      SPBN  ende; 
      L     6; 
      SPA   end; 
NETWORK
TITLE =Step 6
S006: NOP   0; 
//     u xxx
      SPBN  ende; 
      L     7; 
      SPA   end; 
NETWORK
TITLE =Step 7
S007: NOP   0; 
//     u xxx
      SPBN  ende; 
      L     8; 
      SPA   end; 
NETWORK
TITLE =Step 8
S008: NOP   0; 
//     u xxx
      SPBN  ende; 
      L     9; 
      SPA   end; 
NETWORK
TITLE =Step 9
S009: NOP   0; 
//     u xxx
      SPBN  ende; 
      L     10; 
      SPA   end; 
NETWORK
TITLE =Step 10
S010: NOP   0; 
//     u xxx
      SPBN  ende; 
      L     11; 
      SPA   end; 
NETWORK
TITLE =Step 11
S011: NOP   0; 
//     u xxx
      SPBN  ende; 
      L     12; 
      SPA   end; 
NETWORK
TITLE =Step 12
S012: NOP   0; 
//     u xxx
      SPBN  ende; 
      L     13; 
      SPA   end; 
NETWORK
TITLE =Step 13
S013: NOP   0; 
//     u xxx
      SPBN  ende; 
      L     14; 
      SPA   end; 
NETWORK
TITLE =Step 14
S014: NOP   0; 
//     u xxx
      SPBN  ende; 
      L     15; 
      SPA   end; 
NETWORK
TITLE =Step 15
S015: NOP   0; 
//     u xxx
      SPBN  ende; 
      L     16; 
      SPA   end; 
NETWORK
TITLE =Step 16
S016: NOP   0; 
//     u xxx
      SPBN  ende; 
      L     17; 
      SPA   end; 
NETWORK
TITLE =Step 17
S017: NOP   0; 
//     u xxx
      SPBN  ende; 
      L     18; 
      SPA   end; 
NETWORK
TITLE =Step 18
S018: NOP   0; 
//     u xxx
      SPBN  ende; 
      L     19; 
      SPA   end; 
NETWORK
TITLE =Step 19
S019: NOP   0; 
//     u xxx
      SPBN  ende; 
      L     20; 
      SPA   end; 
NETWORK
TITLE =Step 20
S020: NOP   0; 
//     u xxx
      SPBN  ende; 
      L     21; 
      SPA   end; 
NETWORK
TITLE =Step 21 - 253
//Step 21 bis step 254 einrichten wie beispiel Step 0 - 20
      NOP   0; 
//     u xxx
      SPBN  ende; 
      L     253; 
      SPA   end; 
NETWORK
TITLE =Step 254
S254: NOP   0; 
//     u xxx
//     SPBN  ende
      L     1; 
//return to step 1
      SPA   end; 
NETWORK
TITLE =Bits setsen
end:  T     #StepNr; 
ende: NOP   0; 
//Stepbit resetsen
      L     0; 
      T     #RESET_BYTE; 
      CALL SFC   21 (
           BVAL                     := #RESET_BYTE,
           RET_VAL                  := #RetVal,
           BLK                      := #Step);
//stepbit setsen
      L     P##Step; 
      L     #StepNr; 
      ITD   ; 
      +D    ; 
      LAR1  ; 
      SET   ; 
      =     DIX [AR1,P#0.0]; 
END_FUNCTION_BLOCK

M V G,
Joop
 
Zurück
Oben