FIFO Funktionsblock in CoDeSys 2.3 - weil einfach nicht einfach einfach ist...

MaReKa

Level-1
Beiträge
27
Reaktionspunkte
3
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich bin mir nicht sicher ob der Thread hier richtig ist, möglicherweise gehört er eher in "Programmierstrategien" oder auch den "Stammtisch"...

Beflügelt von diesem Thread habe ich mir gedacht ich ersetze den sonntäglichen Mittagsschlaf dadurch dass ich mir mal einen FB bastele der ähnlich funktioniert wie die Funktionen die ich seit Jahren von RSLogix gewohnt bin... Pustekuchen :shock:

Wenn man sich auf einen bestimmten Datentypen einschießt ist das ja alles noch recht überschaubar, zumal wenn man mit fest definierten Array-Längen arbeitet. Will ich aber nicht.
Deklarationen in der Form
Code:
length: INT;
foo: ARRAY[0..length] OF DINT;
werden in der verwendeten Version 2.3.9 mit kopfschütteln seitens CoDeSys quittiert. Alles klar, ich habe schon mal von Pointern gehört, die Siemens Leute brauchten dazu glaube ich AWL, aber wie funktionierts in CoDeSys?
[F1] gedrückt und den Mund nicht mehr zubekommen, die Hilfe ist einen Lacher wert *ROFL* Ich bins gewohnt nicht unbedingt an die Hand genommen zu werden, aber da kam ich mir schon etwas allein gelassen vor.

Hürde Nummer 1 ist genommen, Datentypen schießen mir ins Hirn, ich will nicht viel, aber wenigstens alles was in 32 Bit ausgedrückt werden kann mit einem FB verarbeiten...
REAL in DWORD kopieren? No Señor...

Hat sich da in Version 3 etwas getan? Ich würde gern die Länge des ersten Elements in Bytes ermitteln, den Pointer dann entsprechend positionieren und die benötigte Anzahl an Bytes umladen / einfügen / schreiben etc. Da ich dem Pointer ja schon einen Datentyp zuweisen muss definiere ich damit ja schon die Anzahl der zu bearbeitenden Bits... Wahrscheinlich gibt es dazu eine ganz einfache Lösung, Ideen? Anregungen? Fehler? Man werfe mir Schlagworte um die Ohren, ich kann Google benutzen...
Da ich beruflich zum Glück noch die Finger davon lassen darf belasse ich es jetzt mal dabei, falls jemand mal lachen möchte folgt unten noch ein wenig Code, das ganze kann ein Element in den (bis zu 32766 Elemente langen) FIFO-Speicher laden, ein Element aus dem FIFO-Speicher entladen, automatisch ein Element entladen wenn der Speicher voll ist (Laufspeicher für Historien etc.), have fun :ROFLMAO:

Code:
FUNCTION_BLOCK FIFO
VAR_INPUT
 LoadValue:   POINTER TO DWORD;
 UnloadValue:   POINTER TO DWORD;
 FirstElement:  POINTER TO DWORD;
END_VAR
VAR
 i:      INT;
 Size:    UDINT;
 DestPointer:  POINTER TO DWORD;
 SourcePointer:  POINTER TO DWORD;
END_VAR
VAR_IN_OUT
 Ctrl: ST_CTRL;
END_VAR

Size :=  SIZEOF(FirstElement^);
IF Ctrl.Full AND Ctrl.Autounload AND Ctrl.Load THEN
 SourcePointer := FirstElement + ((Ctrl.Position - 1) * Size);
 UnloadValue^ := SourcePointer^;
 Ctrl.Position := Ctrl.Position - 1;
END_IF;
IF Ctrl.Load AND (Ctrl.Position < Ctrl.Length) THEN
 Ctrl.Done := FALSE;
 FOR i := (Ctrl.Position) TO 1  BY -1 DO
  DestPointer := FirstElement + (i * Size);
  SourcePointer := FirstElement + ((i-1) * Size);
  DestPointer^ := SourcePointer^;
 END_FOR;
 FirstElement^ := LoadValue^;
 Ctrl.Position := Ctrl.Position + 1;
 Ctrl.Done := TRUE;
END_IF;
IF Ctrl.Unload AND (Ctrl.Position > 0) THEN
 Ctrl.Done := FALSE;
 SourcePointer := FirstElement + ((Ctrl.Position - 1) * Size);
 UnloadValue^ := SourcePointer^;
 SourcePointer^ := 0;
 Ctrl.Position := Ctrl.Position - 1;
 Ctrl.Done := TRUE;
END_IF;
IF Ctrl.Position = 0 THEN
 Ctrl.Empty := TRUE;
ELSE
 Ctrl.Empty := FALSE;
END_IF;
IF Ctrl.Position < Ctrl.Length THEN
 Ctrl.Full := FALSE;
ELSE
 Ctrl.Full := TRUE;
END_IF;




Aufruf:

Code:
PROGRAM PLC_PRG
VAR
 AddElement:  BOOL;
 RemoveElement:  BOOL;
 FIFO:  FIFO;
 BufferCtrl: ST_CTRL;
 Value:   DINT;
 Buffer:  ARRAY[0..15] OF DINT;
 Unload: DINT;
END_VAR

BufferCtrl.Enable := TRUE;
BufferCtrl.Autounload := TRUE;
BufferCtrl.Length := 16;
BufferCtrl.Load := AddElement;
BufferCtrl.Unload := RemoveElement;
FIFO(
 LoadValue:= ADR(Value),
 UnloadValue := ADR(Unload),
 FirstElement:= ADR(Buffer[0]),
 Ctrl := BufferCtrl);
IF BufferCtrl.Done THEN
 AddElement := FALSE;
 RemoveElement := FALSE;
END_IF;
 
Zuletzt bearbeitet:
ST ist nicht C

Vielleicht ein paar kleine Anmerkungen.

ST ist nicht C++ und schon gar nicht C, das bedeutet insbesondere, dass Pointer nur in Ausnahmen verwendet werden sollen. Das ist nicht meine Meinung sondern explizit so in der Sprachdefinition enthalten.

Pointer Arithmetik in Codesys ebenfalls ein Tabu Thema, etwa so rudimentär wie in der Intel LowLevel Sprache PLM!!!

Pointer Arithmetik ist nicht Bestandteil der Sprachdefinition und der Implementator kann es sogar weglassen oder so implementieren, wie es ihm gefällt.

Zur Definition des Arrays ganz oben: Wenn Du die Länge als INT angibst, aber keinen Wert nennst, kann der Compiler auch kein Array anlegen.

Auch gibt es keine dynamische Memory Verwaltung aus Sicherheitsgründen in Codesys 2.x!

Wie oben schon gesagt, für Deinen Stil brauchst Du eine modernere Sprache und vielleicht auch keine SPS. Codesys 2.x stammt aus der Zeit von vor Jahr 2000!

Codesys 3.x ist moderner aber ebenfalls auch an die Sprachdefinition gebunden und auch nicht für Informatiker als Hauptkunden gedacht.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke für deine Anmerkungen,

wie oben schon erwähnt, ich brauche Codesys nicht beruflich. Für mich läuft das ganze unter Zeitvertreib, oder um Faust ins Spiel zu bringen: Pudel entkernen.

Ich arbeite seit ca. 10 Jahren mit Software von Rockwell, zur Technikerausbildung kam dann noch Siemens ins Spiel, Basiswissen mit wöchentlicher fallender Tendenz würde ich mir da zuschreiben...

Scheinbar unterscheidet sich die Rockwell Plattform immens von Siemens und Codesys, es sind Sachen möglich die so hier nicht umsetzbar sind. Ich habe nicht vor irgend etwas davon produktiv zu nutzen, mir geht es eher darum die Machbarkeit für mich selbst zu erproben. Das was ich dabei lerne und erfahre macht mich zumindest nicht dümmer, hilft mir vielleicht auch später, bis 2047 kann ich mich beruflich noch ein paar mal verändern. Da mir keine Aufgabenstellungen zugeworfen werden versuche ich eben das Verhalten von mir geläufigen und liebgewonnenen RSLogix Funktionen nachzustellen.

Hoffentlich hats dir die Laune nicht zu sehr verdorben, ich für meinen Teil hab was gelernt ;)

Edit sagt:

Nur um das nochmal klar gesagt zu haben, Sinn und Zweck des Threads: Ich stoße bei meiner spezifischen Problemstellung an Grenzen, in erster Instanz vermute ich dass das ein Problem mangelnden Wissens auf meiner Seite ist und nicht des Systems. Daher hier die Frage ob ich etwas übersehen habe oder es eine Lösung dafür gibt. Wenn das Problem in den Grenzen des Systems nicht zu lösen ist gebe ich mich damit zufrieden.
 
Zuletzt bearbeitet:
Zurück
Oben