Pointer auf Struktur (SCL)?

momo99

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

ich komme wieder mal bei meinem "SCL-Selbstkurs" nicht weiter.
Folgendes Problem, versuche es mal so zu erklären daß auch jemand weiß was ich meine:

Ich habe einen FB, der mir ein EB mit einem AB bitweise vergleicht und dann verschiedene Ergebnisse und Bedienmöglichkeiten pro Bit in einer Struktur in einem Global-DB ablegt. Im Beispiel der UDT_SPS und der DB_SPS für 6 Bytes bzw. 48x Bitabfrage.
Die Schnittstelle des FB´s sieht folgendermaßen aus:
Code:
VAR_INPUT
    EB  :   BYTE; 
    Takt:   BOOL;
    END_VAR

VAR_IN_OUT
    AB  :   BYTE;
    STG :   ARRAY[1..8] OF UDT_SPS;      
END_VAR
Soweit funktioniert alles und sollte nach Möglichkeit nicht verändert werden.

Jetzt möchte ich diesen Vergleich nicht für jedes Byte einzeln aufrufen sondern einen weiteren Baustein erstellen, in dem ich diesen ersten FB aufrufe und bei bei dem ich einen variablen EB/AB-Bereich abarbeiten kann, also z.B. 5 Bytes ab EB2/AB8.

Diese Schnittstelle sollte wiederum optimalerweise so (oder so ähnlich) aussehen:
Code:
VAR_INPUT
    EB: INT; (**Anfangs-EB**)
    AB: INT; (**Anfangs-AB**)
    BYANZ:  INT; (**Byteanzahl**)
    Ausw_Anf:INT; (**1. Zieladresse**)
END_VAR
INT als Datentyp habe ich jetzt einfach mal hingeschrieben, kann natürlich auch alles andere sein.

Ich schaffe es einfach nicht, mir einen Pointer auf diese Zieladresse zu basteln. Entweder weiß ich die richtige Syntax nicht oder ich mache grundsätzlich etwas falsch - keine Ahnung...

Noch eine Frage: Gibt es einen Bytetausch-Befehl in SCL, analog dem TAW in AWL (bzw. wie ist das realisierbar)?

Und, hat jemand einen Literaturvorschlag für mich mit Beispielen und Beschreibungen für Probleme in der o.g. Kategorie?
Es nimmt mir das Erfolgserlebnis wenn ich hier immer nachfragen muß...
Der Wellenreuther streift das Thema SCL nur, das Buch "Automatisieren mit STEP 7 in AWL und SCL" hab ich mir auf Amazon schon angesehen.
Ist ziemlich teuer - auch geeignet für mich? Oder gibt es Alternativen?

Gruß
momo
 

Anhänge

  • DB_SPS.JPG
    DB_SPS.JPG
    88,8 KB · Aufrufe: 42
  • UDT_SPS.JPG
    UDT_SPS.JPG
    82,7 KB · Aufrufe: 34
Link mit SCL Doku von Siemens in deutsch

Du brauchst keine Bücher kaufen, die notwendigen Informationen über SCL sind auf der Siemens Support Seite gratis zum herunterladen. Hier ist der Link:

http://support.automation.siemens.c...&viewreg=WW&nodeid0=10806853&objaction=csopen

Info zu den Pointern: Mit SCL kannst du in keinem FB oder FC einen ANY-Pointer übergeben. Aber in unserer Firma arbeiten wir immer mit Strukturen und übergeben so die Zeiger auf diese Strukturen.

Info zu EB und AB Manipulationen. Direkt EB einzulesen verstehe ich ja noch, aber wozu soll man direkt auf AB schreiben. In SCL programmiert man sauber mit symbloischen Namen und kopiert diese einzeln auf Ein und Ausgänge.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@Krauser:

Die SCL-Hilfe habe ich durchsucht, das was ich für dieses Problem brauche finde ich nicht. Die Beispiele, die Angegeben sind, passen nicht für diese Aufgabe.
Was Siemens zum Thema SCL noch anbietet schau ich mal durch, danke für den Link.

Info zu den Pointern: Mit SCL kannst du in keinem FB oder FC einen ANY-Pointer übergeben. Aber in unserer Firma arbeiten wir immer mit Strukturen und übergeben so die Zeiger auf diese Strukturen.
Was soll mir das sagen? Ich will doch einen Zeiger auf eine Struktur übergeben oder sehe ich das falsch?

Info zu EB und AB Manipulationen. Direkt EB einzulesen verstehe ich ja noch, aber wozu soll man direkt auf AB schreiben. In SCL programmiert man sauber mit symbloischen Namen und kopiert diese einzeln auf Ein und Ausgänge.
Wohin ich schreibe ist für die Thematik irrelevant, könnte genausogut ein Merker- oder ein Datenbyte sein.

Gruss
momo
 
Die grosse Frage ist:
Willst Du wirklich mit Absolut-Addressen arbeiten ?
Oder willst Du vielleicht lieber Symbolisch arbeiten ?

Wenn man mit Strukturen arbeiten, geht man davon aus das die Daten in DBs befindet, und nicht in EBs, ABs oder MBs.
In DBs kann man einfach die Strukturen aufbauen. In EBs, ABs und MBs gibt es eigentlich keine Strukturen. Nur eine grosse "Masse" von Bytes.
 
Hallo Momo,
so ganz werde ich aus deiner Frage nicht schlau.

Zum Punkte Byte-Tausch :
Ein Pendant zumn TAW-Befehl gibt es in AWL nicht. Du könntest aber dein Wort um 8 Bit rotieren (hat ja den gleiche Effekt).

Zum Punkt Bereich übergeben :
So wie ich deine Anfrage verstanden habe hast du hier mehrere Möglichkeiten. Du könntest deinem 1. Baustein den Bereich, der verabeitet werden soll z.B. per ANY-Pointer übergeben. Das sieht von aussen am Baustein schönen aus - du hast dann nur in dem Baustein mehr Programmier-Arbeit um den ANY zu zerlegen. So, wie du es gemacht hast ginge es aber auch.
Die so erzeugten Adressen an den 2. Baustein zu übergeben sollte nicht das Problem sein.
Wenn du nun den 2. Baustein im 1. Baustein mehrfach aufrufen willst, so geht das zwar, aber du kannst nicht indiziert den Instanz-DB übergeben.
Du könntest hier nur im den 2. Baustein in seiner Struktur so definieren, dass alles hineinpasst. Dann kannst du aber auch auf den 1. Baustein verzichten und gleich mit dem 2. Baustein den Bereich abarbeiten.

Falls ich jetzt total daneben liege, dann solltest du deine Anfrage noch mal präzisieren ...

Gruß
LL
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn man wirklich mit absolutaddressen arbeitet, denn geht das auch sehr schön in SCL. Und wenn es um Byte-Mengen von Eingänge, Ausgänge oder Merkern handelt, dann gibt es nur mehr arbeit es in Strukturen zu zerlegen.

Hier ist ein ganz einfache Beispiel:
Code:
 FUNCTION copy_inp_to_outp : VOID
VAR_INPUT
    iInputByte : INT ;
    iOutputByte : INT ;
END_VAR
 
 QB[iOutputByte] := IB[iInputByte] ;
 
END_FUNCTION
 
@jesper

Den Zustand des jeweiligen EB- bzw. AB-Bits kopiert mein fertiger FB bereits auf das V bzw. V1 in der Structur UDT_SPS, also in den Global-DB_SPS. Vielleicht hätte ich ein anderes Symbol wählen sollen (statt "EB" und "AB").
Seht es einfach so, daß "EB" ein beliebiges INPUT-Startbyte ist und "AB" ein beliebiges IN_OUTPUT-Startbyte, meinetwegen auch DB10.DBB2 und DB10.DBB8.

Es geht jetzt um die variable Länge (1...x Bytes) und um den Zeiger auf den Ablageort der Daten.

@LL

zum Byte Tausch: Ist nach rotieren nicht das vorherige Bit x.0 nach der Ausführung x.15 (und x.1 nachher x.14 usw.)?

zur Pointer-Sache:
Der erste Baustein ist für ein Byte vorgesehen und sollte nicht geändert werden. Instanz-DB hat jeder FB seinen eigenen, muß ich nichts übergeben weil alle relevanten Daten im DB_SPS (Global) stehen. Dieser DB muß von der Struktur und der Länge richtig angelegt werden, versteht sich.

Daß die Funktion auch in einem einzigen FB gemacht werden kann (von mir eben nicht, weil ich am Pointerproblem gescheitert bin) war mir bewusst, könnte ich vielleicht auch zusammenführen wenn die Funktion steht.

Und ich möchte den fertigen FB eigentlich im neuen FB nur einmal aufrufen und über eine Schleife die Parameter aktualisieren.


Gruß
momo
 
@jesper

So sieht mein Ansatz auch für die EB- und AB-Verarbeitung aus. Das kann ich über eine Schleife sowie Anfangswert und Bereichslänge adressieren.

Was ich nicht checke, ist wie ich das Ganze in den richtigen Bereich vom DB_SPS schaufeln kann...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hier ist ein Komplett-Beispiel.
(Warnung: Nicht getested)

Eigentlich passiert hier nur dasselbe als in mein vorigen Beispiel.

SCL code:

Code:
 TYPE UDT_PLC_i_bytes
    STRUCT
    byData  : ARRAY[0..7] OF BYTE ;
    END_STRUCT
END_TYPE
 
 
TYPE UDT_PLC_q_bytes
    STRUCT
    byData : ARRAY[0..7] OF BYTE ;
    END_STRUCT
END_TYPE
 
 
DATA_BLOCK PLC_io  
    STRUCT 
        inp  : UDT_PLC_i_bytes ;
        outp : UDT_PLC_q_bytes ;
    END_STRUCT
BEGIN
END_DATA_BLOCK
 
 
 
FUNCTION Copy_via_db : VOID
VAR_input
    structInputs : UDT_PLC_i_bytes ;
    iInputByte : INT ;
    iOutputByte : INT ;
END_VAR
 
VAR_OUTPUT
    structOutputs : UDT_PLC_q_bytes ;
END_VAR
 
structOutputs.byData[iOutputByte] := structInputs.byData[iInputByte] ;
 
END_FUNCTION

Aufruf in OB1:

Code:
 // BLKMOV = SFC20
      CALL  "BLKMOV"
       SRCBLK :=P#I 0.0 BYTE 8
       RET_VAL:=MW10
       DSTBLK :="PLC_io".inp
      NOP   0
 
 
// beispiel: Kopier byte 3 auf byte 4
      CALL  "Copy_via_db"
       structInputs :="PLC_io".inp
       iInputByte   :=3
       iOutputByte  :=4
       structOutputs:="PLC_io".outp
 
      CALL  "BLKMOV"
       SRCBLK :="PLC_io".outp
       RET_VAL:=MW10
       DSTBLK :=P#Q 0.0 BYTE 8
      NOP   0
 
Zuletzt bearbeitet:
@ Jesper

Danke für dein Beispiel, ich glaube aber daß wir etwas aneinander vorbeiposten...

Schau dir den UDT und DB an, die ich am Anfang angehängt habe. Es muss keine neue Struktur und kein neuer Global-DB gemacht werden und es sollen auch nicht die "EB"-Bits direkt auf die "AB"-Bits kopiert werden.

Das Bit EB x.0 wird auf V1_8[1].V kopiert, das Bit EB x.1 auf V1_8[2].V usw. Auf V1_8[1].V1 liegt das Bit AB x.0, auf V1_8[1]V2 bis V1_8[1]V10 andere Bits oder Werte aber alles bezieht sich auf die Bits EB x.0 und AB x.0. Usw. für die Bits 1-7 auf V1_8[2]-V1_8[8].
Soviel zum UDT, muss uns aber nicht kümmern, das macht alles der fertige FB.

Was wenn ich aber nicht nur ein Byte x sondern auch ein Byte y und ein Byte z verarbeiten will?

Ich könnte natürlich den fertigen FB 3x aufrufen und jeweils die Ziele bei den Parametern direkt angeben.

Diese Arbeit will ich mir genauso wie die überflüssigen IDB´s sparen und stattdessen eine Funktion haben die mir nicht nur die Auswertung eines Bytes in den Bereich V1_8 schreibt, sondern auch eine zweite in den Bereich V9_16 und eine dritte auf V17_24.

Ich weiß ich bin ein schwieriger Kunde, und an meiner Ausdrucksweise mag es auch hapern...

Gruss
momo
 
Aha, du misscht die Spielkarten.

Hmmm.... .V-V7 sind BOOLs, V8-V9 sind Bytes, V10 ist ein INT. Dies gefällt mir gar nicht. Aber egal.

Was wenn ich aber nicht nur ein Byte x sondern auch ein Byte y und ein Byte z verarbeiten will?
Es ist mir nicht 100% klar was Du willst, aber ich denke Du brauchst ein weitere indizierung.

Eindimensionale Arrays:
V_x[1].y[8].z[1].V1, V_x[1].y[8].z[1].V2 ...
..
V_x[17].y[24].z[1].V1, V_x[17].y[24].z[1].V2 ...

Oder mit mehrdimensionale Arrays:
V_xyz[1,8,1].V1, V_xyz[1,8,1].V2 ...
..
V_xyz[17,24,1].V1, V_xyz[17,24,1].V2
 
Ja, Jesper, wir nähern uns dem Kern!

Mehrdimensionale Arrays brauche ich m.E. nach nicht. Es ist nur eine x-fache Wiederholung des Eindimensionalen Arrays[1..8] OF UDT_SPS (x ist durch den Eingangsparameter "BYANZ" festgelegt).

Beim einmaligen Aufruf des fertigen FB´s beschalte ich die Parameter wiefolgt:

CALL "FB_Byte","DB_Byte1"
EB :=EB2
AB :=AB10
STG :="DB_SPS".V1_8

Will ich ein zweites Byte auswerten würde es so aussehen:

CALL "FB_Byte","DB_Byte2"
EB :=EB3
AB :=AB11
STG :="DB_SPS".V9_16

usw...
Bis hierhin funktioniert alles.

Diese Aufrufe sollen in einem neuen FB zusammengefasst werden:

CALL "FB_NEU","DB_NEU"
EB :=2 (**Anfang EB**)
AB :=10 (**Anfang AB**)
BYANZ:=2 (**Bereich - Länge**)
Ausw_Anf:= ?????

Und was ich bei Ausw_Anf hinschreibe damit ich dann meine Daten vom EB 2/3 und AB 10/11 aus diesem Beispiel in den Bereich "DB_SPS".V1_8 und "DB_SPS".V9_16 verschalten kann - :confused::confused::confused::confused:

Im FB_NEU könnte ich ja den FB_Byte in einer Schleifenfunktion aufrufen:

CALL "FB_Byte","DB_Byte"
EB :=EB
AB :=AB
STG :=?????

Gruss
momo
 
Das was du da vorhast wird nicht funktionieren.
Wie ich schon geschrieben habe kann SCL keine Instanz indexieren.
Der Befehl :
Code:
call FB_Byte, I_DB[i]
wäre in SCL (z.Zt.) nicht machbar.
Das in die Instanz des FB_Neu zu integrieren wäre möglich - die Ausführung (der FB-Aufrufe) in einer Schleife um dann unterschiedliche Instanzen zu verwenden wird dann aber wieder ein Problem.

Alles andere ist machbar ...

Gruß
LL
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@ LL

OK,
was aber wenn ich den FB_Byte in einer Schleife aufrufe mit einem einzigen IDB und die "Ergebnisse" dann auf meinen Global-DB transferiere.
Dann kann ich doch beim nächsten Schleifendurchlauf wieder den gleichen IDB beschreiben?

FOR i = 1 TO 2 DO

CALL "FB_Byte", "DB_Byte"
EB :=EB
AB :=AB
STG :=????? (** "DB_SPS".UDT_SPS **)

END_FOR;

"DB_SPS".UDT_SPS geht ja leider so nicht ...
 
Soll das wirklich so bleiben ? Also nur 2 Eingangs-Bytes und 2 Ausgangs-Bytes pro FB ?

Es kommt mich vor das es handelt sich um ganz normales FB+IDB programmstruktur, und wo man es sammelt in ein FB mit multiinstanz.
Bis maximal 4 Eingangs-Bytes und 4 Ausgangs-Bytes pro FB, ist es nicht notwendig mit indizierung, pointers oder so was.
 
@ Jesper

Nein, ist wieder nur ein einfaches Beispiel.
Es hätte in meinem letzten Post natürlich heissen müssen:

FOR i = 1 TO BYANZ DO
(** BYANZ = Byteanzahl über Eingangsparameter frei wählbar **)

CALL "FB_Byte", "DB_Byte"
EB :=EB
AB :=AB
STG :=????? (** "DB_SPS".UDT_SPS **)

END_FOR;
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Und da habe ich mir auch falsch formuliert.

In dein 'innere' FB gibt es nur 1 eingangs-byte und 1 ausgangs-byte. Soll das so bleiben ?

Sind die eingangs-bytes und ausgangs-bytes wirklich in zwei blöcken mit denselbe Reihenfolge, ohne 'löckern' ?
 
@Jesper

Ja, das bleibt so.
Die Blöcke sind durchgehend, ohne Löcher. Falls ich mehrere Blöcke brauche muß ich den FB_NEU mehrmals aufrufen.

Der erste Block kann z.B. sein:
EB2 bis EB10 (IN)
und AB6 bis AB14 (IN_OUT)
--> BYANZ = 11

Dann könnte ich den FB_NEU nochmal aufrufen mit z.B.:
EB30 bis EB35 (IN)
und AB40 bis AB45 (IN_OUT)
--> BYANZ = 6

STG vom ersten Aufruf würde dann im DB_SPS.V1_8 beginnen und bis DB_SPS81_88 gehen, weil im ersten Aufruf 11 Bytes = 88 Bits ausgewertet werden.
STG vom zweiten Aufruf würde im DB_SPS.V89_96 beginnen und bis DB_SPS129_136 gehen, weil im zweiten Aufruf 6 Bytes = 48 Bits ausgewertet werden.
Also insgesamt 136 x UDT_SPS, die im DB_SPS vorher manuell angelegt werden müssen.
(Wenn ich mich jetzt nicht verrechnet habe - ich bin schon ganz wucki...)

Gruss
momo
 
"DB_SPS".UDT_SPS geht ja leider so nicht ...

warum nicht ?
Es muss dann halt nur ein ARRAY[1..x] of UDT sein - dann geht das sehr wohl ...

Wenn du in der Schleife immer den gleichen FB mit der gleichen Instanz benutzt, dann gibt das keine Probleme - wenn der FB von seinem Innenleben her (Programm-Code) das so verträgt ...
 
Zurück
Oben