Step 7 Schieberegister in SCL?

Zuviel Werbung?
-> Hier kostenlos registrieren
Nö, M201.0 ist ein Bit das kann nicht (INT) 1 werden, sondern nur TRUE oder FALSE.
Das ganze MW200 könnte 1 werden.
;)

Ja ok, das MW ist ja als Word deklariert, stimmt. Aber wie setze ich dann in SCL ein Bit eines Merkerworts auf 1?

Ich möchte ja nur das Bit0 des MB201 setzen!
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Oh natürlich, bin ich b...!

Nun klappt auch das Schieberegister; nur mit dem Ausgang gibt es noch ein Problemchen...

Wenn ich E0.0 2x aktiv lasse, dann wird hintereinander 2x M201.0 gesetzt.

Wenn jetzt die erste 1 die Stelle 13 (M200.5) erreicht, so wird der Ausgang plötzlich nicht mehr gesetzt, warum das?

Code:
IF E0.1 THEN
  M201.0 := true;
END_IF;

IF TAKT THEN
  SchiebeRegister := SHL(IN := SchiebeRegister, N := 1);
END_IF;

IF M200.5 = true THEN
  A0.1 := 1;
END_IF;
 
Wenn ich E0.0 2x aktiv lasse, dann wird hintereinander 2x M201.0 gesetzt.
Ich vermute mal, Du meinst E0.1.
Flanke bilden oder MW200 auf 0 abfragen.


Wenn jetzt die erste 1 die Stelle 13 (M200.5) erreicht, so wird der Ausgang plötzlich nicht mehr gesetzt, warum das?
Immer diese IF...THEN-Verschwendung. Versuch mal so:
Code:
...
IF TAKT THEN
  SchiebeRegister := SHL(IN := SchiebeRegister, N := 1);
END_IF;

A0.1 := M200.5;
PS: Außer der Ausgang soll auch an bleiben, wenn M200.5 wieder 0 ist, dann:
Code:
[LEFT][COLOR=#333333]IF M200.5 THEN
  [/COLOR][COLOR=#333333]A0.1 := TRUE;[/COLOR][COLOR=#333333]
[/COLOR][COLOR=#333333]END_IF;[/COLOR][COLOR=#333333]
[/COLOR][/LEFT]
 
Zuletzt bearbeitet:
Ich vermute mal, Du meinst E0.1.

PS: Außer der Ausgang soll auch an bleiben, wenn M200.5 wieder 0 ist, dann:
Code:
[LEFT][COLOR=#333333]IF M200.5 THEN
  [/COLOR][COLOR=#333333]A0.1 := TRUE;[/COLOR][COLOR=#333333]
[/COLOR][COLOR=#333333]END_IF;[/COLOR][COLOR=#333333]
[/COLOR][/LEFT]

Lieben Dank hucki!

Ja, meinte E0.1

Also wenn ich schreibe

A0.1 := M200.5;

dann klappt das!

Und mit

Code:
IF M200.5 THEN
  A0.1 := 1;
END_IF;

funktioniert es auch plötzlich...

Könnte es sein, dass es daran gelegen hat, dass nach einer Änderung der Instanz-DB nicht in die Steuerung geladen wurde; bzw. muss nach jeder kleinen Änderung zusammen mit dem FB auch immer der Instanz-DB geladen werden?
 
Zuletzt bearbeitet:
Hi hucki,

du warst schneller mit deiner Antwort als ich mit meiner Korrektur. Also es klappt jetzt alles!

Vorhin allerdings nicht und daher nochmals meine Frage:

Könnte es sein, dass es daran gelegen hat, dass nach einer Änderung der Instanz-DB nicht in die Steuerung geladen wurde; bzw. muss nach jeder kleinen Änderung zusammen mit dem FB auch immer der Instanz-DB geladen werden?
 
Könnte es sein, dass es daran gelegen hat, dass nach einer Änderung der Instanz-DB nicht in die Steuerung geladen wurde; bzw. muss nach jeder kleinen Änderung zusammen mit dem FB auch immer der Instanz-DB geladen werden?
Zumindest, wenn Du an der Instanz was änderst. Und das dürftest Du mit der Flankenerkennung getan haben, oder?

Wenn du aber schon einen FB verwendest, solltest Du nicht mit den absoluten Adressen arbeiten, sondern diese über die Schnittstelle auf lokale Variablen übergeben!
PS: Diese Unart gewöhnt man sich nur schwer wieder ab. Glaub' mir, ich hab's durch.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Ok, dann wird es vermutlich daran gelegen haben.

Also, wenn man an der Deklaration nichts verändert, dann muss man nach Änderungen im FB nicht auch automatisch den Instanz-DB mit in die Steuerung laden, richtig?

Du meinst, bei einem FB sollte mit IN- und Out-Variablen gearbeitet werden, die dann den Aktualparametern übergeben werden? Gibt es da einen Vorteil gegenüber dem Arbeiten mit absoluten Adressen?

Lieben Dank!
 
Gibt es da einen Vorteil gegenüber dem Arbeiten mit absoluten Adressen?
Erstmal kann man den FB dadurch mehrfach im Programm verwenden, dadurch, das man nur die Außenbeschaltung des FBs austauschen muss/kann.
Dann kann man die Adressen viel einfacher austauschen, ohne das ganze Programm des FBs durchsuchen zu müssen.
Dadurch kann man den FB dann auch einfacher in andere Programme kopieren oder weitergeben, ohne prüfen zu müssen, ob die Variablen schon irgendwo anders genutzt werden.

Der FB arbeitet dann intern immer gleich, egal was sich an der Außenbeschaltung ändert.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@hucki: Ja stimmt, das sind viele Vorteile. Dann werde ich das in Zukunft auch so machen! Aber einen Geschwindigkeitsvorteil bringt diese Art von Progr. nicht, oder?

Ich hab auf die schnelle mal ein Beispiel gemacht.
Schau Dir das mal an, ob Du damit was anfangen kannst.

Ganz lieben Dank für dein Beispiel Tigerente!

Gleich am Montag werde ich mich an dein Beispiel machen... hoffe, ich verstehe es auch! ;)

Melde mich dann...
 
Ich hab auf die schnelle mal ein Beispiel gemacht.
Schau Dir das mal an, ob Du damit was anfangen kannst.

Anhang anzeigen 21438

Hi Tigerente,

nochmals Danke für dieses Beispiel. Habe mir es jetzt angeschaut und ich hoffe im Groben auch verstanden.

Wenn ich es richtig sehe, dann schiebst du die vier Elemente aus dem UDT mit jedem Takt im DB100 um eine Stelle weiter und zwar in der Reihenfolge 13-->14, 12-->13, usw. bis 1-->2.

Fragen hierzu:

1)
Hat das einen bestimmten Grund, dass du die vier Elemente nicht zuerst von Platz 1 auf 2, von 2 auf 3, usw. schiebst?

2)
Wie bildest du mit M10.0 den Takt? Er ist doch in der HW-Config. nicht als Taktmerker deklariert.


Der Ausgang 13 wird aktiv, wenn Status_A im DB100 dem Platz 13 zugewiesen wurde und Fehler_A "FALSE" ist.

Frage hierzu:

1)
Wo oder wodurch wird denn z.B. Status_A auf "TRUE" gesetzt?


Lieben Dank…
 
Hallo Spirit,
du mußt in einem Array beim Verschieben immer von hinten nach vorne Schieben.
Wenn du von 1 auf 2 schiebst und dann erst von 2 nach 3 dann hast du in aller Speicherstellen den Inhalt von 1 drinstehen (1 -> 2 , dann 2 == 1 usw.)
Deswegen erst 11 -> 12, dann 10 -> 11 usw.

Der Takt wird hier wahrscheinlich (wie auch bei mir) als Impuls vom Drehtisch kommen.

Den Ausgang gibt es nur für dich (schätze ich) ...

Gruß
Larry

@Tigerente:
Nimmst du für das Verschieben der einzelnen Elemente tatsächlich den Blockmove ? Ich habe bei mir 10-Byte-Blöcke (das Pendant zu deinem UDT) - da hat sich der SFC gegenüber dem regulären Code nicht "rentiert" ...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Spirit,
du mußt in einem Array beim Verschieben immer von hinten nach vorne Schieben.
Wenn du von 1 auf 2 schiebst und dann erst von 2 nach 3 dann hast du in aller Speicherstellen den Inhalt von 1 drinstehen (1 -> 2 , dann 2 == 1 usw.)
Deswegen erst 11 -> 12, dann 10 -> 11 usw.

Den Ausgang gibt es nur für dich (schätze ich) ...

Gruß
Larry

Danke Larry,

ja klaro stimmt - dann hätte ich überall das Gleiche drin stehen! ;)

Nochmals zu den einzelnen Elementen des UDT's:

Würde man in der Praxis das Element Status_A beispielsweise irgendwo im Programm beschreiben, so dass dieses Element dann in einem Takt den Status 0 und in einem anderen Takt z.B. den Status 1 haben kann?
 
@Tigerente:
Nimmst du für das Verschieben der einzelnen Elemente tatsächlich den Blockmove ? Ich habe bei mir 10-Byte-Blöcke (das Pendant zu deinem UDT) - da hat sich der SFC gegenüber dem regulären Code nicht "rentiert" ...

Hier mal der Code.
Den Blockmove finde ich da schon passend. Besonders in dem Beispiel, weil das dann schön allgemein funktioniert.

Code:
FUNCTION_BLOCK schieben

CONST
    erster_Platz := 1;
    letzter_Platz := 14;
END_CONST

VAR_INPUT
    Takt : BOOL;
END_VAR

VAR_IN_OUT
    register : ARRAY[erster_Platz..letzter_Platz] OF Register_typ;
END_VAR

VAR_OUTPUT
    Ausgang_13 : BOOL;
END_VAR

VAR_TEMP
    i : INT;
    Status_SFC20 : INT;
END_VAR

BEGIN

// Alle Elemente von "Register_typ" mit SFC20 "BLKMOV" von hinten nach vorne durchschieben.

IF Takt THEN
    // Erste Schleife : Register[13] -> Register[14]
    // Zweite Schleife: Register[12] -> Register[13]
    // ...
    // Letzte Schleife: Register[1]  -> Register[2]
    
    FOR i := letzter_Platz TO (erster_Platz + 1) BY -1 DO
        Status_SFC20:=BLKMOV(SRCBLK :=register[i-1],DSTBLK :=register[i]);
    END_FOR;
END_IF;

// Ausgang_zuweisen:
Ausgang_13 := register[13].Status_A AND NOT register[13].Fehler_A;

END_FUNCTION_BLOCK

UDT dazu:

Code:
TYPE "Register_typ"
VERSION : 0.1


  STRUCT 	
   Status_A : BOOL ;	
   Fehler_A : BOOL ;	
   Fehler_B : BOOL ;	
   Wert_XY : INT ;	
  END_STRUCT ;	
END_TYPE

Alles ist quasi nur ein Beispiel. Der UDT kann beliebig verändert werden.
Wie vorher schon erwähnt "lohnt" sich das nicht, wenn man nur 1 Bit über den ganzen Tisch schieben möchte.
 
@Spirit:

Das war jetzt mal ein ganz "allgemeines Beispiel". In dem UDT kannst Du die Elemente deklarieren, die mit dem Takt verschoben werden sollen. "Füllen" musst Du das natürlich entsprechend. Den Rest hat Larry schon erklärt.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Würde man in der Praxis das Element Status_A beispielsweise irgendwo im Programm beschreiben, so dass dieses Element dann in einem Takt den Status 0 und in einem anderen Takt z.B. den Status 1 haben kann?

Bleiben wir mal bei dem Rundtisch. Angenommen Status_A ist so etwas wie ein IO/NIO-Bit. Hat eine Station nicht gearbeitet oder eine Prüfstation einen Fehler erkannt, wird der Status an der entsprechenden Stelle zurückgesetzt. Z.B. an Position #6 ist eine Prüfstation, die ein "Schlechtteil" erkannt hat.

Dann wäre der Code etwa so:

Code:
IF #M_Messung_NIO THEN
Status_A[6] := FALSE;
END_IF;

Beim Takten wird das dann weitergereicht. (6-->7) Die nächste Station könnte eine Bearbeitungsstation sein. Die arbeitet nur dann, wenn Status_A "TRUE" ist:

Code:
Ausgang_7 := Status_A[7];

Wie gesagt, alles nur ein Beispiel. Der Rest muss von Dir kommen...
 
Den Blockmove finde ich da schon passend. Besonders in dem Beispiel, weil das dann schön allgemein funktioniert.

Ich habe deshalb gefragt, weill du unter SCL ja auch genausogut so programmieren könntest : (egal wie das Array-Element aufgebaut ist)
Code:
    FOR i := letzter_Platz TO (erster_Platz + 1) BY -1 DO
        register[i-1] :=register[i] ;
    END_FOR;
... das erspart den Compiler "ein wenig" das ANY-Pointer bauen, was ja auch nicht ganz Zykluszeit-unkritisch werden kann ...

Gruß
Larry
 
Zurück
Oben