TIA Variablentyp auslesen

Alde_Oma

Level-2
Beiträge
103
Reaktionspunkte
5
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

ich habe einen nicht optimierten Datenbaustein mit einem UDT. Ich möchte nun alle Variablen des UDT durchlaufen und deren Typ oder zumindest die Länge der Variable ermitteln um daraufhin weitere Schritt zu unternehmen. (Soll auch für weitere Projekte dienen, in denen der UDT anders aufgebaut ist, daher ist eine feste Programmierung nicht möglich)
Zum Auslesen der Länge des gesamten UDT habe ich bereits einen Code im Internet gefunden, der mir weitergeholfen hat.

Code:
#Error := 0; // Rücksetze Error-Variable

#TempAny := #DataStruct; // Hier werden die Daten aus der Eingangsvariable "DataStruct" (ANY-
// Pointer) der temporären Variable "TempAny" (ANY-Pointer mit Zugriff auf
// die Buffer-Variable vom Typ UDT "UDT_AnyPointer") übergeben. Somit ist das Lesen 
// und Schreiben der Daten in den Buffer möglich, um den Zeiger zu bilden.
CASE CHAR_TO_INT(BYTE_TO_CHAR(#Buffer.DataType)) OF
    1:
        #BitCount := #Buffer.DataCount / 8;       // Boolean
    2:
        #BitCount := #Buffer.DataCount;           // BYTE
    3:
        #BitCount := #Buffer.DataCount;           // CHAR
    4:
        #BitCount := #Buffer.DataCount * 2;       // Word, multiply by 2
    5:
        #BitCount := #Buffer.DataCount * 2;       // INT, multiply by 2
    6:
        #BitCount := #Buffer.DataCount * 4;       // DWORD, multiply by 4
    7:
        #BitCount := #Buffer.DataCount * 4;       // DINT, multiply by 4
    8:
        #BitCount := #Buffer.DataCount * 4;       // REAL, multiply by 4
    ELSE:                                           // Andere Typen vom ANY-Pointer, werden nicht unterstützt!
        #Error := W#16#8001;                           // Typ vom ANY-Pointer wird nicht unterstützt
END_CASE;

#Lng := #BitCount; // Länge ausgeben
#"0700_SizeOfStruct" := #Error;

Mit Hilfe dieses Codes kann ich den Datenbaustein mit ein For-Schleife durchlaufen. Nur fehlt mir aktuell die Möglichkeit, den Datentyp der Variablen auszulesen.
Ich denke, das ist auch mit dem oben genannten Code möglich (in abgewandelter Form), nur habe ich mit Zeigern und Any noch nicht wirklich was zu tun gehabt.
Mein Gedanke:

Code:
FOR #i := 0 TO DINT_TO_INT(#tdi_Laenge) DO
        // Datentyp ermitteln
        // ...
        // ...
        
        IF Datentyp = Bool THEN
            #x_RetVal := PEEK_BOOL(area := 16#84, dbNumber := 9, byteOffset := #i, bitOffset:=0);
            
        ELSIF Datentyp = Byte THEN
            #b_RetVal := PEEK(area := 16#84, dbNumber := 9, byteOffset := #i);
            
        END_IF;
        
        // ggf. Zwischenzähler, damit Schleife bei Typen mit mehreren Byte nicht zweimal, sondern erst wieder mit der nächsten Variable prüft
        
    END_FOR;

Ich hoffe mir kann hierbei jemand helfen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi, das mit dem TypeOf ist mir bekannt.
Mein Problem ist eher, dass ich nicht weis, wie ich die Variablen durchlaufe.
Mit meiner For-Schleife durchlaufe ich zwar die gesamte Länge des UDT, aber wie muss der Befehl aus sehen, um wie in deinem Beispiel die Myvar zu erhalten?
Also irgendwie so (um in meinem Beispiel zu bleiben):

Code:
FOR #i := 0 TO DINT_TO_INT(#tdi_Laenge) DO
        IF TypeOf(%DB9.DB(#tdi_Laenge)) = Bool THEN
            ;
        ELSIF TypeOf(%DB9.DB(#tdi_Laenge)) = Byte THEN
            ;
        END_IF;

Hier fehlt mir gerade die passende Anweisung.
 
Das ist, meines Wissens nach, nicht möglich.
In einem Optimierten Baustein kannst du Variablen nur direkt mit dem Symbol ansprechen.
In Nicht-Optimierten kannst du zwar direkt auf den Speicher zugreifen, aber die Datentypen / Längen kann man auch nicht auslesen.
 
Das kann ich mir fast nicht vorstellen.
Mit der Funktion im ersten Beitrag kann man ja auch die Gesamtlänge auslesen. Dann muss es doch auch möglich sein, einzelne Bereiche des UDT auszulesen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich kann es mir sehr gut vorstellen ...
Für das, was du da vorhast benötigst du eine Art Reflektion - das heißt : du übergibst das Objekt (in dem Fall deinen UDT) und du bekommst zurückgeliefert was dieses Objekt so alles beinhaltet (quasi als Liste der Einzel-Variablen und welche Typen das sind).
So etwas kenne ich von .Net - kann mir aber bei Siemens nicht vorstellen, dass das geht. Darüber hinaus würde diese Form der Auflösung, wenn zyklisch durchlaufen, auch richtig gut Zykluszeit generieren ...

Gruß
Larry
 
Ich würde das nicht zyklisch durchlaufen lassen, nur bei bestimmten Ereignissen, und die kommen nicht oft vor.
Manchmal frag ich mich wirklich, wieso wir überhaupt noch Siemens benutzen. Da muss man sich so oft derart Verbiegen und bekommt es dennoch nicht hin. Aber nunja, anderes Thema...

Vielleicht findet ja doch noch jemand eine Lösung. Würde mich sehr freuen.
 
Alde Oma, kannst einen Ungläubigen den Sinn deines Vorhabens mal etwas näher bringen? Was fängt man mit Daten an, deren Bedeutung nicht bekannt ist?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich möchte ein kleines Logbuch schreiben und Änderungen von bestimmten Daten mitschreiben.
Damit man nicht bei jedem neuen Projekt alle Daten, die sich wie bereits gewähnt von Projekt zu Projekt ändern, händisch eingeben und anpassen muss, hätte ich das möglichs Automatisiert.
 
Du kannst doch vergleichen ob der angelegte UDT einem bestimmten UDT entspricht. Wenn in dem DB ein UDT ja schon dieser verwendet wird, kannst du doch auch auf den Vergleichen.

dann kannst du mit Ref_TO auf die Referenz arbeiten.

-chris
 
Also letztendlich hab ich 2 identische UDTs die ich miteinader vergleichen möchte. Ref_To sagt mir gerade überhaupt nichts.
Muss ich mich erst einlesen, ob mich das weiterbringen könnte.
 
Ich möchte ein kleines Logbuch schreiben und Änderungen von bestimmten Daten mitschreiben.
Damit man nicht bei jedem neuen Projekt alle Daten, die sich wie bereits gewähnt von Projekt zu Projekt ändern, händisch eingeben und anpassen muss, hätte ich das möglichs Automatisiert.
"Automatisieren" ist in diesem Zusammenhang eine gute Überleitung zum "Generieren". Das schmeiß ich nur mal so in den Raum ;) .
 
Manchmal frag ich mich wirklich, wieso wir überhaupt noch Siemens benutzen. Da muss man sich so oft derart Verbiegen und bekommt es dennoch nicht hin.

Naja ... die Frage kann ich dir nun nicht beantworten.
Wobei ich mir jetzt die Frage stelle ob es so überhaupt Sinn in der SPS macht ...

Ich unterstelle aufgrund der anderen Antwort von dir mal, dass du in deinem UDT in Projekt_1 neben vielen anderen Variablen noch 2 oder 3 hast, die in jedem Projekt den gleichen Namen und den gleichen Typ haben. Die Struktur des UDT ist aber in Projekt_2 ggf. komplett anders ... Könnte es so sein ? Wenn ja dann könntest du den Baustein doch so schreiben, wie du es vorhast. Dein UDT muss nur in jedem Projekt gleich heißen und die für dich interessanten Variablen auch. Ich denke mal, dass das funktionieren könnte wenn du den UDT an deinen Baustein als Parameter übergibst und du dich in dem Baustein nur für eben die Variablen interessierst - ausprobiert habe ich das jetzt aber auch nicht ...
Ich möchte jetzt aber keinesfalls behaupten, dass ich dieses Vorhaben irgendwie verstanden hätte ...

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Die naheliegendste Variante, nämlich einen eigenen FC zu schreiben wie CMP_UDTa_UDTb_EQ, welche zwei Parameter hat (einmal Typ UDTa und einmal UDTb), die einzelnen Elemente vergleicht und wenn alle gleich sind true zurückgibt, ist zu einfach?
 
"Automatisieren" ist in diesem Zusammenhang eine gute Überleitung zum "Generieren". Das schmeiß ich nur mal so in den Raum :wink: .

Ich kann dir mit Generieren nicht folgen.


Ich unterstelle aufgrund der anderen Antwort von dir mal, dass du in deinem UDT in Projekt_1 neben vielen anderen Variablen noch 2 oder 3 hast, die in jedem Projekt den gleichen Namen und den gleichen Typ haben. Die Struktur des UDT ist aber in Projekt_2 ggf. komplett anders ... Könnte es so sein ? Wenn ja dann könntest du den Baustein doch so schreiben, wie du es vorhast. Dein UDT muss nur in jedem Projekt gleich heißen und die für dich interessanten Variablen auch. Ich denke mal, dass das funktionieren könnte wenn du den UDT an deinen Baustein als Parameter übergibst und du dich in dem Baustein nur für eben die Variablen interessierst - ausprobiert habe ich das jetzt aber auch nicht ...

Der UDT hat den selben Namen, aber eine andere Struktur, wobei das im Prinzip ja auch egal ist, wie das bei anderen Projekt aufgebaut ist. Ich möchte letztendlich die gesamte Struktur des UDT miteinander vergleichen, und herausfinden, wo genau die Änderung liegt, ohne das ich jeden Eintrag des UDT händisch eingeben muss.


Die naheliegendste Variante, nämlich einen eigenen FC zu schreiben wie CMP_UDTa_UDTb_EQ, welche zwei Parameter hat (einmal Typ UDTa und einmal UDTb), die einzelnen Elemente vergleicht und wenn alle gleich sind true zurückgibt, ist zu einfach?

Und wie vergleiche ich die einzelnen Elemente des UDT, ohne alle händisch einzugeben?
 
Und wie vergleiche ich die einzelnen Elemente des UDT, ohne alle händisch einzugeben?

Wenn Dich die Einzelwerte nicht interessieren, sondern nur, ob der Gesamtinhalt des UDT gleich ist, kannst Du doch die Variable1_UDT = Variable2_UDT vergleichen!? Man könnte sonst auch überlegen, wenn die Länge des UDT bekannt ist, den UDT einfach byteweise zu vergleichen.

Oder willst Du einzelne Werte innerhalb des UDT vergleichen, ohne den UDT-Aufbau zu kennen?
Dann würde ich, wie Dagobert vorgeschlagen hat, dem UDT intern "anonyme" Namen geben: Var1, Var2, Var3, ... diese haben dann in jedem Projekt anderen Inhalt und anderen Typen...
Oder: Wie viele Variablen enthält Dein UDT? Du legst Dir einmal ein "Inhaltsverzeichnis" mit den Variablentypen des UDT an und hangelst Dich damit dann durch.
 
Zurück
Oben