TIA Ansätze großes Schieberegister

klusklus

Level-2
Beiträge
25
Reaktionspunkte
2
Zuviel Werbung?
-> Hier kostenlos registrieren
Guten Morgen zusammen,

ich habe hier die Aufgabenstellung
Rundtisch mit 119 Plätzen.
Für die Verwaltung habe ich ein Array mit 119 Feldern vom Typ UDT (Einige Bool, Int, String Variablen).
Ich grüble gerade wie ich nach einem Takt mit dem Tisch die Felder im Array weiterschiebe ohne die Gesamttaktzeit (CPU 1516F) in die Höhe zu treiben.
Meine Ansätze wären FOR Schleifen, kostet aber viel Zeit :-(

Hat vielleicht von Euch jemend eine Idee oder einen besseren Lösungsansatz.?

Vielen Dank.

Gruß K_K
 
Moin,
man schiebt in diesem Fall eigentlich nicht die Einträge umher, sondern verstellt nur einen Zeiger der dir sagt, welcher Eintrag als nächstes geschrieben wird bzw ein weitere welcher Eintrag als nächstes Ausgetragen wird. Das ganze nennt man dann rotierender Fifo oder Ringspeicher. Danach kannst du hier ja mal suchen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Vielen Dank,
auf den Ansatz wäre ich so jetzt nicht gekommen. Ich versuche mich mal über die Suche durchzuackern.
Siemens hat ja so einen Baustein in der LIB (LGF_FIFO), ich versuche gerade das Prinzip zu verstehen wie ich das auf einen Rundtisch übertragen kann.


Gruß K_K
 
Du kannst dabei auch dein Array weiterverwenden. Für die Eintrage/Austrag-Zeiger fügst du vor deinem Array einfach zwei Integer ein. Willst du nun was in dein Array eintragen, dann schaust du in den Eintrage-Zeiger an welcher Stelle des Arrays du den Eintrag vornimmst und erhöhst anschließend den Zeiger um 1. Trägst du etwas aus, dann schaust du auf den Austrags-Zeiger und erhöhst auch diesen nach dem Austrag um 1. Dann musst du dir noch Gedanken darüber machen, was bei einem Überschlag (Zeiger > maximale Anzahl Array-Elemente) passieren muss und wann und wie du dein Array samt Zeiger initialisierst und ob das alles remanent sein muss.
 
Moin klusklus,

Dann musst du dir noch Gedanken darüber machen, was bei einem Überschlag (Zeiger > maximale Anzahl Array-Elemente) passieren muss ...

Da hat sich bei mir die Restberechnung (Modulo) bewährt.

Also bei jedem Eintrag den Zeigerwert inkrementieren und die Restberechnung machen:

Code:
Zeigerwert := (Zeigerwert + 1) mod maxZeigerwert;

VG

MFreiberger
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Der Rundtisch hat vermutlich immer 119 Plätze und die Plätze überholen sich nicht beim Drehen :cool:
Zu jedem Platz ist immer ein Datensatz vorhanden. Das Plätze-Array ist immer voll gefüllt, es wird nie ein Datensatz zugefügt oder entfernt. Das kann man quasi als immer vollen Ringpuffer ansehen/implementieren.

Der Drehtisch dreht sich nur --> die Datensätze sollen alle um eine Position weiterwandern. Das kann man naiv machen, indem man sämtliche Array-Elemente umspeichert. Oder man macht es clever, indem man sich nur merkt, auf welchen Platz der Array-Anfang zeigt und erhöht nur diesen Verwaltungszeiger (AktPos). Wenn ein Platz i auf seinen Datensatz zugreifen will, dann greift er nicht mehr auf das Element PlätzeArray zu, sondern auf PlätzeArray[(i + AktPos) MOD Anzahl_Plätze]
PS: i muß mit 0 beginnen, bis maximal Anzahl_Plätze - 1

Harald
 
Zuletzt bearbeitet:
Ich denke du redest von einem grossen Rundtaktisch oder? Hier würde ich Daten im Kreis schieben vermeiden da der Zeitpunkt an den geschoben wird sehr kritisch ist. Z.B der Schutzkreis wird unterbrochen während der Tisch dreht und der Operator dreht im Einrichtbetrieb zurück usw...

Ich kopiere hier die Daten am Einlegeplatz in das Arrayfeld mit Index Nestnummer welches gerade am Einlegeplatz ist. Danach kopiert sich jede Station die bearbeitet die Daten aus dem Array anhand der Nestnummer die gerade bei der Station ist. Bevor der Tisch dreht werden die Daten wieder ins Array kopiert.

Zum Kopieren der Daten nach dem Takt wird verglichen ob der Tisch korrekt gedreht hat(Ist und Soll-Nestnummer ident)
 
Hallo zusammen,

vielen Dank für die schnelle Reaktion und die sehr hohe Qualität der Antworten.
Ich denke die Strategie von PN/DP verfolge ich weiter. Der Rundtisch hier ist als Kühlstrecke gedacht, deshalb die hohe Teilung. Leider muss ich zu jedem Bauteil zig Informationen mitschleppen da der NIO Abwurf erst nach dem Tisch passiert.

Gruß
K_K
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich mache das mit BLK_MOV_VARIANT. Schiebe dann ARRAY-Länge-1 beginnend bei 2 nach 1 und schreibe ein Nulldatensatz in den letzten Eintrag (Array-Länge). Das alles natürlich für einen Ringspeicher, an dem immer die erste Position gelöscht wird.
 
Ich mache das mit BLK_MOV_VARIANT. Schiebe dann ARRAY-Länge-1 beginnend bei 2 nach 1 und schreibe ein Nulldatensatz in den letzten Eintrag (Array-Länge). Das alles natürlich für einen Ringspeicher, an dem immer die erste Position gelöscht wird.

Also von BLK_MOV_VARIANT kann ich nur abraten, Siemens selbst sagt dass dieser Baustein eine extreme Zyklusbremse ist.
Wird sogar auf TIA 3 Kursen mitunter als Beispiel gezeigt.

Der Ansatz mit den Pointern (Zeigern) ist der Einfachste und effizienteste.

An sich Recht Simpel

Deklaration:
Konstante
PlaetzeMax Int 119

Static
Plaetze Array[1..PlaetzeMax] of Type
AktuellerPlatz Int

Code:
Wenn du immer nur einen Platz betrachten willst bei jedem Aufruf
AktuellerPlatz += 1; //Damit wird der Zeiger um 1 erhöht
If AktuellerPlatz > PlaetzeMax then
AktuellerPlatz := 1; //1 Da es keinen Platz 0 im Array gibt
end_if;

Datenzugriff mit:
Platze[AktuellerPlatz].xxxxxxx


Wenn du auf andere Plätze zugreifen musst musst du halt den Platz errechnen


Über Datentypen darf man streiten, da es in dem Array keine negativen Zahlen gibt können auch Typen ohne Vorzeichen Hilfreich sein ;)
 
Zuletzt bearbeitet:
Also von BLK_MOV_VARIANT kann ich nur abraten, Siemens selbst sagt dass dieser Baustein eine extreme Zyklusbremse ist.
Wird sogar auf TIA 3 Kursen mitunter als Beispiel gezeigt.

Hast du dafür auch Beweise? Eine kurze Googlesuche hat nämlcih nicht ergeben, dass irgendwo davon abgeraten wird diesen Baustein zu benutzen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hast du dafür auch Beweise? Eine kurze Googlesuche hat nämlcih nicht ergeben, dass irgendwo davon abgeraten wird diesen Baustein zu benutzen.
Ob es dies schriftlich gibt weiß ich nicht. Wir waren 2018 auf einem Kurs bei Siemens in Nürnberg und haben den ersten Kurs damals auf TIA15 mitgemacht und dort wurde dies erwähnt und auch mit einem Beispiel auf der Testkoffer SPS vorgeführt.

Sollte aber einfach nachzustellen sein.
Eine normale Zuweisung z.B. von einem UDT
UDT1 := UDT2
Und einmal das selbe mit Block_move_Variant.

Und deine eine Schleife mit x Ausführungen darüber legen und die Zykluszeit vergleichen.

So ähnlich war das Beispiel dort im Kurs. Ich kann nicht mehr mit Bestimmtheit sagen wie groß der Unterschied war. Aber er war signifikant. Eventuell hat Siemens ja schon mit 15.1 oder jetzt 16 nachgebessert.



Gesendet von meinem Redmi Note 5 mit Tapatalk
 
Hey,

ich hab mir mal ein Programm dafür geschrieben, um das zu testen. Ich hab ein UDT angelegt mit einem Int und DTL. Davon hab ich in einem Datenbaustein 5000 Datensätze angelegt und wiefolgt vorbelegt:

Daten[1]
Nummer 1
Datum_Uhrzeit DTL#2019-12-08-11:55:15.078739946
Daten[2]
Nummer 2
Datum_Uhrzeit DTL#2019-12-08-11:55:15.078752102

Mit einer Flanke Schreibe ich die Startzeit (RD_LOC_T) weg dann schiebe ich mit BLK_MOVE_VARIANT 4999 Datensätze um 1 nach vorne, und anschliessend schreibe ich die Endzeit und bilde aus beiden die Differenz und wandle sie in [ms]. Das Auslesen der Start und Endzeit dauert 0,026 ms, werde ich also vernachlässigen. Dann das selbe spiel mit einer einfachen Zuweisung Daten[n+1] nach Daten [n] über MOVE und FOR-Schleife:

Folgende Zykluszeiten habe ich ermittelt über 10 Ablaufe:

[BLK_MOVE_VARIANT]
- 3.991129 ms
- 4.015129 ms
- 4.004889 ms
- 4.016831 ms
- 3.974240 ms
- 3.969703 ms
- 4.015871 ms
- 4.000733 ms
- 4.017871 ms
- 4.027694 ms


FOR-Schleife:
- 8.887071 ms
- 9.556600 ms
- 8.465431 ms
- 8.969613 ms
- 8.536680 ms
- 8.884293 ms
- 8.735151 ms
- 9.542204 ms
- 8.497320 ms
- 8.820773 ms

Die verwendete CPU ist eine 6ES7 516-3AN00-0AB0 (1516-3), mit Firmware V 1.8.5 und projektiert in V15.1. Die durchschnittliche Zykluszeit beträgt beim aktuellen Programm 1.040 ms. Programmiert hab ich diese ganze Sache in FUP.

[Fazit]
Für mich ist also die Aussage von dem Siemenstypen auf deinem Leergang nicht nur nicht richtig ist, sondern grundlegend falsch und zwar solange bis hier andere Beweise vorgelegt werden.
 
Zuletzt bearbeitet:
Hallo,
Das Thema interessiert mich gerade auch. Das mit dem Verwaltungszeiger versehe ich aber wie macht ihr das um es zu Visualisieren?
Da sehe ich nur die Kopierlösung. Oder wie macht ihr das?
(Jeder Platz soll als belegt oder nicht angezeigt werden und denn man drauf klickt sollen zusätzlich Teile Informationen kommen, TIA Comfort Panel)
Bin gespannt auf eure Ideen
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
Das Thema interessiert mich gerade auch. Das mit dem Verwaltungszeiger versehe ich aber wie macht ihr das um es zu Visualisieren?
Da sehe ich nur die Kopierlösung. Oder wie macht ihr das?
(Jeder Platz soll als belegt oder nicht angezeigt werden und denn man drauf klickt sollen zusätzlich Teile Informationen kommen, TIA Comfort Panel)
Bin gespannt auf eure Ideen
Kommt darauf an was du alles Visualisieren willst. Wenn die Informationen nur kommen sollen wenn ein Platz angeklickt wird. Kann man diesen Zeiger genauso berechnen.
Stichwort Multiplexen.
Wenn du immer alle Plätze Visualisieren willst ist es an und für sich genau so möglich allerdings bei der Idee welche ich im Kopf habe eher sehr aufwändig zu gestalten.

Nenne doch Mal ein Beispiel dafür was für Informationen in einem Platz liegen sollen und was alles Visualisiert werden soll.

Da ich jetzt nach den Feiertagen etwas Zeit habe suche ich auch noch einmal das Beispiel mit dem MOVE Block Variant heraus und teste es auch nochmals. Denn ich lasse mich auch gerne eines besseren belehren ;).
Mal morgen oder Übermorgen die kleine 1518 anwerfen.

Gesendet von meinem Redmi Note 5 mit Tapatalk
 
Hallo,
Denke daran das jeder Platz bei belegt Grün sonst grau ist und die Auftragsnummer sowie die Teilelänge anzeigt wenn da ein zugesägtes Werkstück liegt.
Ja beim draufklicken kann ich dann per Skript so einiges machen und im Pop up auch noch die anderen Informationen anzeigen sowie entfernen.
Zwei Register eines für Visualisierung das kopiert wird (nur mit dem nötigsten) und eines für die kompletten Material Informationen per Zeiger würde sicher funktionieren aber muss das sein gibt es nicht etwas eleganteres?
 
So wie es sich anhört reden wir von einer Produktionsstraße.

Von was für Taktzeiten reden wir den überhaupt wo die Plätze weitergeschoben werden?
Und wieviel Plätze

Gesendet von meinem Redmi Note 5 mit Tapatalk
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ja genau ist eine Produktionsstrasse.
Selbst bei Top Speed wird es bei ca. 1-2 sec sein. Gut 400 Plätze.
Klar nicht so Zeitkritsch aber dennoch bin ich der Meinung kann man sich mühgeben und schnell Lösung umsetzen. Vielleicht kann man es dann beim nächsten Projekt wieder nutzen.
 
[Fazit]
Für mich ist also die Aussage von dem Siemenstypen auf deinem Leergang nicht nur nicht richtig ist, sondern grundlegend falsch und zwar solange bis hier andere Beweise vorgelegt werden.

Also grundlegend falsch ist die Aussage - meines Wissens - nicht.
Bis zu einer bestimmten Datenmenge sind Zuweisungen in einer Schleife schneller, danach die BLK_MOVE - Befehle.
Dazu spielen Datentypen (Ausrichtung im Speicher) und Optimiert / Nicht optimiert eine Rolle.

Gruß
Blockmove
 
Hallo zusammen es ist zwar schon lange her aber ich will dieses Thema nochmal aufgreifen, da ich endlich Zeit hatte zu testen.
Das Beispiel von Siemens habe ich leider nicht mehr gefunden auf meiner HDD.

Ich habe fünf Tests in einem FB gemacht (Code folgt).
Optimierter Bausteinzugriff war aktiv.

Hierbei muss ich zugeben das ich je nach Anwendungsfall vom MOVE_BLK_VARIANT wirklich beeindruckt bin.
Je nach Anwendung ist er bedeutend schneller oder bedeutend langsamer.
Für das Schieberegister muss ich meine Aussage zurück nehmen und sagen für diesen Zweck dürfte er Top sein.

Wie es sich in anderen Anwendungsfällen verhält bleibt abzuwarten.


Test 1, Array mit 1000 Byte kopieren
Test 2, udt mit 10 zufälligen Elementen kopieren
Test 3, Array mit 1000 Byte aber nur die ersten 500 Elemente kopieren
Test 4, Array mit 1000 udt kopieren
Test 5, Array mit 1000 udt aber nur die ersten 500 Elemente kopieren

mit folgendem Ergebnis:

Anzahl ausführungenMOVE_BLK_VARIANTZuweisung via SCL
Array 1000 Byte kopieren500069-76 ms5-7 ms
udt mit 10 lementen (Siehe Code)1000044-51 ms2-4 ms
Array 1000 Byte aber nur die ersten 500 kopieren1001-3 ms13-20ms
Array mit 1000 udt kopieren100026-28 ms38-41ms
Array 1000 udt aber nur die ersten 500 kopieren1002-3ms39-44ms


Code von den Tests:

Code:
FUNCTION_BLOCK "test"{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR 
      test1 : Array[1..1000] of Byte;
      test2 : Array[1..1000] of Byte;
      test3 : "testudt";
      test4 : "testudt";
      test5 : Array[1..1000] of "testudt";
      test6 : Array[1..1000] of "testudt";
   END_VAR


   VAR_TEMP 
      t_iRetVal : Int;
      t_Counter : Int;
      t_counter2 : Int;
   END_VAR




BEGIN
    
    REGION Test 1 array mit 1000 Byte
        
    (*
    FOR #t_Counter := 1 TO 5000 DO
        // Statement section FOR
        #test2 := #test1;
        
    END_FOR;
    *)
      (* 
        FOR #t_Counter := 1 TO 5000 DO
            #t_iRetVal := MOVE_BLK_VARIANT(SRC := #test1, COUNT := 1000, SRC_INDEX := 0, DEST_INDEX := 0, DEST => #test2);
        END_FOR;
     *)   
    END_REGION
    
    REGION Test 2 udt mit 10 Elementen
     (* testudt   
        #test1   Byte    16#0    True    True    True    False
        test2   Int 0   True    True    True    False
        test3   DInt    0   True    True    True    False
        test4   Word    16#0    True    True    True    False
        test5   DWord   16#0    True    True    True    False
        test6   Real    0.0 True    True    True    False
        test7   LReal   0.0 True    True    True    False
        test8   Word    16#0    True    True    True    False
        test9   Word    16#0    True    True    True    False
        test10  Word    16#0    True    True    True    False
    *)
        
        
        
        
        
    (*    
        FOR #t_Counter := 1 TO 10000 DO
            // Statement section FOR
            #test4 := #test3;
            
        END_FOR;
     *)
     (*   
        FOR #t_Counter := 1 TO 5000 DO
            #t_iRetVal := MOVE_BLK_VARIANT(SRC := #test3, COUNT := 1, SRC_INDEX := 0, DEST_INDEX := 0, DEST => #test4);
        END_FOR;
      *)
    END_REGION
    
    REGION Test 3 array mit 1000 Byte aber nur 500 Werte kopieren
        
    (*
    FOR #t_Counter := 1 TO 100 DO
        // Statement section FOR
        FOR #t_counter2 := 1 TO 500 DO
            // Statement section FOR
            #test2[#t_counter2] := #test1[#t_counter2];
        END_FOR;
        
    END_FOR;
    *)
    (*
     FOR #t_Counter := 1 TO 100 DO
         #t_iRetVal := MOVE_BLK_VARIANT(SRC := #test1, COUNT := 500, SRC_INDEX := 0, DEST_INDEX := 0, DEST => #test2);
     END_FOR;
     *)
    END_REGION
    
    
    REGION Test 4 array mit 1000 udt
    (*
    FOR #t_Counter := 1 TO 1000 DO
        // Statement section FOR
        #test6 := #test5;
        
    END_FOR;
    *)
    (*
      FOR #t_Counter := 1 TO 1000 DO
          #t_iRetVal := MOVE_BLK_VARIANT(SRC := #test6, COUNT := 1000, SRC_INDEX := 0, DEST_INDEX := 0, DEST => #test5);
      END_FOR;
    *)
    END_REGION
    
    REGION Test 5 array mit 1000 udt aber nur 500 kopieren
        
    (*
    FOR #t_Counter := 1 TO 100 DO
        // Statement section FOR
        FOR #t_counter2 := 1 TO 500 DO
            // Statement section FOR
            #test6[#t_counter2] := #test5[#t_counter2];
        END_FOR;
        
    END_FOR;
    *)
    
     FOR #t_Counter := 1 TO 100 DO
         #t_iRetVal := MOVE_BLK_VARIANT(SRC := #test6, COUNT := 500, SRC_INDEX := 0, DEST_INDEX := 0, DEST => #test5);
     END_FOR;
     
    END_REGION
END_FUNCTION_BLOCK


EDIT: getestet wurde auf einer 1516TF mit deaktiviertem SAFETY
 
Zuletzt bearbeitet:
Zurück
Oben