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?
)
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.