TIA Gleichzeitig Schreiben, Löschen und kopieren von Daten in einem Array

Hondo

Level-1
Beiträge
14
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Guten Abend,

ich programmiere in SCL und ich möchte kontinuierlich Daten in einem Array schreiben, löschen und hoch kopieren, damit der Array immer ein freier Platz hat.

Problemstellung:

ich arbeite mit zwei sensoren S1 und S2, die in zwei unterschiedlichen Stellen auf einem Band eingebaut sind. Außerdem sollen S1 und S2 kontinuierlich Teile erkennen. S1 und S2 sind high, wenn Sie ein Teil erkennen. Jedesmal, dass S1 ein Teil erkennt, dann schreibe ich ein boolischer Wert in den Array. Wenn ein Teil S2 erreicht hat, dann lösche ich der entsprechende boolische Wert dieses Teils aus dem Array und die Speicherinhalte des Arrays wird um 1 hoch kopiert. Zwischen S1 und S2 konnten 4 Teilen liegen.

Code:
IF s1 = 1 THEN
 array[i] := result; // Result ist 0 oder 1
i := i + 1;
END_IF;

IF s2 = 1 THEN
array[i] := 0;
FOR j := 0 TO 9 
    array[j] := array[j+1];
END_FOR;
END_IF;

Ich habe getestet, aber es läuft nicht. Machmal wird ein oder zwei Speicherinhalte beim Kopieren überspringen.
Wie kann ich das Problem lösen?
Danke im Voraus!!
 
Ich würde jetzt einfach mal aus dem Bauch raus sagen, du musst dir mal Gedanken über Flanken machen. Und dann ist die Aktion wenn der S2 kommt nicht unbedingt das richtige. Eigentlich sollst du ja bei erreichen des Sensors 2 nur das Teil 4 Plätze weiter wieder löschen und mit jedem Signal von S1 alle Teile um eins schieben und ein neues abspeichern.

Gesendet von meinem SM-G930F mit Tapatalk
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Oder S1 befüllt von "hinten" dein Array und S2 löscht immer den ersten Platz deines Arrays. Eine Funktion schiebt dann den Inhalt deines Arrays immer nach vorne sobald Platz eins frei geworden ist.


Also ungefähr so:
IF Positive Flanke S1
THEN
PlatzGefunden :=FALSE;
FOR-Schleife suche Platz in Array
IF NOT DatensatzVorhanden THEN
PlatzGefunden :=TRUE;
EXIT
END_FOR

d.h. das erste Teil das über S1 erkannt wird kommt an Platz 1 deines Arrays das zweite an Platz 2 usw.

Dein Sensor S2 löscht immer das Teil an Platz 1
Sobald Platz 1 leer ist, schiebst du alles ein Platz nach vorne

Somit Lagert dein S1 ein und dein S2 aus.
FIFO-Puffer

Ist es das was du möchtest?

Gruß Softi
 
Hallo Softi79,
danke für den Lösungsansatz. Es ist genau, was ich möchte. Ich werde versuchen, deine Idee umzusetzen.

Beste Grüße

Hondo
 
Hallo, das untere Programm macht zumindest, was ich wollte.

Danke noch mal für die Unterstützung

Daten schreiben und dann verschieben
Code:
#length := 20;

IF "M3_Trg1_S1" = 1 THEN
     
     "DB".Daten_Liste[0] := #Data;
     #temp2 := #length;
     
     // WHILE #temp2 >= 2 DO
     //     "DB".Daten_Liste[#temp2 - 1 ] := "DB".Daten_Liste[#temp2 - 2];
     //     #temp2 := #temp2 - 1;
     //     "M3_Trg1_S1" := 0;
     // END_WHILE;
     
     FOR #temp1 := 1 TO #length DO
        IF #temp2 >= 2 THEN
            "DB".Daten_Liste[#temp2 - 1] := "DB".Daten_Liste[#temp2 - 2];
            #temp2 := #temp2 - 1;
            "M3_Trg1_S1" := 0;
        END_IF;
    END_FOR;
    
  END_IF;

Daten aus dem Register suchen und überschreiben
Code:
IF "M4_Trg2_S2" = 1 THEN
   
    #"Pointer_OK/NG" := (#length - 1);
    
    // search
    WHILE "DB".Daten_Liste[#"Pointer_OK/NG"] = 10 DO
        
        #"Pointer_OK/NG" := #"Pointer_OK/NG" - 1;
        
    END_WHILE;
    
    // If found, then clean up
    IF "DB".Daten_Liste[#"Pointer_OK/NG"] <> 10 THEN
        "DB".Daten_Liste[#"Pointer_OK/NG"] := 10;
        "M4_Trg2_S2" := 0;
    END_IF;
    
END_IF;
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo.

Im oberen Teil ist die FOR-Schleife überflüssig. #temp1 wird nirgendwo verwendet.
#temp2 := #temp2 - 1; wiederum ließe sich ersetzen durch eine FOR-Schleife.

Im unteren Teil hast Du eine WHILE-Schleife. Wenn das SPS-Programm in der Schleife verweilt und andere Dinge nicht mehr zyklisch bearbeitet werden können unangenehme Situationen entstehen. In der Regel braucht man keine WHILE-Schleifen und kann mit FOR arbeiten.
Ich denke das könntest Du noch einmal überdenken.
 
Code:
#length := 19;
IF "M3_Trg1_S1" = 1 THEN
     
     "M3_Trg1_S1" := 0;
     "DB".Daten_Liste[0] := #Data;
          
     FOR #temp1 := #length TO 0 BY -1 DO
        "DB".Daten_Liste[#temp1 + 1] := "DB".Daten_Liste[#temp1];
     END_FOR;
    
END_IF;
 
So könnte der obere Teil aussehen, wenn ich richtig verstanden habe was du vorhast:

Neuen Eintrag in Feld 0 speichern und alle anderen um einen nach hinten verschieben.
Bei der Variante wird die 0 dabei direkt nach 1 kopiert. In Feld 0 und 1 steht dann das Gleiche.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Tiegerente,

du hast genau verstanden, was ich machen wollte. Ich danke dir für die Ratschläge und die Lösung. In der Zukunft werde ich vermeiden, While-Anweisung zu nutzen.

Beste Grüße

Hondo
 
Code:
#length := 19;
IF "M3_Trg1_S1" = 1 THEN
     
     "M3_Trg1_S1" := 0;
     "DB".Daten_Liste[0] := #Data;
          
     FOR #temp1 := #length TO 0 BY -1 DO
        "DB".Daten_Liste[#temp1 + 1] := "DB".Daten_Liste[#temp1];
     END_FOR;
    
END_IF;

überschreibst du hier nicht die Daten auf Index 0 vor dem verschieben selbiger?

Da es sich um einen FIFO handelt würde ich das Konzept hier noch mal in Richtung Schreib und Lesezeiger überdenken, es mag sein das es hier so geht, sollte sich das Konzept aber einmal ändern und die Mengengerüste größer werden, kommt man mit der Schleife evtl in Performance Probleme.

VG
RedCali
 
Zuviel Werbung?
-> Hier kostenlos registrieren
das war mir schon klar das die schleife rückwärts läuft :-)
aber die Zuweisung der Daten findet vor dem Schleifendurchlauf statt, dementsprechend überschreibt man im Index null denn alten wert bevor man verschoben hat
Die Schleife müsste doch vor der Zuweisung durchlaufen werden?

Bei einfacher nachvollziehbar als die "Pointer Variante" stimme ich dir zu :-)
War auch mehr als zusätzlicher Hinweis gedacht, manche meinen dann es geht uneingeschränkt und wundern sich dann :-)
 
Zurück
Oben