SCL -1 subtrahieren

sr-83

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

ich bin nun schon ein zweites mal auf dieses Problem gestoßen und konnte es noch nicht lösen.
Ich möchte im DB einen Wert um minus 1 subtrahieren. Das Problem ist, dass entweder der Wert durch die Schleife die ganze Zeit runterzählt oder ich habe es so wie hier im Bsp. das ich einen bestimmten Wert (xb) um 1 erhöhe und beim nächsten Durchlauf soll er es nicht mehr machen. Dann zählt er garnicht mehr :-(... Hoffe ihr versteht das Problem so und könnt mir weiterhelfen.

Code:
FUNCTION FC54 : INT

VAR_INPUT
MagazinLeerenAusgewaehlt:      BOOL;
FreigabeDBWertNullSetzen:    BOOL;
AngefahrenSpalte:               INT;

END_VAR
VAR_OUTPUT

END_VAR

VAR_TEMP
  // temporäre Variablen
z:                           INT;
xb:                           INT;
za:                          INT;
Groesse:                     INT;
END_VAR
VAR_IN_OUT

END_VAR

  // Anweisungsteil


IF FreigabeDBWertNullSetzen = False THEN
    xb := 1;
END_IF;

IF MagazinLeerenAusgewaehlt = True AND FreigabeDBWertNullSetzen = True THEN 
    
    FOR z := 1 TO 3 BY 1 DO
        "lager".Zeile[z].Spalte[AngefahrenSpalte].Belegt := False;
        Groesse := "lager".Zeile[z].Spalte[AngefahrenSpalte].Groesse;
        FOR za := 1 TO 30 BY 1 DO
          IF "anpassung".anpassung[za].Wahre_Groesse = Groesse and xb =1 THEN
            "anpassung".anpassung[za].ISTBestand := "anpassung".anpassung[za].ISTBestand -1 ;
            xb := xb+1;
          END_IF;
        END_FOR;
    END_FOR;

END_IF;
 ;
  FC54 := 100;
END_FUNCTION
 
Setze mal die Bedingungen in Klammern:

IF (MagazinLeerenAusgewaehlt = True) AND (FreigabeDBWertNullSetzen = True) THEN

obwohl man hier auch schreiben könnte:
IF MagazinLeerenAusgewaehlt AND FreigabeDBWertNullSetzen THEN

Aber vor allem diese hier:
IF ("anpassung".anpassung[za].Wahre_Groesse = Groesse) AND (xb =1) THEN
 
Zuletzt bearbeitet:
Ja, wie? Ist da etwa eine FOR NEXT Schleife drumrum???:sm14:

Um das xb hatte ich mir nicht so Gedanken gemacht, frage mich aber nun, wozu dieses.

Ich gestehe, ich habe das Problem noch nicht gerafft, habe aber selbst meist ein Problem mit nicht Boolschen Abfragen in IF-Bedingungen, wenn ich keine Klammern setze, daher der Schnellschuß.

Sorry:rolleyes:
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Du schreibst hier:
Code:
IF FreigabeDBWertNullSetzen = False THEN
    xb := 1;
END_IF;

und dann:
Code:
IF MagazinLeerenAusgewaehlt = True AND FreigabeDBWertNullSetzen = True THEN 
    
    FOR z := 1 TO 3 BY 1 DO
        "lager".Zeile[z].Spalte[AngefahrenSpalte].Belegt := False;
        Groesse := "lager".Zeile[z].Spalte[AngefahrenSpalte].Groesse;
        FOR za := 1 TO 30 BY 1 DO
          IF "anpassung".anpassung[za].Wahre_Groesse = Groesse and xb =1 THEN
            "anpassung".anpassung[za].ISTBestand := "anpassung".anpassung[za].ISTBestand -1 ;
            xb := xb+1;
          END_IF;
        END_FOR;
    END_FOR;

D.h. Dein ganzes Konstrukt wird nur abgearbeitet, wenn "FreigabeDBWertNullSetzen" True ist. Wenn das aber True ist, setzt Du oben aber Dein "xb" nicht mehr auf 1.

Dann ist auch Dein
Code:
 IF "anpassung".anpassung[za].Wahre_Groesse = Groesse and xb =1 THEN
......
nie mehr erfüllt. Also zählt er nicht. ;)
 
Ich habe das nun mit einem kleinen Code ausprobiert, aber ich bekomme das einfach nicht hin.

Sobald Merker und HMerker True sind, zählt der Wert "testwert" immer weiter ins Minus. Kann man die Schleife nur einmal durchlaufen lassen und dann stoppen? Ich will sobald man Merker und HMerker True setzt, dass er den Wert "testwert" um 1 verringert und dann erst wieder ein ins Minus zählt, wenn Hmerker und Merker wieder eine positive Flanke bekommen usw...

Code:
FUNCTION FC54 : INT

VAR_INPUT
    
Merker:     BOOL;
HMerker:    BOOL;
    
    
END_VAR

VAR_TEMP
    // temporäre Variablen
    
x: INT;
s: INT;


END_VAR

    // Anweisungsteil
    IF Merker = True THEN
      FOR s := 1 TO 30 BY 1 DO
            IF s = 10 AND HMerker = true THEN
            "lager".testwert := "lager".testwert -1;
            END_IF;
        END_FOR;
    END_IF;
  
    ;
    FC54 := 100;
END_FUNCTION
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn Du eine Flankenauswertung haben möchtest, hast Du es mit einer Funktion sehr schwer.

Das Problem ist, das Du zum Auswerten einer Flanke ja irgendwo speichern musst, wie der Zustand Deines Bits einen Zyklus vorher war.

Ein Beispiel:

Bit : Bool;
Hilfsbit : Bool;
Meine_Positive_Flanke : Bool;

Eine pos. Flanke hast Du, wenn Dein Bit True ist und im letzten Zyklus False, also so etwa:

Meine_Positive_Flanke := Bit AND NOT Hilfsbit;

Bevor Du den Baustein verlässt, speicherst Du den Zustand Deines Bits in Deiner Hilfsvariable, also so:

Hilfsbit := Bit;

So könnte man also seine eigene Flanke bauen. (FP in AWL funktioniert im Prinzip auch so)

Dein Problem ist nun, dass Du in einem FC zwar diesen Code programmieren könntest, in einem FC aber keine Variablen gespeichert werden können. Die Variable "Hilfsbit" wäre im nächsten Zyklus jedesmal wieder FALSE. Und damit würdest Du immer eine positive Flanke erkennen wo keine ist. Abhilfe würde an dieser Stelle die Verwendung eines FBs schaffen. Diese haben ein "Gedächtnis" in Form eines Instanz-DBs. Die Variable "Hilfsbit" müsste dann statisch angelegt werden und der Code würde funktionieren.
 
Noch mal so am Rande:

Wenn Du eine Schleife vorzeitig verlassen möchtest, kannst Du auch "EXIT" verwenden. Das beendet die For-Schleife, die Dein "EXIT" Kommando umschließt. Hat den Vorteil, das die Schleife nicht mehr unnötig durchlaufen wird.
 
Der Baustein macht ja alles richtig, nur macht er das in jedem Zyklus der SPS von Neuem, daher zählt er immerfort runter. Also muß der Merker oder/und der Hilfsmerker nach dem Ausführen des Bausteins zurückgesetzt werden. Man kann auch gleich eine Flanke an den Input legen, dann wird der Inhalt ja nur einmalig abgearbeitet.
 
Zurück
Oben