Step 7 Bits schieben/verknüpfen und am Ende nur ein Vergleicher?

escride1

Level-1
Beiträge
1.110
Reaktionspunkte
262
Zuviel Werbung?
-> Hier kostenlos registrieren
Hey,

anbei ein Auszug aus einem AWL-Programm das ich zurückgeladen habe, da leider keinerlei Symbolik existiert und ich das Programm nun mit Symbolik ausstatten muss.

Habe es umformatiert damit es im FUP darstellbar ist (hoff ich).



Sehe ich das richtig das aus dem eigentlichen DB230.DWB276 ein Muster erstellt wird um es anschließend mittels DB15.DBW0 und DB15.DBW4 aufzuschlüsseln?
Es wird später nochmals abgefragt ob das jeweilige Ergebnis
DB236.DBW20/22 eine INT-Zahl größer 1000 ist, wodurch das eine, oder wenn nicht, ein anderes Ventil geöffnet wird.

Hängt also vom DB15.DBW0/DB15.DBW4 jeweils ab was darin stand.

Die Zwischenwerte im DB15.DBW50/54/64 werden im Programm nicht nochmals aufgerufen, auch nicht überlappend.

#Ventil_minus1 und #Ventil_wd ist jeweils eine Temp-Variable im FC die ich so benannt habe.




Hätte man nicht also eigentlich auch je nach Zahl (1-15) in DB230.DBW276 abfragen können ob Zahl 4,5,1 da ist und dann schalten?
Schaut irgendwie übersichtlicher aus dann statt...dieses :D

Aus welchem Grund wurde das so programmiert? Weiß das jemand?



edit: Code aus Quelle generiert (sauberer)


Code:
U     M      0.1; 
      =     L      4.0; 
      U     L      4.0; 
      SPBNB _003; 
      L     DB230.DBW  276; 
      L     1; 
      -I    ; 
      T     #Ventil_minus1; 
_003: NOP   0; 
      U     L      4.0; 
      SPBNB _004; 
      L     #Ventil_minus1; 
      T     #Ventil_wd; 
_004: NOP   0; 
      U     L      4.0; 
      SPBNB _005; 
      L     1; 
      T     DB15.DBW   50; 
_005: NOP   0; 
      U     L      4.0; 
      SPBNB _006; 
      L     #Ventil_wd; 
      L     DB15.DBW   50; 
      SLW   ; 
      T     DB15.DBW   50; 
_006: NOP   0; 
      U     L      4.0; 
      SPBNB _007; 
      L     DB15.DBW   50; 
      L     DB15.DBW    4; 
      UW    ; 
      T     DB15.DBW   54; 
_007: NOP   0; 
      U     L      4.0; 
      SPBNB _008; 
      L     DB15.DBW   50; 
      L     DB15.DBW    0; 
      UW    ; 
      T     DB15.DBW   64; 
_008: NOP   0; 
      U     L      4.0; 
      SPBNB _009; 
      L     DB15.DBW   54; 
      T     DB236.DBW   20; 
_009: NOP   0; 
      U     L      4.0; 
      SPBNB _00a; 
      L     DB15.DBW   64; 
      T     DB236.DBW   22; 
_00a: NOP   0;
 
Zuletzt bearbeitet:
Das wurde sehr wahrscheinlich in FUP oder KOP programmiert und geht mit den da vorhandenen Anweisungsboxen (SUB_I, SHL_W, MOVE) und deren EN/ENO-Mechanismus nicht eleganter, insbesondere wenn man durch das Vorschalten eines IMMER1-Merkers künstlich mehrere Strompfade in ein Netzwerk quetscht.
In AWL wäre das selbstverständlich kürzer gegangen, doch vermutlich wollte oder durfte der Programmierer das nicht in AWL programmieren.

PS: wie sah das originale AWL-Programm aus?

Harald
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Wie ich oben bereits geschrieben habe, ich habe es bereits so formatiert das es im FUP lesbar ist. Den Dauermerker hab ich reingeklatscht, aber aus dem Grund den Du schon nanntest - anders hätte ich es kaum dort hineinbekommen in ein Netzwerk, es sei denn ich hätte gleich 9 Stück daraus machen wollen.

Die Anlage wurde 2011 in Betrieb genommen, der Errichter ist wohl insolvent, weshalb ich da nun bei muss.

Mir geht es um die eigentliche Funktion - so wie ich es sehe wird eine Matrix generiert die dann ausgewertet wird durch das WAND.
Später wird dessen Ergebnis nach 1000 überprüft. (Ja/nein)

Fraglich ist nur, warum man das auf diese Weise macht anstatt einfach einen Datenbaustein mit Bits sowie index zu versehen und dort als bool zu hinterlegen ob der Zustand nun so oder so sein soll. Das wäre bei sowas eigentlich meine Lösung gewesen oder sonst halt einen FB mit mehreren Abfragen und nicht alles durch schieben sowie wort-und so zu "maskieren" das man es nichteinmal anständig lesen kann, zumal dieses Daten sind die zur Laufzeit nicht mehr benutzt werden, sondern nur der Eingang DB230.DBW276 und die beiden Ausgänge DB236.DBW20/22, beim Beobachten man aber genau die Bits zählen muss in der Variablentabelle was bei häufigem hin-und herschauen natürlich umständlich ist.


Auf jeden Fall ist dieser AWL-Code kürzer, keine Frage, der Programmierer hat sich auch bestimmt etwas dabei gedacht, mir gehts nur um die Übersichtlichkeit. Da ich ihn nicht kenne, frage ich Euch ob Ihr ein solches Verfahren kennt oder auch so machen würdet.

Mein späteres Problem hierbei wird es so oder so sein wenn mehr Nummern als 1-15 vergeben werden müssen. Das kann diese Abfrage ja garnicht, aber bei 16 Ventilen=16 Farben ist es auch hier nicht darstellbar, da 0 nicht existent ist und eine -1 erzeugen würde was nicht sein darf.


Code:
L     DB230.DBW  276 
L     1
-I    
T     #Ventil_minus1
L     #Ventil_minus1
T     #Ventil_wd
L     1
T     DB15.DBW   50
L     #Ventil_wd
L     DB15.DBW   50
SLW   
T     DB15.DBW   50
L     DB15.DBW   50
L     DB15.DBW    4
UW    
T     DB15.DBW   54
L     DB15.DBW   50
L     DB15.DBW    0
UW    
T     DB15.DBW   64
L     DB15.DBW   54
T     DB236.DBW   20
L     DB15.DBW   64
T     DB236.DBW   22

edit: stehe mit dem Code-Interpreter auf Kriegsfuß :D
 
Mein späteres Problem hierbei wird es so oder so sein wenn mehr Nummern als 1-15 vergeben werden müssen. Das kann diese Abfrage ja garnicht, aber bei 16 Ventilen=16 Farben ist es auch hier nicht darstellbar, da 0 nicht existent ist und eine -1 erzeugen würde was nicht sein darf.

Code:
L     DB230.DBW  276   //   L     DB230.DBW  276   // Numerierung 1 .. 16 (BitNr+1)
L     1                //   L     1
-I                     //   -I    
T     #Ventil_minus1   //   T     #Ventil_minus1   // Numerierung 0 .. 15 (BitNr)
L     #Ventil_minus1   //    
T     #Ventil_wd       //   T     #Ventil_wd       // Anzahl Bit, um die nach links geschoben wird
L     1                //   L     1                // das Bit, das geschoben wird   
T     DB15.DBW   50    //    
L     #Ventil_wd       //    
L     DB15.DBW   50    //
SLW                    //   SLW   
T     DB15.DBW   50    //   T     DB15.DBW   50    // Maske = BitMuster = 2^BitNr
 
L     DB15.DBW   50    //     
L     DB15.DBW    4    //   L     DB15.DBW    4
UW                     //   UW    
T     DB15.DBW   54    //   T     DB15.DBW   54    // das "indirekt adressierte" Bit aus DB15.DBW4
 
L     DB15.DBW   50    //   L     DB15.DBW   50    // Maske
L     DB15.DBW    0    //   L     DB15.DBW    0
UW                     //   UW    
T     DB15.DBW   64    //   T     DB15.DBW   64    // das "indirekt adressierte" Bit aus DB15.DBW0
 
L     DB15.DBW   54    //   L     DB15.DBW   54
T     DB236.DBW  20    //   T     DB236.DBW  20
L     DB15.DBW   64    //   L     DB15.DBW   64
T     DB236.DBW  22    //   T     DB236.DBW  22
Der Code kann aber 1 .. 16.
Für 1 .. 32 müsste man auf DoppelWort aufbohren.

In DB230.DBW276 steht, welches Bit im folgenden ausgefiltert werden soll, allerdings mit der Numerierung 1 .. 16 statt 0 .. 15.
Eine Art indirekter Adressierung eines Bits.
Warum und wozu, kann ich nicht nachvollziehen - das dürfte vielleicht das Drumherum ergeben, das hier fehlt.

Übrigens, Siemens O-Ton zur Erklärung der SchiebeBefehle:
"Die Zahl, die auf eine Schiebeoperation oder einen Wert im niederwertigen Byte des niederwertigen Worts von AKKU 2 folgt, gibt an, um wie viele Bits geschoben werden soll." :ROFLMAO:

"Die Zahl, die auf . . . einen Wert im niederwertigen Byte des niederwertigen Worts von AKKU 2 folgt, gibt an, . . . "
Hmmm, was will uns Siemens denn damit sagen??? Das wird noch Folgen haben???

"Der Operand der Schiebeoperation - sofern vorhanden, sonst der Inhalt des AKKU 2 - gibt an, um wie viele BitPositionen geschoben werden soll."
hätte ich noch verstehen können.

Gruss, Heinileini
 
Zuletzt bearbeitet:
Hm, auf jeden Fall kannst Du AWL besser wie ich :D

Was Siemens uns sagen will mit einigen ihrer Dinge, müssen wir wie immer selbst rausfinden, Anleitungen sind bei denen ja eh nicht verbindlich, irgendwie.

Zum Schieben:
Wenn ich
1000 0000 0000 0001
habe, dann würd beim Schieben doch ein Bit herausgeschoben werden. Das wäre danach doch verloren oder übersehe ich in dem Teil hier irgendwas?

Im Ablauf wird erst in Akku1 geladen, verschoben, wieder geladen, wodurch Akku1 nun in Akku2 ist, dann wieder geladen und nochmals, wodurch
am Ende in Akku1 DB15.DBW50 und in Akku2 die geschobene Bitfolge liegt, welche anschließend per WAND aussortiert wird.



Wenn ich ein Bit "rausschiebe", das aber nicht wieder hole, dann ist es weg, somit wären nach dem Schieben nur 15 mögliche Bits gesetzt sowie das eine Bit (1) was als Integer zuerst geladen wurde.
Also ein "Zwangsbit" sowie 15 mögliche.

Seh ich das da falsch?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn ich ein Bit "rausschiebe", das aber nicht wieder hole, dann ist es weg, somit wären nach dem Schieben nur 15 mögliche Bits gesetzt sowie das eine Bit (1) was als Integer zuerst geladen wurde.
Deine Bedenken sind grundsätzlich berechtigt, aber . . .

denn, nicht "sowie das eine Bit (1) was als Integer zuerst geladen wurde", sondern ausschliesslich die 1 befindet sich zum ZeitPunkt des Schiebens im Akku1.
Im Akku2 befindet sich eine Zahl im Bereich von 0 bis 15, vorausgesetzt, dass DB230.DBW276 eine Zahl im Bereich 1 bis 16 enthält - anders wäre allerdings übel, da (je nach CPU etc.) Werte > 16 bei Wort-SchiebeBefehlen bzw. > 32 bei DoppelWort-SchiebeBefehlen oder < 0 (negative Werte) als Fehler behandelt werden bzw. werden sollten (ist "Geschmackssache" und wurde schon an anderer Stelle hier im Forum diskutiert).

L 1 lädt 0000 0000 0000 0000 0000 0000 0000 0001 nach Akku1 (32 Bit). Dieses "BitMuster" kann um maximal 15 BitPositionen nach links verschoben werden, ohne dass sich die Anzahl der Einsen (nämlich 1) im LSW des Akku1 verändert. So weit - so einfach.

Was hinter der SiemensFormulierung "einen Wert im niederwertigen Byte des niederwertigen Worts von AKKU 2" steckt, weiss ich nicht genau - habe leider nichts zum Testen ;o(
Soll wohl bedeuten, dass die höherwertigen Bytes im Akku2 enthalten können, was sie wollen, weil sie ohnehin ignoriert werden. Und somit wären nur die Zahlen 0 bis 255 darstellbar. Also von vornherein keine negativen Zahlen.

So war es auch bei S5 mit den Befehlen B MWxxx und B DWxxx - es wurde nur das niederwertige Byte von MWxxx bzw. DWxxx ausgewertet - auch damals schon war Testen wesentlich ergiebiger als DokuLesen.

Gruss, Heinileini
 
Deine Bedenken sind grundsätzlich berechtigt, aber . . .

denn, nicht "sowie das eine Bit (1) was als Integer zuerst geladen wurde", sondern ausschliesslich die 1 befindet sich zum ZeitPunkt des Schiebens im Akku1.
Im Akku2 befindet sich eine Zahl im Bereich von 0 bis 15, vorausgesetzt, dass DB230.DBW276 eine Zahl im Bereich 1 bis 16 enthält - anders wäre allerdings übel, da (je nach CPU etc.) Werte > 16 bei Wort-SchiebeBefehlen bzw. > 32 bei DoppelWort-SchiebeBefehlen oder < 0 (negative Werte) als Fehler behandelt werden bzw. werden sollten (ist "Geschmackssache" und wurde schon an anderer Stelle hier im Forum diskutiert).

L 1 lädt 0000 0000 0000 0000 0000 0000 0000 0001 nach Akku1 (32 Bit). Dieses "BitMuster" kann um maximal 15 BitPositionen nach links verschoben werden, ohne dass sich die Anzahl der Einsen (nämlich 1) im LSW des Akku1 verändert. So weit - so einfach.

Was hinter der SiemensFormulierung "einen Wert im niederwertigen Byte des niederwertigen Worts von AKKU 2" steckt, weiss ich nicht genau - habe leider nichts zum Testen ;o(
Soll wohl bedeuten, dass die höherwertigen Bytes im Akku2 enthalten können, was sie wollen, weil sie ohnehin ignoriert werden. Und somit wären nur die Zahlen 0 bis 255 darstellbar. Also von vornherein keine negativen Zahlen.

So war es auch bei S5 mit den Befehlen B MWxxx und B DWxxx - es wurde nur das niederwertige Byte von MWxxx bzw. DWxxx ausgewertet - auch damals schon war Testen wesentlich ergiebiger als DokuLesen.

Gruss, Heinileini

Ich sehe was Du damit meinst. Also ich sehe wie das Muster sich verändert (im Kopf ^^).
Dann muss ich mal untersuchen warum die Anlage bei 32768 (Nummer 16) stehen geblieben ist. Da gab es nämlich ein Problem mit. Und ich hab das falsch verstanden.

Ich denke das ich auf Dauer diese Abfrageart ändern werde. Ist mir echt zu unübersichtlich. Da ist es mir lieber 16 Abfragen zu haben die im FUP auch "ansehnlich" zu beobachten sind. Da wird ja keiner draus schlau wenn man es nicht versteht.

Vielen Dank!
 
Obwohl das Thema als gelöst markiert ist, ist es nach meiner Meinung genau nicht!
Deshalb gebe ich hier mal meinen Senf dazu:
Bemerkungen 1 bezogen auf den Originalcode:
1. Da bei M0.1=0 gesprungen wird, wird bei M0.1=0 nichts gemacht und bei M0.1=alles bearbeitet.
Deshalb kann man bei M0.1=0 auch gleich an das Ende springen.
2. Das Umstapeln von M0.1 nach L4.0 kann man sich deshalb sparen.
Beachtet man beides, verkürzt sich der Code auf das Folgende.
Code:
      U     M      0.1;  
      SPBNB _00a;   // springt bei Mo.1=0
      L     DB230.DBW  276; 
      L     1; 
      -I    ; 
      T     #Ventil_minus1;  
      L     #Ventil_minus1;  // dieser Befehl kann entfallen
      T     #Ventil_wd;  // Ventil_wd und auch Ventil_minus 1 enthalten DBW 276 minus 1!
      L     1;    // Hier beginnt eine eigenständige Sequenz 
      T     DB15.DBW   50;      // DBW 50 enthält jetzt nur das Bitmuster 0...1
      L     #Ventil_wd;  // Ventil_wd enthält DBW276 minus 1, ist scheinbar ein Zeiger auf irgend etwas.
      L     DB15.DBW   50;  // DBW 50 enhält in diesem Moment 0...1
      SLW   ;    // siehe Bemerkungen 2
      T     DB15.DBW   50;  // DBW 50 enthhält jetzt eine einzelne 1, aber nicht mehr im Bit 0 sondern irgend eins der Bit 0...15
      L     DB15.DBW   50;  // Ab hier beginnt eine Auswahlroutine
      L     DB15.DBW    4;  // siehe Bemerkung 3
      UW    ; 
      T     DB15.DBW   54;  // DBW 54 enthält das eine ausgewählte Bit für die Freigabe
      L     DB15.DBW   50; 
      L     DB15.DBW    0;  // siehe Bemerkung 3, aber jetzt für DBW 0 und DBW 64
      UW    ; 
      T     DB15.DBW   64;  // hier kann man wieder vieles einsparen, siehe Endergebnis
      L     DB15.DBW   54; 
      T     DB236.DBW   20; 
      L     DB15.DBW   64; 
      T     DB236.DBW   22; 
_00a: NOP   0;
Bemerkung 2:
Der Befehl SLW ohne Parameter schiebt den Inhalt Akku 1 so oft nach links, wie der als Zahl interpretierte Inhalt der Bit 0...7 des Akku 2 enthält.
Von rechts werden dabei in den Akku 1 Nullen eingeschoben. Die nach links herausgeschobenen Bit gehen verloren!
Sinn machen die Befehle nur, wenn Ventil_wd maximal den Wert 15 enthält!
Bemerkung 3:
DBW 4 müsste 16 1-Signale enthalten, dann würde das DW54 am Ende genau eine 1 aufweisen und z.B. etwas freigeben.
Hat das DBW 4 aber an einer Stelle ein 0-Bit, dann würde genau diese Freigabe genau nicht erfolgen. Auf diese Weise könnte man sehr einfach z.B.
Ventile freigeben oder eben sperren.
Code:
      U     M      0.1;  
      SPBNB _00a;   // springt bei Mo.1=0
      L     DB230.DBW  276; 
      L     1; 
      -I    ; 
      T     #Ventil_minus1;  
      T     #Ventil_wd;  // Ventil_wd und auch Ventil_minus1 enthalten beide DBW 276 minus 1!
      L     1;    // Hier beginnt eine eigenständige Sequenz 
      T     DB15.DBW   50;      // DBW 50 enthält jetzt nur das Bitmuster 0...1
      L     #Ventil_wd;  // Ventil_wd enthält DBW276 minus1, ist scheinbar ein Zeiger auf irgend etwas.
      L     1
      SLW   ;    // siehe Bemerkungen 2
      T     DB15.DBW   50;  // irgend ein Bit des DBW 50 enthhält jetzt eine einzelne 1
      L     DB15.DBW   50;  // Ab hier beginnt eine Auswahlroutine
      L     DB15.DBW    4;  // siehe Bemerkung 3
      UW    ; 
      T     DB236.DBW   20;
      L     DB15.DBW   50; 
      L     DB15.DBW    0;  // siehe Bemerkung 3, aber jetzt für DBW 0 und DBW 64
      UW    ; 
      T     DB236.DBW   22;    
_00a: NOP   0;
Insgesamt also handelt es sich um eine Lösung zur Auswahl 1 aus 16 mit Freigabe oder Sperrmöglichkeit.
Hilfreich wäre natürlich, wenn man die technische Anlage die dahinter steht, kennen würde.
eNDe
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Bemerkungen 1 bezogen auf den Originalcode:
1. Da bei M0.1=0 [...]
Der Original-Code ist der Code aus Beitrag #3. Der Code aus #1 ist bereits bearbeiteter Code für die Darstellbarkeit in FUP/KOP - daher kommen M0.1 und L4.0 und die scheinbar unnötigen Sprünge - das ist Standard-Code für die Verschaltung von EN der FUP/KOP-Boxen.
Du hast jetzt quasi aus dem FUP/KOP-Code wieder den originalen AWL-Code separiert. :D

Harald
 
Habe ich nicht darauf geachtet. Als "Entschuldigung" hier mein Vorschlag für die 32-Bit-Version
Code:
L     DB230.DBW  276  // kann enthalten die Zahl 1 ... 32 (z.B. über Wahlschalter)
L     1
-I    
T     #Ventil_minus1  // kann enhalten die Zahl 0 ... 31 (einer der beiden Befehle könnte im)
T     #Ventil_wd // kann enhalten die Zahl 0 ... 31 (vorliegenden Codeschnippsel entfallen)
L     1
SLW   
T     DB15.DBW   50 // 1 geschoben auf Pos. Bit 0 ... 31 (für die Maskierung)
L     DB15.DBW   50
L     DB15.DBW    4
UW    
T     DB15.DBW   20 // Nur 1 Bit hat 1-Signal (Bit 0 ... Bit 31, falls alle Bit des DBW 4 = 1)
L     DB15.DBW   50
L     DB15.DBW    0
UW    
T     DB15.DBW   22 // Nur 1 Bit hat 1-Signal (Bit 0 ... Bit 31, falls alle Bit des DBW 0 = 1)
eNDe
 
Als "Entschuldigung" hier mein Vorschlag für die 32-Bit-Version
Ganz so einfach ist die Umstellung auf 32 Bit leider nicht. Es genügt nicht, die Kommentare auf 32 Bit umzuschreiben.
SLW und UW müsste man ersetzen durch SLD und UD. Und die Operanden DBx.DBWy durch DBx.DBDy.
Aber letzteres setzt voraus, dass die dadurch zusätzlich belegten Bytes im DBx nicht anderweitig benutzt werden.
Das ist im Falle von DB15.DBD20 und DB15.DBD22 eindeutig nicht gegeben.
Apropos Kommentare: ". . . (Bit 0 … Bit 31, falls ALLE Bit . . . = 1)" ist schon ziemlich verkorkst, findest Du nicht?

Schönes WE, Heinrich
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Heinileini hat ja Recht, deshalb hier die funktionierende Lösung für 32 Bit, aber auf die Schnelle mit Merkerworten.
Code:
L    27                           // Ventilauswahl (1...32), 27 als Test
T    MW      276       
L    DW#16#FFFFFFF7               // 31 von 32 Bit = 1, Ventil 4 gesperrt (als Test)      
T    MD        4       
T    MD        0
// Bis hier nur Dateneingabe zum Testen 
       
L    MW      276                  // kann enthalten die Zahl 1 ... 32 (z.B. über Wahlschalter)        
L    1       
-I      
T    MW       10                  //  Ventil-1
       
L    1       
SLD        
T    MD       50                  // 1 geschoben auf Bit 27 (für die Maskierung)               
L    MD        4       
UD        
T    MD       20                  // Nur Bit 27 hat 1-Signal        

L    MD       50      
L    MD        0       
UD      
T    MD       24                  // Nur Bit 27 hat 1-Signal 

// getestet und läuft (16.3.2019)
ebenfalls schönes WE
eNDe
 
Zurück
Oben