Step 7 Top 10 Auswertung

MichiW

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

hat von euch mal einer eine Top 10 Auswertung aus sagen wir mal 500 Werten gemacht?

Dabei sollen Störungen nach Häufigkeit und und Dauer ausgewertet werden. Excel kann sowas ja Prima. S7 leider nicht.
Bevor ich mir jetzt viel Arbeit mache, fage ich lieber mal hier bei euch. :ROFLMAO:

Dabei sollte das Format des DB wie folgt aussehen

DBW 0 Störmeldenummer
DBW 2 Anzahl der aufgetretenen Störung zu vorangehender Nummer
.
.
.

DBW 0 Störmeldenummer
DBD 2 Dauer der aufgetretenen Störung zu vorangehender Nummer
.
.
.

Sortiert werden müsste dann immer das zusammengehörende Paar aus Meldenummer und Anzahl/Dauer
Oder wie ihr es halt gelöst habt.


Ich habe als Visu nur WinCC flexible. Das kann sowas meiner Meinung nach nicht im Gegensatz zu WinCC


Gruß
Michael.
 
Man kann ja alles mögliche programmieren ...
Eine Sortierung (auch in der CPU) ist dabei schon einmal kein Problem - das wäre machbar.
Die Frage, die sich mir jetzt gerade stellt ist : wie kommt die Störmelde-Nummer und damit der Störungszähler in den DB ?

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Larry,

die Anzahl und die Zeit zu jeder Störung gibt es schon. Falls es jemanden intereesiert wie ich das gemacht habe, kann ich das gerne hier einstellen.
Das habe ich mir bisher im in Excel kopiert. Ich will es aber jetzt in der Visu für den Kunden sichtbar machen, bzw. als CSV exportieren aus Flexible, ohne das ich den ganzen Datenmüll mit anzeige.
 
Das geht ja genial einfach mit dem Bubblesort. Habs gerade mal ausprobiert. Muss mir nur noch ausdenken, wie ich die Meldnummer mitziehe.
Aber dafür finde ich schon eine Lösung. :ROFLMAO:

Um die Zykluszeit nicht so aufzublasen, schreibe ich das in einen FB um und mach das zyklisch. Ich habe immerhin eine Woche Zeit dazu. :ROFLMAO:
 
Zuletzt bearbeitet:
Das geht ja genial einfach mit dem Bubblesort. Habs gerade mal ausprobiert. Muss mir nur noch ausdenken, wie ich die Meldnummer mitziehe.
Aber dafür finde ich schon eine Lösung. :ROFLMAO:

Das ginge recht einfach wenn du alles was mitsortiert werden soll gleich in einem UDT zusammenfasst. Dann kannst du über Bubblesort auch sämtliche UDT Mitglieder mitsortieren. In SCL ist das superkompakt (CPU effektiv spielt es aber keine grosse Rolle ob AWL oder SCL).

mfG René
 
Hallo Rene,

so ganz kann ich dir nicht folgen, wie du das angehen willst und wie UDT und DB aussehen soll.
Ich wäre aber für nähere Informationen dankbar.
 
Zuletzt bearbeitet:
Je nach dem wie groß dein Array und die Datenmengen in den UDT sind, würde ich folgendes in Betracht ziehen.
- Bubblesort ist eines der langsamsten Sortierverfahren, es gibt bessere
- Anstatt beim Sortieren jedes Mal die kompletten UDTs umzusortieren, würde ich das Sortieren auf einer Hilfsliste mit den Array-Indizes durchführen.
In dieser Hilfsliste steht dann der Array Index des Elements an dieser sortieren Stelle. Bei Bedarf kann das Array mit den UDTs dann später einmalig nach dieser Liste neu aufgebaut werden, wenn es damit besser am HMI angezeigt werden kann.

Beispiel:
Bubblesort benötigt im ungünstigsten Fall n(n-1)/2 Vertauschungen.
Bei 500 Elementen à 20 Bytes schiebst du bei einem Sortiervorgang 124750*20 Bytes ~2,5 MByte durch die Gegend.
Wenn du auf einer Hilfsliste arbeitest, dann sind es mit max. ~260 kByte (249500 + 10000 Liste aufbauen) ungefähr ein Zehntel.
 
Hallo Rene,

ich habe bisher nur die Realisierbarkeit mit einem 5 DBD DB geprüft. Ich werde in jedem Fall mit einem Quell und Ziel DB arbeiten.
Die Sortierung wird dann Ereignisorentiert ausgeführt. Den Weg zum Ziel habe ich mir bisher noch nicht ausgedacht. Das kommt auch erst in frühestens 2 Wochen in Arbeit.
Derzeit habe ich noch einige andere Sachen zu bearbeiten. Bis 15 Dezember muß es jedoch fertig sein und in 11 Anlagen laufen. Weil danach habe ich 4 Wochen Urlaub. Weiße Weihnachten am schneeweißen Strand in Vietnam:ROFLMAO:

DATA_BLOCK DB 270
TITLE =
VERSION : 0.1

STRUCT
DB_VAR : DINT := L#10; //vorläufige Platzhaltervariable
DB_VAR1 : DINT := L#12; //vorläufige Platzhaltervariable
DB_VAR2 : DINT := L#8; //vorläufige Platzhaltervariable
DB_VAR3 : DINT := L#4; //vorläufige Platzhaltervariable
DB_VAR4 : DINT := L#16; //vorläufige Platzhaltervariable
DB_VAR5 : DINT ; //vorläufige Platzhaltervariable
DB_VAR6 : DINT ; //vorläufige Platzhaltervariable
DB_VAR7 : DINT ; //vorläufige Platzhaltervariable
DB_VAR8 : DINT ; //vorläufige Platzhaltervariable
DB_VAR9 : DINT ; //vorläufige Platzhaltervariable
END_STRUCT ;
BEGIN
DB_VAR := L#10;
DB_VAR1 := L#12;
DB_VAR2 := L#8;
DB_VAR3 := L#4;
DB_VAR4 := L#16;
DB_VAR5 := L#0;
DB_VAR6 := L#0;
DB_VAR7 := L#0;
DB_VAR8 := L#0;
DB_VAR9 := L#0;
END_DATA_BLOCK
FUNCTION FC 7 : VOID
TITLE =
{ S7_language := '7(1) Deutsch (Deutschland) 07.11.2016 11:09:49' }
VERSION : 0.1

VAR_INPUT
Data_DB : BLOCK_DB ;
DB_length : WORD ; //Anzahl Doppelworte
END_VAR
VAR_TEMP
Sort_done : BOOL ;
Temp : DWORD ;
Count : WORD ;
END_VAR
BEGIN
NETWORK
TITLE =Sort a Data Block using the bubble sort method
//Data Block will be sorted in ascending order.
//
AUF #Data_DB; //Open Data Block
M002: LAR1 P#DBX 0.0;
SET ; //LET #Sort_done = TRUE
S #Sort_done;
L #DB_length;
L 1;
-I ;
Loop: T #Count; //FOR INDEX = Count TO DB_length
L D [AR1,P#0.0]; //IF M(INDEX) > M(INDEX+1) THEN
L D [AR1,P#4.0];
<=D ;
SPB M003;
// change M(INDEX+1) for M(INDEX)
L D [AR1,P#0.0]; //LET TEMP = M(INDEX)
T #Temp;
L D [AR1,P#4.0]; //LET M(INDEX) = M(INDEX+1)
T D [AR1,P#0.0];
L #Temp; //LET M(INDEX+1) = TEMP
T D [AR1,P#4.0];
SET ;
R #Sort_done; //LET #Sort_done = FALSE
M003: TAR1 ;
L 32; //NEXT INDEX
+D ;
LAR1 ;
L #Count;
LOOP Loop; //End of sorting pass
UN #Sort_done; //If sorting is not done
SPB M002; //Jump Conditionally to M002
END_FUNCTION
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Ein paar Fragen dazu, da du da ja etwas nicht so ganz triviales planst :
- was hältst du grundsätzlich von "sprechenden Variablen-Namen" ? (also eine Variable so benennen wie das, wofür sie da ist)
- was hältst du von Vollmi's Vorschlag mit der SCL-Umsetzung ?
- wie sieht deine zu sortierende Struktur denn nun tatsächlich aus ?
- hast du schon realisiert, dass man in einem DB auch ein "Array of Struct" anlegen kann ? (macht das Ganze vielleicht "etwas" übersichtlicher)

Gruß
Larry
 
Hallo Larry,

wie schon gesagt, habe ich erst mal de Realisierbarkeit geprüft. Der Lösungsweg ist noch nicht in meinem Kopf zusammen gebaut. Zu gegebener Zeit wird das ordentlich dokumentiert.
Die Quelle oben habe ich fast identisch zum ausprobieren hier aus dem Forum kopiert. Der DB der dran hängt ist irrelevant. War halt nur ein Versuch auf Funktion.
Der Aufbau von Strukturen und UDT ist mir durchaus bekannt. Die zu sortierende Struktur ist noch nicht festgelegt.
Ich habe 2 Daten die zusammen gehören. Eine Information wird Sortiert (Anzahl/Dauer) die andere Information mitgezogen (Meldenummer)
Zur Zeit habe ich nur die Datenbausteine nach Störnummer sortiert mit Anzahl und Dauer der Störungen. Die kann man natürlich so nicht sortieren, weil die Information fehlen würde, um welche Störung es sich handelt.

SCL habe ich nicht, daher scheidet es aus.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Schade ... dabei gehört das doch bei Siemens mittlerweile schon zum Standard ...
Auf alle Fälle kannst du diese Sortierung mit SCL seeeehr viel übersichtlicher programmieren ... schau dir mal BubbleSort als SCL- (oder VB-) Code an ...

Ich hab hier mal n kleines Beispiel eines SCL Bubblesorters gemacht. Der komplette Strukturen umsortiert. Struct ist hier nur drin damit ich nicht noch UDT Quelle fürs Forum generieren muss. üblicherweise würde man das STRUCT in einen UDT Packen.

Ich hab hier Bubblesort als Beispiel genommen weils halt übersichtlich ist. Quicksort wäre bei grösseren Datenmengen vielleicht lohnenswert.

Code:
FUNCTION "Sortieren" : Void
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT 
      values : Array[1..100] of Struct
         sortierwert : Real;  // nach diesem wert soll sortiert werden
         ID : Int; // zusätzliche daten die dazu gehören
         Fehler : Bool; // nochwas
         Beschreibung : String[20]; // vielleich will man noch n Text mitsortieren
      END_STRUCT;
   END_VAR


   VAR_IN_OUT 
      values_sortet : Array[1..100] of Struct
         sortierwert : Real;
         ID : Int;
         Fehler : Bool;
         Beschreibung : String[20];
      END_STRUCT;
   END_VAR


   VAR_TEMP 
      index : Int;
      swapped : Bool;
      merker : Struct
         sortierwert : Real;
         ID : Int;
         Fehler : Bool;
         Beschreibung : String[20];
      END_STRUCT;
   END_VAR




BEGIN
	#values_sortet := #values; // Kopiere Array in Array zum sortieren


// Beginne Bubblesort
	IF #Bedienung.Sort THEN
	    #Bedienung.Sort := false;
	    REPEAT
	        #swapped := false;
	        FOR #index := 100 TO 1 BY -1 DO
	            IF #values_sortet[#index - 1].sortierwert > #values_sortet[#index].sortierwert THEN
	                #merker := #values_sortet[#index];
	                #values_sortet[#index] := #values_sortet[#index - 1];
	                #values_sortet[#index - 1] := #merker;
	                #swapped := true;
	            END_IF;
	        END_FOR;
	    UNTIL NOT #swapped
	    END_REPEAT;
	END_IF;
END_FUNCTION

Die UDTs umzukopieren wird im Hintergrund zumindest bei den 300ern per Blockmove gemacht. Mir ist bisher keine nennenswerte Zyklusbelastung aufgefallen. Aber wenn man das natürlich mit 1000 Werten macht wird sich das niederschlagen.
Ggf sollte man das über mehrere Zyklen verteilen

Du siehst, für so eine Funktion ist SCL wirklich das Werkzeug der Wahl. Natürlich kann man das auch in AWL machen aber da muss man dann wirklich alle Pointer im Blick haben weil man eben komplette struktur offsets händisch berechnen muss.

mfG René
 
Danke Rene für das Beispiel.

Vielleicht sollte ich mir doch mal überlegen SCL zu benutzen. Wie adressiert der denn den Blockmove denn in AWL? Ich weiß nicht, wie ich bei indirekter Adressierung die Länge des Datenbereichs einstellen kann.
Wahrscheinlich ist es in AWL besser die beiden Doppelworte mit 2 Moves zu machen.
 
Zurück
Oben