TIA Typ Variant und wie geht man damit um

vollmi

Level-3
Beiträge
5.435
Reaktionspunkte
1.409
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich weiss der Datentyp ist sicher noch nicht in so richtig in Benutzung. Trotzdem dachte ich mir ich frag mal wie man den Typ richtig handhabt.

Variant ist ja eigentlich ein Any, kann aber auch nur ein Typ Datenbaustein oder jede art Variable sein.

Wenn ich jetzt einen Variant habe in dem z.B. ein Operandenbereich abgelegt wurde.

z.B. P#DB120.dbx0.0 byte 100.

Wie hole ich denn im Baustein aus dem Variant z.B. die länge oder die DB nummer und Startadresse wieder einzeln raus?

Kann ich
 
Also im V13 Handbuch ist auf Seite 13 noch Inhaltsverzeichnis ;) kein wunder bei dem über 10'000 Seiten starken Werk.
Aber der Link zum Siemens Forum ist mal ein guter Ansatzpunkt. Leider noch nicht genau das was ich suche.

mfg René
 
Ich glaube die Seitenzahl war 213.
Lade doch einfach mal das Handbuch runter und tippe Variant bei der Suche ein.
Dort ist ein Codebeispiel in SCL zu dem Thema.
Any Pointer gibt es nach wie vor. Aber Variant ist ein Allgemeiner Variablembegriff um mit Symbolischen Variablen unerschiedlichster Sruktur/ Datentyp flexibel arbeiten zu können, was halt bei Classic der Any Pointer ist.
Varinant erkennt automatisch wo der Datentyp beginnt und endet.
Das Codebeispiel in dem Handbuch ist so etwas wie ein universales FIFO oder Schieberegister
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi all

aus den Beschreibungen die Siemens so liefert, wird man zwar schlauer, aber nicht klug. Hier mal meine Zusammenfassung:

Variant ist nicht Any. Variant ist mehr! Und Pointer ist er auch nicht, denn der kann noch weniger.

Pointer zeigt auf ein einzelnes Bit irgendwo im Standard-Speicher einer Simatic. Warum er nicht auf optimierten Speicher zeigen kann ... ist "böse" Absicht :-|. Damit hat er in etwa den Nutzen eines Byte* aus C, du kannst das auf alles casten was du willst. Aber wehe du machst es falsch, dann viel Spaß beim Fehlersuchen. Noch schlimmer wenn es nicht dein eigener Code ist.

Any zeigt auf einen Bereich irgendwo im Standard-Speicher einer Simatic. Auch der kann nicht auf optimierten Speicher. Der Any kann was über den Datentyp des Speichers wissen, auf den er zeigt. Er kann die einfachen Datentypen unterscheiden. er kann z.B. auf ein Feld von 20 REAL zeigen. Er kann jedoch nicht auf einen String[47] oder einen UDT5 zeigen. Aus komplexen Datentypen werden (fast) immer Byte-Arrays. :cry:

Variant zeigt auf einen Bereich irgendwo im Speicher einer Simatic. Der kann auf optimierten Speicher zeigen. Der Variant weiß was über den Datentyp. Er kann sich (fast?) alle Datentypen merken. Also auch sowas wie array[20] of UDT21. Klingt doch gut! :p ... naja ... hier tritt der erste Mangel zutage. Er weiß nichts über die Ober und Untergrenzen von Arrays. Was nicht geht ist ein Array[1..5] of FB7. Also ein Feld aus Instanzen. Das ist jetzt ein Henne-Ei-Problem. Man kann das nicht Deklarieren, also kann der Variant auch nicht drauf zeigen. Oder ist das umgekehrt? Egal, Instanz-Arrays gehen nicht. :neutral:

Also ist der Variant deutlich besser als ein Any. Und gleichzeitig ist er für den AWL-Profi deutlich schlechter, denn es gibt keine Möglichkeiten den Variant zu manipulieren. Auch das ist Absicht, hat mit der CS versichert :evil:


Zur V12 konnte man mit den Variant nichts machen. Es gab Systemfunktionen, die damit zauberten, aber für uns normal sterbliche Anwender, war nur durch reichen. Seit der V13 kommt Bewegung in die Sache. Leider viel zu viel Bewegung. Es gibt jetzt zwei Funktionen VariantGet und VariantPut, die es uns erlauben zu dereferenzieren.

Wenn du einen Input vom Typ Variant und einen Temp von irgendeinem Typ, sagen wir mal UDT13, anlegst, dann kannst du mit VariantGet den Inhalt des UDT13 kopieren. Das finde ich ziemlich blöd, denn wenn der UDT13 nun so 1k groß ist, dann wird da ein ganzes Kilobyte kopiert :shock:. Wenn du einen InOut anlegst dann kannst du sogar mit dem VariantPut rein schreiben. Das setzt voraus, dass du beim Aufruf deiner Funktion aber auch ein DB-Element vom Typ UDT13 an den Parameter anlegst. Verwendest du jedoch einen UDT14, dann melden VaraintPut und VaraintGet einen Typkonflikt. Insofern hättest du eben auch gleich einen UDT13 an die Schnittstelle schreiben können. Die Sache hat aber eben doch einen Vorteil. Man kann wie die Systemfunktionen mehrere verschiedene Datentypen behandeln. Dazu legst du eben nicht nur einen Temp vom Typ UDT13 an sondern deiner Anwendung entsprechend einen t13:UDT13; t14:UDT14; t15:UDT15. Nun gibt es eine Konstrukt, mit dem man prüfen kann ob der Schnittellen input einen bestimmten Typ hat und kann man ganz gezielt mit diesem Typ weiter machen. Sieht etw so aus (ich zitiere aus dem Kopf)

Code:
if typeof(in1) = Int then
     VariantGet( v1, tint );
elsif typeof(in1) = UDT13 then
     VariantGet( v1, t13 );
elsif typeof(in1) = UDT14 then
     VariantGet( v1, t14 );
...

Damit lässt sich dann ein begrenztes Operation-Overloading machen. Siemens macht das bei vielen Systemfunktionen vor. Einfachstes Beispiel sind MIN und MAX, trickreicheres z.B. TCON, wo man die verschiedenen Strukturen zum Aufbau einer Kommunikation angeben soll.


Man kann den Variant nicht im DB anlegen! An einer Schnittstelle ja, aber nicht DB. Also kann man ihn nicht speichern. Er lebt nur so lange der Baustein mit seiner Deklaration auf dem Stack liegt. Ist der Baustein beendet, ist der Zeiger weg.:roll: Warum ist das so? ... eine dünne Vermutung meinerseits: Download im Run. Damit verliert die Sache aber sehr viel an Reiz. Wenn ich große Datenmengen habe und mir merken will, dass damit was zu tun ist, dann kann ich den Variant genau dafür nicht verwenden. Man muss so wie S. das im Beispiel zeigt die Daten kopieren.
Der einzige Ausweg aus diesem Dilemma scheinen diese seltsamen ArrayDB zu sein, aber das ist wieder eine ganz andere Geschichte.



Seit der V13 kann man also mit dem Variant was anfangen. ABER

man muss viel zu viel Daten kopieren --> schnell ist das nicht
man kann nicht auf einzelne Elemente einer Struktur zugreifen
man kann den Variant nicht speichern



So taugt mir das nicht. Kennen die eigentlich die IEC61131-3 3rd Edition. Die dort gezeigten Referenzen, das ist das was man verwenden kann. Das kann zwar etwas weniger flexibel als Variant, ist aber trotzdem viel intuitiver.

'n schön' Tach auch
HB
 
Damit lässt sich dann ein begrenztes Operation-Overloading machen. Siemens macht das bei vielen Systemfunktionen vor. Einfachstes Beispiel sind MIN und MAX

War bei der S7-300/400 aber auch schon mit dem Any-Pointer möglich, und wurde auch bei den MIN/MAX Funktionen aus der IEC-Lib verwendet. Mit den Nachteilen dass man keine Konstanten übergeben konnte, und man keine Typprüfung zum Übersetzungszeitpunkt mehr hat.
Hat aber mit der Operator- bzw. ist es hier ja Parameterüberladung wie man es aus C++ kennt nicht viel zu tun. Dort gibt es für verschiedene Funktionssignaturen (d.h. Datentypen der Parameter) eigene Funktionen, und es wird zur Compilezeit entschieden welche aufgerufen wird.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi Thomas

cool, wie findest du sowas?

Patentdeutsch ist echt krass. Wenn ich das richtig interpretiere, dann steht da genau das was ich schon vermute. Der Variant besteht aus zwei Zeigern. Einer auf den Wert, der andere auf den Typ.

Wo ist denn da der Unterschied zu anderen Sprachen, eigentlich deren Implementierung?
...

Ok bei C hat man einen Zeiger der auf den Wert zeigt und davor liegt am Wert der Zeiger auf den Typ.

Also bei C wird jedes Objekt 4 Bytes größer.
Bei der Simatic wird jeder Zeiger 4 Bytes größer.
Da ist ein Unterschied!


'n schön' Tach auch
HB
 
Hi Thomas

cool, wie findest du sowas?

Patentdeutsch ist echt krass. Wenn ich das richtig interpretiere, dann steht da genau das was ich schon vermute. Der Variant besteht aus zwei Zeigern. Einer auf den Wert, der andere auf den Typ.

Wo ist denn da der Unterschied zu anderen Sprachen, eigentlich deren Implementierung?

Ich hatte vor einiger Zeit mal nach Patenten im Zusammenhang mit dem TIA-Portal gesucht, da jemand anmerkte dass dort etwas bezüglich Zugriff auf SPS-Variablen z.B. von einem HMI patentiert sei (ist es auch).
Aber jetzt sehe ich bei diesem Variant-Patent ganz unten:

2. Apr. 2014 18R Refused

Ist also abgewiesen worden. Da waren die Unterschiede wohl doch nicht groß genug.
Ich sehe da auch keine große Neuerung. Der Siemens Variant kann zwar mehr als z.B. der aus der Microsoft-COM Umgebung bekannte Variant Typ, aber die Dinge um die sie ihren erweitert haben wie typeOf() gibt es in zig anderen neueren Sprachen.
 
Hallo!

Ich muss das Thema noch einmal aufgreifen.
Ich möchte in einem SCL-FB einen Variant (Input) auf einen anderen Variant (Temp) setzen. Der Compiler meldet immer einen Fehler dass der Variant (Temp) nicht initialisiert ist.
Grund der Frage: Ich habe in Summer 64 Variant Inputs und möchte nicht den gleich Code 64x eintippen. Daher würde ich gerne den Input mittels FOR-Schleife auf eine temporäre Variable schreiben und die dann bearbeiten.
Geht das überhaupt? Mach ich was falsch?

Danke für eure Antworten!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Naja ... du mußt dir mit GetVariant erstmal die eigentliche Variable holen - Variant selbst ist nämlich nur eine Referenz.
Um dir aber möglicherweise helfen zu können wäre dein Code schon hilfreich ...

Gruß
Larry
 
Mit GetVariant muss ich aber bereits einen Speicher - und somit auch einen Datentyp definieren. Genau das möchte ich aber verhindern weil ich das dann für jeden meiner Eingänge separat machen muss. Ich möchte das gerne aber nur 1mal zentral programmieren.
 
... du mußt es in etwa so machen, wie es Hellebarde im Beitrag #6 dieser Frage beschrieben hat. Anders geht es nicht, da, wie von mir geschrieben, du nicht wirklich mit einer Variable herummachst sondern mit einer Referenz. Willst du mit dieser dahinterstehenden Variablen arbeiten dann geht das nur wenn du den Type der Variablen kennst (am Besten sogar den Typ des Variant noch überprüfst, ob das passt) und dann diese Referenz auf deine Baustein-interne Variable überträgst. Das ist dann halt die "Spielregel" ...

Was hast du denn so ganz genau vor ...?

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wie meinst Du das mit FOR-Schleife? Die einzelnen Bytes des Variant-Datentyps kopieren oder Input_1 + Input_2 + ... + Input_64 kopieren? Indiziert auf Variablen zugreifen geht nur mit Arrays.

Harald
 
Hallo!
Ich möchte 64 Eingänge (das können INT oder REAL oder ... sein) nach WORD konvertieren und in ein Array schreiben (Das hat dann also 32-64 Einträge). Jetzt muss ich für den Eingang den Typ abfragen und in Abhängigkeit davon die Konvertierung nach WORD vornehmen. Das wollte ich nur 1mal programmieren und deshalb den IN_x(x..0-63) auf einen temporären IN schreiben. Danach kann ich alle 64 Eingänge in einer Forschleife bearbeiten.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Naja ... deine einzelnen IN's mit einer Schleife abfragen wird sowieso schonmal nichts - die kannst du nicht indexieren ...
Dann : wie willst du einen REAL sinnvoll zu WORD konvertieren ?

Gruß
Larry
 
Hallo!

1. Ich weiß, dass ich meine INs nicht indexieren kann. Deswegen ja der Umweg über die Temp Variable. Ich kann den IN auf einen Temp schreiben. Aus dem Temp kann ich dann Datentyp und Wet extrahieren und in ein Array speichern. Das ganze packe ich in eine Schleife wobei der Schleifenzähler gleichzeitig der Array-Index ist. Schon kann ich alle meine INs abfragen und hab dafür nur 1x Code tippen müssen. Geht aber anscheinend nicht...
2. Daten: Ich möchte den Eingang nicht konvertieren sondern nur die Bitfolge in ein WORD-Register ablegen. Zusätzlich übergebe ich extra den Datentyp. Damit kann sich dann die lesende Funktion aus der Bitfolge wieder einen REAL, DINT, ... zusammenbasteln.
 
Naja ... deine einzelnen IN's mit einer Schleife abfragen wird sowieso schonmal nichts - die kannst du nicht indexieren ...

Wieso sollte das nicht gehen? Dafür ist doch Peek und Poke da. Natürlich muss man sich im klaren sein das die Adressierung dann schon in der Hardwarekonfig fortfolgend sein muss. Ausserdem kann man ja auch ein Array über einen Eingangsbereich legen, dann wärs wieder vollsymbolisch.

mfG René
 
Zurück
Oben