FIFO Strukturierter Text / TwinCat 2

Hendrik

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

ich stehe vor folgendem Problem ich versuche gerade mit TwinCat 2 und ST ein ARRAY mit First in First Out zu erstellen.

Es soll so sein, das sobald ein Signal anliegt, ein STRING in das ARRAY an Pos. 1 geschrieben wird und sobald das gleiche Signal wieder anliegt
der Vorherige STRING auf Pos. 2 rutscht und der neue STRING auf POS. 1. Ich versuche damit eine Alarmhistroie zuerstellen.


vielen Dank schon mal für eure hilfe =)
 
Du schreibst das du eine Alarmhistorie erstellen möchtest. Bevor du selber was programmierst. Hast du eine HMI und wenn ja, welche?
Die meisten HMIs haben sowas schon an Bord.
 
Na... das ist doch nichts Dramtisches ...

Du baust dir zunächst einen FB mit einem Array_of_String in der entsprechenden Größe.
Dieser FB hat dann einen IN-Parameter vom Typ Bool als Trigger für die Übernahmen des neuen Strings, vielleicht noch einen OUT-Parameter vom Typ Bool als Feedback, dass das geschehen ist.
Dann brauchst du noch einen IN-Parameter vom Typ String, der ja den neuen String repräsentiert.
Was du dir noch überlegen mußt ist, was du mit dem String machst, den du irgendwann einmal aus deinem Array heraus-schiebst - wird vielleicht ein OUT-Parameter deines FB.
Nun machst du dir in dem FB eine Flankenauswertung auf den Trigger (damit dieser nur bearbeitet wird wenn Trigger = True und Flanke noch nicht = True - Flanke ist somit eine STAT-Bool).
Ist das gegeben (also Trigger and not Flanke) dann schiebst du dir in einer Schleife deine Array-Inhalte um eins nach oben (also von hinten nach vorne) und schreibst dann den neuen String bei Index 1 in das Array.

Versuch mal, dass als Code umzusetzen ...

Gruß
Larry
 
Du kannst auch mal in die Oscat-Library (findet man leicht mit Google) schauen, die bringt viele Funktionen mit und im Bedarfsfall kann man sich diese als "Vorbild" nehmen. FIFO für numerische Werte sind auf jeden Fall enthalten, diese für Strings anzupassen dürfte nicht schwer sein.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hey Larry ich bin leider noch sehr sehr neu in sachen ST.

Ich versuch deinen Text gleich mal zu Programmieren habe aber noch eine Frage die Fanke von der du Sprichst ist das eine Positive oder Negative

und kannst du mir noch einen Tipp geben wegen den Trigger?
Soll das In_Bool einfach nur ein kurzer Signal erzeugen? z.b. mit einem Pulsgeber? oder wie ist das gemeint?

Danke und grüße
Hendrik
 
Naja,
in ST hast du ja (zumindestens für diesen Anwendungsfall) nicht wirklich positive oder negative Flanken. Ich würde es vom Code her ggf. so machen :
Code:
if Trigger and not Flanke then
   // Daten umschaufeln
end_if ;
Flanke := Trigger ;

Das IN-Bool soll ein Signal sein, dass du dann anlegst, wenn du einen neuen String in dein Array hineinschieben möchtest - also eigentlich kein Pulsgeber oder so sondern m.E. eher etwas, dass das deinem Restprogramm irgendwie generiert wird ... (Situations-abhängig)

Gruß
Larry
 
Hallo Larry
Habe das jetzt folgendermasen mal programmiert:
(Leider weis ich an dieser Stelle noch nicht wie ich das so als CODE fenster darstelle (nehme gerne gleich alle Tipps an)

FUNCTION_BLOCK TEST
VAR_INPUT
Trigger:BOOL;
String_Neu:STRING;
END_VAR
VAR_OUTPUT
END_VAR
VAR
ARRAY1:ARRAY [0..100] OF STRING;
index:INT;
Flanke: BOOL;
END_VAR

IF Trigger AND NOT Flanke THEN
ARRAY1[index+1]:=ARRAY1[index];

ARRAY1[0]:= STRING_Neu;
END_IF
Flanke := Trigger;


Leider funktionierte es irgendwie nicht wenn ich (Fanke:= Trigger;) Dort stehen haben ohne diese Anweisung läuft es. Befürchte aber das es später zu problemen kommen könnte:S

Mfg Hendrk
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
für die Code-Darstellung nimmst du die Code-Tags. Die erhältst du z.B. wenn du die Taste im Antwortfenster mit dem Doppelkreuz drauf (#) drückst.

Zu deinem Code :
Ich hatte da im Beitrag #4 auch noch etwas von einer Schleife geschrieben ... du willst ja schließlich ALLE Array-Elemente aufschieben ...
Das sähe dann z.B. so aus :
Code:
for i := 100 to 2 by -1 do
   ARRAY1[i]:=ARRAY1[i-1];
end_for ;
...

Gruß
Larry
 
Rufst Du den FB in jedem Zyklus auf oder nur dann, wenn ein neuer String eingetragen werden soll? Im zweiten Fall kann die Flankenauswertung innerhalb des FB's nicht funktionieren und ist auch überflüssig.
Ausserdem brauchst Du für das Verschieben der FIFO-Daten eine Schleife, denn jetzt kopierst Du nur ARRAY1[0] nach ARRAY1[1]:
Code:
FOR index:=100 TO 1 BY -1
   ARRAY1[index]:=ARRAY1[index-1];
END_FOR
Bei Strings sind das dann aber schon 25600 Bytes, die verschoben werden. Da würde ich eine Lösung vorziehen, bei der nicht die Daten, sondern nur die Schreib-/Lesezeiger verschoben werden.
 
so das funktioniert schonmal so:
Code:
FUNCTION_BLOCK TEST
VAR_INPUT
    Trigger:BOOL;
    String_Neu:STRING;
END_VAR
VAR_OUTPUT
END_VAR
VAR
    ARRAY1:ARRAY [0..100] OF STRING;
    index:INT;
    Flanke: BOOL;
END_VAR

IF Trigger AND NOT Flanke THEN
    FOR Index :=100 TO 0 BY - 1 DO
        ARRAY1[index]:=ARRAY1[index-1];
    END_FOR;

    ARRAY1[0]:= STRING_Neu;
END_IF
Flanke := Trigger;

Wie meinst du das StructuredTrash?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... das dürfte eigentlich nicht ohne Fehler funktionieren, da du in der Schleife am Ende aus dem deklarierten Array heraus läufst :
wenn Index = 0 dann lädst du in das Array[0[] das Element Array[-1] hinein - das gibt es aber nicht in der Deklaration - Aufpassen !
 
Was ST dir sagen wollte ist, dass es 2 Möglichkeiten gibt, dies umzusetzen.
Die erste Möglichkeit ist das, was ich dir vorgeschlagen habe : der Baustein wir IMMER bearbeitet und durch die externe Beschaltung wird festgelegt, ob und was er machen soll - dann brauchst du die Flankenauswertung wie von mir vorgeschlagen im Code des Bausteins - das wäre meine Arbeitsweise.
Die zweite Möglichkeit ist : der Baustein wir nur dann von dir aufgerufen wenn er seine Arbeit amchen soll - Dann brauchst du die Flankengeschichte ausserhalb des Bausteins (aber nicht mehr innerhalb).

Du mußt entscheiden, wie du vorgehst ...

Gruß
Larry
 
Der gesammte Baustein bwird nur dann aufgerufen wenn Aktuell ein Fehler da ist.

Ja das ist mir auch schon aufgefallen habe das im richtigen CODE schon geändert.

Danke für eure Hilfe!
bin auf jedenfall wieder etwas schlauer :D
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Der gesammte Baustein bwird nur dann aufgerufen wenn Aktuell ein Fehler da ist.
Wenn sich das auf Deinen Code aus #11 bezieht, heisst das aber, das der FB über mehrere Zyklen hinweg aufgerufen wird. Wenn Du mal einen Fehler hast, der nur für einen Zyklus ansteht, wird es nicht funktionieren.
Ich würde mich für eine der Möglichkeiten entscheiden, die Larry genannt hat:
Entweder so wie jetzt mit interner Flankenauswertung, aber den FB immer aufrufen (wenn kein Fehler eingetragen werden soll, Trigger:=FALSE)
oder den Triggerimpuls ausserhalb des FB's erzeugen und ihn nur im Triggerzyklus aufrufen, dann können Triggereingang und Flankenmerker entfallen.
 
Habe da noch eine Frage gerade kann ich aus einem mit CONCAT zusammengesetzem String z.b.
Code:
String1:= CONCAT (Datum, Text);
in einem anderem Abschnitt String1(Text) mit String2 vergleichen?
also quasi teile von einem String auslesen?
wenn ja wie?

Grüße Hendrik
 
Zurück
Oben