Konstanten an FB übergeben

wonderfulworld

Level-1
Beiträge
114
Reaktionspunkte
10
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

ich habe mehrere global deklarierte Arrays, die von mehreren Instanzen des selben FBs bearbeitet werden sollen. Wenn ich diese global deklarierten Arrays alle gleichgroß mache, dann bekomme ich ein Speicherplatzproblem, deshalb habe ich folgende Lösungsansätze probiert:

1. Lösungsansatz funktioniert leider nicht

Einem FB ein Array als IN_OUT Variable deklariere, und die Größe des Arrays mit einer Konstanten definiere.
Diese Konstante dann aber als INPUT_VARIABLE übergeben
Code:
VAR_INPUT CONSTANT
   MYCONSTANT : INT;
END_VAR
VAR_IN_OUT 
   myArray : ARRAY[0..MYCONSTANT] OF BYTE;
END_VAR
Wenn ich das so mache, und den FB mit den nötigen Eingangsvaribalen versorge kommt immer die Fehlermeldung
Unzulässiger Typ für Eingang myArray von Baustein TEST: KANN ARRAY[0..76] of BYTE nicht in ARRAY[0..MYCONSTANT] of BYTE(VAR_IN_OUT) konvertieren.

2.Lösung die tutm gefällt mir aber nicht

Abhilfe würde das Arbeiten mit Pointern schaffen, etwa so.
Code:
VAR_IN_OUT 
   startAdresseArray : WORD;
   sizeOfArray : WORD;
END_VAR

Die zweite Lösung gefällt mir aus folgenden Gründen nicht:
1. Pointer sind an sich kein Problem, aber die obere Lösung wäre aus meiner Sicht schöner und auch sicherer.
2. Ich müsste bei der zweiten Lösung relativ viel im FB ändern.
3. Die erste Lösung hatte außerdem den Charme, dass man Konstanten an FBs übergeben kann. Das heißt ich sehe am FB-Eingang, dass er von Konstanten abhängig ist und von welchen.

Weiß jemand noch ne dritte Lösung oder wich ich das mit Lösung eins doch noch hinbekommen kann?

Vielen Dank schon mal im vorraus
wonderfulworld

P.S.
Das von mir eingesetzte System ist eine ELAU-Steuerung (EPAS-4 basiert auf Codesys 2.3). Wäre aber auch an einer Lösung die nur in Codesys V3 funktioniert interessiert.
 
Zuletzt bearbeitet:
Warum willst du die Arrays an die FBs übergeben? Wenn die Arrays global sind, kannst du aus deinem FB direkt auf sie zugreifen. Das ist ja der Sinn von globalen Variablen (global = überall verfügbar).
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Code:
VAR_INPUT CONSTANT
   MYCONSTANT : INT;
END_VAR
VAR_IN_OUT 
   myArray : ARRAY[0..MYCONSTANT] OF BYTE;
END_VAR
Wenn ich das so mache, und den FB mit den nötigen Eingangsvaribalen versorge kommt immer die Fehlermeldung

Ich sehe da mehrere Probleme:

Als Eingangsvariable deklarierst Du eine NEUE Variable MYCONSTANT. Das ist vom Wert vielleicht das gleiche wie die Globale Variable MYCONSTANT aber eine andere neue Variable!

Weiterhin ist die Eingangsvariable MYCONSTANT als CONSTANT deklariert aber beim Aufruf wirst Du doch MYCONSTANT einen Wert zuweisen wollen? Das ist nicht erlaubt, der Wert einer CONSTANT wird bei der Deklaration festgelegt.

In C++ ist so etwas zulässig, da bedeutet es aber einen Hinweis an den Compiler, dass er sicher stellen muss, dass die Variable Innerhalb der Funktion nicht verändert wird.
 
Warum willst du die Arrays an die FBs übergeben? Wenn die Arrays global sind, kannst du aus deinem FB direkt auf sie zugreifen. Das ist ja der Sinn von globalen Variablen (global = überall verfügbar).
Ich will einen FB mehrere unterschiedliche Arrays bearbeiten. Das heißt ich habe drei Instanzen von dem FB, die jeweils ein anderes Array bearbeiten. Wenn ich jetzt nicht für jedes Array einen eigenen FB schreiben will, dann muss ich das Array mittels IN_OUT übergeben.
[QOUTE=RobiHerb;446787]
Als Eingangsvariable deklarierst Du eine NEUE Variable MYCONSTANT. Das ist vom Wert vielleicht das gleiche wie die Globale Variable MYCONSTANT aber eine andere neue Variable!
[/QUOTE]
Das ist auch nicht ganz richtig. Ich weise MYCONSTANT nämlich keine Variable sondern eine KONSTANTE zu. Somit ist MYCONSTANT immer noch eine Konstante und das interessante ist, dass der Kompiler ja auch akzeptiert, das ich MYCONSTANT eine KONSTATNE zuweise. Er meckert ja nur an, dass das übergebene Array scheinbar andere Grenzen hat, als das im FB benutzte.

Gruß wonderfulworld
 
Zuletzt bearbeitet:
Wenn der Compiler etwas schluckt, heisst das noch lange nicht, dass es auch funktioniert. Wenn MYCONSTANT eine Konstante ist, kannst Du ihr nicht erst zur Laufzeit einen Wert zuweisen. So wie Du die Deklaration geschrieben hast (ohne Wertzuweisung), hat MYCONSTANT den Wert 0 und behält den auch, selbst wenn Du beim FB-Aufruf versuchst, etwas anderes zu übergeben. Trotzdem, ein sehr kreativer Versuch, Arraygrössen erst zur Laufzeit festzulegen. Aber das geht nun mal nicht, Du wirst also in den sauren Pointer beissen müssen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Warum willst du die Arrays an die FBs übergeben? Wenn die Arrays global sind, kannst du aus deinem FB direkt auf sie zugreifen. Das ist ja der Sinn von globalen Variablen (global = überall verfügbar).

M.M.n. ganz schlechter Stil !

Ea gibt mehrere gute Gründe so einen Unfug nicht zu machen:
- Wie wonderfulworld schon geäussert hat, ist das Array dann fix und jedes mal wenn ein neues Array benötigt wird, bedeutet das eine neue Instanz vom FB. Stichwort Wiederverwendbarkeit.
- Der Code wird schlecht zu warten sein, weil unleserlich. An einen FB gehört eine saubere Schnittstelle.
Allein um den Code im FB nachvollziehen zu können, ist es wichtig alle Variablen in seiner eigenen Schnittstelle wiederzufinden
- Nicht umsonst gibt es in modernen, zugegeben objektorientierten Programmiersprachen, keine globalen Variablen mehr. Man wird gezwungen sauber zu kapseln. Das kann in der SPS Welt auch nicht schaden.


Um zur Problemlösung beizutragen:

Ich würde die Pointer Variante bevorzugen. So bist du in der Arraylänge flexibel und hast eine saubere Schnittstelle.


Daniel
 
Recht hast du.
Ich hatte aus dem Anfangspost nicht herausgelesen das jede Instanz nur auf bestimmte Arrays zugreifen soll und nicht auf alle ....
Dann bleiben wirklich nur noch Pointer. Auf echte dynamische Speicherverwaltung werden wir im SPS Bereich noch lange warten müssen. Da gibt es noch zu viele Probleme mit der Sicherheit und/oder der Echtzeitfähigkeit.
 
Recht hast du.
Ich hatte aus dem Anfangspost nicht herausgelesen das jede Instanz nur auf bestimmte Arrays zugreifen soll und nicht auf alle ....
Dann bleiben wirklich nur noch Pointer. Auf echte dynamische Speicherverwaltung werden wir im SPS Bereich noch lange warten müssen. Da gibt es noch zu viele Probleme mit der Sicherheit und/oder der Echtzeitfähigkeit.

Also, das was ich wollte ist ja keine dynamische Speicherverwaltung. :) Ich will eigentlich nur die Möglichkeit eine Konstante an eine andere Konstante (die in einem FB deklariert wurde) zu übergeben. Die Übergabe soll nicht zur Laufzeit stattfinden, sondern bei der Initialisierung der FB-Instanz. Dass das nicht geht, hatte ich mir schon fast gedacht, aber als ich gesehen habe das man VAR_INPUT das Schlüsselwort CONSTANT mitgeben kann, habe ich halt gehofft...
Naja, jetzt geht das halt nicht. Dann muss ich halt die Pointer-Variante einsetzten. (Die eigentlich ja auch nur eine verkappte dynamische Speicherverwaltung ist und deshalb auch so gefährlich). Aber warum kann man dan VAR_INPUT das Schlüsselwort CONSTANT dann mitgeben?

Vielen Dank für eure Beteiligung es hat Spaß gemacht mit euch zu fachsimpeln
wonderfulworld
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Aber warum kann man dan VAR_INPUT das Schlüsselwort CONSTANT dann mitgeben?
Was nicht verboten ist, ist erlaubt, auch wenn es wenig sinnvoll erscheint. Gut, mit VAR_INPUT CONSTANT könnte man ein Zwischending zwischen globaler und FB-lokaler Konstante bauen, nämlich eine FB-lokale Konstante, die auch noch in der aufrufenden POU lesbar ist. VAR_OUTPUT CONSTANT wäre dafür aber wohl die bessere Wahl.
 
Die 3te Version des Standards ist ja erst seit Anfang des Jahres in trockenen Tüchern. Auch wenn in vielen Entwicklungstools schon Teile davon umgesetzt wurden (CodeSys3, TC3 ...) wirst du dich sicher noch etwass gedulden müssen bis du alle Features nutzen kannst ....
 
Die gibt es ganz sicher, zumindest einen.
Mir ist gerade ein Ansatz für eine Eigenbaulösung in den Sinn gekommen. Noch frisch und nicht ganz zu Ende gedacht, aber da müsste sich was machen lassen. Man könnte einen abstrakten FB oder ein Interface bauen mit Lower_Bound und Upper_Bound als Properties und einer Property für den Zugriff auf die einzelnen Felder eines Arrays, das dann in konkreten Nachkommen-FB's bzw. FB's mit dem Interface mit beliebiger Grösse deklariert wird.
 
Ja, da gibt es in Java ein Desginpattern für. Das heißt Iteratorpattern. Da definiert man einen Interface mit Namen Iterator und gibt die Methoden getNext():Object und hasNext():BOOL. Dann kann man eine while-schleife bauen die so aussieht: (hoffe das der Syntax stimmt. Benutze while-schleifen nie)

Code:
WHILE iterator.hasNext()
   myObject :=  iterator.getNext();
  //tu irgendwas mit myObject
END_WHILE

Zusätzlich kann man dem Iterator auch noch andere Methoden wie getPrevious(), getFirst(), getLast() etc. mitgeben.

Gruß
wonderfulworld
 
Zurück
Oben