Fester Speicherbereich

StructuredTrash

Level-3
Beiträge
1.165
Reaktionspunkte
309
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
vermutlich wäre ich mit meiner Frage bei 3S oder Beckhoff besser aufgehoben, aber vielleicht weiss ja jemand etwas. Gibt es bei CoDeSys/TwinCat einen Speicherbereich, der bei Online Changes garantiert NICHT verschoben wird? Was ist z. B. mit dem Merkerbereich MB?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich meine z. B.
myVar AT %MB4:BYTE;
myVar wird natürlich immer an Byte 4 des MB-Bereichs stehen. Meine Frage ist allerdings, ob der gesamte MB-Bereich bei einem Online Change möglicherweise an eine andere Speicheradresse verschoben wird oder nicht.
 
Ich habe z. B. in meiner Lib einen FB, der die Adresse eines zweiten FB's benötigt. Diese Verknüpfung zu dem zweiten FB bleibt während der gesamten Laufzeit unverändert. Bei nur einem zyklischen Aufruf würde ich die Adresse per VAR_IN_OUT übergeben und mir keine weiteren Gedanken machen. Jedoch hat der FB auch Aktionen, die in der Anwendung recht häufig aufgerufen werden und bei denen ich die VAR_IN_OUT auch jedesmal übergeben muss. Ich würde die FB-Adresse lieber nur einmal bei der Programminitialisierung als Pointer übergeben. Dafür müsste ich aber sicher sein, dass der FB durch Online Changes auf keinen Fall verschoben wird.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Mahlzeit,

du übergibst per Pointer eine Instanz eines FB an einen FB???
Warum?
Greifst du auf die Instanzdaten zu oder was passiert da?

Die Aktion eines FB greift doch auf den Variablenhaushalt des FB zu. Da muss man doch nichts neues übergeben.

Auch wenn du per Pointer auf die Anfangsadresse einer FB Instanz zeigst, sollte sich doch hier nichts verschieben. Die Adresse bleibt die Adresse bleibt die Adresse...

Abgesehen davon halte ich deine Vorgehensweise für unsauber was Wartung und Erweiterung deines Codes angeht. Gerade für andere Programmierer die mal auf soetwas stoßen.

M.M.n. sollten man sauber trennen und verwendete Speicherbereiche z.B. in strukturen sammeln um dann per IN_OUT darauf zu zeigen.

Oder ich habe deine Beschreibung einfach nicht verstanden ;)

Poste doch mal ein Codebeispiel!


Gruß und schönes Fest!
 
du übergibst per Pointer eine Instanz eines FB an einen FB???
Warum?
Greifst du auf die Instanzdaten zu oder was passiert da?
Ich rufe den übergebenen FB auch auf. Wenn ich nur auf seine Daten zugreifen will, was bei anderen FB's meiner Lib der Fall ist, packe ich die benötigten Daten in eine Struct im VAR_OUTPUT-Bereich des FB's und übergebe dann nur diese Struct an andere FB's.
Die Aktion eines FB greift doch auf den Variablenhaushalt des FB zu. Da muss man doch nichts neues übergeben.
Tue ich auch nicht. Aber wenn ich in einem FB VAR_IN_OUT deklariere, muss ich die bei jedem Aufruf, auch bei dem von Aktionen, übergeben. Die dafür benötigte Rechenzeit stört mich bei einem Beckhoff CX kaum. Die Schreibarbeit schon etwas mehr. Vor allem stört mich aber, dass die Aktionen die VAR_IN_OUT gar nicht benötigen, sondern nur auf die lokalen FB-Daten zugreifen.
Auch wenn du per Pointer auf die Anfangsadresse einer FB Instanz zeigst, sollte sich doch hier nichts verschieben. Die Adresse bleibt die Adresse bleibt die Adresse...
Dein Wort in Beckhoffs Ohr. Aber ich bin mir da nicht so sicher. Ich habe schon Online Changes erlebt, nach denen sich die Werte von Konstanten munter änderten. Einmal wusste der Rechner sogar nicht mal mehr, wo seine Eingänge waren. Daher auch meine eigentliche Frage.
Abgesehen davon halte ich deine Vorgehensweise für unsauber was Wartung und Erweiterung deines Codes angeht. Gerade für andere Programmierer die mal auf soetwas stoßen.
Da gebe ich Dir sogar ein wenig Recht. Was ich da mache, ist eigentlich ein Fall für OOP-Vererbung und die damit verbundene erweiterte Typkompatibilität. Aber ich kann mich derzeit noch nicht zum Umstieg auf TwinCat3 durchringen. Habe zu oft Versuchskaninchen gespielt.
Eine andere Möglichkeit wäre der Einsatz von Quelltextbibliotheken, die die Deklaration bestimmter Bezeichner in der Anwendung voraussetzen. In Pascal konnte man damit einiges machen, in CoDeSys
ist so etwas aber nur sehr umständlich durch Export/Import einzelner POUs, DUTs usw. möglich.

So, jetzt wünsche ich aber auch erst mal ein frohes Fest. Die Frage entspringt sowieso keiner aktuellen Notlage. Aber wenn es so kurz vor Weihnachten auch vorm Laptop etwas besinnlicher wird, kommt man schon mal auf Ideen, für die man sonst gar keine Zeit hat.
 
Dein Wort in Beckhoffs Ohr. Aber ich bin mir da nicht so sicher. Ich habe schon Online Changes erlebt, nach denen sich die Werte von Konstanten munter änderten. Einmal wusste der Rechner sogar nicht mal mehr, wo seine Eingänge waren. Daher auch meine eigentliche Frage.

Das ist natürlich übel!
Ich habe auch schon viel Dreck mit den Beckhoff Sachen erlebt. Aber Konstanten die keine Konstanten mehr sind...
Einen großen Bogen gehe ich auch um neue Beckhoff Produkte. Die werden m.M.n. zu früh auf den Markt geworfen.
Lasst die Kunden mal damit klar kommen... oder... wir müssen mit unseren Prospekten erster sein...
Nur gut das die Jungs aus dem Support so gut sind!

Aber zurück zum Thema:
So ganz konnte ich deine Ausführungen nicht nachvollziehen.
Kannst du mal ein Beispielcode (um die vorgehensweise zu Schildern) posten?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Der Code wird nicht viel nützen, weil es ja nicht um ihn geht, sondern um Deklarationsort und Beziehungen zwischen FB's. Ich beschreibe das Ganze aber gern noch mal etwas genauer.
In meiner Lib habe ich einen FB, der eine Störungsliste für die Visu verwaltet. Die Anwendung kann direkt, durch Aufruf einer FB-Aktion, Störungen in die Liste eintragen, tut das aber normalerweise nicht. Stattdessen werden noch Störungs-FB's zwischengeschaltet, die ebenfalls in der Lib deklariert sind. So ein Störungs-FB sammelt die Störungen einer Maschine oder Baugruppe, speichert sie bis zu ihrer Quittierung und trägt sie flankengetriggert in die Störungsliste ein. Dazu braucht der Störungs-FB die Adresse des Listen-FB's, um seine entsprechende Aktion aufrufen zu können. Ich könnte dazu bereits in der Lib eine globale Instanz des Listen-FB's deklarieren. Das möchte ich aber nicht, um im Ernstfall auch einen anwendungsspezifisch abgewandelten Listen-FB einsetzen zu können.
Listen-FB und Störungs-FB's werden also in der Anwendung instanziiert, und dort muss ich den Störungs-FB's die Adresse des Listen-FB's übergeben. Derzeit mache ich das per VAR_IN_OUT. Die Störungs-FB's haben eine Aktion, mit der die Anwendung die Störungen in den FB's speichern kann. Am Ende der POU erfolgt dann der zyklische Aufruf des Störungs-FB's, und erst dabei werden die Störungen in die Liste eingetragen. Die Adresse des Listen-FB's wird also nur beim zyklischen Aufruf des Störungs-FB-Hauptcodes benötigt. Da man VAR_IN_OUT-Parameter aber nicht unbelegt lassen kann, muss ich die Adresse auch beim Aufruf der Speicher-Aktionen übergeben, obwohl sie dabei gar nicht gebraucht wird. Das ist zwar keine Katastrophe, stört mich aber ein wenig.
Wenn ich die Adresse des Listen-FB's nicht als VAR_IN_OUT, sondern als VAR_INPUT-Pointer übergeben würde, könnte ich die Übergabe auf den zyklischen Aufruf des Störungs-FB's beschränken. Wirklich toll finde ich das aber auch nicht, weil ich die Typüberprüfung des Compilers bei VAR_IN_OUT nicht ohne Not aufgebe. Wenn ich die Adresse dagegen nur einmal beim Programmstart übergeben bräuchte, würde mir das die Pointerlösung vielleicht etwas schmackhafter machen. Dann darf aber die Adresse des Listen-FB's durch Online Changes nicht verschoben werden. Und nach meinen bisherigen Erfahrungen schreckt das Laufzeitsystem vor nichts zurück, wenn es ihm für die Speicherreorganistation in den Kram passt. Meine einzige Hoffnung ist, dass vielleicht der MB-Speicherbereich verschont bleibt, solange man in ihm keine Änderungen vornimmt.
 
Nach einem Beispiel hatte ich gefragt, weil wenige Zeilen abgespeckter Code mehr als 1000 Worte sagt.

Ein PLC Programm würde ich so nicht programmieren.
Grundsatzdiskussionen helfen dir aber hier nicht weiter und beantworten ja nicht deine Frage...

Am meisten Sicherheit würde mir bei deinem "Konstrukt" die IN_OUT Variante geben.
Nach deinen negativen Erfahrungen würde mich das wenige Mehr an Tipparbeit nicht stören.
Ich kaufe mir gerne Sicherheit,Stabilität,einfach zu wartenden Code usw. durch Tipparbeit!

Wie wäre es mit einem Input
ADR(FB_Instance)
?

Auch wenn sich FB_Instance irgendwo im Speicher verschiebt, wird ja die neue Adresse übergeben.


Gruß
 
Nach einem Beispiel hatte ich gefragt, weil wenige Zeilen abgespeckter Code mehr als 1000 Worte sagt.
Stimmt meistens, aber in diesem Fall hätte das vermutlich mehr Fragen gestellt als beantwortet. Aber gut, meine Texte haben das ja auch getan.:cool:
Ein PLC Programm würde ich so nicht programmieren.
Ich habe jahrelang eine eigene Soft-SPS mit Borland Pascal programmiert. Das hat mich sicher mehr in Richtung ereignisorientierte Denk- und Arbeitsweise geschoben als für einen SPS-Programmierer üblich. Der Aufruf einer Init-Methode oder eines Init-Konstruktors für jedes Objekt stammt aus dieser Zeit, das Konzept habe ich dann beim Umstieg auf Beckhoff übernommen. Genauso den intensiven Einsatz von Aktionen als Ersatz für Objekt-Methoden und die Eigenart, nicht unbedingt alle Input-Parameter bei jedem Aufruf zu übergeben.
Am meisten Sicherheit würde mir bei deinem "Konstrukt" die IN_OUT Variante geben.
Mir auch, und deshalb werde ich wohl dabei bleiben. Die Diskussion mit Dir hat ihren Beitrag zu dieser Entscheidung geleistet, deshalb Dank dafür.
Wie wäre es mit einem Input
ADR(FB_Instance)
?
Das hatte ich ja vor, aber die fehlende Typüberprüfung macht mir Pointer eben unsympathisch. Vor allem bei dieser Anwendung, bei der der Typ des zu übergebenden Parameters bekannt und konstant ist.




Gruß und guten Rutsch!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wie wäre es mit einem Input
ADR(FB_Instance)
?

Auch wenn sich FB_Instance irgendwo im Speicher verschiebt, wird ja die neue Adresse übergeben.

Wird dies eben gerade nicht gemacht bei einem Online-Change? Manchmal erscheinnt ja so ein Fenster, das einem warnt, das gewisse Variablen verschoben werden, und bei Pointerzugriff nicht mehr funktionieren??

Ich würde das versuchen nachzustellen. Denn bei einem Pointerzugriff auf falsche Speicherbereiche kann Einiges kaputt gehen (So aus Erfahrung ;))
 
Der Speicher wird immer dann neu organisiert wenn man neue Variablen einfügt oder welche löscht. Das ist einerseits eine Klasse Angelegenheit weil es die Fragmentierung des Speichers minimiert, andererseits gibt es gerade bei der Verwendung von Pointern natürlich Stress wenn sich die Adressen verschieben. Im günstigen Fall crasht das Programm und man merkt das da was schief gelaufen ist, wenn man Pech hat werden "nur" die falschen Variablen beschrieben und man wird bei der Fehlersuche bekloppt.....

Ich stehe momentan vor dem gleichen Dilemma und habe auch noch keine richtige Lösung gefunden. Ich muss 70 Antriebe steuern. Die 70 Instanzen meines Antriebs-Steuer FBs werden je nach Betriebszustand und Betriebsmodus der Anlage als Pointer an verschiedene übergeordnete Programm-FBs übergeben. Das funktioniert super und ich kann mir ne Menge redundanten Code ersparen indem ich die Antriebe dynamisch im Progamm verteile.
Im Idealfall müsste ich mir nur bei Programmstart in einem Initialisierungsschritt die Adressen aller Antriebs-FBs holen und die in ein Array Schreiben und gut. Da ich aber bei bei der IBN immer mal wieder Variablen hinzufüge oder lösche muss ich die Initialisierung dann jedesmal wiederholen um sicher zu gehen das die Pointeradressen noch stimmen. Zur zeit läuft die Initialisierung bei mir in jedem Zyklus ab damit ich das nicht vergesse, aber dann kann ich auch gleich mit VAR_IN_OUT arbeiten (was ich auch machen werde, wenn ich keine andere Lösung finde).

Klasse wäre ein Compilerbefehl (Pragma) der definierte Speicherbereiche (bei der Variablendeklaration) von der Neuorganisierung ausschließt.
 
Zurück
Oben