Strukturprobleme Multiinstanz ...

rs-plc-aa

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

ich möchte ein ziemlich umfangreiches Programm so umbauen daß alle "Kernkomponenten" multiinstanzfähig werden...

Mein Ausgangspunkt ist nicht gerade günstig - alles direkt adressiert, FC calls im FB, direkte Global DB zugriffe usw.

Das Problem: Die ganze Sache neu machen is nich weil es ganz einfach viel zu lange dauern würde und weil ich die Logik als solches lassen möchte da das Programm ausgiebig getestet wurde und prima läuft (so lange es alleine auf einer CPU ist)

Nun sollen davon aber mehrere (variabel) Instanzen auf einer CPU laufen - und das möglichst schon gestern.

Am einfachsten wäre es natürlich die Bausteine unter anderen Nummern einzufügen und als solches zu lassen - wobei hier auch schon die ganzen Adressen von Hand nachgepflegt werden müssten und es eine absolute "Notkrücke" bleiben würde.

Die Idee der Multiinstanz ist zwar nicht neu aber die Umsetzung für mich schon ein wenig -> daher hoffe ich daß ihr mich nicht hängen lasst.

Es dreht sich im wesentlichen um ein Hauptprogramm das wie ein Tintenfisch aufgebaut ist (ich war jung und...:) ) und nun eine Schnittstelle verpasst bekommen soll die es mit der Aussenwelt verbindet.

Hier müssen digitale IOs, skalierte und rohe Messwerte, Meldebits, Merker und Störungsbits untergebracht werden.

Das mit der Peripherie ist kein Problem nur mit den Bits und den Unterprogrammen haperts noch.

Die Bits müssen aus der SymTabelle raus und in GDBs rein, ok.

Wie mache ich jetzt aber z.B einen Gesamtzugriff auf z.B. 32 Bits ?

Vorher habe ich eben das Doppelwort aus dem Adressbereich mit 0 überschrieben - aber wie geht das beim DB mit Symbolischem zugriff ?

Ich wollte Arrays definieren welche immer 32 Bits einer Sorte enthalten um entweder einzeln oder eben auf alle zugreifen zu können aber irgendwie schaff ich das nicht.

In der Hilfe steht nichts konkretes und hier habe ich zu Arrays zwar was gefunden aber das half mir jetzt so auch nicht weiter.

Das zweite ist das mit den Unterprogrammen.

Sehe ich das richtig daß alles was an die Schnittstelle des Unterprogramms übergeben werden soll auch in der Schnittstelle des Hauptprogramms enthalten sein muss ? Wird das nicht sehr aufgebläht ?

Und ist das überhaupt zu empfehlen ?

Wäre für Anregungen jeglicher Art sehr dankbar.
 
...

Es dreht sich im wesentlichen um ein Hauptprogramm das wie ein Tintenfisch aufgebaut ist


????
...
Die Bits müssen aus der SymTabelle raus und in GDBs rein, ok.

Kann, man, muss man aber nicht - kommt immer drarauf an, was man wie machen möchte - hat aber nix mit Multiinstanzen zu tun und ist auch nicht Vorraussetzung für diese.


...

Wie mache ich jetzt aber z.B einen Gesamtzugriff auf z.B. 32 Bits ?

Vorher habe ich eben das Doppelwort aus dem Adressbereich mit 0 überschrieben - aber wie geht das beim DB mit Symbolischem zugriff ?

Ich wollte Arrays definieren welche immer 32 Bits einer Sorte enthalten um entweder einzeln oder eben auf alle zugreifen zu können aber irgendwie schaff ich das nicht.

Hier könnten wir denke ich mal besser helfen, wenn Du mal ein paar Code-Ausschnitte postest (Multiinstanz, oder nicht) und beschreibst, wann konkret klemmt.

...
Das zweite ist das mit den Unterprogrammen.

Sehe ich das richtig daß alles was an die Schnittstelle des Unterprogramms übergeben werden soll auch in der Schnittstelle des Hauptprogramms enthalten sein muss ? Wird das nicht sehr aufgebläht ?

So ganz habe ich es nicht verstanden. Vielleicht ist aber das gemeint:
Also beim Aufruf müssen nicht alle IN, INOUTs, oder OUTs beschrieben werden - die INs werden halt beim ersten Mal mit ihren Initalwerten beschrieben und die bleiben auch so, bis sie überschrieben werden.

Du kannst Dir auch mal hier ansehen, wie so eine Multiinstanzaufruf aussieht: http://www.automatisierungsprofi.de/TON/index.htm

...
Und ist das überhaupt zu empfehlen ?

Auch das kommt wieder daruf an, was man haben möchte. Es gibt auf dieser Welt leider nichts, was nur Vorteile hat oder bringt. Der Vorteil ist halt, dass man Multiinstanzen, wenn man sie ordentlich programmiert gut wiederverwenden kann - wenn man keine globalen Variablen (Symboltabelle) beenutzt hat, sondern nur mit Lokalen- und Instanzdaten auskommt.

Für die Erstellung eine Biblitohek (das sind ja meistens Bausteine drin, die universell einsetzbar sein sollen), macht es schon Sinn Instanzbausteine zu erzeugen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
????
Der Vorteil ist halt, dass man Multiinstanzen, wenn man sie ordentlich programmiert gut wiederverwenden kann - wenn man keine globalen Variablen (Symboltabelle) beenutzt hat, sondern nur mit Lokalen- und Instanzdaten auskommt.

Für die Erstellung eine Biblitohek (das sind ja meistens Bausteine drin, die universell einsetzbar sein sollen), macht es schon Sinn Instanzbausteine zu erzeugen.

Genau hierum geht es...

Das mit dem Tintenfisch war übrigens als Metapher gemeint um die Verzweigung in andere Bausteine hinein zu umschreiben...

Vielleicht bin ich auch nicht genau genug auf den Punkt gekommen aber ich möchte hier noch mal die Frage neu stellen:

Wenn ich jetzt das stehen habe:

Code:
U DB100.dbx0.0
= A0.0
 
und z.B.
 
L 0
T DB100.DBD0

Und nachher möchte ich das haben:

Code:
U #Bits.Bit0
= ...
 
oder
 
L 0
T #Bits.erste32Bits

Also z.B. die Nummer des DB als VARINPUT und die einzelnen Bits beim Namen nennen oder auch beim Rücksetzen alle Bits auf einmal löschen mit einem Lade/Transferierbefehl.

Frage: Brauche ich hierfür im DB100 ein Array of BOOL oder geht das auch ohne ?
Der syb. Zugriff auf die Bits geht ohne Array auch - nur der Gesamte nicht da ich ja im DB die verwendete Adresse nur ein mal vergeben kann.

Die zweite Frage hat sich erledigt da es ja nicht anders gehen wird als die Parameter die das Unterprogramm benötigt über die Schnittstelle des Hauptprogramms zu übergeben...
 
"Symbolisch" über # wird das wohl nicht gehen, denke ich.

Du könntest mit

AUF DB[DB_Nr]
U DBX0.0
...

arbeiten, aber das ist auch nicht immer fein.

Wenn die Daten im Instanz-DB liegen kannst du auch auf die Instanzdaten zugreifen

L 0
T DIW 0

Dazu muß dir bekannt sein, wo die Daten im Instanz-DB denn genau liegen.
 
OK, noch mal eine Korrektur:

Der Code den ich schrieb war falsch.

Ich habe im Instanz DB (also in der Schnittstelle des FB) Variablen deklariert.

Zum einen eine ganze Reihe von Bits die im FB mit #Bit0 angesprochen werden und für diese Bits jeweils für 32 Stück eine DWORD Variable die im Falle eines Tranferierens einer 0 alle ihr zugeordneten Bits "löschen" soll.

Beim Aufruf der Instanz im OB1 muss die Schnittstelle ja versorgt werden -> hier kommt ja eigentlich erst der DB ins Spiel der die Bits enthält...

Also gebe ich dort an daß #Bit0 := DB100.DBX0.0 ist bzw. sein soll.

Soweit schon klar aber das DWORD aus dem FB kann ich eben nur "absolut" also mit DB100.DBD0 zuweisen da im DB100 unter der Adresse 0* eben die BOOL Variablen stehen und es gleichzeitig keine Variable vom Typ DWORD mit der Anfangsadresse 0 geben kann.

Hier war meine Frage ob es geht wenn ich ein Array definiere das dann meine DWORD Variable ist und Ihm untergeordnet im gleichen Adressbereich die Bits zu finden sind.

Da ich 0 Ahnung von Arrays habe weiss ich nicht wie ich das sonst noch formulieren soll...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Mit dem Array, das geht so nicht, glaube ich jedenfalls ;).

Alle INPUT, OUTPUT etc. sind doch im Instanz-DB enthalten.

Du kannst einmal auf die definierten Variablen über #... zugreifen und ebenso direkt auf das DIW zugreifen. Wenn also deine Bits im Instanz-DB die Bits 100.0, 100.1, 100.2 .... belegen solltest du sie alle mit L 0 T DIW 100 loschen können. Hab das auch noch nie so gemacht, probiers doch mal aus.
 
Mit dem Array, das geht so nicht, glaube ich jedenfalls ;).

Alle INPUT, OUTPUT etc. sind doch im Instanz-DB enthalten.

Du kannst einmal auf die definierten Variablen über #... zugreifen und ebenso direkt auf das DIW zugreifen. Wenn also deine Bits im Instanz-DB die Bits 100.0, 100.1, 100.2 .... belegen solltest du sie alle mit L 0 T DIW 100 loschen können. Hab das auch noch nie so gemacht, probiers doch mal aus.

Bei direktem Zugriff auf Instanzdaten gibts aber den unschönen Effekt, das bei Änderungen des FB (z.B. neuer Eingangsoperand) sich alle darauf folgenden Adressen verschieben...

Das sind dann die direkten Zugriffe auch alle falsch...
 
@ug

Richtig, man kann ebend nicht alles haben. :( Gibt ja vielleicht noch eine schönere Methode, kenne aber im Moment nichts anderes.

Ich mag Instanz-DB genau aus diesem Grund überhaupt nicht. Auch eine Fehlersuche in Multiinstanzen mit mehreren FB-Aufrufen (möglichst noch die gleichen FB) ist ein super Katastrophen-Szenario.
Man könnte natürlich die betreffenden Daten in einem extra DB ablegen, jeder Aufruf des FB bekommt noch zusätzlich diesen DB mit. In dem kann man dann ohne Angst vor Verschiebungen arbeiten.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Genau um das zu verhindern möchte ich es ja so machen...

Der DB100 ist nicht mein InstanzDB sondern ein Global DB der quasi ein Abbild der Struktur enthält.

Im FB selbst wird nur auf die in der Schnittstelle deklarierten Variablen zugegriffen. Diese Variablen werden von aussen beim Aufruf im OB versorgt.

Wenn an der Schnittstelle des FB was geändert wird so hat das keine Auswirkung aud den GlobalDB da im OB bei der Deklaration "nur" eine Lücke entsteht die dann wieder versorgt werden muss.

Auch möchte ich von anderen Bausteinen aus auf diese Daten zugreifen daher halte ich es für besser sie neutral zu speichern.

Bei Lese+Schreibzugriff sind das natürlich Durchgangsparameter.

Worauf ich also hinaus möchte ist wie ich den GlobalDB strukturiere.

Hier können z.B. sehr wohl Lücken mit Dummys belegt werden um später an einer bestimmten Stelle was einfügen zu können.

Zur besseren Übersicht habe ich schon Unterstrukturen erstellt aber immer bleibt das Problemchen übrig daß es keine Möglichkeit gibt eine "Gruppe" von Bits noch mal mit einer übergeordneten DWORD-Variable zu definieren --> ausser eben vielleicht mit einem Array - und das weiss ich nicht wie man eines erstellt das so aussieht:

Code:
+0.0 Array1 DWORD [adressiert von 0.0-3.7]
 +0.0 Bit0 BOOL
 +0.1 Bit1 BOOL
...
 +3.7 Bit32 BOOL
 
+4.0 Array2 DWORD [adressiert von 4.0-7.7]
 +4.0 Bit33 BOOL
...
 
Auch möchte ich von anderen Bausteinen aus auf diese Daten zugreifen daher halte ich es für besser sie neutral zu speichern.

Das ist IMHO ein vernünftiger Gedanke.


Worauf ich also hinaus möchte ist wie ich den GlobalDB strukturiere.

Knapp gesagt: gar nicht !
Welche Struktur sollte er denn haben ?
Die der FB ist doch unnötige Arbeit.

Setzt die Struktur des Global DB so, wie es für das Programmverständniss am sinnvollsten ist, eigendlich "frei Schnautze".

Wenn du deine Parameter über Globalen DB (oder auch Merkerbereich...) anbindest, dann hast du ja den Vorteil der "wilkürlichen" Variablenbelegung.

Du kannst z.B. einen DB-Bereich für einen Anlagenteil nehmen.

Lass etwas Reserve zwischendrinn, und die Sache passt.

Die Globalstruktur an die FB - Struktur anzupassen macht IMHO keinen Sinn!
Dann kann man den GlobalDB ja gleich weg lassen....
 
Ja, hast wohl recht...

Den GlobalDB erzeuge ich aus Excel heraus ziemlich komfortabel daher ist auch ruck zuck was geändert.

Auch kann ich eigentlich alles machen - ich habe mich vielleicht auch nur zu sehr an dem einen Detail aufgehalten den Zugriff auf die Einzelbits per Alias zu erledigen.

Jetzt steht halt im OB so was in der Art:

Code:
      CALL  "Hauptprogramm" , "DI_FB410_M1"
...
       PrgControl_1            :=DB611.DBD12
       PrgControl_2            :=DB611.DBD16
       Merker_NotAus           :="Merkerbits_M1".PrgControl_1.Merker_NotAus
       Merker_NormalAus        :="Merkerbits_M1".PrgControl_1.Merker_NormalAus
...

... und anstatt DB611.DBD12 wollte ich eben so was wie "Merkerbits_M1".PrgControl_1 da dran stehen haben.

Und ausserdem hätte mich eben generell interessiert ob das mit einem Array gegengen wäre...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... und anstatt DB611.DBD12 wollte ich eben so was wie "Merkerbits_M1".PrgControl_1 da dran stehen haben.

Und ausserdem hätte mich eben generell interessiert ob das mit einem Array gegengen wäre...

Die Symbolische Adresse kann nicht überlappen.
Da helfen leider auch Tricks mit Arrays oder structs nicht.

Vielleicht in einer der nächsten S7 - Versionen.
Ist nur ein S7Manager - Problem, hat mit dem eigendlichen Programm ja nichts zu tun.
 
schade...

hätte dann nämlich noch den Vorteil gehabt daß wenn im global DB was eingefügt wird die Zuordnung immer noch primär über den Alias anstatt der Adresse stattgefunden hätte...

Aber wie schon gesagt wurde es gibt halt keine Lösung die nur Vorteile bietet.

Wobei ich es hier wiederum ja gar nicht mit einem "echten" Nachteil zu tun habe da ja das was ich machen wollte in der anderen Variante auch nicht geht :)
 
Geht auch mit UDT nicht.
Ich meinte auch nur das hier:

...
Code:
      CALL  "Hauptprogramm" , "DI_FB410_M1"
...
       PrgControl_1            :=DB611.DBD12
       PrgControl_2            :=DB611.DBD16
       Merker_NotAus           :="Merkerbits_M1".PrgControl_1.Merker_NotAus
       Merker_NormalAus        :="Merkerbits_M1".PrgControl_1.Merker_NormalAus
...

... und anstatt DB611.DBD12 wollte ich eben so was wie "Merkerbits_M1".PrgControl_1 da dran stehen haben....
Mit dem "symbolischen Überlappen heht es nicht. Jedoch könnte man eventuell zum Überschreiben die SFC "Fill" verwenden.


Gruß, Onkel
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich meinte auch nur das hier:

Mit dem "symbolischen Überlappen heht es nicht. Jedoch könnte man eventuell zum Überschreiben die SFC "Fill" verwenden.


Gruß, Onkel

Aber der SFC "Fill" muß ich ja auch wieder sagen was sie "fillen" soll --> also DB611.DBD12 z.B. kommt ja dann aufs gleiche raus...
 
Aber der SFC "Fill" muß ich ja auch wieder sagen was sie "fillen" soll --> also DB611.DBD12 z.B. kommt ja dann aufs gleiche raus...
Verstehe ich nicht so ganz. Du kannst doch die Parameter symbolisch verwenden. So etwa:

Code:
//*** TESTARRAY ist IN-Parameter
      U     #TESTARRAY[1]
      =     A      0.0
      L     0
      T     #TEMP_BYTE
      CALL  SFC   21
       BVAL   :=#TEMP_BYTE
       RET_VAL:=#TEMP_INT
       BLK    :=#TESTARRAY
 
//*** TESTUDT ist IN-Parameter
      U     #TESTUDT.Bit_0
      =     A      0.0
      L     0
      T     #TEMP_BYTE
      CALL  SFC   21
       BVAL   :=#TEMP_BYTE
       RET_VAL:=#TEMP_INT
       BLK    :=#TESTUDT

Wahrscheinlich ist es aber ohnehin besser, du baust dein Programm vollkommen neu auf.


Gruß, Onkel
 
Verstehe ich nicht so ganz. Du kannst doch die Parameter symbolisch verwenden. So etwa:

Code:
//*** TESTARRAY ist IN-Parameter
      U     #TESTARRAY[1]
      =     A      0.0
      L     0
      T     #TEMP_BYTE
      CALL  SFC   21
       BVAL   :=#TEMP_BYTE
       RET_VAL:=#TEMP_INT
       BLK    :=#TESTARRAY
 
//*** TESTUDT ist IN-Parameter
      U     #TESTUDT.Bit_0
      =     A      0.0
      L     0
      T     #TEMP_BYTE
      CALL  SFC   21
       BVAL   :=#TEMP_BYTE
       RET_VAL:=#TEMP_INT
       BLK    :=#TESTUDT

Wahrscheinlich ist es aber ohnehin besser, du baust dein Programm vollkommen neu auf.


Gruß, Onkel

Das wäre aber doch etwas viel Aufwand für ein "bischen Symbolik" oder ?
 
Zurück
Oben