Verständnisproblem bei DB aufruf im FC

S7online

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

Bin gerade am Basteln eines FC´s welcher Werte aus einem DB lesen soll.
Dabei soll die Datenbausteinnummer über die In-Schnittstelle übermittelt werden.

FC 1

In: #DB_Nummer INT

Code:
AUF DB [#DB_Nummer]
...
Bringt mir die Meldung: "Keine indirekten Operationen erlaubt für FC-Parameter DB_Nummer!

Lege ich in der Temp-Schnittstelle noch einen Parameter:

Temp: #DB_NummerW INT
an und verwende Ihn folgendermaßen:

Code:
L #DB_Nummer
T #DB_NummerW
AUF DB [#DB_NummerW]
...
Dann funktioniert´s.

Könnte mir da bitte jemand mal kurz erklären aus welchem Grund die erste Variante nicht funktioniert??
Steh da seid guten 3 Stunden im Wald und seh nur Bäume..

Ich danke schonmal!
 
Da ein parameter und lOkaldaten für eine s7 grundverschiedene dinge sind, aber im awl code halt gleich aussehen! Und es eben keinen mc7 code für öffne db indirekt über parameter gibt
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Auszug aus der Hilfe...

· Der Pointer muß für die speicherindirekte Adressierung in einem der folgenden Bereiche gespeichert werden:
· M - Merker
· L - Lokaldaten
· D - Datenbaustein (DB oder DI)
· STAT - Statische Daten (nicht bei multiinstanzfähigen Bausteinen)
 
Speicherindirekte Adressierung mit "Pointer im Wortformat" = Index geht nur mit Index in L, M, D oder STAT - also NICHT mit Index als IN-Parameter.
(siehe Step7-Hilfe)

Einen DB indirekt öffnen sollte man besser so machen:
In: #DB_Nummer BLOCK_DB
Code:
      AUF   #DB_Nummer
dann erscheint Deine indirekte Verwendung von DB wenigstens in den Referenzdaten.

Harald
 
:D

Danke, ich glaub ich hab´s verstanden.

Der In-Wert (#DB_Nummer) ist in diesem Fall ein Pointer der auf den Wert Zeigt, welchen ich in der Außenbeschaltung anlege.

Richtig??

Dann ist mir klar daß dann die Fehlermeldung kommt.

Grüße!
 
Nee ... ist so nicht richtig.
Alle Variablen bis DWORD-Breite werden immer byValue übergeben und nicht byReference.
Es ist (oder muss schon so sein) wie oben beschrieben ...

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Besser als die Variante wäre imho sowieso der IN-Parameter als Block_DB,
damit findet man diese Art des DB Zugriffs, wenigstens bis zum Aufruf des FC, FB, in den Referenzdaten.

Edith sagt:
PN/DP war "schneller"

Mfg
Manuel
 
Zuletzt bearbeitet:
Alle Variablen bis DWORD-Breite werden immer byValue übergeben und nicht byReference.

Schön wär's. Das gilt nur für elementare Datentypen. Jeder UDT wird "by reference" übergeben.

Außerdem wird in (fast) jedem Fall intern ein weiteres Pointer-Level dazwischengeschaltet. Diese Pointer stehen mitten im Code vor dem Call und zeigen auf die eigentlichen Daten; bei INOUT-, OUT- und UDT-Parametern wieder ein Pointer. Diese letztgenannten Pointer, Konstanten und vermutlich anderes werden vermutlich irgendwo in den Lokaldaten angelegt.

Das erklärt, warum FC-Calls mit Parametern so extrem viel Rechenzeit und Speicherplatz brauchen; ebenso die Zugriffe im FC auf die Parameter.

Nur bei BLOCK_DB-Übergaben und ähnlichem wird der DB selbst im Code abgelegt. Deshalb muss er beim Aufruf konstant sein. Wenn er nicht konstant ist, muss man wieder auf INT ausweichen, womit sich der Kreis zur ürsprünglichen Frage schließt. ;)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi!

Kann mir jemand verraten, wie ich in einem FB auf Daten von einem Global-DB zugreifen kann? (Die DB-Nummer ist variabel und wird dem FB via INT übergeben)

Meine Vorstellung ala:
Code:
U DB[#IN_int].DBX174.7
R DB[#IN_int].DBX200.7
funktioniert ja leider nicht :-(

Könnte sich jemand meiner erbarmen? :roll:

lG
Michael
 
Code:
L    #IN_int
T    #IN_int_TMP     //Muss Temp oder Merker sein


AUF  DB[#IN_int_TMP]
     U DBX174.7
     R DBX200.7
Solch ein symbolloses Addressgestochere wird halt schnell undurchsichtig.
 
Erstmal Danke!

Muss ich den Befehl "AUF DB" jedes mal vor einem Zugriff durchführen, oder bleibt der DB während des ganzen FB Zyklus erhalten, bis auf Widerruf durch ein erneutes "AUF" mit anderer DB-Nr?


Wenn ich die Symbole erhalten will, muss ich wohl den ganzen Global-DB in der Instanz nachbauen und dann den DB am Ende des FB abgleichen, oder?

lG
Michael
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Muss ich den Befehl "AUF DB" jedes mal vor einem Zugriff durchführen, oder bleibt der DB während des ganzen FB Zyklus erhalten, bis auf Widerruf durch ein erneutes "AUF" mit anderer DB-Nr?
Solange bis du entweder ein AUF mit einem anderen DB oder einen gewöhnlichen Zugriff auf einen anderen DB machst.

Wenn ich die Symbole erhalten will, muss ich wohl den ganzen Global-DB in der Instanz nachbauen und dann den DB am Ende des FB abgleichen, oder?
Das hängt stark von deiner Datenstruktur ab wie man soetwas am besten umsetzen kann. Hängt davon ab was deine Daten im DB darstellen. Sind die in irgendwelchen Strukturen oder UDT abgelegt sodass man eventuell eine ganze Struktur an den FB übergeben kann? Was verbirgt sich den hinter den Adressen? Welche Funktion erfüllt das gezeigte Rücksetzen?
 
Zuletzt bearbeitet:
hmm.. Wie sieht dann ein Befehl aus, wenn ich einen anderen DB dazwischen habe?

Code:
      U     DB50.DBX    5.4
      U     #Enable_Servo
[B]  AUF   DB [#TEMP_DB][/B]
      UN    DBX  172.3
      U     DBX  213.1
      UN    DB50.DBX    5.3
      UN    DB50.DBX    4.7
 [B] AUF   DB [#TEMP_DB][/B]
      S     DBX  174.7

      U     DB50.DBX    5.3
      U     DB50.DBX    4.7
 [B] AUF   DB [#TEMP_DB][/B]
      R     DBX  174.7

bzw aufgeräumter:

Code:
      U     DB50.DBX    5.4
      UN    DB50.DBX    5.3
      UN    DB50.DBX    4.7
      U     #Enable_Servo
[B]  AUF   DB [#TEMP_DB][/B]
      UN    DBX  172.3
      U     DBX  213.1
      S     DBX  174.7

      U     DB50.DBX    5.3
      U     DB50.DBX    4.7
 [B] AUF   DB [#TEMP_DB][/B]
      R     DBX  174.7

So?

Oder muss ich temporäere Variablen verwenden und darf "AUF" nur am Anfang einer Anweisung verwenden?


Code:
[B]  AUF   DB [#TEMP_DB][/B]
      UN    DBX  172.3
      U     DBX  213.1
      U     DB50.DBX    5.4
      UN    DB50.DBX    5.3
      UN    DB50.DBX    4.7
      U     #Enable_Servo
      S     [B] #temp_var[/B]

      U     DB50.DBX    5.3
      U     DB50.DBX    4.7
[B]      R     #temp_var[/B]

 [B] AUF   DB [#TEMP_DB]
      U    #temp_var[/B]
      =    DBX  174.7

Das hängt stark von deiner Datenstruktur ab wie man soetwas am besten umsetzen kann. Hängt davon ab was deine Daten im DB darstellen. Sind die in irgendwelchen Strukturen oder UDTS abgelegt sodass man eventuell eine ganze Struktur an den FB übergeben kann? Was verbirgt sich den hinter den Adressen? Welche Funktion erfüllt das gezeigte Rücksetzen?

Der entsprechende DB wird aus UDTs generiert, stimmt.
Es geht um den FB283 (SINA_FB), welcher mir einen DB mit UDT30000 (Basis) und UDT30010 (UDT_TVB+MDI_TLG110) erzeugt. Mich interessiert nur der UDT30010, welcher bei 162.0 anfängt und 90 Byte hat. (Sollte ich also mit Pointer hineinmappen, oder?)
(Am liebsten wäre es mir, wenn ich den Global-DB weglassen könnte und direkt in den Instanz-DB integriere, aber das ist ja unsauber und unleselich...)


Der erste Code-Auszug war nur ein Beispiel. Im Code-Auszug dieses Beitrags geht es darum den MDI-Modus je nach Rahmenbedingung zu aktivieren (Referenziert, Enable, kein Manuell-Betrieb, ...) oder deaktivieren (Manuell-Betrieb).


Zum Background:
Ich schreibe gerade einen FB, der mir die Ansteuerung einer Sinamics-Achse vereinfachen soll. Desweiteren soll das anfügen einer neuen Achse vereinfacht werden und die generelle Ansteuerung über mehrere Projekte (unterschiedliche Maschinentypen) vereinheitlichen.


Nachtrag:

Ich lass das jetzt mal mit dem "AUF DB" und übertrage den entsprechenden UDT mit SFC 20.

Code:
//Zuerst kopiere ich den WR_PZD und RD_PZD um, damit ich die Pointer auch lesend verwenden kann
      L     P##WR_PZD                   // WR_PZD ist IN- Variable vom Typ ANY
      LAR1                              //AR1 zeigt nun auf die Anfangsadr. der Eingangsvariable
      L     P##WR_PZD_temp              // --> source = temporäre Variable vom Typ ANY
      T     #p_tmp1                     // p_tmp1 (DWORD) ist ein Zeiger auf source

// copy in-parameter ANY to tmp ANY
      L     D [AR1,P#0.0]
      T     LD [#p_tmp1]                //Byte 0 bis Byte 3 des ANY kopieren
      L     #p_tmp1
      +     32
      T     #p_tmp1                     // zeiger auf temp. ANY um 4 Byte weiterstellen
      L     D [AR1,P#4.0]
      T     LD [#p_tmp1]                // Byte 4 bis Byte 7 des ANY kopieren
      L     #p_tmp1
      +     32
      T     #p_tmp1                     // zeiger auf temporären ANY um 4 Byte weiterstellen
      L     W [AR1,P#8.0]
      T     LW [#p_tmp1]                // Byte8 bis Byte10 des ANY kopieren

[B]//Habe ich aus einer Siemens Hilfe kopiert und abgeleitet, ist das so richtig?[/B]


      CALL  SFC   20
       SRCBLK :=#WR_PZD_temp                   //Pointer auf DB Adresse mit Bereich
       RET_VAL:=#SFC_int1
       DSTBLK :=#Achse.RD_PZD_POSBETR    //UDT im Static Bereich meines FB

      CALL  SFC   20
       SRCBLK :=#RD_PZD_temp                    //Pointer auf DB Adresse mit Bereich
       RET_VAL:=#SFC_int2
       DSTBLK :=#Achse.WR_PZD_POSBETR    //UDT im Static Bereich meines FB

.
.
.
Bearbeitung
.
.
.
//Am Ende des Bausteins übertrage ich den WRITE Bereich des UDT wieder in den Global-DB

      CALL  SFC   20
       SRCBLK :=#WR_PZD_temp                    //Pointer auf DB Adresse mit Bereich
       RET_VAL:=#SFC_int2
       DSTBLK :=#Achse.WR_PZD_POSBETR    //UDT im Static Bereich meines FB
 
Zuletzt bearbeitet:
Code:
      U     DB50.DBX    5.4
      UN    DB50.DBX    5.3
      UN    DB50.DBX    4.7
      U     #Enable_Servo
[B]  AUF   DB [#TEMP_DB][/B]
      UN    DBX  172.3
      U     DBX  213.1
      S     DBX  174.7

      U     DB50.DBX    5.3
      U     DB50.DBX    4.7
 [B] AUF   DB [#TEMP_DB][/B]
      R     DBX  174.7
So?
Ja, genau so. Dementsprechend ist das mischen von AUF und "starren Global-DB-Zugriffen" schwierig.
Wenn du aber was wiederverwendbares baust, dann haben solche Global-DB-Zugriffe (U DBxx.DBXyyy) da eh weniger was verloren.
Was steckt denn hinter deinem DB50?

Am liebsten wäre es mir, wenn ich den Global-DB weglassen könnte und direkt in den Instanz-DB integriere, aber das ist ja unsauber und unleselich...
Was wäre daran so schlimm?
Wenn du den SINA-FB (kenn den jetzt nicht genau) und dessen Daten ansteuern willst, dann könntest du den ja als Multiinstanz in einen FB-packen und dir eine passende Schnittstelle nach außen bauen.
Sonst könntest du den jeweiligen UDT auch über die Schnittstelle übergeben, also die Daten als Kopie in den FB/FC übernehmen um am Ende rückschreiben.
Tipps sind natürlich schwierig ohne wirklichen Einblick wie es funktionieren soll. Aber das oben gezeigte ist halt alles andere als ideal.
 
Zurück
Oben