UDT // Ringpuffer

zloyduh

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

Gibt es die Möglichkeit einen UDT – Satz (z.B. 40Byte lang) an einen Ringpuffer zu senden bzw. mehrere. Welche nach einander abgearbeitet werden.???

Habe folgendes vor:
1. Einen UDT erstellen welcher meinem Datensatz entspricht
2. Diesen in einem DB als ARRAY [1..100] anlegen
3. Die Datensätze einzeln in den ARRAY mittel Ringpuffer ablegen. Anschließend zyklisch die Sätze aus dem Puffer holen und abarbeiten.
4. Die Sätze manuell Löschen (wahlweise einzeln oder alle)

Hat jemand schon mal so eine Aufgabe bewältigt??
Würde gerne das ganze mit SCL umsetzen??
 
Das ist der richtige Ansatz und SCL ist das passende Werkzeug.
Fang an, das wird!
Und wenn es klemmt frag nach.
Gruß
Erich
 
Hallo,
auf jeden Fall SCL ...
Und für deinen Fall gibt es im Forum auch schon Beispiele (auch in SCL) für die Code-Realisierung geben - sonst fragen ...

Gruß
Larry
 
Tach...

der DB bzw. die Struktur würde dann etwa so aussehen?:

Code:
TYPE 
   DeineStruktur : STRUCT
      Byte0_39 : ARRAY[0..39] OF BYTE;    // Deine 40-Byte-Struktur
   END_STRUCT;
END_TYPE


DATA_BLOCK XXX (* DB *)
   STRUCT
      DeinRingBuffer : ARRAY [1..100] OF DeineStruktur;
      Aktueller_Buffer : INT;    // Zeiger auf den aktuellen Buffer (1 - 100)
      Delete_Aktuellen_Buffer : BOOL; // löscht den aktuellen Buffer
   END_STRUCT
BEGIN
END_DATA_BLOCK


Der FB/FC ist dann auch nicht mehr schwierig...
 
Für was ein Beispiel ? Für das weiterschieben ?
Code:
IF Takt_vor AND NOT Takt_vor_zur_OK THEN
    
   FOR i := Array_max TO 1 BY -1 DO
      Platz[i +1] := Platz[i]  ;
   END_FOR ;
   Platz[1] := Platz[Array_max +1]  ;
END_IF ;

IF Takt_zur AND NOT Takt_vor_zur_OK THEN
    
   Platz [Array_max +1] := Platz [1] ;
   FOR i := 1 TO Array_max BY 1 DO
      Platz [i] := Platz [i +1]  ;
   END_FOR;
END_IF ;
Takt_vor_zur_OK := Takt_vor OR Takt_zur ;
Gruß
Larry
 
Sorry Larry,

der Trick bei einem Ringpuffer ist ja gerade, dass man die Daten nicht verschiebt, sondern nur die Zeiger erhöht oder erniedrigt.
Also ein Zeiger für das Ablegen der Daten, ein Zeiger für das älteste Element und wenn die Daten noch von einem anderen Prozess reium bearbeitet werden sollen, dafür noch einen Zeiger. Die Daten im Puffer werden nicht verschoben, das ist Rechenzeitverschwendung.
Gruß
Erich
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Naja ... das kann man m.E. so und so sehen ... und im Falle von SCL halte ich die Pointer-Geschichte doch eher für fragwürdig - aber klar ... du kannst dir natürlich auch den Index merken für Schreiben und den für Lesen.
Ich mache es nicht so und es ist auch nicht so schlimm, wenn dann bei mir die Zykluszeit der Steuerung mal um 2 oder 3 Millisekunden ansteigt.

(derartige Funktionen habe ich mehrfach in meinen Anlagen - sogar z.T. mehrfach in einer Steuerung)

Gruß
Larry
 
... im Falle von SCL halte ich die Pointer-Geschichte doch eher für fragwürdigLarry
ich meinte natürlich damit einen Array-Index, also eine Integer Zahl, was ist da fragwürdig?

... wenn dann bei mir die Zykluszeit der Steuerung mal um 2 oder 3 Millisekunden ansteigt.
Ihr jungen Hüpfer seid verwöhnt von den modernen CPUs;)

(derartige Funktionen habe ich mehrfach in meinen Anlagen - sogar z.T. mehrfach in einer Steuerung)
dito:-D

Gruß
Erich
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke für schnelle Hilfe:
habe bis jetzt folgendes Ergebniss erziehlt:

PHP:
FUNCTION_BLOCK FB_Verwalten
// Konstanten festlegen
CONST
    MaxW:= 99;                      // max. Datensatz Nr
    MinW:= 1;                       // min. Datensatz Nr
END_CONST

VAR_INPUT
    Taste_Hoch:     BOOL;           // Blättern hoch
    Taste_Max_Wert: BOOL;           // Springe zum max. Wert
    Taste_Runter: BOOL;             // Blättern runter
    Taste_min_Wert: BOOL;           // Springe zum min. Wert
    Speichern:  BOOL;               // Satz speichern (OP)
    Loeschen: BOOL;                 // Satz löschen (Platzhalter)
    Alle_Loeschen: BOOL;            // Alle Sätze löschen (Platzhalter)
END_VAR
VAR
    Satz: Datensatz;                // entspricht UDT-Satz
    Index: INT;
    FL1: BOOL;
    FL2: BOOL;
    FZ1: BOOL;
    FZ2: BOOL;
    
END_VAR
BEGIN
// Blättern
IF Taste_Hoch AND NOT FZ1 THEN Index:= Index + 1; END_IF;
IF Taste_Runter AND NOT FZ1 THEN Index:= Index - 1; END_IF;
FZ1:= Taste_Hoch OR Taste_Runter;
IF Index < MinW THEN Index:= MinW; END_IF;
IF Index > MaxW THEN Index:= MaxW; END_IF;

// Satz speichern
IF Speichern AND NOT FL1 THEN
    Daten.Datensatz_DB [Index]:= Satz;
END_IF;
FL1:= Speichern;
// Satz anzeigen

// Satz löschen

// Alle Sätze löschen

END_FUNCTION_BLOCK
Also die Tasten für Blättern hoch bzw. runter benutze ich im Panel Programm.
Das ablegen der Daten im ARRAY nach Vorwahl des Index funktioniert auch (Ist zwar keine ilegante Lösung aber es geht..)
Aber::
Ich möchte beim Blättern im OP immer den Aktuellen Satz anzeigen lassen.
z.B. Satz 1: 100 mm
Satz 2: 200mm
Satz 3: 0 // Wurde noch nichts eingegeben
Satz 4: 0 //
.....


Zur Zeit werden bei mir beim Blättern immer die letzten eingabe Werte angezeigt.
Ich greife aus dem OP auf die Variable "Satz" ..
Wie kann ich das umsetzen..??
 
... dann müßtest du den angewählten Datensatz immer in den Koppelbereich_Anzeige übertragen / zuweisen. Das wäre dann mit dem Index so nicht mehr zu machen ...

Gruß
Larry
 
... dann müßtest du den angewählten Datensatz immer in den Koppelbereich_Anzeige übertragen / zuweisen. Das wäre dann mit dem Index so nicht mehr zu machen ...

Gruß
Larry

Danke Larry! Wie meinst du das "in den Koppelbereich_..." ??
Hast du vielleicht eine andere Idee wie ich soetwas realisieren kann??
 
Zuviel Werbung?
-> Hier kostenlos registrieren
In deinem Fall ist "Satz" dein Koppelbereich.
Du mußt halt, wenn du die Daten vom angewählten Satz geändert hast, diesen in deinen Datenbereich schreiben (das tust du ja schon) und du mußt, wenn du die Daten einer bestimmten Stelle ansehen/editieren willst diese in "Satz" übertragen.
Eine andere Möglichkeit weiß ich nicht und gibt es da m.E. auch nicht ...

Aber ... was spricht denn dagegen, es auf die oben dargestellte Art und Weise zu realisieren ? Die eine Hälfte davon hast du ja schließlich auch schon ...

Gruß
Larry
 
Ich hoffe ich habe Dein Problem richtig verstanden.

Du könntest auf dem Panel 2 Felder nebeneinander legen.
Eines davon zeigt die Variable "Index" an. Damit hast Du eine Satznummernanzeige. Das Feld daneben ist dann nicht schon die Variable "Satz" sondern eine weitere Variable "Anzeige". Du schreibst aus dem Array immer auf die Variable "Anzeige", damit die Anzeige permanent aktualisiert wird. Bei speichern schreibst Du dann "Anzeige" auf "Daten"
 
Danke für die Tipps::

Ich habe das so gelösst, dass bei jeder Flanke (Hoch, Runter blättern) ich den Koppelbereich beschreibe.

Satz:= Daten.Datensatz_DB [Index];

Scheint so zu funktionieren..
 
Zurück
Oben