FC Move mittels Any-Pointer

Toki0604

Level-1
Beiträge
670
Reaktionspunkte
133
Zuviel Werbung?
-> Hier kostenlos registrieren
Guten Tag liebe "SPS-Gemeinde",

ich habe vor ein paar Wochen bei Siemens Lehrgänge zu S7/300 besucht und die Prüfung zum Programmierer abgelegt. Es gab jedoch eine Aufgabenstellung die ich bis heute nicht gelöst habe.(Prüfungsaufgabe, daher hilft Siemens nicht). Das läßt mich Nachts nicht schlafen ;).
Ich möchte auf keinen Fall eine fertige Lösung zu meinem Problem!
Ich benötige vielmehr eine Starthilfe um das Problem selbst zu lösen.

Thema indirekte Adressierung:
Es sollte ein FC erstellt werden, der "wiederverwendbar" programmiert ist.
Die Funktion ist kurz erklärt:
In-Parameter : Start ( Bool )
In-Parameter : Quelle ( Any-Pointer )
In/Out-Parameter : Ziel ( Any-Pointer )

Mit dem Start-Impuls sollte aus einem DB-Prozessdaten ein UDT mit einer Datenlänge von 4 Doppelworten in einen DB-Datensicherung geschrieben werden. ( Grundfunktion )
Wenn diese Funktion hergestellt wurde, sollte man die Programmierung und den DB-Datensicherung in soweit ändern, das es 10 Speicherplätze gibt und nach erreichen des letzten Speicherplatz von vorne überschrieben wird. ( erweiterte Funktion )

Problem meinerseits ist das mir bis jetzt jeder Gedankenansatz fehlt wie ich den Datenbereich innerhalb des FC´s von IN nach OUT bekomme.
Ausprobiert habe ich schon vieles, aber ich bekomme immer nur Fehlermeldungen im Simatic Manager das die benutzten Befehle in einem FC nicht gestattet sind etc.

Würde mich freuen wenn mir jemand "auf die Sprünge" helfen könnte.
Danke
Torsten
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi Daniel,
danke für deine schnelle Antwort.
Habe mir den Link angeschaut. Soweit so gut. Aber der Any-Pointer steht am IN-Parameter eines FC. Ich habe hier keine lokale Adressen die ich nutzen kann. Ich glaube genau hier ist mein Problem ( Gedankenblockade meinerseits?! ).

Gruß, Torsten
 
Hallo,
was Dalbi schreibt bezieht sich auf den IN-Parameter ANY schlecht hin.
Du kannst ihn nicht einfach zu dem FBC20 durchreichen - das geht nicht. Du mußt die Adresse, auf die er zeigt, in einem eigenen "LOKAL angelegten" ANY nachbilden und die dann an den SFC20 übergeben.
Das wird aber in dem Beitrag, den Dalbi dir verlinkt hat, auch dargestellt.
Ansonsten gibt es (speziell zu diesem Thema) hier im Forum noch viele andere Beiträge (Suchfunktion), die das auch noch behandeln ...

Gruß
Larry
 
Vielleicht hilft das folgende Programmbeispiel weiter:

In einem FC werden zwei ANY-Pointer (Quellbereich und Zielbereich) aus dem IN-Bereich in den TEMP-Bereich kopiert.

Anschließend wird ein SFC20 BLKMOV mit den beiden ANY-Pointer (Quellbereich und Zielbereich) aus dem TEMP-Bereich beschaltet.

Der SFC20 BLKMOV kopiert dann den Quellbereich (Eingangsbereich) in den Zielbereich (Datenbaustein).

Code:
UNCTION FC 100 : VOID
TITLE =ANY-Pointer
//14
AUTHOR : Kai
FAMILY : SPSForum
NAME : 'ANY'
VERSION : 1.0
VAR_INPUT
  IN_Quelle : ANY ; 
  IN_Ziel : ANY ; 
END_VAR
VAR_TEMP
  TEMP_DB_Register : WORD ; 
  TEMP_AR1_Register : DWORD ; 
  TEMP_AR2_Register : DWORD ; 
  TEMP_Quelle : ANY ; 
  TEMP_Ziel : ANY ; 
  TEMP_RET_VAL : INT ; 
END_VAR
BEGIN
NETWORK
TITLE =Register sichern
 
      L     DBNO; // DB-Register
      T     #TEMP_DB_Register; 
 
      TAR1  ; // AR1-Register
      T     #TEMP_AR1_Register; 
 
      TAR2  ; // AR2-Register
      T     #TEMP_AR2_Register; 
 
NETWORK
TITLE =Quelle (ANY-Pointer)
//Versorgung ANY-Pointer-Variable mit IN-Variable
//
//Adressierung AR1 im V-Stack
//
//L     P#IN_Quelle
//LAR1
//
//L     B [AR1,P#0.0]
//
//Versorgung ANY-Pointer-Variable mit TEMP-Variable
//
//Adressierung AR2 im L-Stack 
//
//L     P#TEMP_Quelle
//LAR2
//
//T     LB [AR2,P#0.0]
//   
      L     P##IN_Quelle; // Quelle (ANY-Pointer)
      LAR1  ; 
 
      L     P##TEMP_Quelle; // Quelle (ANY-Pointer)
      LAR2  ; 
 
      L     B [AR1,P#0.0]; // Syntax-ID
      T     LB [AR2,P#0.0]; 
 
      L     B [AR1,P#1.0]; // Datentyp
      T     LB [AR2,P#1.0]; 
 
      L     W [AR1,P#2.0]; // Anzahl
      T     LW [AR2,P#2.0]; 
 
      L     W [AR1,P#4.0]; // DB-Nummer
      T     LW [AR2,P#4.0]; 
 
      L     D [AR1,P#6.0]; // Bereichszeiger
      T     LD [AR2,P#6.0]; 
 
NETWORK
TITLE =Ziel (ANY-Pointer)
//Versorgung ANY-Pointer-Variable mit IN-Variable
//
//Adressierung AR1 im V-Stack
//
//L     P#IN_Ziel
//LAR1
//
//L     B [AR1,P#0.0]
//
//Versorgung ANY-Pointer-Variable mit TEMP-Variable
//
//Adressierung AR2 im L-Stack
//
//L     P#TEMP_Ziel
//LAR2
//
//T     LB [AR2,P#0.0]
//   
      L     P##IN_Ziel; // Ziel (ANY-Pointer)
      LAR1  ; 
 
      L     P##TEMP_Ziel; // Ziel (ANY-Pointer)
      LAR2  ; 
 
      L     B [AR1,P#0.0]; // Syntax-ID
      T     LB [AR2,P#0.0]; 
 
      L     B [AR1,P#1.0]; // Datentyp
      T     LB [AR2,P#1.0]; 
 
      L     W [AR1,P#2.0]; // Anzahl
      T     LW [AR2,P#2.0]; 
 
      L     W [AR1,P#4.0]; // DB-Nummer
      T     LW [AR2,P#4.0]; 
 
      L     D [AR1,P#6.0]; // Bereichszeiger
      T     LD [AR2,P#6.0]; 
 
NETWORK
TITLE =Quelle (ANY-Pointer) nach Ziel (ANY-Pointer) kopieren
 
      CALL SFC   20 (
           SRCBLK                   := #TEMP_Quelle,
           RET_VAL                  := #TEMP_RET_VAL,
           DSTBLK                   := #TEMP_Ziel);
      NOP   0; 
 
NETWORK
TITLE =Register wiederherstellen
 
      AUF   DB [#TEMP_DB_Register]; // DB-Register
 
      L     #TEMP_AR1_Register; // AR1-Register
      LAR1  ; 
 
      L     #TEMP_AR2_Register; // AR2-Register
      LAR2  ; 
 
END_FUNCTION

Gruß Kai
 

Anhänge

  • OB1.pdf
    5,6 KB · Aufrufe: 93
  • FC100.pdf
    8,3 KB · Aufrufe: 122
  • DB10.pdf
    4,8 KB · Aufrufe: 65
  • Any-poin.zip
    33,2 KB · Aufrufe: 81
Zuviel Werbung?
-> Hier kostenlos registrieren
Und noch ein paar Bilder aus der Simulation mit PLCSIM.

Gruß Kai
 

Anhänge

  • VAT.jpg
    VAT.jpg
    227,2 KB · Aufrufe: 104
  • ONLINE_1.jpg
    ONLINE_1.jpg
    353,5 KB · Aufrufe: 121
  • ONLINE_2.jpg
    ONLINE_2.jpg
    373 KB · Aufrufe: 89
  • ONLINE_3.jpg
    ONLINE_3.jpg
    377,6 KB · Aufrufe: 72
  • ONLINE_4.jpg
    ONLINE_4.jpg
    343,1 KB · Aufrufe: 72
Erstes Ziel erreicht - Grundfunktion steht

Mit bestem Dank an Dalbi, Larry und Kai !
Das Einlesen und Schreiben funktioniert. Nun gehe ich an die erweiterte Funktion die Ziel-Speicherplätze dynamisch zu gestalten.
Dazu denke ich muss ich nur entsprechend einen Offset an den Zielspeicherort anhängen. :D Werde ich jetzt mal ausprobieren.

Gruß
Torsten
 

Anhänge

  • FC32.pdf
    6,2 KB · Aufrufe: 65
Erweiterte Funktion läuft auch

Hi,
habe meinen Offset auch ans laufen gebracht. (Schwitz ) :s11:
Schaut ihr vielleicht mal ob das OK ist, oder es ggf. eine elegantere Lösung gibt !? Habe es als PDF angehängt, weil Quellcode ist glaub ich zu viel.
Danke, Gruß
Torsten
 

Anhänge

  • FC32.pdf
    7 KB · Aufrufe: 106
Zuviel Werbung?
-> Hier kostenlos registrieren
Aufruf des FC mit Temp-Daten

Hallo Leute,

ich habe dieses Beispiel von Kai ausprobiert.
Klappt gut. Warum kann ich aber keine Lokaldaten als Destination angeben:

Code:
Call "Any"
IN_Quelle:=P#DB100.DBX0.0 Byte 10
IN_Ziel:=P#L 0.0 BYTE 10

Gruß,
Aksels
 
Hallo Aksels,

Du kannst mit dem Any-Pionter auf Lokal-Variablen des aktuellen und auf die L-Variablen vorhergehenden
Bausteins zugreifen. D.h. Du könntest im Baustein "Any" auf die L-Variablen des aufrufenden Bausteins
zugreifen. Der SFC 20 kann nur auf seine und die des "Any" zugreifen.
Auf die L-Variablen des vor-vorhergehenden Bausteins kann man nicht zugreifen.

Grüße
Gebs
 
Hallo, ich habe den FC32 nun so nachprogrammiert.

Bei mir verhält er sich aber nicht ganz richtig, weil der Offset nicht richtig berechnet wird:

ich habe 4 DBD und das 10 mal im SicherungsDB
wenn ich den FC nochmal aufrufe, dann erhöht er zwer den Offset aber nur um ein DW und nicht um 4 DW, ich habe haltepunkte gesetzt, und die akkus kontrolliert.

L P##Ziel
LAR1

L W [AR1,P#2.0]
T #Datenlaenge
L W [AR1,P#4.0]
T #Ziel_DBNr

AUF DB [#Ziel_DBNr]

L DBW 2
L DBW 0
>=I
SPBN weit
L 0
T DBW 2

weit: L #Datenlaenge
L DBW 2
*I
SLW 3
T #Offset

L DBW 2
L 1
+I
T DBW 2

L DBW 2


intressanterweise ist bei L #Datenlaenge der Akkuwert auf 10 (das ist die maximale anzahl an sicherungen), dieser wird doch vor der Sprungmarke gelesen, um zu checken, ob die DB voll ist. es ist egal ob ich #datenlaenge oder dbw 2 einlese an der stelle. Gibt es für dieses Phänomen eine Erklärung?

wenn ich das Ganze mal 4 mache (4 Bytes ist ein DW) dann gehts einwandfrei.

und dann hab ich noch eine zweite Frage:

Für was werden die Register (DB,AR1,AR2) in NW 1 und 6 gesichert bzw wiederhergestellt? hat das was mit dem Bausen auf sich, der den FC aufgerufen hat?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo dkaserer!

Wie rufst Du den FC 32 auf? Stell doch mal den Aufruf hier rein.

Für was werden die Register (DB,AR1,AR2) in NW 1 und 6 gesichert bzw wiederhergestellt? hat das was mit dem Bausen auf sich, der den FC aufgerufen hat?

=> Such mal nach Multiinstanz.

Grüße
Gebs
 
Bei mir heist er FC10, ist aber egal

CALL FC 10
Start :=M4.0
Quelle :=P#DB110.DBX 16.0 DWORD 4
RET_VAL:=LW40
Ziel :=P#DB120.DBX 4.0 DWORD 4
 
Hallo dkaserer!

Da haben wir doch schon das Problem!!!

Der Baustein von Toki ist so programmiert, dass er den Offset in
Bytes berechnet.
Entweder programmierst Du die Berechnung des Offsets um, oder Du
gibst beim Aufruf die Länge in Bytes an.

Grüße
Gebs
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke Gebs, also noch mal zum Verständnis

wenn ich einen ANY Zeiger übergebe, dann ist der Wiederholungsfaktor in BYTE angegeben, ganz egal welcher Datentyp das ist?

dann müsste man sich den Wiederholungsfaktor anhand des Datentyps ausrechnen.
 
Hallo dkaserer,

wenn ich einen ANY Zeiger übergebe, dann ist der Wiederholungsfaktor in BYTE angegeben, ganz egal welcher Datentyp das ist?
Nein, der Wiederholungsfaktor bezieht sich auf das Datenformat.
4 DBD = 8 DBW = 16 DBB

dann müsste man sich den Wiederholungsfaktor anhand des Datentyps ausrechnen.
Du musst Dir hier Dein Offset anhand Wiederholungsfaktor und Datentyp ausrechnen.
Wie Du den Datentyp aus einem ANY auslesen kannst steht hier:
http://www.sps-forum.de/showthread.php?t=12923

Grüße
Gebs


Grüße
Gebs
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo dkaserer,

da Wiederholungsfaktor/Datenformat etc. schon so schön erläutert wurden, möchte ich noch kurz auf deine Frage bezüglich der Sicherung der Register eingehen.
Das ist keine Erfindung von mir, sondern ich habe mir das von 4Lagig (glaube ich) damals abgeschaut und mir zu eigen gemacht.
Es geht darum das dieser Baustein in mitten anderer Codes aufgerufen werden kann.
Falls diese Codes sich darauf verlassen was vor dem Aufruf dieses Bausteins in den Registern steht (stehen müsste), könnte es ungewollt Fehlfunktionen in der Programmierung geben.
Um dem grundsätzlich vorzubeugen, ob notwendig oder nicht, wird der Zustand der Register nach Aufruf des Bausteins in den Ursprungszustand zurückversetzt.
Es soll angeblich Firmen geben die darauf sogar bestehen ?!
Ich hatte selbst noch keine Anwendung bei der dies zum Tragen kam, aber ich finde es immer gut wenn etwas verlassen wird wie es vorgefunden wurde ;-)

Gruß
Toki
 
Zurück
Oben