TIA Nie mehr als zwei Ausgänge setzen können.

Zuviel Werbung?
-> Hier kostenlos registrieren
Code:
// ID Zuweissen 
#Schalter_ID[1] := 101;
#Schalter_ID[2] := 102;
#Schalter_ID[3] := 103;
#Schalter_ID[4] := 104;
#Schalter_ID[5] := 105;


// Schalter_Flanek abspeichern
#Schalter_zustand[1] := #schalter_1;
#Schalter_zustand[2] := #schalter_2;
#Schalter_zustand[3] := #schalter_3;
#Schalter_zustand[4] := #schalter_4;
#Schalter_zustand[5] := #schalter_5;


// Puffer eintrag abspeichern  
FOR #i:=1 TO 5 BY 1 DO
  #Schalter_Flanke[#i] := #Schalter_zustand[#i] AND NOT #Schalter_flanke_speicher[#i]  ;
  #Schalter_flanke_speicher[#i] := #Schalter_zustand[#i] ;
  IF #Schalter_Flanke[#i] THEN
// wird die Schalter_ID zu den ersten freien Ebene hingefügt.
    #Plaziert := FALSE ;
    FOR #j:=1 TO 5 BY 1 DO
      IF #Puffer[#j]=0 AND NOT #Plaziert THEN 
        #Puffer[#j] := #Schalter_ID[#i]  ;
        #Plaziert := TRUE ;
      END_IF ;
    END_FOR ;
  END_IF ;
END_FOR ;


// Puffer eintrag löschen
FOR #x:=1 TO 5 BY 1 DO  
  #Schalter_Flanke[#x] := NOT #Schalter_zustand[#x] AND #Schalter_flanke_speicher[#x]  ;
  #Schalter_flanke_speicher[#x] := #Schalter_zustand[#x] ;  
  IF #Schalter_zustand[#x]  THEN
// wird die Schalter_ID in der entsprechenden Zelle gelöscht und die eins höhere Zelle wird dann verschoben in die tiefste Zelle
    #Entfernt := false ;
    FOR #y:=1 TO 5 BY 1 DO
      IF #Puffer[#y] <> 0 AND NOT #Entfernt THEN 
        #Puffer[#y] := #Puffer[#y + 1]  ;
        #Entfernt := TRUE ;
      END_IF ;
    END_FOR ;
  END_IF ;
END_FOR ;

// reseten
IF "reset" THEN
FOR #k := 1 TO 5 BY 1 DO
  #Puffer[#k] := 0;
END_FOR;
END_IF;

Jetzt geht gar nichts mehr:D:D:D:D:D:D
hoffe du kannst mir weiter helfen

gruss
 
Ich weiss schon aber deinen Teil hatte ich auch schon. Die Schwierigkeit von dieser Aufgabe ist es wenn man einen schalter deaktiviert dann halt der Wert im Array verschwindet und die restlichen werte im Array um eins verschoben werden, weil ich das noch nie so gemacht habe weiss ich nicht wie ich diesen Teil bewältigen kann. Das füllen der Array nach der Reihe ist es kein Problem weil das schon gemacht habe. Ich habe einmal ein 4 gewinnt programmiert dort ist das selbe gewesen nach der reihenfolge zu füllen. Deswegen hatte ich keine Probleme.

Mein wesentliches Problem ist halt das entfernen und dem entsprechend zu verschiebe.

Es tut mir leid das ich dich zu sehr gestresst habe, weil ich ja noch unerfahren bin, bin ich zu euch gekommen.


Gruss
 
Es geht ja mir nicht um den Code-Verbesserung. Ich will ja nur einen Tipp oder besser einen kleine Spick. Ich arbeite nicht sehr will mit Array und ich finde es ist etwas tolles, deswegen wollte ich mein wissen vertiefen. Deswegen frage ich euch könnt ihr mir nicht einen kleinen Ansatz geben?
Ich hoffe ich verlange nicht zu viel:neutral::neutral:

Gruss
 
Ich hab' mich da jetzt selbst mal in SCL (von S7 V5.5, weil ich da Arrays mit Konstanten deklarieren kann :)) 'ran gesetzt.
Auf der "großen" SPS ist das Ganze wirklich etwas einfacher, vor allem wenn ich an die Erweiterung der LOGO!-Aufgabe von 4 auf 5 Ein-/Ausgänge denke.


wie würdest du es machen kannst du mir ein Beispielcode aufzeigen?
Ich denke, da sich bkizilkaya schon intensiv mit der sich selbst gestellten Aufgabe beschäftigt und auch einen eigenen Lösungsweg fast fertig hat, ist es auch in dieser Phase schon legitim, meine Variante als solche zu posten.
:)confused: Warum glaub' ich eigentlich, mich dafür rechtfertigen zu müssen? :confused:)

Ich habe mir 2 FBs erstellt.
Der erste FB "X_aus_N" enthält die eigentliche Aufgabe, wobei die Ein- und Ausgänge der Einfachheit halber jeweils als Array's deklariert sind:
Code:
[FONT=Courier New]FUNCTION_BLOCK "X_aus_N"

CONST
    N:=  5;                                                                 // Anzahl Ein-/Ausgänge
    XS:= 2;                                                                 // Standard-Anzahl max. eingeschalteter Ausgänge
END_CONST

VAR_INPUT
    IN:     ARRAY [1 .. N] OF BOOL;                                         // Neuer Zustand der Eingänge
    X:      INT;                                                            // Anzahl max. eingeschalteter Ausgänge
END_VAR

VAR_OUTPUT
    OUT:    ARRAY [1 .. N] OF BOOL;                                         // Ausgänge
END_VAR

VAR
    IN_OLD: ARRAY [1 .. N] OF BOOL;                                         // letzter Zustand der Eingänge
    ORDER:  ARRAY [1 .. N] OF INT;                                          // Speicher für Einschaltreihenfolge
END_VAR

VAR_TEMP
    i:      INT;                                                            // Hilfsvariable Schleife Ein-/Ausgänge
    j:      INT;                                                            // Hilfsvariable Schleife Reihenfolgespeicher
END_VAR



    // Eingänge auf Zustandsänderungen prüfen:
    FOR i:= 1 TO N BY 1 DO                                                  // Alle Eingänge der Reihe nach prüfen
        IF IN[i] AND NOT IN_OLD[i] THEN                                     //      Wenn positive Flanke des Eingangs
            FOR j:=  1 TO N BY 1 DO                                         //      dann Reihenfolgespeicher von unten an durchsuchen
                IF ORDER[j] = 0 THEN                                        //              Wenn Reihenfolgefeld noch leer
                    ORDER[j]:= i;                                           //              dann Nummer des Eingangs eintragen
                    EXIT;                                                   //                   und Schleife abbrechen
                END_IF;
            END_FOR;                                                        //           nächstes Speicherfeld
        ELSIF IN_OLD[i] AND NOT IN[i] THEN                                  //      sonst wenn negative Flanke des Eingangs
            FOR j:= 1 TO N BY 1 DO                                          //      dann Reihenfolgespeicher von unten an durchsuchen
                IF ORDER[j] = i THEN                                        //              Wenn Eintrag des Eingangs gefunden,
                    ORDER[j]:= 0;                                           //              dann Eintrag löschen
                    EXIT;                                                   //                   und Schleife verlassen (und Stelle merken)
                END_IF;
            END_FOR;                                                        //           nächstes Speicherfeld
            // Ggf. alles Folgende 1 Stelle nach unten schieben
            IF j < N THEN                                                   //           Wenn Eintrag nicht im letzten Speicherfeld
                FOR j:= j TO N - 1 BY 1 DO                                  //           dann vom Feld des Eintrags bis zum vorletzten Feld
                        ORDER[j]:= ORDER[j+1];                              //                   Inhalt vom Speicherfeld drüber kopieren
                END_FOR;                                                    //                nächstes Speicherfeld
                ORDER[N]:= 0;                                               //                letztes Speicherfeld Eintrag löschen
            END_IF;
        END_IF;
        IN_OLD[i]:= IN[i];                                                  //      Zustand des Eingangs für nächsten Zyklus speichern
    END_FOR;
    
    // alle Ausgänge rücksetzen
    FOR i:= 1 TO N BY 1 DO
        OUT[i]:= false;                                                     // alle Ausgänge rücksetzen
    END_FOR;
    
    // Anzahl X (max. eingeschalteter Ausgänge) ggf. korrigieren
    X:= SEL ( G:= X < 1 OR X > N, IN0:= X, IN1:= XS);                       // Wenn X innerhalb 1 und Maximum, dann verwenden
    
    // max. Anzahl Ausgänge setzen
    FOR i:= 1 TO X BY 1 DO
        OUT[ ORDER[i] ]:= true;                                             // max. gewünschte Anzahl Ausgänge setzen
    END_FOR;
    

END_FUNCTION_BLOCK[/FONT]

Der 2. FB "IN_OUT_to_Array" steckt mir die Ein- und Ausgänge jeweils in ein Array bzw. holt sie wieder raus. Dabei kann jeweils ein Startbyte angegeben werden, von dem mit Bit 0 begonnen wird. So konnte ich schön variabel mit den beiden rumspielen, ohne immer den Code an x Stellen anpassen zu müssen:
Code:
[FONT=Courier New]FUNCTION_BLOCK "IN_OUT_to_Array"

CONST
    N:= 5;                                                                  // Anzahl Ein-/Ausgänge
END_CONST

VAR_INPUT
    S_IN:  INT;                                                             // Startbyte der Eingänge
    S_OUT: INT;                                                             // Startbyte der Ausgänge
    X: INT;                                                                 // Anzahl max. eingeschalteter Ausgänge
END_VAR

VAR
    IN:  ARRAY [1..N] OF BOOL;                                              // Array der Eingänge für "X_aus_N"
    X_N: "X_aus_N";                                                         // FB "X_aus_N" als Multiinstanz
END_VAR

VAR_TEMP
    i: INT;                                                                 // Hilfsvariable
END_VAR


    // Eingänge ins Array
    FOR i:= 1 TO N  BY 1 DO
        IN[i] := E[ S_IN + ( i - 1 ) / 8 , ( i - 1 ) MOD 8 ];               // Eingang ( Byte, Bit ) ins Array eintragen
    END_FOR;
    
    // "X_aus_N" aufrufen
    X_N ( IN:= IN, X:= X );
    
    // Ausgänge aus Array übernehmen
    FOR i:= 1 TO N  BY 1 DO
        A[ S_OUT + ( i - 1 ) / 8 , ( i - 1 ) MOD 8 ]:= X_N.OUT[i];          // Ausgang ( Byte, Bit ) aus Array übernehmen
    END_FOR;
    
END_FUNCTION_BLOCK[/FONT]
Wie einfach es doch sein kann, aus 5 Eingängen 8, 16 oder x machen zu können.
Und dann noch die Anzahl der max. eingeschalteten Ausgänge sogar im lfd. Betrieb ändern.
:D
 
Zuletzt bearbeitet:
Hallo hucki

Ich habe jetzt dein Code an mich angepasst und getestet und habe festgestellt wenn du zum Beispiel schalter 1 2 3 aktiv hast in dieser Reihenfolge und ich zum beispiel schalter 2 deaktiviere dann hallt passiert halt ganz komisches. Dann ist keiner in der Reihenfolge!
Mein Code:

Code:
// Schalter_Flanek abspeichern
#Schalter_zustand[1] := #schalter_1;
#Schalter_zustand[2] := #schalter_2;
#Schalter_zustand[3] := #schalter_3;
#Schalter_zustand[4] := #schalter_4;
#Schalter_zustand[5] := #schalter_5;




// Eingänge aus Zustandsänderung prüfen
FOR #i := 1 TO 5 BY 1 DO
  IF #Schalter_zustand[#i] AND NOT #Schalter_Zustand_OLD[#i] THEN
    FOR #j:= 1 TO 5 BY 1 DO
      IF #ORDER[#j] = 0 THEN
        #ORDER[#j] := #i;
        EXIT;
      END_IF;
    END_FOR;      
  ELSIF #Schalter_Zustand_OLD[#i] AND NOT #Schalter_zustand[#i] THEN
    FOR #j := 1 TO 5 BY 1 DO
      IF #ORDER[#j] = #i THEN
        #ORDER[#j] := 0;
        EXIT;
      END_IF;
    END_FOR;
    IF #j < 5 THEN
      FOR #j := 1 TO 5 BY 1 DO
        #ORDER[#j] := #ORDER[#j + 1];
      END_FOR;
      #ORDER[5] := 0;
    END_IF;
  END_IF;
    #Schalter_Zustand_OLD[#i] := #Schalter_zustand[#i];
END_FOR;


// reseten
IF "reset" THEN
FOR #k := 1 TO 5 BY 1 DO
  #ORDER[#k] := 0;
END_FOR;
END_IF;
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Du hast einen Logik- und Progammfehler im Code:
Mein Code:
Code:
...
  ELSIF #Schalter_Zustand_OLD[#i] AND NOT #Schalter_zustand[#i] THEN
    FOR #j := 1 TO 5 BY 1 DO
      IF #ORDER[#j] = #i THEN
        #ORDER[#j] := 0;
        EXIT;
      END_IF;
    END_FOR;
    IF #j < 5 THEN

   [COLOR=#FFA500]// [/COLOR]FOR #j := 1 TO 5 BY 1 DO   [COLOR=#ffa500]  -->
// hier darf nicht an Stelle 1 des Arrays begonnen werden, sondern dort,
// wo die vorige Schleife nach dem Löschen des Inhalts abgebrochen wurde.
// Die Stelle steht in der Variable #j  -> Jetzt werden auch Stellen verschoben,
// vor denen gar nichts gelöscht wurde und die erste Stelle geht z.B. immer verloren,
// wenn eine spätere Stelle gelöscht wird!

// Außerdem darf die Schleife auch nur bis zur vorletzten Stelle des Array's gehen,
// weil sonst bei "#j + 1" eine Bereichsüberschreitung stattfindet!
[/COLOR][COLOR=#00ff00]
// Richtig: 
[/COLOR]      FOR #j := [COLOR=#00ff00]#j[/COLOR] TO [COLOR=#00ff00]4[/COLOR] BY 1 DO[COLOR=#ffa500]
[/COLOR] 
       #ORDER[#j] := #ORDER[#j + 1];
      END_FOR;
      #ORDER[5] := 0;
    END_IF;
  END_IF;
    #Schalter_Zustand_OLD[#i] := #Schalter_zustand[#i];
END_FOR;
...
Die Zuweisungen für die Ausgänge sind nur nicht gepostet?
:confused:


Für so wiederkehrende Zahlen, wie hier bei Dir die 5 (Ausgänge), sollte man immer wenigstens Konstanten deklarieren. Wenn Du später mal die Anzahl der Ausgänge verändern willst, musst Du so nur an einer Stelle ändern und nicht das ganze Programm durchsuchen.
In der äußeren FOR-Schleife für die Kontrolle der Eingange sind allein schon 6 Verwendungsstellen. Da wird bei späteren Änderungen schnell mal was übersehen.
;)
Bei TIA muss man dann allerdings bei solchen Änderungen noch zusätzlich die Array-Deklarationen anpassen. Das ist bei Classic definitiv besser!
:(
 
Hallo hucki.

Wie deklariert man Konstanten in Classic ? Und als Bereiche für Arrays verwendet ?
Das wurde mich interessieren.
Hatte gedacht das diese Funktionalität gibt es gar nicht.
 
Hallo hucki.

Wie deklariert man Konstanten in Classic ? Und als Bereiche für Arrays verwendet ?
Das wurde mich interessieren.
Hatte gedacht das diese Funktionalität gibt es gar nicht.
Äh... , so wie oben in meinem Code?
...
Code:
[FONT=Courier New]FUNCTION_BLOCK "X_aus_N"

[COLOR=#00ff00]CONST
    N:=  5;                                                                 // Anzahl Ein-/Ausgänge[/COLOR][COLOR=#00ff00]
    [/COLOR]XS:= 2;                                                                 // Standard-Anzahl max. eingeschalteter Ausgänge[COLOR=#00ff00]
[/COLOR][COLOR=#00ff00]END_CONST[/COLOR][COLOR=#00ff00]
[/COLOR]
VAR_INPUT
    IN:     ARRAY [1 .. [COLOR=#00ff00][B]N[/B][/COLOR]] OF BOOL;                                         // Neuer Zustand der Eingänge
    X:      INT;                                                            // Anzahl max. eingeschalteter Ausgänge
END_VAR

VAR_OUTPUT
    OUT:    ARRAY [1 .. [COLOR=#00ff00][B]N[/B][/COLOR]] OF BOOL;                                         // Ausgänge
END_VAR

[/FONT][FONT=Courier New]...[/FONT]
...
;)

:ROFLMAO:
 
Zuviel Werbung?
-> Hier kostenlos registrieren
PS: Es gehen damit auch solch nette Sachen (aus der "4 gewinnt"-Sache):
Code:
[FONT=courier new]CONST
[COLOR=#00FF00]    Spalten:= 7;                                                                    // Anzahl Spalten
    Zeilen := 6;                                                                    // Anzahl Zeilen[/COLOR]
END_CONST

VAR
    SPIELFELD:   ARRAY [1 .. [COLOR=#00FF00]Spalten[/COLOR], 1 .. [COLOR=#00FF00]Zeilen[/COLOR]] OF INT;                          // Spielfeld               (7 Spalten,  6 Zeilen)
    SPIELZUEGE:  ARRAY [1 .. [COLOR=#00FF00]Spalten * Zeilen[/COLOR], 0 .. 3] OF INT;                      // Speicher Spielzüge (max. 7 Spalten x 6 Zeilen = 42 Spielzüge,
[/FONT]...
 
Danke hucki.

Das ist ein Super tip.
CONST und END_CONST sind gar nicht zu finden in den Online Hilfe zu SCL !
edit: Doch es gibt, aber ist nur etwas versteckt.

Und mein Hans Berger Buch über SCL hat auch keine Informationen darüber.
Aber nach eine kleine test scheint es tatsäglich zu funktionieren.

Weil du so kundig bist, weist du ob man auch globale Konstanten deklarieren kann ?
 
Zuletzt bearbeitet:
1. Hast Du das PS noch gesehen?
Nicht das es durch Deinen Post untergegangen ist.

2. ich bin da gar nicht so kundig, wie Du vlt. gerade glaubst. Aber ich glaube, es ist möglich. In TIA nur noch global. Allerdings kann man in TIA die Arrays leider nicht mit Konstanten deklarieren.

3. SCL-Anleitung für S7 V5.5 von Siemens. Da hatte ich das drin gelesen.
 
Zurück
Oben