TIA SPBN und UW in SCL?

statusbass

Level-1
Beiträge
12
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo, ich brauche Eure Hilfe bei umsetzen einer kleiner Funktion (sehe CODE)
S7-300 soll gegen S7-1200 getauscht werden. AWL kann nicht mehr benutzt werden und ich versuche mich in SCL.
Wie soll ich das anpacken? Hat jemand eine Idee?

Input:
In_Flanke_Ein Bool
In_Freigabe_Motor Byte

In_Out:
In_Out_Start_Motor Byte



// Impuls Anlage Ein (mit p-Flanke)

UN #In_Flanke_Ein
SPB m010

//
L #In_Out_Start_Motor
L 0
==I
SPBN m014 // Startreihenfolge noch auf 0

L 1
T #In_Out_Start_Motor // dann mit 1 laden

m014:

L #In_Freigabe_Motor
L 0 // ist mindestens ein Motor bereit: dann weiter...
==I
SPBN m012

L 0 // wenn nicht, Startreihenfolge auf Null setzen und Baustein verlassen
T #In_Out_Start_Motor
SPA m010

m012:

L #In_Out_Start_Motor // einen Motor hochzählen (Startreihenfolge verdoppeln)
L 2
*I
T #In_Out_Start_Motor
L 255 // max. Anzahl Motoren, die aktiv sind
>I
SPBN m011

L 1 // dann wieder von vorne anfangen
T #In_Out_Start_Motor

m011: NOP 0

L #In_Out_Start_Motor // ist ausgewählter Motor bereit: dann fertig
L #In_Freigabe_Motor
UW
L 0
==I

SPB m012 // wenn nicht, nochmal prüfen


m010: NOP 0


VG.
 
Tip: Programmcode wird besser lesbar, wenn man ihn in [CODE]-Tags postet (der #-Button im Beitragseditor):
Code:
            Input:                                  
            In_Flanke_Ein         Bool                           
            In_Freigabe_Motor       Byte    
 
            In_Out: 
            In_Out_Start_Motor       Byte                
 
           
 
//  Impuls Anlage Ein (mit p-Flanke)
 
      UN    #In_Flanke_Ein
      SPB   m010
 
//
      L     #In_Out_Start_Motor
      L     0
      ==I
      SPBN  m014                                                   // Startreihenfolge noch auf 0
 
      L     1
      T     #In_Out_Start_Motor                              // dann mit 1 laden
 
m014:
 
      L     #In_Freigabe_Motor
      L     0                                                             // ist mindestens ein Motor bereit: dann weiter...
      ==I
      SPBN  m012
 
      L     0                                                           // wenn nicht, Startreihenfolge auf Null setzen und Baustein verlassen
      T     #In_Out_Start_Motor
      SPA   m010
 
m012:
 
      L     #In_Out_Start_Motor                          // einen Motor hochzählen (Startreihenfolge verdoppeln)
      L     2
      *I
      T     #In_Out_Start_Motor
      L     255                                                           // max. Anzahl Motoren, die aktiv sind
      >I
      SPBN  m011
 
      L     1                                                            // dann wieder von vorne anfangen
      T     #In_Out_Start_Motor
 
m011: NOP 0
 
      L     #In_Out_Start_Motor                             // ist ausgewählter Motor bereit: dann fertig
      L     #In_Freigabe_Motor
      UW
      L     0                                                         
      ==I
 
      SPB   m012                                                // wenn nicht, nochmal prüfen
 
 
m010: NOP 0
AWL: Bedingung / SPBN Mxxx / Anweisungen / Mxxx
wird übersetzt zu:
SCL: IF Bedingung THEN Anweisungen; END_IF;

Falls nach der Bedingung SPB anstatt SPBN verwendet wird, dann muß man die Bedingung für das IF negiert formulieren.

z.B.
Code:
*** AWL ***
      UN    #In_Flanke_Ein
      SPB   m010

      L     #In_Out_Start_Motor
      L     0
      ==I
      SPBN  m014                       // Startreihenfolge noch auf 0 ?
 
      L     1
      T     #In_Out_Start_Motor        // dann mit 1 laden
 
m014:
      ...
m010:

*** SCL ***
IF #In_Flanke_Ein THEN

    IF #In_Out_Start_Motor = 0 THEN    // Startreihenfolge noch auf 0 ?
        #In_Out_Start_Motor := 1;      // dann mit 1 laden
    END_IF;

    ...
END_IF; //m010

Im zweiten Teil des Codes ist eine Schleife - erkennbar an dem bedingten Rücksprung "SPB m012".
Die Schleife soll wiederholt werden, wenn kein weiterer freigegebener Motor in dem Motor-Bitfeld (#In_Out_Start_Motor) gefunden wurde.

UW heißt "Wortweise nach UND verknüpfen" (die positionsgleichen Bits von 2 Words UND-verknüpfen, siehe TIA Hilfe)

Code:
*** AWL ***
[COLOR="#0000FF"]      L     #In_Out_Start_Motor        // ist ausgewählter Motor bereit: dann fertig
      L     #In_Freigabe_Motor
      UW
      L     0                                                         
      ==I[/COLOR]
 
      SPB   m012                       // wenn nicht, nochmal prüfen
 
 m010: NOP 0

*** SCL ***
... [COLOR="#0000FF"](#In_Out_Start_Motor AND #In_Freigabe_Motor) = 0[/COLOR] ...
Das "SPB m012" muß man nun in ein Schleifen-Konstrukt umwandeln. Die Bedingung für den Rücksprung (Wiederholung der Schleife) muß man hier vermutlich negiert formulieren, weil es in SCL keine DO..WHILE-Schleife gibt. Ob eine REPEAT..UNTIL oder WHILE..DO Schleife hier besser ist, sehe ich jetzt auf die Schnelle nicht. Vielleicht kann man sogar die extra Prüfungen vor der Schleife (von m014 bis m012) weglassen bzw. in die Schleifenbedingung übernehmen.
Code:
*** SCL ***
REPEAT
    ... //m012..m011
UNTIL (#In_Out_Start_Motor AND #In_Freigabe_Motor) <> 0
END_REPEAT;

[FONT=Arial]oder vielleicht passt WHILE..DO besser?[/FONT]

WHILE (#In_Out_Start_Motor AND #In_Freigabe_Motor) <> 0 DO
    ... //m012..m011
END_WHILE;

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Harald,
Vielen Dank für deine wertvolle Tipps. Ich werde am WE versuchen dies umzusetzen.
Ich bin, wenn um SCL geht, eher am Anfang. IF…Then usw. sind klar.
For oder Case habe ich auch schon verwendet.
Bei meiner Funktion war ich mir nicht klar ob ich unbedingt springen muss.
Ich habe am Anfang mit Goto probiert aber…. es hat nicht funktioniert.
AWL nach SCL „übersetzen“ geht, wie man sieht, nicht.
VG - Jo.
 
Code:
IF #In_Start THEN
    IF #In_Out_Byte = 0 THEN
        #In_Out_Byte := 1;
    END_IF;
    
    WHILE (#In_Out_Byte AND #In_Byte) <> 0 DO
        
        IF #In_Byte > 0 THEN
            #In_Out_Byte := #In_Out_Byte * 2;
        END_IF;
        
        IF #In_Out_Byte > 255 THEN
            #In_Out_Byte := #In_Out_Byte + 1;
        END_IF;
        
    END_WHILE;
    
    
END_IF;

Hallo, irgendwie klappt es mit der Schleife nicht. mein Baustein "schiebt" den Bit eins weiter aber nur einmalig...
Was mache ich falsch?

VG.
 
Ich denke ...
Code:
IF #In_Byte = 0 THEN
    #In_Out_Byte = 0 ; // optional, löscht #In_Out_Byte, wenn #In_Byte = 0
ELSIF NOT #In_Start OR #In_Start_PRV THEN
    ;
ELSE // wenn #In_Byte <> 0 UND pos. Flanke von #In_Start
    REPEAT
        IF #In_Out_Byte AND 16#7F = 0 THEN
            #In_Out_Byte = 1;
        ELSE
            #In_Out_Byte := #In_Out_Byte * 2;
        END_IF ;    
    UNTIL (#In_Out_Byte AND #In_Byte) <> 0
    END_REPEAT ;
END_IF ;    
#In_Start_PRV := #In_Start ; // #In_Start_PRV muss 'static' sein!
... sollte das tun, was Du möchtest.

In Deinem Code ist 'IF #In_Out_Byte > 255 THEN' überflüssig/unwirksam, da das Byte nie grösser als 255 werden kann.

Die WHILE-Schleife 'WHILE (#In_Out_Byte AND #In_Byte) <> 0 DO' soll doch ausgeführt werden, wenn '(#In_Out_Byte AND #In_Byte) = 0' ist!?

Aber Vorsicht! Endlosschleife, wenn '#In_Byte' = 0 ist!

Habe vorsichtshalber die FlankenErkennung von '#In_Start' in den Baustein integriert.
 
Hallo,
Code:
IF #In_Byte = 0 THEN
    #In_Out_Byte = 0 ; // optional, löscht #In_Out_Byte, wenn #In_Byte = 0
ELSIF NOT #In_Start OR #In_Start_PRV THEN
    ;
ELSE // wenn #In_Byte <> 0 UND pos. Flanke von #In_Start......

Kannst du mir dies bitte neher erklären?

Ich habe deine Idee umgesetzt aber wie bei mir: Bit wird nur einmalig um ein "Platz" weiter geschoben und das was.
Was mache ich falsch?

VG.
 
Code:
IF #In_Byte = 0 THEN
    #In_Out_Byte = 0 ; // optional, löscht #In_Out_Byte, wenn #In_Byte = 0
ELSIF NOT #In_Start OR #In_Start_PRV THEN
    ;
ELSE // wenn #In_Byte <> 0 UND pos. Flanke von #In_Start......

Wenn #In_Byte 0 ist dann wird auf #In_Out_Byte 0 geschrieben.
Sonst passiert nichts da im ElseIf kein Befehl eingetragen ist.

Steht ja als Kommentar auch schon so dabei:
// optional, löscht #In_Out_Byte, wenn #In_Byte = 0
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Bit wird nur einmalig um ein "Platz" weiter geschoben und das was.
Was sollte Deiner Meinung nach passieren?
Welche Bits sind in '#In_Byte' gesetzt?
Ist '#In_Out_Byte' nicht nur dem Namen nach eine In-Out-Variable, sondern auch als solche deklariert?

Die Funktionsweise, die ich vorgesehen habe, ist, dass jedesmal, wenn '#In_Start' von 0 auf 1 wechselt, die jeweils nächste, laut '#In_Byte' freigegebene Bit-Position in '#In_Out_Byte' auf 1 geht und alle anderen Bits auf 0.

Zu den Abfragen:
- IF ... : Wenn '#In_Byte' = 0 ist (also keine einzige Freigabe enthält), dann wird '#In_Out_Byte' ebenfalls auf 0 gesetzt und es wird gar nicht erst untersucht, ob eine passende Freigabe vorhanden sein könnte, weil die Schleife sich "einen Wolf suchen" würde und es zu einer ZykluszeitÜberschreitung käme.
- ELSIF ... : Diese Abfrage wird nur durchlaufen, wenn '#In_Byte' <> 0 ist (s.o.) und hier wird abgefragt, ob KEINE positive Flanke von '#In_Start' vorliegt. Wenn keine Flanke vorliegt, wird nichts weiter getan.
- ELSE : Die folgenden ProgrammZeilen bis 'END_IF' werden also nur durchlaufen, wenn 'In_Byte' <> 0 ist UND eine positive Flanke von '#In_Start' vorliegt.
Hier wird in einer Schleife das Bit in '#In_Out_Byte' um eine Position nach links geschoben (durch Multiplikation mit 2) oder, wenn das höchstwertige Bit 1 ist, wird stattdessen das niederwertigste gesetzt. Dies wird solange wiederholt, bis die UND-Verknüpfung von '#In_Out_Byte' und 'In_Byte' ungleich 0 ist, was bedeutet, dass das nächste der freigegebenen Geräte aktiviert wird (oder wieder dasselbe Gerät, wenn kein anderes freigegeben ist).

PS:
Wenn die Freigabe des aktiven Gerätes entfällt, wird nicht automatisch das nächste, freigegebene Gerät gesucht. Sollen wir dies noch "nachstricken"?
 
Zuletzt bearbeitet:
Hallo,

„In_Out_Byte“ ist natürlich als In_Out Variable deklariert.
Es sollte, wie Du richtig geschrieben hast: „jedes mal, wenn '#In_Start' von 0 auf 1 wechselt, die jeweils nächste, laut '#In_Byte' freigegebene Bit-Position in '#In_Out_Byte' auf 1 geht und alle anderen Bits auf 0“
Ich habe im „In_Byte“ alle Bits freigegeben (alle sind TRUE)
Mit erste pos. Flanke wurde Bit 0 = TRUE (alle andere FALSE), mit zweite pos. Flanke Bit 1 = TRUE
(alle andere FALSE) und weiter ist nichts passiert. Egal wie oft die pos. Flanke kommt.
CPU ist im RUN, erst
nach STOP>RUN der CPU kann ich dies wiederholen: Bit0 dann Bit 1 und … wieder nichts)

Die Freigaben (was im In_Byte auf TRUE gesetzt wird) habe ich bereits fertig.
Beispiel: Sind Bits 0,2,4,6 > TRUE sollte mit Flanke In_Start erst Bit 0 dann 2 dann 4 dann 6 und wieder 0 dann 2 usw. TRUE sein.
 
Ich habe im „In_Byte“ alle Bits freigegeben (alle sind TRUE)
Mit erste pos. Flanke wurde Bit 0 = TRUE (alle andere FALSE), mit zweite pos. Flanke Bit 1 = TRUE
(alle andere FALSE) und weiter ist nichts passiert. Egal wie oft die pos. Flanke kommt.
CPU ist im RUN, erst
nach STOP>RUN der CPU kann ich dies wiederholen: Bit0 dann Bit 1 und … wieder nichts).
Hmmm. Ja, wenn das so ist, dann interpretiere ich Deinen Satz ...
Ich habe deine Idee umgesetzt aber wie bei mir: Bit wird nur einmalig um ein "Platz" weiter geschoben und das was.
... diesmal etwas anders.
Mittlerweile gehe ich davon aus, dass das Problem nicht bei dieser kleinen Routine liegen kann, sondern, dass im "Drumherum" irgendetwas schief laufen muss.

Wird die Routine wirklich in jedem Zyklus durchlaufen oder wird sie unter bestimmten Umständen "umgangen" oder "abgehängt"?
Wird die Variable, die an '#In_Out_Byte' angelegt ist, noch an einer anderen Stelle im Programm verändert, also überschrieben?

Was bedeutet "Bit0 dann Bit 1 und … wieder nichts"? Wenn der Zustand "wieder nichts" erreicht ist, wie sieht er aus? Sind dann alle Bits = 0 oder bleibt es beim vorherigen Zustand hängen, dass Bit1 = 1 ist?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
In_Out_Byt wird definitiv nicht überschrieben. Ich habe nur den einen FB mit dem Code aufgerufen.
Nochmal die Erklärung: pos. Flanke > TRUE , Bit 0 ist TRUE und alle anderen False, bei nächste Flanke Bit 0 False, Bit 1 > TRUE alle anderen sind FALSE, bei nächste Flanke bleibt Bit 0 False, Bit 1 > TRUE und alle andern sind FALSE.
Die routine läuft und wird nicht umgangen.
 
Hallo,

Mittlerweile gehe ich davon aus, dass das Problem nicht bei dieser kleinen Routine liegen kann, sondern, dass im "Drumherum" irgendetwas schief laufen muss.
Korrekt. Meine Flanke kamm nicht "sauber"
Routine funktioniert und macht alles wie mein AWL Code.
Vielen Dank für die Hlfe.
VG
 
Zurück
Oben