TIA Array variabler Länge an FB übergeben (TIA 12, SCL, S7-1200 & S7-1500)

joergflorian

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

Ich konnte leider über Google bisher nichts finden was mir weiterhilft. Sorry, falls das Thema schon abschliessend irgendwo behandelt wurde.

Ich möchte in meinem FB kein Array fester Grösse als IN_OUT Variable definieren, da dessen Grösse sich erheblich unterscheiden kann -> Unötige Speichervorbelegung, da ich vom grössten Fall ausgehen muss.
Da der Baustein auf einer S7-1200 und einer S7-1500 gleichermassen laufen sollte, fällt AWL weg. Pointer gibt es auf der 1200 nicht und Variant scheint noch nicht "öffentlich" nutzbar zu sein.

Kenn jemand von Euch einen Weg, wie ich ein Array so übergeben kann und wie ich anschliessend auf die Daten lesend/schreibend zugreifen kann?

Vielen Dank
Florian
 
Warum musst Du denn das Array erst in den FB übergeben und arbeitest nicht direkt mit der Quelle?
Bei IN_OUT stecket dieses doch bestimmt in einem DB, oder?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ja das Array steckt in einem DB.
Der Baustein muss aber multi-instanz-fähig sein. D.h. ich muss ja jedem Instanz-Aufruf ein eigenes Array übergeben können.
Oder versteh ich Dich falsch?
 
Ja das Array steckt in einem DB.
Der Baustein muss aber multi-instanz-fähig sein. D.h. ich muss ja jedem Instanz-Aufruf ein eigenes Array übergeben können.
Kann es sein, dass Du gerade Multiinstanz und mehrfache Verwendung des FB miteinander verwechselst?

Arbeitet denn jede Instanz des FBs mit einem eigenen Array-DB? Wenn ja, übergib' den DB z.B. als BlockDB.
Bin da jetzt aus dem Kopf nicht so firm drin, aber halt anstatt die ganzen Daten nur den Weg zu diesen übergeben und dann dort direkt bearbeiten.
 
Da ist mir auch noch nichts elegantes eingefallen.
Bei Step7 habe ich mir wenn ich sowas brauchte in der Quelle immer eine Konstante (CONST ARR_SIZE := 100; END_CONST) angelegt, und dann in einem Rutsch beim Anlegen eines Arrays diese Konstante mit angeben können, und auch bei Schleifenbearbeitung gleich auf diese Konstante aufsetzen können.

Bei TIA hat man sich überlegt die lokalen Konstanten entfallen zu lassen und auf globale Konstanten zu wechseln. Prinzipiell war die Idee ja nicht schlecht, nur kann man diese Konstanten nicht mehr bei einer Variablendeklaration angeben.

In einer externen Quelle kann man zwar CONST immer noch angeben und der Compiler frisst das sogar anstandslos (außer wenn man anstelle CONST VAR_CONST schreibt, dann stürzt das TIA Portal beim Übersetzen ab). Vielleicht war das irgendwann mal aktiv, und als man feststellte man bekommts nicht gebacken ist es rausgeflogen. In der Doku ist CONST auch noch als Schlüsselwort gelistet.

Wahrscheinlich könnte man um das umzusetzen etwas mit PEEK/POKE zusammenbauen. Meiner Meinung nach sind diese Funktionen aber das schlimmste was Siemens sich bei den neuen Steuerungen hat einfallen lassen. Ein einfacher Pointer-Datentyp wie bei Codesys, und man hätte sich den ganzen Käse mit Peek/Poke/Any/Variant und sowas schenken können.

Mit einem UDT der das Array beinhaltet und einer globalen Konstante mit der Array-Größe könnte man das noch halbwegs anständig hinbekommen. Wenn sich die Array-Größe ändert müsste man zumindest nur zwei Stellen bearbeiten. Ändert man nur eines von beiden handelt man sich einen Fehler ein.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@hucki
Ich glaube nicht. Jede Instanz kriegt Ihren eigenen Instanz-DB.

also z.B.
Instanz1 des FB soll mit DB1.Array1 und DB1.Array2 ... gefüttert werden können (je nach Aufruf). Wobei Array1 und Array2 ... unterschiedlich gross sein können.
Instanz2 des FB mit DB1.Array10 und DB1.Array11 ...

Mit Block_DB müsste ich ja dem FB jeweils noch den Startoffset des jeweiligen Arrays mitgeben, was mir bei vielen Arrays etwas mühselig scheint...
Oder halt für jedes Array einen eigenen DB verwenden.

Danke für Dein Vorschläge.

@Thomas_v2.1
Ja ein einfacher Pointer-Datentyp... Das wärs ;)...
Das mit der Const geht leider nur, wenn alle Arrays gleich gross sein können.

Danke auch Dir. Da sollte Siemens noch was tun!
 
Spätestens wenn du in einem DB die wirkliche Array-Größe angibst, musst du die Größe wissen und als Konstante eingeben.
Oder willst du auch die Datenbausteine erst während der Laufzeit erzeugen? Wie entscheidest du dann wie viel Platz noch in der CPU ist, und was passiert wenn zu wenig?

Ich finde es am Besten wenn alle Größen statisch und zur Compilezeit festgelegt sind. Mit den Konstanten des Step7-SCL ging das noch halbwegs komfortabel. Wenn man beim TIA die Anwenderkonstanten auch bei Array-Größen einsetzen könnte, wäre das sogar noch besser als bei Step7. Das wäre mein Favorit.
Vielleicht kommts ja in einer späteren Version.
 
@hucki
Ich glaube nicht. Jede Instanz kriegt Ihren eigenen Instanz-DB.

also z.B.
Instanz1 des FB soll mit DB1.Array1 und DB1.Array2 ... gefüttert werden können (je nach Aufruf). Wobei Array1 und Array2 ... unterschiedlich gross sein können.
Instanz2 des FB mit DB1.Array10 und DB1.Array11 ...
Ich glaube doch. ;)

Bei einer Multiinstanz beinhaltet der Instanz-DB eines übergeordnetem FBs die Instanz eines (oder mehrerer) untergeordneten FBs, so das dieser keinen eigenen Instanz-DB besitzt.
Es sind also nicht viele Instanz-DBs eines FBs vorhanden, sondern viele Instanz-DBs in einem Multiinstanz-DB zusammengefasst.



Mit Block_DB müsste ich ja dem FB jeweils noch den Startoffset des jeweiligen Arrays mitgeben, was mir bei vielen Arrays etwas mühselig scheint...
Oder halt für jedes Array einen eigenen DB verwenden.
Ja, mit den separaten DBs ist es da wahrscheinlich einfacher, aber nicht unbedingt übersichtlicher.

Aber wenn nicht mal Thomas_v2.1 dafür 'ne Lösung hat ... :(
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich glaube doch. :wink:

Du glaubst richtig ;)... Der Baustein sollte trotzdem auf beide Arten funktionieren

Spätestens wenn du in einem DB die wirkliche Array-Größe angibst, musst du die Größe wissen und als Konstante eingeben.
Oder willst du auch die Datenbausteine erst während der Laufzeit erzeugen? Wie entscheidest du dann wie viel Platz noch in der CPU ist, und was passiert wenn zu wenig?

Ich finde es am Besten wenn alle Größen statisch und zur Compilezeit festgelegt sind.

Das sind berechtigte Einwände und ich bin Deiner Meinung, dass alle Grössen bereits zur Compilezeit festgelegt sind.
Ich möchte dem Anwender halt möglichst viel Flexibilität bei der Grösse der Arrays geben. Zum Beispiel sind nicht alle Rezepturen von gleicher Grösse (Komplexität). Da wären verschiedene Arraygrössen gut, um Speicherplatz zu sparen.


Ich danke Euch beiden für die Inputs!

Ich tendiere zur Umsetzung mit BLOCK_DB. Damit bleibt der Anwender flexibel, was ein wenig zu Lasten der Übersicht geht.
 
Zuletzt bearbeitet:
Hi

noch geht das was du machen willst nicht. Zumindest nicht für dich.
Aber vielleicht bringt die V13 neben vielen neuen Fehlern ja doch ein paar Verbesserungen.

Wer sich mal den TSEND oder den TRCV angesehen (gibt es glaube ich seit V11), der stellt fest, dass es diese Bausteine schaffen Arrays unterschiedlicher Länge entgegen zu nehmen und mit deren Inhalt etwas zu tun.
Es ist also möglich dem TSEND an der einen Stelle im Programm ein Array[1..100] of DTL und an anderer Stelle im Programm ein Array[-1..33] of "MyUdt4711" zu übergeben. Beide werden korrekt auf eine andere Steuerung übertragen und können dort von TRCV wieder in entsprechende Arrays abgelegt werden. Der Datentyp dieses Wunderbeinchens ist VARIANT.

S. hat also noch ein paar Asse im Ärmel und laut Mitarbeitern am Messestand soll die V13 auch uns armen Anwendern die echte Verwendung von VARIANT erlauben. Wie viel hatte der allerdings keine Ahnung.

Die Verwendung von BLOCK_DB klappt auf einer 1200 gar nicht. Dort gibt es statt dessen nur einen DB_ANY. Eben das was an diese unsäglichen PEEK und POKE dran kommt.

Wir merken halt immer wieder, das TIA noch recht grün ist.

'n schön' Tach noch
HB
 
Hallo HB,

Danke für Deine Hinweise. Das macht Hoffnung ;).

Die Verwendung von BLOCK_DB klappt auf einer 1200 gar nicht. Dort gibt es statt dessen nur einen DB_ANY. Eben das was an diese unsäglichen PEEK und POKE dran kommt.

Ja, das hab ich leider auch bemerkt. Ich bin mittlerweile wieder am Anfang und verwende halt momentan fixe Arraygrössen.

Ich hoffe auf die nächsten Versionen von TIA.

Grüsse
Florian
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich hatte bzw. habe immer noch das gleiche Problem wie joergflorian. Ich habe bis heute keine Lösung gefunden, die auf beiden Steuerungen lauffähig ist. Die einfachste Lösung wäre, wenn big S den Variant Data type für den user benutzbar gestalten würde, was nach meinen Informationen von Siemens NICHT für die V13 vorgesehen ist (Aussage: Man möchte den User vor sich selbst schützen).

... naja ich habe die Hoffnung zumindest noch nicht aufgegeben ;-)
 
... was nach meinen Informationen von Siemens NICHT für die V13 vorgesehen ist (Aussage: Man möchte den User vor sich selbst schützen).

... naja ich habe die Hoffnung zumindest noch nicht aufgegeben ;-)

Hi Beckx-net

mir hat man auf der Messe gesagt dass was zur V13 käme. Man soll den Typ prüfen können und lesen und schreiben können. Aber so richtig konkret wurde er leider nicht.

Warten wir es ab
HB
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi

in der V13 kann man lokale Konstanten für Array-Grenzen einsetzen.
Aber globale Konstanten aus einer Symboltabelle gehen nicht. (Ach so da heißt ja jetzt Tagtable)
Wieder mal nur die halbe Hausaufgabe gemacht.

'n schön' Tach auch
HB
 
Hallo,

ich stehe anscheinend an dem selben Problem momentan.
Ich habe mir einen FC geschrieben, der einen String zerlegen soll. Am Ausgang würde ich gerne ein Array of String anlegen, indem dann die Teilstrings reinkommen. Aber die Größe des Arrays will ich nicht festlegen. Kann ich da irgendwie mit Pointer arbeiten und auch die Größe rauskriegen?
Der FC wird dann in einem FB aufgerufen und das Array ist im Static abgelegt.
 
Wenn du das Array im Static ablegst ist es doch auch fest.
Wahlweise könntest du vielleicht für die Obergrenze eine Konstante einsetzen, so dass du wenigstens beim Projektieren das Array verändern kannst.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hab es jetzt mit Variant geschafft.
Klappt prima.

Code:
#iElements := UDINT_TO_INT(CountOfElements(#RESULT));
IF #iElements = 0 OR NOT IS_ARRAY(#RESULT) OR TypeOfElements(#RESULT) <> String THEN
    ENO := false;
    RETURN;
END_IF;

#sTmp := '';
FOR #iElement := 0 TO (#iElements - 1) DO
    #iError := MOVE_BLK_VARIANT(SRC := #sTmp, COUNT:=1, SRC_INDEX:=0, DEST_INDEX:=#iElement, DEST=>#RESULT);
    IF #iError <> 0 THEN
        ENO := false;
        RETURN;
    END_IF;
END_FOR;

#iLen := LEN(#STRING);
#sTmp := #STRING;
#iElement := 0;

WHILE #iLen > 0 AND #iElement < (#iElements - 1) DO
    #iDelimiterPos := FIND(IN1 := #sTmp, IN2 := #DELIMITER);
    IF #iDelimiterPos > 0 THEN
        #iElementLen := #iDelimiterPos - 1;
        #iError := MOVE_BLK_VARIANT(SRC := LEFT(IN := #sTmp, L := #iElementLen),
                                    COUNT := 1, SRC_INDEX := 0, DEST_INDEX := #iElement, DEST => #RESULT);
        IF #iError <> 0 THEN
            ENO := false;
            RETURN;
        END_IF;
        #iRestLen := #iLen - #iDelimiterPos;
        #sTmp := RIGHT(IN := #sTmp, L := #iRestLen);
    ELSE
        #iError := MOVE_BLK_VARIANT(SRC := #sTmp, COUNT := 1, SRC_INDEX := 0, DEST_INDEX := #iElement, DEST => #RESULT);
        IF #iError <> 0 THEN
            ENO := false;
            RETURN;
        END_IF;
        #sTmp := '';
    END_IF;
    #iLen := LEN(#sTmp);
    #iElement := #iElement + 1;
END_WHILE;
 
Hallo Mobi

du solltest dir für solche Zwecke mal SPLIT ansehen. Das kann Char-Arrays nach Begrenzungszeichen durchsuchen und in einzelne Strings zerlegen.
Damit hast du FIND, LEFT und RIGHT in einem. Ich kann es jetzt gerade nicht ausprobieren, aber so weit ich mich erinnere, akzeptiert SPLIT auch STRINGs am SrcArray. Und wenn nicht, dann mach ein Kopie von #STRING mittels StringToChars() in ein #aTmp : CHAR[0..255];
Das was SPLIT liefert kommt dann in #sTmp und das kann dann mittels MOVE_BLK_VARIANT nach #RESULT kopiert werden.

Damit hast du jeden Buchstaben nur drei mal kopiert. Dein Programm kopiert jeden Buchstaben im Schnitt 3+#iElements/2 oft.
Das erste mal wegen #sTmp:=#STRING. Das zeite Mal bei SRC:=LEFT(). Diese Zuweisung legt dir einen weiteren versteckten String nach TEMP! Das dritte mal wegen MOVE_BLK_VARIANT(). Und dann hast du in deiner Schleife durch #sTmp:=RIGHT() jeden bis dahin übrig gebliebenen Buchstaben kopiert.

Vor allem das Kopieren wegen RIGHT, spart dir SPLIT.

'n schön' Tach auch
HB
 
Zurück
Oben