Baustein mit INOUT oder Baustein mit Interface?????

SY50

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

ich habe mir einen Baustein erzeugt, welcher diverse Aufgaben einer Verfahrachse erledigt.
Hierzu habe ich für die Ansteuerung eine Struktur als INOUT deklariert, welche Bspw. Reglerfreigabe, Betriebsart Geschwindigkeit, Sollposition usw. enthält.

Ist dies eurer Meinung nach eine Gute Lösung, oder sollte man an so etwas mit einem Interface ran gehen?
Wenn ich ein Interface mit den Eigenschaften Reglerfreigabe usw. hätte, müsste ich diese aber ja auch immer von den wirklichen Variablen zuweisen, oder?

Kann mir jemand mal Tipps geben, ob ich da schon auf dem richtigen Weg bin? :)
 
Wie bekommst Du Deine boolschen Eingangs-/Ausgangszustände in/aus den STRUCT?
Es ist viel übersichtlicher und schön beobachtbar, wenn man in FUP oder KOP die Signale an den Baustein schaltet, als sie in extra Programmteilen in/aus den Struct zu kopieren.

Nur eine STRUCT mit allen Werten an INOUT legen würde ich nicht machen. Es kommt auf eine gesunde Mischung Bausteinschnittstelle IN + OUT und extra Werte per STRUCT an.

Außerdem solltest Du mal einen Blick in die Referenzdaten bzw. GeheZu werfen, ob und wie die verwendeten Operanden da auftauchen (sprich: findbar sind) und ob das Deinem Verständnis von wartungsfreundlichem bzw. diagnostizierbarem und verstehbarem Code entspricht.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo, habe mich vielleicht etwas schlecht ausgedrückt. Ich habe eine Mischung aus in, inout ... Ich habe aber eine Struktur, welche alle Variablen der Ansteuerung enthält (Sollwert, Sollposition usw.) und eine Struktur für die stati. Diese habe ich als inout gewählt, um die Performance zu schonen und nicht immer alle Werte an den Baustein übergeben zu müssen. Ich will auch keine tausend Eingänge an dem fb. Im Prinzip ist das ja schon ne Schnittstelle, verstehe nur nicht so ganz den Sinn eines Interface, wenn ich von außen auf den du zugreifen will.
Also ob ich jetzt Interface.xy im Quellcode schreibe, oder bausteininstanz.xy, das bleibt sich doch gleich oder?
Andersrum finde ich es schon interessanter, wenn der fb einen Eingang vom Typ Interface hat und dann während der Laufzeit quasi eine Methode eines externen fbs aufruft. ..... Aber egal... Auf die Variablen kommt man doch sehr gut drauf innerhalb des fbs und zwar mit. Inoutname.variable.... Indien der Struktur gebe ich außen vor. Strukturinstanz.sollwert := 100.
Ist doch übersichtlich.????
 
Der Sinn eines Interfaces (aus meiner Sicht) wäre, wenn mehrere Bausteine die gleiche Variablen-Struktur mit gleichen Namen und Typen verwenden sollen. Wäre das bei dir so
dann macht ein Interface Sinn - ansonsten ist es eigentlich sinnlos ...

Gruß
Larry
 
Ja ich habe 2 verschiedene Regler, welche ich durch die Gleiche Struktur gleich ansprechen will. Die Konvertierung übernehmen dann 2 FBs.
Aber ein Interface kann ja nur Eigenschaften und Methoden beinhalten.
Da meine Struktur allerdings von einer übergeordneten Steuerung übertragen wird, müsste ich ja meine Variablen in der Struktur dem Interface zuweisen. Finde ich irgendwie umständlich.
Auch wenn das nicht der Fall wäre. Was hätte ich durch ein Interface für ein Vorteil im Gegensatz zu der InOut Struktur?
Keinen oder?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
INOUT gegen Einzelparameter

Bei IN_OUT machst Du einen Call By Reference, d.h. Du übergibst im Prinzip einen Zeiger auf die Datenstruktur.

Das ist bei vielen Parametern auf jeden Fall das effektivste, was die Performance angeht. Die meisten Implementationen der Softmotion machen das so.

Es gibt aber 2 Probleme:

Bei IN_OUT kann (bei nicht sorgfältiger Programmierung) die FB Implementation alle Member der Structur nachhaltig verändern, d.h. es kommt potentiell auch etwas zurück, was wo anders dann böse Nebeneffekte haben kann. (deshalb auch bei Safety nicht gern gesehen)

In Safety ist so etwas ab SIL2 meines Wissens nach nicht erwünscht/erlaubt, wenn Ihr also in Zukunft das mal braucht, dann ist ein Refactoring angesagt.

Ich hatte es in der Vergangenheit aber so gehalten, dass ich bei FBs, die ich allein aufrufe und somit übersehen kann, IN_OUT aus Performance Gründen verwende.

Eine Aufteilung in mehrere Strukturen kann sich auch anbieten.
 
Ja ich habe es auch in Ansteuerung und in Status aufgeteilt.
Aber eben aus Performance gründen beides auf Inout belassen.
Interface ist meines Erachtens dann ne sinnvoll, wenn ich Methoden aufrufen will, welche in irgend einem Baustein vorhanden sein sollen. Rein für variablen Übergabe sehe ich das nicht als sinnvoll an, oder seht ihr das anders?
 
Bei IN_OUT machst Du einen Call By Reference, d.h. Du übergibst im Prinzip einen Zeiger auf die Datenstruktur.

Das ist bei vielen Parametern auf jeden Fall das effektivste, was die Performance angeht.
Ich glaube, das mit der Performance stimmt so nicht.
Das könnte stimmen, wenn Zeiger auf große Datenstrukturen übergeben werden, aber nur auf wenige Strukturmember tatsächlich zugegriffen wird.

Bei Struktur an IN_OUT muß bei jedem Zugriff auf eine Variable zur Laufzeit erst aufwendig die Adresse berechnet werden. Das bläht den Code auf und kostet auch mehr Ausführungszeit.

Wenn sowieso auf jede Variable zugegriffen wird, dann ist es ziemlich sicher performanter, das kopieren der Aktual-Struktur auf die Bausteinschnittstelle (IN und OUT) dem Aufrufer zu überlassen. Das kann der Compiler sehr effektiv machen.

Vorsicht: bei Übergabe von Strukturen per IN_OUT erhält man keine konsistente Kopie der Daten sondern greift jedesmal erneut auf die original-Daten zu. Wenn der Code durch einen höher priorisierten Prozess unterbrochen wird, der auf die original Daten schreibt, dann können mehrfache Zugriffe im Baustein unterschiedliche Ergebnisse liefern.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Also ich würde mal sagen, dass in meinen Bausteinen Ca. 50% der übergebenen Inout Daten zyklisch gelesen/geschrieben werden. Zu bestimmten Zuständen, dann eben auch der Rest.
Trotzdem nochmal die Frage... 😊 Interface macht bei variablenübergabe keinen Sinn oder?
 
... wie ich schon geschrieben habe : das mußt du selbst entscheiden. Ich (für mich) habe darin noch keinen wirklichen Sinn gefunden - nicht mal bei meinen .Net-Konstrukten.

Gruß
Larry
 
Interfaces lohnen sich vorallem dann wenn man Bausteine / Klassen mit gleichen Eigenschaften und oder Methoden verwendet, die aber ansonsten einen unterschiedlichen Unterbau haben.
Gerade Antriebsbausteine sind da ein Paradebeispiel für. Die Funktionen sind idR. gleich (Links-/Rechtlauf, Stop, Vsoll etc.) aber die Ansteuerung variiert von Hersteller zu Hersteller.

Das Larry meint, dass er in .net keine Interfaces nutzt, zeigt wie gut man damit arbeiten kann ohne sich Gedanken darüber zu machen. So ziehmlich alle Klassen die im Framework enthalten sind, haben min. ein Interface implementiert. Und wenn es nur IDisposable oder im Falle von Collections IEnumerable ist.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... das heißt auch nicht, dass ich die .Net-Interfaces nicht selbst schon mit eingebunden habe - ich habe nur noch keinen Ansatz gefunden, wo es wichtig (für mich) gewesen wäre, Eigene zu erstellen ...
 
Finde es halt grade im Bereich, wo man Daten auch in einer Visu darstellen will "einfacher" oder "sinnvoller" direkt eine Struktur zu erstellen und an den FB zu übergeben, als dann nochmals die Eigenschaften eines Interfaces an Visu Variablen zu übergeben.
 
Verständnisfrage

Finde es halt grade im Bereich, wo man Daten auch in einer Visu darstellen will "einfacher" oder "sinnvoller" direkt eine Struktur zu erstellen und an den FB zu übergeben, als dann nochmals die Eigenschaften eines Interfaces an Visu Variablen zu übergeben.

Ich denke, man sollte einmal klar stellen, worüber man reden möchte. Ich gebe mal meine etwas verkürzte Vorstellung der beiden Begriffe hier.

Interface: Ein Interface beschreibt abstrakt eine Menge von Methoden und deren Aufrufumgebung. Es enthält keine Informationen, wie innerhalb der Methoden konkret gearbeitet wird. Also keine Implementation von irgendwelchen Funktionalitäten.

Interfaces dienen dazu, verschiedene vergleichbare aber unterschiedlich gelöste Aufgaben unter einen Hut zu bringen, damit man sie von einer höheren Ebene mit der gleichen Strategie ansprechen kann.

Structuren: In Structuren fasst man Variablen gleichen oder unterschiedlichen Typs zusammen, um sie gebündelt bearbeiten zu können. Structuren sind selbst definierte Datentypen und können selber wieder Structuren enthalten.

Auf verschiedenen Ebenen werden Structuren entweder als ganzes gesehen oder aufgedröselt in die einzelnen Elemente bearbeitet.

Structuren werden also dazu verwendet, um auf einer höheren Ebene zusammengehörige Einzeldaten zusammenzufassen, eben zu strukturieren.

Deshalb aus meiner Sicht erübrigt sich die Frage von SY50: er braucht keine Interfaces im Moment sollte aber seine Daten auf der höheren Programmier Ebene übersichtlich in Structuren zusammenfassen.

N.B. Da vorher einmal gepostet wurde, dass die Adressberechnung für die Structurelemente aufwendig ist, das erledigt im Prinzip zum grossen Teuil der Compiler, der weiss, an welcher Adresse der Startpunkt der Structur liegt und muss dann lediglich noch den Offset zum Punkt hinzuaddieren, an dem dann innerhalb der Structur das gewünschte Element liegt.

In der Regel müsste das im Maschinencode so aussehen: Lade Adressregister, Addiere Offset und fertig ist es, das ist keine Aufblähung vom Code.
 
Da muss man als alter Siemensianer auch umdenken, denn alles was auf einer S7 extrem langsam und speicherfressend abläuft, ist auf allen anderen (heutzutage üblichen) Prozessoren gerade schnell und speichersparend, wie eben die Parameterübergabe über Zeiger.
 
N.B. Da vorher einmal gepostet wurde, dass die Adressberechnung für die Structurelemente aufwendig ist, das erledigt im Prinzip zum grossen Teuil der Compiler, der weiss, an welcher Adresse der Startpunkt der Structur liegt
Bei Übergabe per Referenz: Der Compiler kann nicht wissen, an welcher Adresse die zur Laufzeit übergebene Struktur liegt. Er muß zunächst die Adresse aus dem Übergabeparameter lesen und kann erst danach auf die Struktur zugreifen. Das sollte doch wenigstens "ein klein wenig" aufwendiger sein als direkt auf die an bekannter Adresse liegende Struktur zuzugreifen.
Weiß denn jemand sicher, wieviel aufwendiger oder weniger aufwendig diese Parameterübergabe per Zeiger ist? Wäre ja mal interessant die Programmgrößen und Ausführungszeiten zu vergleichen, z.B. eine Struktur von 20 REAL an eine Funktion oder eine Funktionsbaustein-Instanz übergeben und die Summe der 20 Werte zurückgeben. Mal als Struct an IN und mal an INOUT.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Eine INOUT Variable kann aber nicht zur Laufzeit dynamisch verknpüft werden. D.h. der Compiler kennt schon die Addresse der Variablen / Struktur.
Ansonsten muss man Pointer verwenden, und da hängt es halt vom ADR Befehl ab (oder was halt immer benutzt wird um die Startaddresse zu holen). Die restlichen Offsets sind ja dann wieder im Pointer-Typ enthalten.
Einzig beim Any-Datentyp könnte ich mir vorstellen, das da einiges zu rechnen ist. Aber ich bin mir nichtmal sicher ober der Überhaupt von CodeSys oder TwinCAT unterstützt wird (TC3 kennt den Any-Type glaube ich).
 
Bei x86 oder besser aktuell IA-32 macht es keinen Sinn mehr die Zyklen zu zählen, weil die Geschwindigkeit zusätzlich von diversen anderen Faktoren abhängt.

Bei Übergabe eines Zeigers auf eine Struktur, wird in der Funktion nur einmalig ein Register wie ebx mit der Adresse geladen, und die folgenden Anweisungen laufen dann über sowas wie MOV eax, word ptr [ebx+0]. Bei Intel schimpft sich das dann Micro-Fusion, wo mehrere einzelne Anweisungen zu einer kombiniert werden. Zumindest schafft der Prozesser dann trotzdem 4 oder 5 Anweisungen pro Zyklus zu bearbeiten. Ich würde darum mal annehmen, dass es trotz kompliziert aussender Operation in einem Zyklus verarbeitet wird.

Wenn die ganzen Werte einer Struktur als einzelne Parameter übergeben würden, müssten diese bei Funktionsaufruf auch einzeln auf den Stack gepusht werden. Ich glaube nicht dass das performanter ist. Die Prozessoren sind auf die Sprache C ausgelegt, und da ist eine Übergabe einer Struktur per Zeiger Standard, d.h. alles ist darauf optimiert.
 
Eine INOUT Variable kann aber nicht zur Laufzeit dynamisch verknpüft werden. D.h. der Compiler kennt schon die Addresse der Variablen / Struktur.
Das betrifft die äußere Beschaltung - da weiß der Compiler, welche Adresse in den INOUT geschrieben wird. Doch wie ist das mit der Entgegennahme des Zeigers in einer Instanz eines Funktionsbausteines? Wie kann der Compiler die an der FB-Instanz außen angelegte Adresse berücksichtigen? Oder wenn die FB-Instanz oder eine Function mehrmals aufgerufen wird, wie kann in dem Baustein die Adresse schon zur Compilierzeit bekannt sein?

Harald
 
Zurück
Oben