TIA S7-1500 SCL Any Pointer auf UDT zuweisen

kamikaaze

Level-1
Beiträge
11
Reaktionspunkte
2
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

folgendes Problem:

Aus einem S7-300 Projekt muss ich Bausteine für die nutzung in einer S7-1500 umwandeln.
In den alten Bausteinen wird ein UDT als INPUT Parameter an eine Funktion übergeben. Innerhalb der Funktion wird ein Any Pointer auf diese Struktur erzeugt, und der Pointer in einem DB gesichert.
Ein anderer Baustein lädt diesen Pointer und beschreibt den Speicherbereich mit gültigen Daten. Das ganze funktioniert auch schon so, wie ich mir das vorstelle.

Allerdings nicht mehr, wenn ich versuche den SCL Code für eine S7-1500 zu kompilieren.

Als beispiel hier mal folgender Baustein auf der S7-300:

Code:
FUNCTION FC100 : VOID

VAR_INPUT
    SESSION : tHSC_Session;
END_VAR

VAR_TEMP
    pSession : ANY;
END_VAR

    pSession := SESSION;
    
END_FUNCTION


und hier der leicht abgewandelte Code für die S7-1500:

Code:
FUNCTION "Test" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
   VAR_INPUT 
      SESSION : "tHSC_Session";
   END_VAR

   VAR_TEMP 
      pSession : Any;
   END_VAR


BEGIN
    #pSession := #SESSION;
END_FUNCTION

Als Fehlermeldung erhalte ich hier aber:
"Ungültige Zusweisung"

Wo liegt bei mir jetzt der Denkfehler, bzw. wie kann ich in SCL auf einer S7-1500 einen Any Pointer auf eine Struktur erzeugen, welche als Input Parameter übergeben wird?


Vielen Dank schonmal im Vorraus
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ok. Ich versuche mal etwas mehr zu erklären.

Im Anhang ein Beispiel, wie die Funktionen im Programm aufgerufen werden.

Am Ersten Baustein (FC1101) wird der UDT übergeben. Dieser wird vom Baustein in einem temporären DB gesichert (hier nicht zu sehen). Anschließend wird mit beliebig vielen funktionen diese "Session" erweitert und mit dem letzten Baustein (FC1109) wieder zurück auf den UDT kopiert.
Ich brauche den Pointer also, damit ich nicht am letzten Baustein wieder die Session angeben muss (Weniger Aufwand / Fehler / Arbeit bei Inbetriebnahme der Funktionen bzw. Änderung ;-) )

Falls es dafür aber eine noch sauberere / einfachere Lösung gibt, bin ich für vorschläge offen.

HSC.png
 
Ich brauche den Pointer also, damit ich nicht am letzten Baustein wieder die Session angeben muss (Weniger Aufwand / Fehler / Arbeit bei Inbetriebnahme der Funktionen bzw. Änderung ;-) )
Wo gibst Du denn am letzten Baustein "den Pointer" bzw. die "Session" an? Woher weiß der FC1109, wohin er den temporären UDT zurück-kopieren muß?
Deine gekürzte Bausteinerklärung sieht mir irgendwie noch relativ verworren aus. Vielleicht läßt Du uns mehr Details sehen.

Um den UDT von Input in eine Arbeitskopie zu kopieren braucht man keinen ANY erzeugen, da kümmert sich SCL bei Bedarf selber drum:
Code:
  "MyTempDB".Arbeitskopie := #SESSION;

Wie groß ist der UDT? Der wird ja mindestens 4 mal kopiert. Man könnte argumentieren, daß er an IN_OUT passender wäre, zumal er ja tatsächlich auch beschrieben wird.

Harald
 
Wohin der temporäre UDT kopiert werden muss, weiß ich dann ja über den ANY Pointer, den ich mir im ersten Baustein erzeugt und gesichert habe ;-)
Das ich die Daten mit dem Obigen Befehl umkopieren kann ist mir auch klar, auch wenn ich dazu den SFC20 - BLKMOV nutze, da der etwas schneller arbeitet.

Im Anhang mal die Struktur der Temporären Daten.

Im ersten Baustein werden wird die Session zwischengespeichert (Offset +0.0), sowie der Pointer auf den ursprünglichen UDT (Offset +2312.0).
Der letzte Baustein (FC1109) lädt sich dann wieder den ANY Pointer aus den Temporären Daten, und kopiert mittels SFC20 - BLKMOV die Daten zurück auf den originalen UDT.

Das ganze funktioniert ja auch schon wunderbar auf einer 300-er CPU. Allerdings lässt sich der Any Pointer auf einer 1500-er nicht erzeugen.

temp.png
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Gibt es den SFC20 überhaupt auf der S7-1500? Funktioniert der ggf. auch mit '"optimierten" DB? Wieso nimmst Du an, daß ein von Dir erzwungener BLKMOV schneller arbeitet als ein vom SCL-Compiler automatisch erzeugtes Kopieren?


(A) Du könntest Deine Bausteinaufrufe umstellen und in einen "Session-Bearbeiten"-FC/FB einbetten (statt dem FC1101) und aus diesem Baustein auch das zurückkopieren ausführen. Dann braucht man sich die Adresse des übergebenen UDT #SESSION nicht merken.

Inhalt des "Session-Bearbeiten"-FC/FB:
- kopieren von #SESSION in globale Arbeitskopie
- Aufruf FC1102
- Aufruf FC1107
- zurückkopieren von globaler Arbeitskopie zu #SESSION


(B) Deine "Sessions" kommen immer aus einem Array? Du könntest alternativ statt der Adresse den Array-Index übergeben.

Harald
 
Danke für die Vorschläge. Nochmal zur ursprünglichen Frage, die vielleicht nicht ganz gut rüber kam:
Ich nehme mal an, dass die urpsrüngliche Idee also auf einer 1500-er nicht mehr funktioniert, warum auch immer?!? Bzw. warum erlaubt er mir das erstellen des ANY Pointer nicht?

Die ganze Sache wird, vermutlich nicht auf diesen "optimierten DBS" funktionieren, aber damit habe ich mich noch nicht genug mit beschäftigt... Sollte ich vielleicht mal nachholen ;-)


Die Idee mit den Arrays und angabe eines index hatte ich auch ganz am Anfang habe ich aber wieder verworfen aus mehreren Gründen.
1. Die Anzahl der Einträge des Arrays ist nicht immer gleich, somit muss ich das Array als Any Pointer übergeben -> Keine / Beschränkte Typsicherheit. (OK Kann man argumentieren, dass der Programmierer wissen sollte was er tut :-D )
2. Es kann mehrere Arrays mit Variabler Anzahl an Einträgen geben. Eins im DB1 eins im DB2 etc.
3. Ich muss überprüfen, ob der Index außerhalb des Array liegt. Dazu brauche ich wieder einen Any Pointer auf den UDT, um die Länge zu bestimmen. Zumindest bei einer 300-er.

Zu den Kopierzeiten:
Die habe ich gemessen, und wenn ich alles richtig gemacht habe, dann war der unterschiedlich deutlich spürbar in der Zykluszeit ~5-10 mal schneller. Beim kopieren, ohne SCL wird entweder eine Schleife erstellt, bzw. ein L;T Befehl nach dem anderen. SFC20 ist da deutlich schneller unterwegs. auch wenn man in die CPU Manual schaut, und die Zeiten grob hochrechnet. Ob dies noch bei 1500-er gilt, habe ich nicht überprüft!
Ausserdem kann ich mit der aktuellen funktionalität über den ANY Pointer sowieso nur mit SFC20 arbeiten, da SCL dummerweise kein dereferenzieren von Pointern unterstützt :-x

Zu Vorschlag A:
Bei deinem Vorschlag müsste ich den "Session-Bearbeiten"-FC mehrfach aufrufen? Das möchte ich ja nicht, da ich ihn dann ja auch mehrfach mit dem UDT beschalten muss. Das möchte ich nur an einer stelle machen, um fehler zu vermeiden. Ansonsten könnte ich es ja auch an den letzten Baustein schreiben.


Sry, falls ich zu hohe Ansprüche haben sollte :-D
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn die datenstruktur bleibt, kann man die Arraygröße doch an der Schnittstelle mitgeben?Kraatz?
Die Größe der Datenstruktur steht ja vorher fest.Die wird ja nicht zur Laufzeit erzeugt.
Das mit der Schnelligkeit kann stimmen.Wobei der SFC20 ja auch in SCL benutzt werden kann.

Aber vielleicht sind deine Ansprüche wirklich zu hoch für mich!:ROFLMAO:
 
Ja, man kann die größe an der Schnittstelle mitgeben, aber dann komme ich auch nur vom Regen in die Traufe:
- Der Programmierer (Ich :-D ), kann wieder falsche werte angeben
- Ich Programmiere nicht mehr zu 100% symolisch. Sprich wenn ich den UDT der Session ändere, also die größe, dann MUSS ich daran denken, die neue größe an allen stellen anzugeben, und kann nicht einfach die Bausteinkonsistenz prüfen, und der Rest im Programm passt sich einfach automatisch an. Das geht bis jetzt nämlich wunderbar ;-)

Ok, man kann dafür auch einen SIZEOF Baustein programmieren, aber das möchte ich wieder nicht, und hilft ja auch nicht gegen mein eigentliches Problem.
 
Zu Vorschlag A:
Bei deinem Vorschlag müsste ich den "Session-Bearbeiten"-FC mehrfach aufrufen?
Nein, nicht mehrfach aufrufen, sondern einen Baustein als "Wrapper" um die FC-Aufrufe legen und das Kopieren von #SESSION zur Arbeitskopie und zurück zu #SESSION im selben Baustein, und dazwischen die *_Add_*-Bausteine aufrufen:
Code:
FUNCTION FCxxx : VOID

VAR_IN_OUT
  SESSION : tHSC_Session;
END_VAR

  "MyTempDB".Arbeitskopie := SESSION; //Session-Start

  HSC_Session_Add_Any(...);
  HSC_Session_Add_Bool(...);

  SESSION := "MyTempDB".Arbeitskopie; //Session-End

END_FUNCTION
(classic SCL)

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ok. Habs jetzt verstanden :)

Nicht böse sein, wenn ich das so nicht umsetzen will, da ich mit Kollegen Arbeite, die SCL "verfluchen" und daher mit der Lösung nicht einverstanden sind... Die brauchen halt ihre klötzchen :-D
Und ich müsste dann für jede Session einen extra Wrapper-FC erstellen, bzw. sogar 2, da das auswerten der Session am Programmende, nach dem gleichen Prinzip funktioniert.

Ich bin auf jeden Fall noch weiter am basteln. Vielleicht finde ich ja eine andere Lösung ;-)
 
Hmm.. unabhängig davon was für die Anwendung die beste Lösung ist.

Das erzeugen eines ANY von einem UDT am FC-IN geht tatsächlich nicht auf der 1500. Auch wenn man ein 300er-Projekt (wo es so geht), auf eine 1500er migriert, geht es dann nicht mehr.
Das dürfte beim Migrieren von 300er-Programmen öfters Probleme machen, ich würde mal den Support darauf ansprechen. So kann das ja auch nicht richtig sein, oder?
 
Hallo,

falls es noch wen interessiert hier mal der aktuelle Status.

Der Support von Siemens sagt, dass das erzeugen eines ANY Pointers möglich sein muss!
Laut deren Aussage, funktioniert das ganze momentan mit TIA V13 nur in einem FB, nicht aber wie in meinem Fall in einem FC, aufgrund eines Fehlers im Compiler.

Mit etwas Glück wird der Fehler in einer der nächsten Versionen (V14?) behoben.

Als temporärer workaround habe ich mir einen FC in AWL geschrieben. Hier funktioniert das ganze. Die Lösung mit dem FB war nicht möglich wegen dem benötigten Instanz DB.

Hier mal der Code für den FC, der mir jetzt einen ANY Pointer erzeugt:
Code:
FUNCTION "MOVE_ANY" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
   VAR_INPUT 
      IN : Any;
   END_VAR

   VAR_OUTPUT 
      OUT : Any;
   END_VAR


BEGIN
NETWORK
TITLE = Move Any Pointer
      L P##IN;
      LAR1;

      L P##OUT;
      LAR2;

      L W[ AR1, P#0.0];
      T W[ AR2, P#0.0];
      L D[ AR1, P#2.0];
      T D[ AR2, P#2.0];
      L D[ AR1, P#6.0];
      T D[ AR2, P#6.0];
NETWORK
TITLE = Set ENO
      SET;
      SAVE;
END_FUNCTION

Aufruf im Programm:
Code:
FUNCTION "HSC_Session_Add_Start" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.0
   VAR_IN_OUT 
      SESSION : "tHSC_Session";
   END_VAR

   VAR_TEMP 
      pSession : Any;
      _pSession AT pSession : Struct
         ID : Word;
         NBR : Int;
         DBN : Int;
         PTR : DWord;
      END_STRUCT;
   END_VAR


BEGIN
    
    (* Save the Pointer to the Session *)
    "MOVE_ANY"(IN := #SESSION, OUT => #pSession);
    "DB_HSC".Temp.pSession := #_pSession;

END_FUNCTION
 
Zurück
Oben