Auswahlkriterium Betriebsstunden

rs-plc-aa

Well-known member
Beiträge
727
Punkte Reaktionen
57
Zuviel Werbung?
->Hier kostenlos registrieren
Hallo,

ich bin noch ein wenig am rätseln für eine demnächst anstehende Aufgabe...


Kurzbeschreibung:

Es geht um 7 Betriebsmittel die angefordert werden sollen.

Die Anforderung kommt über digitale Eingänge (7 Stück)

Nur ist nicht jedem Eingang ein bestimmtes Betriebsmittel zugeordnet, sondern sollen anhand der Anzahl momentan geschalteter Eingänge die Betriebsmittel herausselektiert werden mit den wenigsten Betriebsstunden.

Wenn also 3 beliebige (von diesen 7) digitaleingänge "high" sind sollen die 3 Betriebsmittel angewählt werden welche am wenigsten Stunden drauf haben.

Kommt ein weiterer hinzu - oder fällt einer weg, geht das Spielchen weiter...



Hierfür gibt es bestimmt verschiedene Lösungsmöglichkeiten - aber nicht eine (komplett verwendbare zumindest) ist mir bis jetzt eingefallen... *schäm* :oops:



Hat jemand so was ähnliches schon mal gemacht ?


Am schlimmsten stelle ich mir das zwischenspeichern vor, da ich keine Lösung mit 300 Merkern bevorzugen würde.

Der Kniff ist ja auch, das das ganze ununterbrochen so weiterläuft.


Es muß natürlich zunächst geprüft werden ob das Betriebsmittel überhaupt bereit ist - was ja an sich kein Problem ist - nur muß man das auch mit verankern.


Man könnte "nicht bereite" von der Prüfung ausschließen oder mitprüfen und anschließend doch feststellen daß es nicht bereit ist - dann muß ja ersatzweise das nächst höhere genommen werden usw. ...



Hat hier vielleicht SCL eine Wunderlösung parat?

Damit habe ich aber noch keine Erfahrung - aber das wäre ja dann ein separater Baustein der immer nur die entsprechende Nummer(n) ausspuckt die dann letztendlich vom Hauptprogramm an- oder abgewählt werden.

Somit könnte ich mir vielleicht schon vorstellen damit was anzuleihern




Also

besten Dank schon mal für eure Beiträge
 
OP
rs-plc-aa

rs-plc-aa

Well-known member
Beiträge
727
Punkte Reaktionen
57
Hallo,

ich hab beim Stöbern in der Biliothek unter der Rubrik "IEC Function Blocks" den FC25 und FC27 ausfindig gemacht.

Das wäre eine Möglichkeit zu ermittlung des größten bzw. kleinsten Wertes.

Man könnte diesen dann markieren und vom nächsten Durchlauf ausschließen, und weitersuchen...

Aber die Bausteine können leider immer nur drei werte miteinander vergleichen - wie praktisch.

Also gerade einen mehr als ich ohnehin auch so schon vergleichen kann...


Das müßte ja dann so K.O.-Systemmäßig ablaufen - oder?

Der Gewinner wird mit dem nächsten verglichen usw.


Aber ich hatte halt gedacht daß es auch einfacher gehen müßte.



Ich gebe die Hoffnung mal noch nicht auf...
 

Question_mark

Well-known member
Beiträge
3.381
Punkte Reaktionen
578
Zuviel Werbung?
->Hier kostenlos registrieren
Hallo rs-plc-aa,
Am schlimmsten stelle ich mir das zwischenspeichern vor, da ich keine Lösung mit 300 Merkern bevorzugen würde.
Muss glaube ich nicht unbedingt sein. Meine Idee dazu sieht so aus :
Betriebsstundenerfassung läuft für alle 7 möglichen Betriebsmittel zyklisch durch, ist also immer aktuell (glaube aber, dass eine Toleranz von +- 1 Stunde irrelevant ist, kann also durchaus auch in einem Zeit-OB erfolgen). Dann würde ich auswerten (Flanke steigend oder fallend der Eingänge), ob sich eine Anwahl der Betriebsmittel geändert hat. In dem Fall würde ich dann einen FCxxx aufrufen. Den FCxxx solltest Du erstellen und dem sollte als Parameter die Anzahl der angewählten Betriebsmittel übergeben werden. Im Baustein FCxxx wertest Du anhand des übergebenen Parameters anhand der z.B. in einem DB abgelegten Betriebsstunden das entsprechende Betriebsmittel aus und übergibst das als Rückgabewert. War jetzt mal aus der Hüfte geschossen, aber sowas wäre mein erster Denkansatz dazu (bestimmt auch nicht der letzte), es gibt immer noch bessere Lösungen.
Gruss
Question_mark
 

Question_mark

Well-known member
Beiträge
3.381
Punkte Reaktionen
578
Hallo rs-plc-aa,
also ungefähr so :
im DB mit den Betriebsstunden steht z.B. folgendes :
Betriebsmittel 1 = 50 h
Betriebsmittel 2 = 450 h
Betriebsmittel 3 = 40 h
Betriebsmittel 4 = 120 h
Betriebsmittel 5 = 200 h
Betriebsmittel 6 = 80 h
Betriebsmittel 7 = 20 h

Zur Zeit sind z.B. 3 Betriebsmittel angewählt, also BM7, BM3 und BM1.
Jetzt wird ein viertes BM dazugeschaltet, diese 4 gibt Du als Parameter dem FCxxx mit. In dem FCxxx wertest Du dann aus, welches BM den 4-niedrigsten Betriebsstundenzähler hat. Dieses Betriebsmittel dann als Rückgabewert im FCxxx ausgeben und dann im weiteren Programm entsprechend zuschalten (b.z.w. abschalten, je nach übergebenem Parameter). Das nur als Denkanstoss, weiter ausbauen, z.B. mit Verfügbarkeit des Betriebsmittels kannst Du ja dann selber machen.
Gruss
Question_mark
 

Question_mark

Well-known member
Beiträge
3.381
Punkte Reaktionen
578
Hallo rs-plc-aa,
Hat hier vielleicht SCL eine Wunderlösung parat?
Naja, siehe oben, SCL ist für sowas noch nicht nötig. Mit SCL kann wirklich sehr komplexe Berechnungen in der SPS durchführen (die man früher wirklich auf externen Rechnern in Hochsprachen durchführen musste), aber bei Deinem Problem ist das absolut noch nicht nötig. Dieses Problem lässt sich durchaus in normalen STEP7 (z.B. AWL) lösen.
Gruss
Question_mark
 

Zottel

Well-known member
Beiträge
2.299
Punkte Reaktionen
277
Zuviel Werbung?
->Hier kostenlos registrieren
Zunächst sortierst du die Betriebsmittel nach den Betriebstunden. Dazu würde ich keinen der FCs verwenden, sondern eine einfache Vergleichsoperation, die zwei Operanden vergleicht. Um mit einem solchen Vergleich eine geordnete Liste zu erzeugen, gibt es viele Sortieralgorithmen. Diese unterscheiden sich in der Effizienz und Komplexität. Ferner unterscheiden sich Algorithmen, die eine völlig chaotische Menge gleich effizient sortieren, hinsichtlich der Effizienz bei teilweise geordneten Mengen. Die Effizient mißt man, indem man vergleicht, nach welcher Funktion die Ausführungszeit mit der Zahl der Elemente steigt. Schlecht ist n*n, gut ist log2(n) Llogarithmus zur Basis 2). Das alles interessiert erst bei mehr als einigen hundert Elementen wirklich.

Damit man bei langen Einträgen nicht die Datenmenge der Einträge selbst "umschaufeln" muß, verwendet man einen Index. Dieser kann aus Zeigern auf die Elemente bestehen oder aus Platznummern in einer ungeordneten Liste.

Einer der einfachsten Algorithmen heißt "Bubble sort", weil bei ihm das oberste Element in der Liste aufsteigt wie eine Blase.
Buble sort funktioniert so: Wenn Nummer1 kleiner ist als Nummer 2, tausche Nummer 1 mit Nummer 2, sonst mach nix. Wenn Nummer2 kleiner ist als Nummer 3, tausche Nummer 2 mit Nummer 3, sonst mach nix. So gehts weiter bis zum Ende der Liste. Am Ende der Liste steht nun das kleinste Element. Weil man das sicher Weiß, braucht de nächste Durchgang nur noch alle vorigen Elemente zu untersuchen. Mit jedem Durchgang wird es eins weniger. Wenn im letzten Durchgang nur noch 2 Elemente verglichen wurden, ist die Liste sortiert.

Realisierung:
Du hast nun z.B. eine Liste im DB2. Jeder Eintrag ist ein DWORD, daß die Betriebsstunden (Betriebszeit) enhält. Ein DB2 enthalte deinen "Index". Er enthält jeweils ein Byte mit der Platznummer des Betriebsmittels.

Code:
L DB2.DBB0	//lade 1.Eintragsnummer aus Index
L 32			//Länge eines DWORDS in bits
*I			//ergibt Adresse des eigentlichen Elements
T LD0		//zwischenspeichern

L DB2.DBB1	//lade 2.Eintragsnummer aus Index
L 32			//Länge eines DWORDS in bits
*I			//ergibt Adresse des eigentlichen Elements
T LD4		//zwischenspeichern

L DB1.DBD[LD0]	//Lade Betriebsstunden des 1. Betriebsmittels
L DB1.DBD[LD4]	//Lade Betriebsstunden des 2. Betriebsmittels
>D
SPB nixtun		//wenn das 1.größer ist, ist nichts zu tun, sonst wird jetzt getauscht:
L DB2.DBB0		//lade 1.Eintragsnummer aus Index
T LB0			// zwischenspeicher für Ringtausch
L DB2.DBB1		//lade 2.Eintragsnummer aus Index
T DB2.DBB0		//speicher als neue 1.Eintragsnummer aus Index
L LB0			//Hole Zwischenspeicher zurück
T DB2.DBB1		//speicher als neue 2.Eintragsnummer aus Index
nixtun: NOP
Diesen Code kannst du nun aneinanderhängen :
Code:
L DB2.DBB1	//lade 2.Eintragsnummer aus Index
L 32			//Länge eines DWORDS in bits
*I			//ergibt Adresse des eigentlichen Elements
T LD0		//zwischenspeichern

L DB2.DBB2	//lade 3.Eintragsnummer aus Index
L 32			//Länge eines DWORDS in bits
*I			//ergibt Adresse des eigentlichen Elements
T LD4		//zwischenspeichern

L DB1.DBD[LD0]	//Lade Betriebsstunden des 2. Betriebsmittels
L DB1.DBD[LD4]	//Lade Betriebsstunden des 3. Betriebsmittels
>D
SPB nixtun2		//wenn das 1.größer ist, ist nichts zu tun, sonst wird jetzt getauscht:
L DB2.DBB1		//lade 1.Eintragsnummer aus Index
T LB0			// zwischenspeicher für Ringtausch
L DB2.DBB2		//lade 2.Eintragsnummer aus Index
T DB2.DBB1		//speicher als neue 1.Eintragsnummer aus Index
L LB0			//Hole Zwischenspeicher zurück
T DB2.DBB2		//speicher als neue 2.Eintragsnummer aus Index
nixtun2: NOP
Du mußt du ihn sinngemäß für Eintrag 1-7,1-6,1-5,1-4,1-3,1-2 ausführen. Das wären 27 der oben gezeigten Code-Blöcke mit angepassten Indexnummern (für 7 Elemente kann man das wohl so machen).

Du kannst den Code abkürzen, indem du ihn in zwei Schleifen packst: Die äußere Schleife zählt die Durchgänge. Die innere Schleife zählt die zu vergleichenden Elemente. Sie hat mit jedem Durchgang der äußeren ein Element weniger.

Am Ende enthält dein Index in DB2 eine Liste der Art
5
4
2
3
6
7
1
Das bedeutet, daß die Betriebsstunden des 5. Elementes am geringsten sind, nächst-geringer die des 4. und 2. Du kanst statt des Eintrags der reinen Zeit im DB1 auch einen UDT verwenden, der z.B. zusätzliche einen Zeiger auf den einzuschaltenden Ausgang enthält.

Wann immer sich die Betriebstunden signifikant verändern, mußt du das sortieren der Liste wiederholen. Signifikant heißt: Wenn es dir nur auf Betriebsstunden ankommt, reicht es ja die Liste alle Stunde neu zu sortieren. Wenn das Betriebsmittel nicht gewechselt wird, nur weil es eine Minute oder Sekunde mehr auf dem Buckel hat als ein anderes, brauchst du die Liste auch nur dann zu sortieren, wenn sich die Kombination der Eingänge ändert.

[/code]
 
OP
rs-plc-aa

rs-plc-aa

Well-known member
Beiträge
727
Punkte Reaktionen
57
@Zottel: das Sortieren war meine Hauptsorge - aber bei derartiger Unterstützung ...


Zunächst wollte ich mich erst mal bedanken.

Das muß ich erst mal durchstudieren....

.... aber gefällt mir gut.
 
OP
rs-plc-aa

rs-plc-aa

Well-known member
Beiträge
727
Punkte Reaktionen
57
Hallo,

ich hatte leider nicht die Zeit gehabt am WE mich darauf zu stürzen wie ich es eigentlich vorhatte...

Ich hab´s mir nun aber noch mal durchgesehen.

@Zottel:Meinst du in deiner Beschreibung
>> Zitat:

Du hast nun z.B. eine Liste im DB2. Jeder Eintrag ist ein DWORD, daß die Betriebsstunden (Betriebszeit) enhält. Ein DB2 enthalte deinen "Index". Er enthält jeweils ein Byte mit der Platznummer des Betriebsmittels.

>> Ende Zitat...

mit DB 2 eigentlich DB1 ?

Laut dem Code müsste das so sein.


Ich hänge eigentlich nur noch ein wenig an dem Index fest...
 

Zottel

Well-known member
Beiträge
2.299
Punkte Reaktionen
277
Zuviel Werbung?
->Hier kostenlos registrieren
Ja, ich meinte, daß die Einträge in DB1 stehen.
Man muß auch nicht zwigend einen Index verwenden, aber wenn du in der Liste nur die Betriebsstunden hast, hast du nach dem Sortieren halt nur eine geordnete Liste von Betriebsstunden und weißt nicht mehr, zu welchem Betriebsmittel si gehören. Das kann man auch mit einem UDT lösen, der die Nummer des BM enthält, aber mit Index kopierst du nur sowenige Bytes wie wirklich nötig.
 
OP
rs-plc-aa

rs-plc-aa

Well-known member
Beiträge
727
Punkte Reaktionen
57
Hallo,

das mit dem Index ist schon o.k. - will ich auch so machen.

Ich habe jetzt einen Global-DB (DB 20) angelegt für die Indexierung, und einen Global-DB für die Stunden (DB 10) - (ich kopiere die Stunden in den DB, die ich über Profibus von den BM´s erhalte).


Die reihenfolge des Stunden DB´s (DB10) bleibt ja unverändert.

Die Default-Reihenfolge der Index-Bytes ist ja 1,2,3,4...., und wird durch die Vergleiche getauscht.

So weit kann ich folgen.


Jetzt haben wir ja irgendwann im Index-DB eine Reihenfolge die sortiert ist.

Aber das erste Byte trägt doch immer noch die selbe bezeichnung wie vorher - oder ?


Ich versteh also nicht ganz wie ich das anschließend zuordnen soll...

Sorry - aber ich hab was derartiges noch nicht gemacht.
 

Zottel

Well-known member
Beiträge
2.299
Punkte Reaktionen
277
Zitiere mal mich selbst:
Am Ende enthält dein Index in DB2 eine Liste der Art
5
4
2
3
6
7
1
Bzw. bei dir im DB 20.
Dies bedeutet, daß der 5. Eintrag in der (unsortierten) Liste im DB10 der kleinste (größte?, das hängt davon ab, ob du beim Sortieren auf größer oder kleiner vergleichst.) ist, der 4. Eintrag der zweitkleinste, der 2. der drittkleinste.
Du schaltest also die Betriebsmittel 5,4, und 2 ein, weil sie noch am wenigsten gelaufen haben.
[/quote]
 
OP
rs-plc-aa

rs-plc-aa

Well-known member
Beiträge
727
Punkte Reaktionen
57
Zuviel Werbung?
->Hier kostenlos registrieren
Hallo,

das habe ich schon gelesen - nur stehe ich wahrscheinlich auf dem Schlauch...

Hier mal zunächst das was im FB passiert...

Code:
// Bubble Sort



      L     DB20.DBB    0               //lade 1.Eintragsnummer aus Index 
      L     32                          //Länge eines DWORDS in bits 
      *I                                //ergibt Adresse des eigentlichen Elements 
      T     LD     0                    //zwischenspeichern 

      L     DB20.DBB    1               //lade 2.Eintragsnummer aus Index 
      L     32                          //Länge eines DWORDS in bits 
      *I                                //ergibt Adresse des eigentlichen Elements 
      T     LD     4                    //zwischenspeichern 

      L     DB10.DBD    0               //Lade Betriebsstunden des 1. Betriebsmittels 
      L     DB10.DBD    4               //Lade Betriebsstunden des 2. Betriebsmittels 
      >D    
      SPB   nix1                        //wenn das 1.größer ist, ist nichts zu tun, sonst wird jetzt getauscht: 

      L     DB20.DBB    0               //lade 1.Eintragsnummer aus Index 
      T     LB     0                    // zwischenspeicher für Ringtausch 
      L     DB20.DBB    1               //lade 2.Eintragsnummer aus Index 
      T     DB20.DBB    0               //speicher als neue 1.Eintragsnummer aus Index 
      L     LB     0                    //Hole Zwischenspeicher zurück 
      T     DB20.DBB    1               //speicher als neue 2.Eintragsnummer aus Index 

nix1: NOP   0

      L     DB20.DBB    1               //lade 2.Eintragsnummer aus Index 
      L     32                          //Länge eines DWORDS in bits 
      *I                                //ergibt Adresse des eigentlichen Elements 
      T     LD     0                    //zwischenspeichern 

      L     DB20.DBB    2               //lade 3.Eintragsnummer aus Index 
      L     32                          //Länge eines DWORDS in bits 
      *I                                //ergibt Adresse des eigentlichen Elements 
      T     LD     4                    //zwischenspeichern 

      L     DB10.DBD    4               //Lade Betriebsstunden des 2. Betriebsmittels 
      L     DB10.DBD    8               //Lade Betriebsstunden des 3. Betriebsmittels 
      >D    

      SPB   nix2                        //wenn das 2.größer ist, ist nichts zu tun, sonst wird jetzt getauscht: 

      L     DB20.DBB    1               //lade 2.Eintragsnummer aus Index 
      T     LB     0                    // zwischenspeicher für Ringtausch 
      L     DB20.DBB    2               //lade 3.Eintragsnummer aus Index 
      T     DB20.DBB    1               //speicher als neue 2.Eintragsnummer aus Index 
      L     LB     0                    //Hole Zwischenspeicher zurück 
      T     DB20.DBB    2               //speicher als neue 3.Eintragsnummer aus Index 

nix2: NOP   0

      L     DB20.DBB    2               //lade 3.Eintragsnummer aus Index 
      L     32                          //Länge eines DWORDS in bits 
      *I                                //ergibt Adresse des eigentlichen Elements 
      T     LD     0                    //zwischenspeichern 

      L     DB20.DBB    3               //lade 4.Eintragsnummer aus Index 
      L     32                          //Länge eines DWORDS in bits 
      *I                                //ergibt Adresse des eigentlichen Elements 
      T     LD     4                    //zwischenspeichern 

      L     DB10.DBD    8               //Lade Betriebsstunden des 3. Betriebsmittels 
      L     DB10.DBD   12               //Lade Betriebsstunden des 4. Betriebsmittels 
      >D    

      SPB   nix3                        //wenn das 3.größer ist, ist nichts zu tun, sonst wird jetzt getauscht: 

      L     DB20.DBB    2               //lade 3.Eintragsnummer aus Index 
      T     LB     0                    // zwischenspeicher für Ringtausch 
      L     DB20.DBB    3               //lade 4.Eintragsnummer aus Index 
      T     DB20.DBB    2               //speicher als neue 3.Eintragsnummer aus Index 
      L     LB     0                    //Hole Zwischenspeicher zurück 
      T     DB20.DBB    3               //speicher als neue 4.Eintragsnummer aus Index 

nix3: NOP   0

      L     DB20.DBB    3
      L     32
      *I    
      T     LD     0

      L     DB20.DBB    4
      L     32
      *I    
      T     LD     4

      L     DB10.DBD   12
      L     DB10.DBD   16
      >D    

      SPB   nix4

      L     DB20.DBB    3
      T     LB     0
      L     DB20.DBB    4
      T     DB20.DBB    3
      L     LB     0
      T     DB20.DBB    4

nix4: NOP   0

      L     DB20.DBB    4
      L     32
      *I    
      T     LD     0

      L     DB20.DBB    5
      L     32
      *I    
      T     LD     4

      L     DB10.DBD   16
      L     DB10.DBD   20
      >D    

      SPB   nix5

      L     DB20.DBB    4
      T     LB     0
      L     DB20.DBB    5
      T     DB20.DBB    4
      L     LB     0
      T     DB20.DBB    5

nix5: NOP   0

      L     DB20.DBB    5
      L     32
      *I    
      T     LD     0

      L     DB20.DBB    6
      L     32
      *I    
      T     LD     4

      L     DB10.DBD   20
      L     DB10.DBD   24
      >D    

      SPB   nix6

      L     DB20.DBB    5
      T     LB     0
      L     DB20.DBB    6
      T     DB20.DBB    5
      L     LB     0
      T     DB20.DBB    6

nix6: NOP   0


Nun sieht ja mein Stunden-DB etwa so aus:

Stunden_M1 DWORD DW#16#0
Stunden_M2 DWORD ....


Und der Index-DB etwa so:

Index_M1 BYTE B#16#0
Index_M2 BYTE B#16#0
Index_M3 BYTE ....


___________________________________________


Getauscht werden ja die Indexes

Aber wird da nicht nur der Wert getauscht ?

Bleibt da nicht die Reihenfolge M1,M2,M3,M4.....


Kann es sein das ich da was nicht blicke ?


Mir geht einfach nicht runter wie ich nachher erkennen soll welches Betriebsmittel welchem Byte zugeordnet ist (aber bitte nicht auslachen - und wenn dann heimlich... :roll: )
 

Zottel

Well-known member
Beiträge
2.299
Punkte Reaktionen
277
rs-plc-aa schrieb:
...
Und der Index-DB etwa so:

Index_M1 BYTE B#16#0
Index_M2 BYTE B#16#0
Index_M3 BYTE ....

Mir geht einfach nicht runter wie ich nachher erkennen soll welches Betriebsmittel welchem Byte zugeordnet ist (aber bitte nicht auslachen - und wenn dann heimlich... :roll: )

Ein sinnvoller Anfangswert für den Index-DB ist:
Index_M1 BYTE B#16#1
Index_M2 BYTE B#16#2
Index_M3 BYTE B#16#3
Index_M4 BYTE B#16#4
Index_M5 BYTE B#16#5
Index_M6 BYTE B#16#6
Index_M7 BYTE B#16#7

Zwei Dinge noch:
Dein "Bubblesort" FB hat nur 6 Durchgänge (wenn ich richtig gezählt habe). Nötig sind aber 27!
Beim Index habe ich was falsch gemacht: Der 1. Eintrag im Betriebsstunden DB hat den Array-Index 0.
Ein wirklich sinnvoller Anfangswert für den Index-DB ist:
Index_M1 BYTE B#16#0
Index_M2 BYTE B#16#1
Index_M3 BYTE B#16#2
Index_M4 BYTE B#16#3
Index_M5 BYTE B#16#4
Index_M6 BYTE B#16#5
Index_M7 BYTE B#16#6
 
OP
rs-plc-aa

rs-plc-aa

Well-known member
Beiträge
727
Punkte Reaktionen
57
Hallo,

alles klar...

Hat jemand den Link schon besucht?



Jetzt muß ich aber noch mal mit dem Index nerven.


Wenn die Sortierung fertig ist dann sind ja die Bytes, die vorher aufsteigend im DB nummeriert waren - also von 1 bis 7 und der Wert von 0 bis 6 - nun, wenn wir mal davon ausgehen daß sich nach der Sortierung eine veränderte Reihenfolge ergibt, von der Benennung ( also M1 - M7) her immer noch gleich - da dies ja an die Bausteinadresse geklammert ist.

Es ändert sich also nur der Wert - z.B.:

M1 = 5
M2 = 3
M3 = 0
M4 = 6
...


Wenn das bis hierher stimmt, dann muß ja jetzt noch von Hand oder halt eben extra noch bestimmt werden Welche BM-Nummer auch am wenigsten, am zweitwenigsten, ... usw. Stunden hat...


oder ist dies schon erledigt und ich habe immer noch nicht bemerkt wo ?
 

Zottel

Well-known member
Beiträge
2.299
Punkte Reaktionen
277
Wenn ich da geschrieben habe:
L DB20.DBD[DB10.DBB0] oder so ähnlich: Das kann die S7 gar nicht, aber es ist ein Pseudo-Code, mit dem sich der Algorithmus übersichtlich darstellen läßt. Und Anweisungen dieser Art sind in allen höheren Computersprachen Gang un Gäbe.
Es fiel mir dann später auf, daß du in einem folgenden Posting richtigen S7-Code hineingestellt hast, der keinerlei indirekte Adressierung enthält...

Der Witz an indirekter Adressierung ist, daß nicht immer mit derselben Variable gearbeitet wird, sondern mit derjenigen, deren Positionsnummer (array index) oder Adresse (pointer) in einer anderen Variablen steht.
Ich werde mal im Laufe von morgen Code für Bubblesort mit real existierenden S7-Befehlen posten. Er wird weniger übersichtlich aussehen.

Zuletzt wirst du noch folgendes tun müssen:
Du hast im DB10 eine Liste mit den Betriebsmitteln in absteigender Reihenfolge der Stunden.
Zunächst ermittelst du wieviele eingeschaltet werden sollen:
L 0
T MW2 //Zahl der BM, Annahme 0
UN E0.0 //keine Anforderung da?
SPB N1
LMW2
L1
+I
TMW2
N1: NOP 0
UN E0.1 //keine Anforderung da?
SPB N2
LMW2
L1
+I
TMW2
N2: NOP 0
...
Am Ende steht in MW2 die Zahl der einzuschaltenden Betriebsmittel.

nun kommt:
Wenn mindestens 7 Betriebsmittel gefordert, alle einschalten
Wenn mindestens 6 Betriebsmittel gefordert, die Nummern 1-6 der Indexliste einschalten
Wenn mindestens 5 Betriebsmittel gefordert, die Nummern 1-5 der Indexliste einschalten
...
Wenn mindestens 1 Betriebsmittel gefordert, die Nummer 1 der Indexliste einschalten
 
OP
rs-plc-aa

rs-plc-aa

Well-known member
Beiträge
727
Punkte Reaktionen
57
Zuviel Werbung?
->Hier kostenlos registrieren
Hallo,

super :!: danke bis jetzt...

Ich bin noch ein relativer Neuling, und habe wenig bis gar keine Erfahrung mit Arrays oder Pointern - umso interessanter lausche ich weiter.


Ich habe den Code mal geändert - jetzt fange ich als eröffnung mit:

7>6 ? - wenn ja machnix
6>5 ? - ...

2>1 ? - ...

macht 6 Vergleiche im ersten durchgang...

im zweiten lasse ich den letzten weg - usw.


Damit komme ich auf die 21.

Der letzte Durchgang wäre dann:

7>6 ? - wenn ja machnix.


Ich hoffe das passt :?:

So hätte ich dann den kleinsten oben usw. - wie ich ja will.


Jetzt muß ich die festen Adressen nur noch gegen die entsprechenden Variablen austauschen.


@Zottel:

Da warte ich aber noch auf deinen Vorschlag...




Ich für meinen Teil fahre jetzt los nach Nürnberg - ihr könnt euch wahrscheinlich denken wohin...



Also an alle die auch da sind:


Viel Erfolg bei den Verhandlungen, viel Spaß und alles was dazugehört.
 

Zottel

Well-known member
Beiträge
2.299
Punkte Reaktionen
277
Ok, hier meine Lösung zum Bublesort mit S7:
Code:
//FC16
// Parameter
laenge  INT  Laenge der Liste -1 
indexDB  INT  Nummer des Datenbausteins, der den Index enthält 
datenDB  INT  Nummer des Datenbausteins, der die Daten enthält 
datenLaenge INT  Länge eines Daten-Elements 
AUF_AB  BOOL  Sortierrichtung 
INIT_INDEX BOOL  Index inititialisieren 
//
// lokale Variablen:
//
i WORD  //Schleifenzaehler der äußeren Schleife 
j WORD  Schleifenzaehler der inneren Schleife 
idx1 DINT  Adresse des 1.Index-Elementes 
idx2 DINT  Adresse des 2. Index-Elementes 
iw1 WORD  Wert des ersten Index-Elementes 
iw2 WORD  Wert des 2. Index-Elementes 
dix1 DINT  Adresse des 1.Daten-Elementes 
dix2 DINT  Adresse des 2.Daten-Elementes 
DDBN WORD   
IDBN WORD   
VerglErg BOOL   
//
// Parameter umladen, weil AUF DB[x] nicht mit Parametern funktioniert:
//
      L     #indexDB 
      T     #IDBN
      L     #datenDB
      T     #DDBN
//
// Index initialisieren, wenn gewünscht.
//
      UN    #INIT_INDEX
      SPB   M005
      L     #laenge
      T     #i
      AUF   DB [#IDBN]
M004: NOP   0
      L     #i
      L     8 // 8 Bit pro Eintrag im Index
      *D    
      T     #idx1
      L     #i
      T     DBB [#idx1]
      L     1
      -I    
      T     #i
      SPPZ M004
 
M005: NOP   0

// die nächsten 8 Zeilen sind nur zum Beobachten:
      AUF   DB [#IDBN]
      L     DBB    0
      L     DBB    1
      L     DBB    2
      L     DBB    3
      L     DBB    4
      L     DBB    5
      L     DBB    6


      L     #laenge
      T     #i

M003: L     #laenge
      L     #i
      -I    
      L     1
      +I    
      T     #j

M002: NOP   0
      AUF   DB [#IDBN]
      L     #j
      L     8
      *D    
      T     #idx1
      L     DBB [#idx1]
      T     #iw1

      L     #idx1
      L     8                           //Länge eines Indexelements in Bit
      -D    
      T     #idx2                       //Index des letzten Elements
      L     DBB [#idx2]
      T     #iw2                        //Index des letzten Elements

      L     #iw1
      L     #datenLaenge
      *D    
      T     #dix1

      L     #iw2
      L     #datenLaenge
      *D    
      T     #dix2

      AUF   DB [#DDBN]

      L     DBD [#dix1]
      L     DBD [#dix2]
      >D    
      =     #VerglErg
      U     #VerglErg
      U     #AUF_AB
      O(    
      UN    #VerglErg
      UN    #AUF_AB
      )     
      SPB   m001
      AUF   DB    10
// das muss auch AUF DB [#IDBN] werden! Sonst klpppt's nicht mit anderen DB-Nummern als 10.
Leider geht das rot nicht innerhalb von code. Der folgende Code gehört noch zu FC16:

Code:
      L     #iw1
      T     DBB [#idx2]
      L     #iw2
      T     DBB [#idx1]
m001: NOP   0
      L     #j
      L     1
      -I    
      T     #j
      T     MB    22
      SPP   M002
      L     #i
      L     1
      -I    
      T     #i
      T     MB    23
      SPP   M003
      L     MB    22
      T     MW     0
// die nächsten 8 Zeilen sind nur zum Beobachten:
      AUF   DB [#IDBN]
      L     DBB    0
      L     DBB    1
      L     DBB    2
      L     DBB    3
      L     DBB    4
      L     DBB    5
      L     DBB    6
      BE
//
// OB1 zum Testen des FC16:
//
Code:
      CALL  FC    16
       laenge     :=6
       indexDB    :=10
       datenDB    :=20
       datenLaenge:=32
       AUF_AB     :=FALSE
       INIT_INDEX :=TRUE
      L     DB10.DBB    0
      L     DB10.DBB    1
      L     DB10.DBB    2
      L     DB10.DBB    3
      L     DB10.DBB    4
      L     DB10.DBB    5
      L     DB10.DBB    6

      CALL  FC    16
       laenge     :=6
       indexDB    :=10
       datenDB    :=20
       datenLaenge:=32
       AUF_AB     :=TRUE
       INIT_INDEX :=TRUE
      L     DB10.DBB    0
      L     DB10.DBB    1
      L     DB10.DBB    2
      L     DB10.DBB    3
      L     DB10.DBB    4
      L     DB10.DBB    5
      L     DB10.DBB    6
      BE
 
OP
rs-plc-aa

rs-plc-aa

Well-known member
Beiträge
727
Punkte Reaktionen
57
Hallo,

bin wieder von der Messe zurück.


@Zottel:

Die lokalen Variablen kenne ich bei FC´s nicht - nur bei FB´s unter "STAT" (Instanz-DB).

Oder meinst du damit die "Temp" bei der FC ?
 
Oben