UDT Länge mit SCL auslesen

Panzerknacker

Level-1
Beiträge
116
Reaktionspunkte
23
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,
ich suche eine Möglichkeit per SCL die Länge eines UDT's auszulesen. Habe hier schon reichlich Threads zu diesem Thema abgeklappert, jedoch noch keine Lösung gefunden, da meistens nicht die Länge des UDT's ausgelesen werden soll sondern der Struktur im DB wo der UDT verwendet wird.

Beispiel:
UDT1:
Code:
a   WORD    W#16#0
b   WORD    W#16#0
Also ist mein UDT 4 Byte lang

DB:
Code:
x    ARRAY[1..100]
      UDT1
Der DB hingegen ist nun 400 Byte lang

An meinem FC binde ich einen ANY-Pointer al VAR_INPUT an über den ich ja die DB Nummer, die Länge der Struktur etc. alles verarbeiten kann. Aber wie funktioniert es, das ich nur die Länge des UDT's erhalte?

Viele Grüße
Matthias
 
Also meiner Meinung nach:
Überhaupt nicht.

Der UDT ist in der SPS in keinster Weise vorhanden, und somit auch nicht irgendwie dynamisch auswertbar.
Ein UDT definiert ja lediglich eine Reihe von Daten/Datentypen im DB, oder wo auch immer.

Mfg
Manuel
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Da hast du natürlich recht das er in der SPS nicht vorhanden ist,
allerdings kann ich ihn in SCL ja auch als eine Variable anlegen. Daher dachte ich eigentlich das es wohl Mittel und Wege geben müsste die Länge von dieser
"UDT Variable" ermitteln können.

Gruß
Matthias
 
blöde Frage:
Warum willst du das wissen bzw. auswerten?
Vielleicht gibts nen eleganteren Weg

Da hast du natürlich recht das er in der SPS nicht vorhanden ist,
allerdings kann ich ihn in SCL ja auch als eine Variable anlegen. Daher dachte ich eigentlich das es wohl Mittel und Wege geben müsste die Länge von dieser
"UDT Variable" ermitteln können.

Gruß
Matthias
 
Nein ... geht nicht ...
SCL kann nur mit Variablen oder Typen arbeiten, die es schon kennt. Die Länge eines ihm unbekannten UDT's oder die Struktur eines ihm unbekannten DB's kann es nicht erfassen.

Grundsätzlich kannst du die Länge eines UDT's oder ähnlich aber erfassen/errechnen in dem du Differenz des Anfangs-Pointers der Struktur zu dem Pointer auf die danach folgende Variable/Struktur bildest ...

Gruß
LL
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Nein ... geht nicht ...

Doch, geht doch!

Dass es keine sizeof Funktion gibt ist der tollen Pascal Sprache geschuldet.

Ich habe dafür einen sizeof AWL-Baustein geschrieben, müsste sich aber auch in mittels der AT-Sicht in SCL schreiben lassen:

Code:
FUNCTION "sizeof" : INT
TITLE =Gibt die Länge in Bytes eines ANY-Pointers zurück
//nur für BYTE, CHAR, WORD, INT, DWORD, DINT, REAL
//Return: 0 wenn OK, -1 bei Fehler
VERSION : 0.1


VAR_INPUT
  pUDT : ANY ;    //nur für BYTE, CHAR, WORD, INT, DWORD, DINT, REAL
END_VAR
VAR_OUTPUT
  LEN : INT ;    
END_VAR
VAR_TEMP
  SyntaxID : BYTE ;    
  DataType : BYTE ;    
  DataCount : INT ;    
  DB_Number : WORD ;    
  BytePointer : WORD ;    
END_VAR
BEGIN
NETWORK
TITLE =
//
//
      L     P##pUDT; 
      LAR1  ; 
      L     B [AR1,P#0.0]; 
      T     #SyntaxID; 
      L     B [AR1,P#1.0]; 
      T     #DataType; 
      L     W [AR1,P#2.0]; 
      T     #DataCount; 
// Länge soll in Bytes ausgegeben werden
      L     #DataType; 
      SPL   err; 
      SPA   err; // 0= NIL
      SPA   err; // 1= BOOL
      SPA   byte; // 2= BYTE (Bytes 8 Bits)
      SPA   byte; // 3= CHAR (Zeichen 8 Bits)
      SPA   word; // 4= WORD (Wörter 16 Bits)
      SPA   word; // 5= INT (Ganzzahlen 16 Bits)
      SPA   dwor; // 6= DWORD (Wörter 32 Bits)
      SPA   dwor; // 7 = DINT Ganzzahlen (32 Bits)
      SPA   dwor; // 8= REAL (Gleitpunktzahlen 32 Bits)
err:  L     0; 
      T     #LEN; 
      L     -1; 
      T     #RET_VAL; 
      BEA   ; 
// BYTE
byte: L     #DataCount; 
      T     #LEN; 
      L     0; 
      T     #RET_VAL; 
      BEA   ; 
// WORD
word: L     #DataCount; 
      L     2; 
      *I    ; 
      T     #LEN; 
      L     0; 
      T     #RET_VAL; 
      BEA   ; 
// DWORD
dwor: L     #DataCount; 
      L     4; 
      *I    ; 
      T     #LEN; 
      L     0; 
      T     #RET_VAL; 
      BEA   ; 
END_FUNCTION
Aufzurufen dann in SCL z.B. so:
Code:
TYPE UDT1111
    STRUCT
        b0 : BYTE;
        b1 : BYTE;
        b2 : BYTE;
    END_STRUCT
END_TYPE

TYPE UDT1112
    STRUCT
        w0 : WORD;
        w1 : WORD;
        w2 : WORD;
    END_STRUCT
END_TYPE

FUNCTION_BLOCK FB1100

VAR_TEMP
    len1 : INT;
    len2 : INT;
    ret : INT;
END_VAR
VAR
    dat3byte : UDT1111;
    dat3word : UDT1112;
END_VAR
 
ret := sizeof(pUDT :=  dat3byte
             ,LEN :=  len1
             ); 
ret := sizeof(pUDT :=  dat3word
             ,LEN :=  len2
             ); 
END_FUNCTION_BLOCK
 
Erstmal vielen Dank für eure Beiträge zu dem Thema.

@Thomas_v2.1 Ich denke nicht das das funktionieren würde. Denn wenn ich den ANY auf den DB anlege wo ich den UDT als Array verwende, dann bekomme ich vom ANY ja auch wieder die Länge des gesamten Arrays und nicht des einzelnen UDT's

Besispiel:
Code:
TYPE "UDTabc"
VERSION : 0.1


  STRUCT     
   a : INT ;    
   b : INT ;    
  END_STRUCT ;    
END_TYPE

DATA_BLOCK DB 1
VERSION : 0.1


  STRUCT     
   x : ARRAY  [1 .. 10 ] OF "UDTabc";    
  END_STRUCT ;    
BEGIN
   x[1].a := 0; 
   x[1].b := 0; 
   x[2].a := 0; 
   x[2].b := 0; 
   x[3].a := 0; 
   x[3].b := 0; 
   x[4].a := 0; 
   x[4].b := 0; 
   x[5].a := 0; 
   x[5].b := 0; 
   x[6].a := 0; 
   x[6].b := 0; 
   x[7].a := 0; 
   x[7].b := 0; 
   x[8].a := 0; 
   x[8].b := 0; 
   x[9].a := 0; 
   x[9].b := 0; 
   x[10].a := 0; 
   x[10].b := 0; 
END_DATA_BLOCK
Wenn ich jetzt das array an einen FC anbinden will würde ich ja den P#DB1.DBX0.0 BYTE 40 anbinden (symbolisch "DB1".x)

Da ich aber gerne von einem Array-Element in das andere immer die komplette Struktur umkopieren will muss ich ja die Länge des UDT's kennen.
Sprich ich möchte z.B. im FC gerne folgendes kopieren:
x[9].a nach x[10].a
x[9].b nach x[10].b

Soweit ja keine Problem, aber wenn ich jetzt den UDT erweitern möchte um die Variable .c, dann habe ich das Problem das im DB sich alles verschiebt weil der UDT sich ja geändert hat. Denn dann möchte ich kopieren:
x[9].a nach x[10].a
x[9].b nach x[10].b
x[9].c nach x[10].c

So wie ich das im Moment sehe fallen mir 3 Ansätze an:
1. Einen VAR_INPUT (z.B. UDTLen : INT; ) erstellen wo ich manuell die UDT Länge angeben muß
2. Im DB vor den UDT eine Kopfvariable zu setzen wo die UDT Länge schon drin steht.
3. Einen weiteren VAR_INPUT als ANY erstellen, dann im DB vor dem array einen einzelnen UDT anlegen (natürlich der gleiche der auch für das array genutzt wird) und mit diesem weiteren ANY auf den einzelnen UDT zu schauen und daher die Länge zu beziehen

Was denkt ihr was wohl die beste Lösung ist?

Gruß
Matthias
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das geht mit SCL viel einfacher.

X[10] := X[9];

oder auch in Verbindung einer Schleife oder ähnliches indirekt adressiert

X[n+1] := X[N];

Der Compiler macht Dir daraus einen SFC20-Aufruf und du brauchst dich
um nix weiter zu kümmern.

Wenn Du das UDT dann später erweiterst, einfach die Quelle neu übersetzen => das wars
 
Das mache ich ja auch mit SCL.
Die ganze Geschichte ist auch um einiges komplexer, das war jetzt nur ein einfaches Beispiel.

Der Punkt ist halt das der Kunde es erweitern können soll OHNE in der Quelle zu wühlen
 
@Thomas_v2.1 Ich denke nicht das das funktionieren würde. Denn wenn ich den ANY auf den DB anlege wo ich den UDT als Array verwende, dann bekomme ich vom ANY ja auch wieder die Länge des gesamten Arrays und nicht des einzelnen UDT's

Doch, das funktioniert schon, wenn du die Länge eines einzelnen Array Elements bestimmst.

Code:
ret := sizeof(pUDT :=  DB_udt_daten.x[1]
             ,LEN :=  len3
             );
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Doch, das funktioniert schon, wenn du die Länge eines einzelnen Array Elements bestimmst.

Code:
ret := sizeof(pUDT :=  DB_udt_daten.x[1]
             ,LEN :=  len3
             );

Okay, ich werde das ganze heute Nacht, morgen oder Freitag mal testen.
Ich weiß nur nicht ob ich dem ANY einfach eine [1] hinten anhängen kann.

Moment, mir kommt da noch eine Idee...
Was wäre denn wenn ich die DB_udt_daten.x[1] direkt an den ANY übergebe und dann die DB-Länge prüfe? Damit hätte ich dann ja am ANY die einfache UDT Länge und durch die DB Länge bekomme ich die Anzahl der Schleifen.
 
d.h. also du willst/darfst den Kunden die Quelle nicht geben
Know-How-Schutz oder ähnliches?

Vielleicht kannst Du aber die Kopierfunktion in einen eigenen Baustein auslagern bei der der Kunde die Quelle bekommen darf?


Das mache ich ja auch mit SCL.
Die ganze Geschichte ist auch um einiges komplexer, das war jetzt nur ein einfaches Beispiel.

Der Punkt ist halt das der Kunde es erweitern können soll OHNE in der Quelle zu wühlen
 
also erstens will ich dem Kunden die Quelle nicht geben,
zweitens möchte ich gar nicht das der Kunde irgendwelche Quellen übersetzen muss, da man da auch viel Dummfug mit machen kann.

Wenn es nur eine einfache Kopierfunktion wäre, wär das alles kein Thema, aber da gehts um Berechnungen, Regler, Laufzeiten, Garantien über einen gewissen Prozentsatz vom Mittelwert u.s.w.

Know How Schutz ist eh Kinderkram.
Aber durch die SCL Kompilierung steigt keiner durch... Folglich wird auch niemand versuchen was zu ändern weil sie sonst ganz derbe auf die Nase fliegen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
also erstens will ich dem Kunden die Quelle nicht geben,
zweitens möchte ich gar nicht das der Kunde irgendwelche Quellen übersetzen muss, da man da auch viel Dummfug mit machen kann.

Also ich habe ziemlich exakt 2 Typen Kunden:
Die einen wollen ein vollständig dokumentiertes Programm, wobei Vollständig auch wirklich vollständig meint,
also inkl. evtl. Quellen und ohne Know-How Schutz ...

Den anderen geht die Software am Arsch vorbei, die wollen eine Maschine/Anlage die tut, was immer die tun soll ...

Andere Varianten habe ich bisher noch nicht kennengelernt ...

Mfg
Manuel
 
Doch, geht doch!

Dass es keine sizeof Funktion gibt ist der tollen Pascal Sprache geschuldet.

Ich habe dafür einen sizeof AWL-Baustein geschrieben, müsste sich aber auch in mittels der AT-Sicht in SCL schreiben lassen:
Klar ... an den ANY-Pointer hatte ich nicht gedacht. Kommt aber der Sache mit dem Pointer-Verrechnen, von der ich geschrieben habe sehr nahe ...

Ich glaube dennoch nicht, dass Panzerknacker so wirklich weiter kommt, da immer noch das Problem besteht, dass die Struktur bekannt sein muß und erkannt werden muß. Wie wollt ihr das lösen ? Kann natürlich sein, dass ich da falsch liege, aber der angestrebte flexible Speicherzugriff beinhaltet das m.E..

Klösen läßt sich das Problem allerdings, wenn man die Struktur und den Aufbau der Datenquelle komplett festlegt ...

Gruß
LL
 
Also meine Lösung vorerst wird sein das ich zwei ANY Pointer anbinde.
Der eine beinhaltet das gesamte Array von dem UDT und der andere bekommt genau ein Array-Element.
Aus dem hole ich mir dann die Länge des Pointers und habe somit die Länge des UDT.
 
Zurück
Oben