Step 7 Dynamischer Insanz-DB bei FB-Aufruf

W7X

Level-1
Beiträge
8
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo!

Ich habe hier ein Problem, das mich jetzt schon ein paar Tage beschäftigt. Die Aufgabenstellung klingt einfach, ist aber offenbar gar nicht so trivial in der Umsetzung. Also...

Ich habe folgende Aufrufkette von Funktionen und Funktionbausteinen: OB1 --> FC4 --> FB4 --> FC5 --> FB10. Der FB10 am Ende der Kette soll mit einem dynamischen Instanz-DB aufgerufen werden. Dynamisch deshalb weil der DB ganz am Anfang der Kette (im FC4) festgelegt wird. Im Grunde geht es also nur darum, einen Datenbaustein über mehrere Aufrufe weiterzugeben um ihn dann am Ende als Instanz-DB zu verwenden. Das Problem ist nur: Es funktioniert nicht. Natürlich kann ich einfach die DB-Nummer als Integer übergeben und dann den DB über den Befehl AUF DB [#Variable] öffnen. Das funktioniert aber leider nicht mit dem CALL-Befehl (CALL FB10, DB [#Variable] ist nicht erlaubt). Schade, es hätte so einfach sein können. Aber es gibt ja noch eine Möglichkeit: Den Datentyp Block_DB. Diesen kann ich für eine Input-Variable verwenden und den Instanz-DB damit weiterreichen. Aber auch hier gibt es ein kleines (und für mich genauso unverständliches) Problem: Variablen vom Typ Block_DB können nicht als Parameter an Funktionen übergeben werden, nur an Funktionsbausteine, womit ich bei FC5 Schiffbruch erleiden würde. Eine weitere Alternative wären Fallunterscheidungen und Sprungmarken, aber damit würde ich wieder seitenweise unübersichtlichen Spaghetticode produzieren.

Ich bin langsam mit meinem Latein am Ende. Wie kann ich einen FB mit dynamischem Instanz-DB aufrufen? Die wenigen Threads, in denen dieses Problem besprochen wurde brachten leider keine Lösung. Ich bin für jede Hilfe dankbar.

Falls sich jemand wundert, warum ich mit so vielen FBs und FCs arbeite, ich mache das um redundanten Quelltext zu vermeiden und um das Projekt übersichtlich zu halten (Ich programmiere in AWL).
 
ich mache das um redundanten Quelltext zu vermeiden und um das Projekt übersichtlich zu halten
:ROFLMAO:
... und dafür völlig undurchsichtigen und unwartbaren Programmcode zu produzieren, den höchstwahrscheinlich nur Du selber verstehst und in einem halben Jahr wird es überhaupt niemand mehr verstehen. In Zeiten von TIA und vollsymbolischer Programmierung muß man sich solche vorsintflutlichen Schweinereien garnicht erst angewöhnen.

Gut, daß Siemens die Verwendung dynamischer IDB so schwer gemacht hat, daß nur wirkliche Profi-Programmierer sowas hinkriegen, welche genau wissen was sie tun. ;)

Was verstehst Du unter vermeidbarem "redundanten Quelltext"?

Ich behaupte mal, daß Dein Konzept falsch ist und Du Deine Idee besser in die Tonne kloppst.
Warum hast Du mehrere Instanz-DBs, von denen Du anscheinend immer nur einen nutzen willst?
Hat Dein FB10 gar keine Übergabeparameter oder wie bekommst Du Deine Werte in/aus den betreffenden IDB?

Beschreibe doch mal etwas genauer, was Du da vorhast und warum das so umständlich gelöst werden soll.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Harald!

Danke erstmal für die schnelle Antwort.

Ich muss dazu sagen, dass ich Neuling bin in der SPS-Programmierung. Von daher könntest du schon Recht haben, vielleicht ist mein Konzept falsch. Ich versuche mal zu erklären, worum es geht...

Die SPS soll insgesamt 6 bewegliche Spiegel steuern, die wiederum von jeweils 2 Motoren bewegt werden. Jeder Motor wird mit einem Servoverstärker vom Typ Kollmorgen S600 über den PROFIBUS betrieben. Der bereits erwähnte FB10 ist ein fertiger Funktionsbaustein, der dem Benutzer die Funktionalität der Servoverstärkers bereitstellt. Nun soll es möglich sein, ausgehend von den gemeldeten Istwerten der Motoren frei wählbare Zielwerte anzusteuern. Da die Spiegel aber in ihrer Beweglichkeit eingeschränkt sind muss vorher eine Überprüfung der Zielwerte stattfinden und eventuell ein Umweg gefahren werden. Aufgrund dieser, etwas komplexeren, Abläufe habe ich mich für die genannte Struktur entschieden. FC4: Aufrufe für alle 6 Spiegel, FB4: Prozesssteuerung für einen Spiegel, FC5: Prozesssteuerung für einen Motor. Ich könnte natürlich FB4 und FC5 zusammenlegen, aber dann hätte ich den Code für die Motorsteuerung schon wieder doppelt drin.

Ich habe früher hauptsächlich objektorientiert programmiert und da ist es eben so, dass man jede Funktion wenn möglich nur einmal implementiert und dafür entsprechend eine Klasse deklariert und daraus Objekte erzeugt. Selbst wenn man dabei manchmal ein bisschen ausholen muss finde ich solche Strukturen dann immernoch übersichtlicher (und vor allem einfacher zu ändern) als einen Quelltext, in dem alles 10 mal drin steht. Aber wie gesagt, ich bin SPS-Neuling und wenn du einen guten Vorschlag hast, wie man das anders lösen kann dann wäre ich dafür natürlich auch dankbar.

Grüße,
Niko
 
Du mußt ja nicht die Ansteuerfunktion 10 mal schreiben sondern nur einmal in einem FB. Dann rufst Du diesen FB je einmal für jeden Motor (oder jeden Spiegel) auf, jedesmal mit einem anderen IDB. Ich sehe da keinen redundanten/mehrfach vorhandenen Code. Es wird immer wieder der gleiche Code ausgeführt, jedoch jedesmal mit einem anderen Satz Variablen (der IDB).

Harald
 
Naja, im Grunde mache ich ja genau das - mit dem FB4. Nur dass ich dann zusätzlich die Steuerung für die einzelnen Motoren nochmal auslagern will. Ich hab das Problem jetzt erst mal dadurch gelöst, dass ich aus dem FC5 einen FB5 gemacht habe. Dadurch habe ich zwar einen zusätzlichen Instanz-DB, den ich nicht gebraucht hätte, aber immerhin kann ich jetzt die Block_DB-Variable bis zum FB10 durchreichen.

Gruß,
Niko
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Und den FB5 packst du jetzt in die Schnittstelle eines aufrufenden FBs z.B. FB100

FB100 ruft also FB5 10 mal auf mit jeweils anderer Deklaraktion in der Schnittstelle von FB100. Stichwort Multiinstanz.

Dann hast du nur noch einen Instanzdb nämlich den von FB100.

mfG René

PS: Grad letztens wieder geflucht wieso unsere Lehrlinge das in der Berufsschule nichtmal anschneiden. Die lernen immernoch alles mit Merkern (nein keine DBs sondern echte Schmiermerker in FCs) :(
 
aber immerhin kann ich jetzt die Block_DB-Variable bis zum FB10 durchreichen.
Du solltest aber nicht die Nummer des IDB durchreichen. Wenn Du Multiinstanzen benutzt, dann brauchst Du gar nichts an die FB10 durchreichen und trotzdem werden die 12 FB10-Instanzen automatisch klar unterschieden.
z.B.:
* "IDB_Spiegel1".Motor1.ServoFB
* "IDB_Spiegel1".Motor2.ServoFB
* "IDB_Spiegel2".Motor1.ServoFB
* "IDB_Spiegel2".Motor2.ServoFB
...
* "IDB_Spiegel6".Motor1.ServoFB
* "IDB_Spiegel6".Motor2.ServoFB

Das erreichst Du so:
- FC5 umwandeln zu FB5
- im FB5 in STAT als Multiinstanz eine Instanz von FB10 : #ServoFB
- im FB4 in STAT als Multiinstanz zwei Instanzen von FB5 : #Motor1 + #Motor2
- im FC4 6x FB4 aufrufen mit 6 verschiedenen IDB

Code:
OB1 --> FC4 --> CALL FB4,"IDB_Spiegel1"
                     --> #Motor1 (FB5) --> #ServoFB (FB10)
                     --> #Motor2 (FB5) --> #ServoFB (FB10)
            --> CALL FB4,"IDB_Spiegel2"
                     --> #Motor1 (FB5) --> #ServoFB (FB10)
                     --> #Motor2 (FB5) --> #ServoFB (FB10)
            --> CALL FB4,"IDB_Spiegel3"
                     --> #Motor1 (FB5) --> #ServoFB (FB10)
                     --> #Motor2 (FB5) --> #ServoFB (FB10)
            --> CALL FB4,"IDB_Spiegel4"
                     --> #Motor1 (FB5) --> #ServoFB (FB10)
                     --> #Motor2 (FB5) --> #ServoFB (FB10)
            --> CALL FB4,"IDB_Spiegel5"
                     --> #Motor1 (FB5) --> #ServoFB (FB10)
                     --> #Motor2 (FB5) --> #ServoFB (FB10)
            --> CALL FB4,"IDB_Spiegel6"
                     --> #Motor1 (FB5) --> #ServoFB (FB10)
                     --> #Motor2 (FB5) --> #ServoFB (FB10)

Du könntest auch den FC4 in einen FB umwandeln und alle 6 Spiegel als Multiinstanz in diesen Mutter-FB packen, dann brauchst du nur 1 IDB für alles.

Btw: "Tiefe" Aufruf-Strukturen sind bei SPS eher unüblich (die Schachtelungstiefe der Bausteinaufrufe ist begrenzt), Dein Beispiel ist aber noch machbar.
Und bei SPS kommt es nicht so drauf an, Code möglichst kompakt zu packen, sondern mehr auf Lesbarkeit und besonders Beobachtbarkeit der einzelnen "Objekte". Da wird durchaus lieber keine Schleife programmiert sondern "stupide" 10x nacheinander das Gleiche programmiert, weil das viel besser zu beobachten ist und kleine unterschiedliche Spezialbehandlungen leichter einzubauen sind. Außerdem kann solch linearer Code einfacher von Programmgeneratoren erzeugt werden.

Harald
 
OK, jetzt ist bei mir der Groschen gefallen. Ich habe gerade festgestellt, dass ich bisher keinen Schimmer hatte, was Multiinstanzen sind. Aber das ist genau das was ich brauche: Die Motorsteuerung kommt einfach als Multiinstanz zweimal in die Spiegelsteuerung mit rein und das wars - genial. Damit sollte es funktionieren.

Vielen Dank für die Hilfe!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Und bitte nicht vergessen den FB5 multiinstanzfähig zu programmieren, sonst gibt es tolle Effekte. Gibt hier gute Threads zum Nachlesen. Offset vom Adressregister dazuzählen und und und.....;)
 
Muss ich das ar2 auch berücksichtigen, wenn ich symbolisch adressiere?
Nur wenn Du Dich auf die Adresse einer Instanzvariable beziehst, wie z.B. P##statvar - das liefert nur den Offset innerhalb der Instanz.
Nicht wenn Du über den Name auf den Inhalt der Variable zugreifst (L #statvar), da berücksichtigt der MC7-Compiler den Multiinstanz-Offset zur Laufzeit.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Nur wenn Du Dich auf die Adresse einer Instanzvariable beziehst, wie z.B. P##statvar - das liefert nur den Offset innerhalb der Instanz.
Ok, dann also noch hintendran:
Code:
LAR1 P##statBool
TAR2 // Instanz-Offset
+AR1 // im Bereichszeiger berücksichtigen

U #inBool
= DIX [AR1, P#0.0] // indirekte Adressierung von #statBool

PS: Theoretisch müsste man jeden FB in dem die eigenen Lokaldaten indirekt adressiert werden multiinstanz-fähig machen, da man nicht weiß ob der FB als Multiinstanz verwendet wird.
 
Zuletzt bearbeitet:
Vorsicht, das +AR1 funktioniert nur bis Multiinstanzadressen kleiner 4kB.
Benutze besser diese Berechnung:
Code:
L P##statBool     //relative Adresse #statBool in dieser Instanz (DI) 
TAR2              //Lade Adressregister2 mit Offset dieser Multiinstanz (DB) in Akku1 
UD DW#16#FFFFFF   //Bereichskennung (DB) ausblenden 
+D                //Addiere 
LAR1              //Lade AR1 mit Inhalt von Akku1: absolute Adresse #statBool im IDB (DI)

Wenn man FB mit dem Attribut "multiinstanzfähig" erstellt, dann sollte man sie auch tatsächlich voll multiinstanzfähig programmieren ;)

Harald
 
Zurück
Oben