Wie kann man übersichtlich DBs im FB als IN aufrufen?

Jan

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

ich habe folgendes vor.

Ich habe einen FB und möchte in diesem FB öfters verschiedene Adressen von zwei verschiedenen DBs ansprechen.

Als Beispiel:


Schnittstelle:

IN: DB_CAQ_PLC // Datentyp: Block_DB
IN: DB_PLC_CAQ // Datentyp: Block_DB

Netzwerk 1: (in FUP)

U DB_CAQ_PLC [DBX0.0]
= DB_PLC_CAQ [DBX0.0]


Netzwerk 2: (in FUP)

L DB_CAQ_PLC [DBW2]
T DB_PLC_CAQ [DBW2]

Leider nimmt STEP7 diesen Befehl nicht an.
Ich habe leider in der STEP7-Hilfe nichts finden können.
Und hier in den FAQ ist mein spezieller Fall nicht beschrieben (jedenfalls habe ich nichts passendes gefunden).

Hat jemand einen Hinweis, wie ich so einen Befehl realisieren kann, oder einen Hinweis, wo in den FAQ ich die passende Erklärung finde?
 
STEP7 kennt keine "teilindirekten" DB-Zugriffe, das heißt, Du musst Dir ganz klassisch mit AUF [DB] helfen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Mit dem Datentyp "Block_DB" kannst du nicht auf DB-Elemente zugreifen.

Du könntest damit allenfalls den DB öffnen in alter S5-Manier und dann über Adresse auf DB-Elemente zugreifen.

z.B.

AUF DB_CAQ
U DBX0.0

Wenn du symbolisch bleiben willst, dann kannst du das z.B. über den Datentyp "STRUCT" machen. Dazu definierst du in deinem DB eine Struktur "STRUCT" und legst in den Eingangsdaten des FB´s ebenfalls solch eine Struktur an.
Das ganze hat aber denn Nachteil, dass du dabei die komplette Struktur quasi doppelt anlegst (1x im Global-DB und einmal im Instanz-DB des FB) - das bläht natürlich in gewisser Form das Programm auf.

Am elegantesten löst man sowas mit einem Any-Pointer.
Dabei wird die Datenstruktur des Global-DB´s dem FB per Any-Pointer mitgeteilt. Im FB hohlt man sich dann die Struktur des Global-DB´s und kopiert sich diese in den TEMP-Bereich.
Dann kann man im FB symbolisch weiter programmieren.

Den Any-Pointer musst du aber im FB mit etwas Code auflösen. Dazu findest du hier im Forum aber bestimmt ein paar Beispiele und Beschreibungen.
 
Aber man darf doch immer nur einen DB aufrufen, oder nicht?

Ich wage zu behaupten, dass dieser Befehl nicht funktionieren würde:

AUF DB_CAQ_PLC
AUF DB_PLC_CAQ

U DBX0.0
= DBX0.0

Wie kann ich denn meine Befehle in FUP schreiben?
In AWL wäre klar.

AUF DB_CAQ_PLC
U DBX0.0
AUF DB_PLC_CAQ
= DBX0.0

Aber das Programm sollte möglichst in FUP und Übersichtlich geschrieben werden.
 
@uncle-tom

Ich werde deinen Vorschlag mal ausprobieren.

Danke.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Mit dem Datentyp "Block_DB" kannst du nicht auf DB-Elemente zugreifen.

Du könntest damit allenfalls den DB öffnen in alter S5-Manier und dann über Adresse auf DB-Elemente zugreifen.

z.B.

AUF DB_CAQ
U DBX0.0

Wenn du symbolisch bleiben willst, dann kannst du das z.B. über den Datentyp "STRUCT" machen. Dazu definierst du in deinem DB eine Struktur "STRUCT" und legst in den Eingangsdaten des FB´s ebenfalls solch eine Struktur an.
Das ganze hat aber denn Nachteil, dass du dabei die komplette Struktur quasi doppelt anlegst (1x im Global-DB und einmal im Instanz-DB des FB) - das bläht natürlich in gewisser Form das Programm auf.

Am elegantesten löst man sowas mit einem Any-Pointer.
Dabei wird die Datenstruktur des Global-DB´s dem FB per Any-Pointer mitgeteilt. Im FB hohlt man sich dann die Struktur des Global-DB´s und kopiert sich diese in den TEMP-Bereich.
Dann kann man im FB symbolisch weiter programmieren.

Den Any-Pointer musst du aber im FB mit etwas Code auflösen. Dazu findest du hier im Forum aber bestimmt ein paar Beispiele und Beschreibungen.

Habe mir die Beschreibung in der FAQ angesehen.
Wenn ich das richtig sehe, muss ich für jeden Datenpunkt einen einzelnen Pointer bauen, was ich aber nicht möchte, weil wir hier von über 200 einzelnen Datenpunkten reden.
Da wird der Baustein extrem aufgebläht und unübersichtlich.
Gibt es eine Möglichkeit, nur einen Pointer für den DB zu machen, um die Adresse z.b. so anzusprechen?

U P#DB_POINTER [DBX0.0]
L P#DB_POINTER [DBW2]

Es wäre kein Problem, wenn ich die DB-Nummer in einem bestimmten Format an den FB schreiben müsste.
BLOCK-DB, INT, HEX, etc.

Ich möchte nur nicht einen Pointer für jede einzelne Variable erzeugen.
 
wie bereits oben erläutert.

Du bräuchtest 2 Any-Pointer für deine 2 Global-DB Bereiche. Diese beiden DB-Bereiche müsstest du dann auf TEMP-Bereiche des FB´s umkopieren und am Ende des FB´s wieder zurücksichern auf die Global-DB´s (z.B. mit BLKMOVE).

Es gibt auch noch die Möglichkeit mit 2 geöffneten DB´s zu arbeiten, indem man das DI-Register also quasi den Instanz-DB mit verwendet.
Wenn dir die Symbolik nicht so wichtig ist, wäre das vielleicht eine Möglichkeit.

z.B.

AUF DI[#DI_Nr]
L DIX0.0

Dabei müsstest du deine DB-Nummer aber direkt als INT übergeben - der Datentyp Block_DB geht hier natürlich nicht.

Weiterhin musst du aber zwingend vor solchen Operationen das Instanz-DB Register sichern und anschliessend wiederherstellen.

L DINO
T #SaveDINr

....

AUF DI[#SaveDINr]


Du kannst auch noch mit den beiden Adressregistern (AR1, AR2) zaubern.
Das AR2 musst du aber ebenfalls sichern und wiederherstellen - sonst gibt´s evtl. böse Überaschungen.
 
Ich habe eine ganz andere Idee.

Wie wäre es, wenn ich in dem FB Absolute Adressen verwende z.B. (DB511.DBX0.0) / (DB512.DBX0.0)

Wenn dann meine zu verwendende DB-Nummern anders sind; z.B. DB411 und DB412, dann kann ich doch einfach DB511 mit BLOCKMOVE in DB411 und DB412 mit BLOCKMOVE in DB 512 schieben und brauche meinen FB nicht zu ändern, sondern muss nur an den zwei BLOCKMOVES die entsprechende DB-Nummer ändern.

Somit könnte ich im FB in FUP übersichtlich direkt adressieren, weil ich keine Pointer benötige.

Dann fallen auch Fehlerquellen wie z.B. sichern des Registers weg.

Was hälst du von der Idee?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Es wäre hilfreich, wenn Deine Signale in der gleichen Reihenfolge wären, dann könntest Du die FB-Schnittstelle mit einem UDT aufrufen und extern als auch intern symbolisch arbeiten.
 
Es wäre hilfreich, wenn Deine Signale in der gleichen Reihenfolge wären, dann könntest Du die FB-Schnittstelle mit einem UDT aufrufen und extern als auch intern symbolisch arbeiten.

das hab ich ja oben schon beschrieben dass man mittels STRUCT oder eben einem UDT auch arbeiten kann. Dann hast du aber die doppelten Daten in der CPU (1x im Global-DB und einmal im Instanz-DB).

Was hälst du von der Idee ?

Nicht viel - da dies nicht besonders elegant gelöst ist. In einem mehrfach zu verwendenden FB sollte man keine absoluten Adressen bei globalen Variablen verwenden.
 
das hab ich ja oben schon beschrieben dass man mittels STRUCT oder eben einem UDT auch arbeiten kann. Dann hast du aber die doppelten Daten in der CPU (1x im Global-DB und einmal im Instanz-DB).



Nicht viel - da dies nicht besonders elegant gelöst ist. In einem mehrfach zu verwendenden FB sollte man keine absoluten Adressen bei globalen Variablen verwenden.

Da muss ich dir zustimmen. Das mag ich auch nicht, aber als Alternative so viel in AWL drumherum zu programmieren scheint mir den FB zu unübersichtlich zu machen, da ich ja so schon etwa 200 Signale händeln muss.
Der FB wird nicht mehrfach aufgerufen. Immer nur einmal pro CPU.

Ich denke, ich werde es erstmal so machen, weil auch etwas Zeitdruck dahinter steht.

Auf jeden Fall werde ich mir später die Vorschläge genauer ansehen um den FB zu verbessern.

Aber allen vielen Dank für die Tips.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
das hab ich ja oben schon beschrieben dass man mittels STRUCT oder eben einem UDT auch arbeiten kann. Dann hast du aber die doppelten Daten in der CPU (1x im Global-DB und einmal im Instanz-DB).

Hast Du Deinen Speicherplatz so eng bemessen um auf Komfort zu verzichten? Brauchst Du zwingend einen FB? Ansonsten nimm einen FC, der hat keine Instanzdaten! Wäre sinnvoll, wenn Du keine oder kaum Instanzdaten hättest!
 
Hast Du Deinen Speicherplatz so eng bemessen um auf Komfort zu verzichten? Brauchst Du zwingend einen FB?

Nehmen wir mal an, es gibt einen Softwarestandard mit Standardbausteinen. Hier gibt es dann z.B. FB´s für Antriebe, Analogeingänge, Regler, etc.
Jeder dieser Standard-FB´s hat eine zugehörige Schnittstelle, die mittels UDT in einem Global-DB zwecks Zugriff von HMI, PLS, etc. definiert ist.
Wenn jetzt diese Schnittstellen, den FB´s via UDT-Parameter übergeben werden, dann werden diese Schnittstellenvariablen, wie schon geschildert doppelt angelegt (Global-DB und Instanz-DB).
Bei einer grossen Anlage mit vielen Antrieben, Analogeingängen, Reglern, etc. gibt es dann natürlich auch jede Menge solcher Schnittstellen in Global-DB´s - da kommt dan schon ein bissel was zusammen.

Von daher ist es sinnvoller und effizienter, wenn man diese Schnittstellen bzw. Global-DB´s den FB´s als Any-Pointer übergibt, und dann mittels Any-Pointer im FB die Datenbereiche auf den TEMP-Bereich im FB um- und am Ende wieder zurückkopiert.

Das Auflösen der Any-Pointer ist zwar etwas "gefriemel" - wenn man sich das aber einmal zurecht gelegt hat, dann ist es immer wieder das gleiche.
 
Zurück
Oben