Zuviel Werbung? - > Hier kostenlos beim SPS-Forum registrieren

Results 1 to 5 of 5

Thread: Ringpuffer in TwinCAT 3

  1. #1
    Join Date
    07.08.2019
    Posts
    3
    Danke
    0
    Erhielt 0 Danke für 0 Beiträge

    Default


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Hallo Zusammen,

    ich muss nach vielen Jahren wieder eine SPS programmieren (sonst nutze ich eher LabView, Matlab).
    Meine Aufgabe besteht darin, Daten in einen RingPuffer zu schreiben und zyklisch in eine CSV zu schreiben.

    Probleme habe ich vorallem bei den RingPuffer. Probiert habe ich FB_MemRingBuffer und FB_MemRingBufferEx.
    Mit beiden Funktionen kann ich in einen Puffer speichern und auch die wieder (teilweise) auslesen.
    Was ich aber nicht verstehe ist folgendes:

    1. Die beiden Funktionsblöcke funktionieren nicht als Ringpuffer, d.h. wenn die Größe des Puffers überschritten ist, schreibt es nicht am Anfang weiter (überschreibt somit nicht die ältesten Werte).
    2. Ich erstelle meinen Puffer: ARRAY[1..10] OF INT; Danach schreibe ich 10 Integer Werte rein (1..10) --> im Array steht jetzt [2,0,1,2,0,2,2,0,3,0]; Die Funktion gibt einen Fehler zurück und wenn ich die Werte beginnend beim ältesten auslese, erhalt ich nur 3 Werte;

    Beides verstehe ich nicht. In der Dokumentation steht auch nichts.

    Hat jemand von euch Erfahrung damit? Sicher könnte ich den Puffer deutlich vergrößern, aber ist das sinnvoll?

    Vielen Dank für Eure Hilfe.
    EffEff
    Reply With Quote Reply With Quote Ringpuffer in TwinCAT 3  

  2. #2
    Join Date
    20.12.2015
    Posts
    86
    Danke
    1
    Erhielt 17 Danke für 16 Beiträge

    Default

    Zur ersten Frage. Hast du dir das Beckhoff Beispiel im Infosys angesehen? Da wird erklärt wie du es bei vollem Puffer erreichst, dass neue Daten durch alte ersetzt werden.

    Zur zweiten Frage, zeig deinen Quelltext bitte. Dies macht die Fehlersuche einfacher für uns

  3. #3
    EffEff is offline Neuer Benutzer
    Themenstarter
    Join Date
    07.08.2019
    Posts
    3
    Danke
    0
    Erhielt 0 Danke für 0 Beiträge

    Default

    Ja, habe es z.B. mit dem Beispiel entsprechend deinem Link ausprobiert (ohne Structure-Element, einfach Integer zum speichern). bOverwrite ist auf TRUE gesetzt. Macht es aber trotzdem nicht
    Hier der Code:
    Globale Variable:
    Code:
    VAR_GLOBAL CONSTANT
        MAX_BUFFER_SIZE: INT := 10;
    END_VAR
    MAIN:
    Code:
    PROGRAM MAIN
    VAR
        fbFifo         : FB_DataSetFifo := ( bOverwrite := TRUE );
        newEntry    : INT := 0;
        oldEntry    : INT := 0;
        aOut        : ARRAY [1..GVL.MAX_BUFFER_SIZE] OF INT;
        bSuccess    : BOOL;
        nCount        : UDINT;
        nLoad        : UDINT;
        bReset         : BOOL := TRUE;
        bAdd         : BOOL := TRUE;
        bGet        : BOOL := TRUE;
        bRemove        : BOOL := TRUE;
        i: INT;
    END_VAR
    ________________________________________________________________________
    IF bReset THEN
        bReset := FALSE;
        fbFifo.A_Reset(    in := newEntry, bOk=>bSuccess, nCount=> nCount, nLoad => nLoad );
    END_IF
    
    IF bAdd THEN
        bAdd := FALSE;
        FOR i := 1 TO GVL.MAX_BUFFER_SIZE DO
        newEntry := newEntry + 1;
        fbFifo.A_Add(    in := newEntry, bOk=>bSuccess, nCount=> nCount, nLoad => nLoad );
        END_FOR
    END_IF
    
    IF bGet THEN
        bGet := FALSE;
        fbFifo.A_Get( out => oldEntry, bOk => bSuccess, nCount => nCount, nLoad => nLoad );
    END_IF
    
    IF bRemove THEN
        bRemove:= FALSE;
        FOR i := 1 TO GVL.MAX_BUFFER_SIZE DO
            fbFifo.A_Remove( out => oldEntry, bOk => bSuccess, nCount => nCount, nLoad => nLoad );
            aOut[i] := oldEntry;
        END_FOR
    END_IF
    FB_DataSetFifo(FB):
    Code:
    FUNCTION_BLOCK FB_DataSetFifo
    VAR_INPUT
        bOverwrite    : BOOL;
        in             : INT;
    END_VAR
    VAR_OUTPUT
        bOk            : BOOL;
        nCount        : UDINT;
        nLoad        : UDINT;
        out            : INT;
    END_VAR
    VAR
        arrBuffer     : ARRAY[1..GVL.MAX_BUFFER_SIZE] OF INT; // Buffer memory used by FB_MemRingBuffer function block
        fbBuffer    : FB_MemRingBuffer;
    END_VAR
    ________________________________________________________________________
    ;
    FB_DataSetFifo - A_Add(Action):
    Code:
    fbBuffer.A_AddTail( pWrite:= ADR( in ),
                        cbWrite:= SIZEOF( in ),
                        pBuffer:= ADR( arrBuffer ),
                        cbBuffer:= SIZEOF( arrBuffer ),
                        bOk=> bOk,
                        nCount => nCount );
    
    
    IF NOT bOk THEN (* overflow ? *)
        IF bOverwrite THEN
            fbBuffer.A_RemoveHead(); (* remove one oldest entry *)
            fbBuffer.A_AddTail( bOk => bOk, nCount => nCount );
        END_IF
    END_IF
    nLoad := (fbBuffer.cbSize * 100) / GVL.MAX_BUFFER_SIZE;
    FB_DataSetFifo (FB) - A_Get (Action):
    Code:
    fbBuffer.A_GetHead( pRead:= ADR( out ),
                        cbRead:= SIZEOF( out ),
                        pBuffer:= ADR( arrBuffer ),
                        cbBuffer:= SIZEOF( arrBuffer ),
                        bOk=> bOk,
                        nCount => nCount );
    nLoad := (fbBuffer.cbSize * 100) / GVL.MAX_BUFFER_SIZE;
    FB_DataSetFifo (FB) - A_Remove (Action):
    Code:
    fbBuffer.A_RemoveHead(     pRead:= ADR( out ),
                            cbRead:= SIZEOF( out ),
                            pBuffer:= ADR( arrBuffer ),
                            cbBuffer:= SIZEOF( arrBuffer ),
                            bOk=> bOk,
                            nCount => nCount );
    nLoad := (fbBuffer.cbSize * 100) / GVL.MAX_BUFFER_SIZE;
    FB_DataSetFifo (FB) - A_Get (Action):
    Code:
    MEMSET( ADR( arrBuffer ), 0, SIZEOF( arrBuffer ) ); (* reset (optional) internal buffer *)
    fbBuffer.A_Reset(bOk=> bOk,nCount => nCount );
    nLoad := (fbBuffer.cbSize * 100) / GVL.MAX_BUFFER_SIZE;
    Danke für deine Hilfe!!!

  4. #4
    Join Date
    20.12.2015
    Posts
    86
    Danke
    1
    Erhielt 17 Danke für 16 Beiträge

    Default

    Ich habe es mir mal angesehen. Dein Code funktioniert nicht, weil dein MAX_BUFFER_SIZE zu klein ist. Warum dies so ist, erfährst du hier.

    cbSize: Liefert die aktuelle Anzahl der belegten Datenbytes im Puffer. Die Anzahl der belegten Datenbytes ist immer größer als die tatsächliche Anzahl der geschriebenen Value-Daten. Jeder Datensatz wird um zusätzliche Informationen ergänzt um ihn später lokalisieren zu können.
    Via
    Code:
    nLoad := (fbBuffer.cbSize * 100) / MAX_BUFFER_SIZE;
    wird die Anzahl der Bytes ermittelt für ein Element im Ringpuffer. Auf dein Beispiel bezogen sind dies 6 Bytes pro Wert. Um 10 Elemente zu speichern brauchst du somit

    Code:
    MAX_BUFFER_SIZE : INT := 60;

  5. #5
    EffEff is offline Neuer Benutzer
    Themenstarter
    Join Date
    07.08.2019
    Posts
    3
    Danke
    0
    Erhielt 0 Danke für 0 Beiträge

    Default


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Danke. Genau das war das Problem beim Speichern.
    Als Ringpuffer funktioniert es aber noch nicht, obwohl bOverwrite auf TRUE steht. Mal schauen...

Similar Threads

  1. Step 7 Ringpuffer, Schieberegister Schwiriegkeiten
    By ChopinJunkie in forum Simatic
    Replies: 4
    Last Post: 28.04.2014, 22:30
  2. Step 7 Ringpuffer mit SCL
    By SKNGO in forum Simatic
    Replies: 2
    Last Post: 28.01.2014, 09:38
  3. Problem mit Ringpuffer
    By nutellahase in forum Simatic
    Replies: 1
    Last Post: 12.09.2011, 19:09
  4. Ringpuffer mit Mittelwert
    By taucherd in forum Simatic
    Replies: 28
    Last Post: 19.05.2011, 23:30
  5. UDT // Ringpuffer
    By zloyduh in forum Simatic
    Replies: 16
    Last Post: 06.03.2011, 08:18

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •