# SCL Steuerung FOR Schleife



## SpeeChamp (23 Januar 2018)

Hallo Zusammen,

ich bin Neuling in der SPS Welt und moechte in SCL eine Steuerung entwickeln, die Abhängig von Bits in einem Array Bits in einem anderen Array schreibt.

Erste Funktion: Die Steuerung soll Bits, die in dem Array1= 1 sind erkennen und ggf. Nullen ueberspringen. Ich komme in die Funktion mit einem Impuls, der alle 5 Sekunden erzeugt wird.
Es soll bei jedem Impuls an der Stelle, wo im Array1 eine 1 eingetragen ist in das Array2 an der selben Stelle eine 1 eingetragen werden. 

Meine Loesung dazu ist:

IF Impuls=1 THEN

    FOR i:= 1 TO 8 BY +1 DO

        IF Array1_ = true THEN

            IF Zwischenspeicher_Array =0  THEN

                Array2 := true;
                Zwischenspeicher_Array := true;

                EXIT;

            END_IF;
        END_IF;
    END_FOR;
END_IF;

Dies funktioniert soweit ich das einschaetzen kann auch. Es wird bei jedem Impuls das Bit in Array2=1 gesetzt, welches vorher in Array1 angewaehlt wurde. (Und das in Abhaengigkeit vom Impuls)

Eine zweite Funktion, die Aehnlich aufgebaut ist, setzt die Bits des Array2 wieder auf Null! (Wieder bei einem (anderen) Impuls)

Nun habe ich aber noch folgendes Problem:

Ich moechte auf jeden Fall, dass jedes Bit des Array2 gesetzt wird. Ist z. B. Array1[2]=1 und Array1[4]=1 und Array1[5]=1 und Array1[7]=1 und ich bekomme drei Mal einen Impuls zu "Bits auf eins setzen" funktioniert auch alles (Array2[2]=1 und Array2[4]=1 und Array2[5]=1). 
Folgt jetzt ein Impuls zum "Bits auf Null setzen" wird Array2[2]=0 gesetzt, was auch noch korrekt ist.
Folgt jetzt wieder ein Impuls zum "Bits auf eins setzen" wird Array2[2]=1 gesetzt, da die FOR Schleife vorne wieder anfängt...

Ich moechte aber, dass in dem Fall das Bit Array2[7]=1 gesetzt wird, da dies in diesem Fall ja noch nicht eins war. 
Es soll sozusagen so laufen, dass die Bits, die als erstes eingeschaltet wurden auch als erstes ausgeschaltet werden. (Funktioniert ja automatisch ueber die Schleifen Variable i)
Und anders herum, die Bits die in Array1 angewählt sind und die "kuerzeste Laufzeit" haben sollen als nächstes eingeschaltet werden.

Es muss sich also in irgendeiner Weise die FOR Schleife die Stelle merken, wo in dem Array1 die nächste eins ist und zusätzlich alle Nullen überspringen, damit bei jedem Impuls auch wirklich nur die Einsen geschaltet werden. (Ist sozusagen FIFO Prinzip)

Ich hoffe ich habe mich einigermassen verständlich ausgedrueckt und bedanke mich im Voraus._


----------



## Ralle (23 Januar 2018)

Da du Neuling im SPS-Programmieren bist, wäre es gut, wenn du mal erläuterst, wozu genau diese Vorgehensweise dienen soll, denn mir kommen ein wenig Zweifel, ob die gewählte Strategie überhaupt sinnvoll ist und man nicht besser einen anderen Ansatz wählen sollte. Dann versuchen hier mehrere Leute krampfhaft eine Lösung zu finden, die evtl. am Ende zwar funktioniert, aber unübersichtlich und nicht optimal ist.

Du mußt dir wohl merken, bis zu welchem Bit du bereits auf True geschalten hast. Also eine extra Variable, die sich den letzten Index merkt, den du geschalten hast.
in deinem Beispiel die 5.
Die For-Schleife lauten dann:



> IF Impuls=1 THEN
> 
> FOR i:= Index TO 8 BY +1 DO
> 
> ...


_

Die Variable "Index" mußt du natürlich irgendwann auch mit 1 initialisieren bzw. nach getaner Arbeii neu besetzen.

Nachtrag: Index muß wohl eher auf Index := i+1 in der Schleife, sonst sentzt man das letzte Bit evtl. noch einmal. Da muß dann aber noch eine Behandlung, falls i>8 wird!_


----------



## SpeeChamp (23 Januar 2018)

Hallo Ralle,

danke für deinen Hinweis und deine Hilfe.

Mit der Steuerung sollen Pumpen geschaltet werden. Funktion 1: Anwahl des Arrays über Panel sichert, dass Pumpenplätze, die nicht besetzt sind, nicht eingeschaltet werden. Falls diese in Wartung sind.
Funktion 2: FIFO bringt die Betriebsstunden auf einen einigermaßen konstanten Niveau, da bei jedem Impuls eine andere (angewählte) Pumpe ein- oder ausgeschaltet wird.


----------



## PN/DP (23 Januar 2018)

Wieviele Pumpensätze sollen gleichzeitig laufen können? Wieviele Pumpensätze gibt es insgesamt?
Wenn Du mit "_sozusagen FIFO Prinzip_" tatsächlich FIFO meinst, dann könntest Du auch einen FIFO benutzen. Deine Bit-Kopier-Lösung ist kein FIFO.
Deine Bit-Kopier-Lösung oder ein FIFO wird Deine Aufgabenstellung vermutlich nicht erfüllen können - wo ist der ausgleichende Zusammenhang zu Betriebsstunden?

Besser:
- erfasse die Betriebsstunden für jeden Pumpensatz (und kopiere die ggf. in ein Array)
- verwende für jeden Pumpensatz ein BOOL (am besten Array) für "Pumpensatz verfügbar"
- suche den Pumpensatz (oder sortiere die Pumpensätze) nach "verfügbar" und "niedrigste Betriebsstunden"
- schalte beim nächsten Einschaltbefehl den Pumpensatz ein, der von den "verfügbaren" Pumpensätzen die niedrigsten Betriebsstunden hat

Anmerkung: Wenn Du dafür sorgst, daß alle Pumpensätze gleich viele Betriebsstunden bekommen, dann sorgst Du gleichzeitig dafür, daß alle Pumpensätze gleichzeitig in Wartung gehen (müssen). Ist das sinnvoll?

Harald


----------



## SpeeChamp (23 Januar 2018)

Es sind acht Pumpen anzuwählen und wenn alle Pumpenplätze belegt sind sollen auch alle Pumpen benutzt werden. Wie viele gleichzeitig laufen soll nach Bedarf durch die Steuerung ausgewählt werden. 
Deinen Einwand wegen dem Betriebsstundenzähler verstehe ich aber dies ist ausdrücklich so abgesprochen. Da die Anlage eine Gewisse Anzahl an Schaltvorgängen macht wechseln sich die Pumpen ab. 

Gruß


----------



## Larry Laffer (23 Januar 2018)

... das widerspricht sich jetzt aber in keiner Weise mit dem Vorschlag von PN/DP ... (eher im Gegenteil ...)

Gruß
Larry


----------



## _Eddi_ (24 Januar 2018)

Für eine "echte" FIFO würde ich einen anderen Ansatz verfolgen, und zwar hast du neben deinem ARRAY für die verfügbaren und dem ARRAY für die aktiven pumpen noch ein ARRAY das die Reihenfolge speichert:
also:

```
VAR
  verfuegbar : ARRAY[1..MAX_PUMPEN] OF Bool: (*von der Visu gesetzt*)
  aktiv : ARRAY[1..MAX_PUMPEN] OF Bool: (*Ausgänge*)
  fifo : ARRAY[1..MAX_PUMPEN] OF 1..MAX_PUMPEN;
  fifo_laenge: 0..MAX_PUMPEN;
```

dann machst du eine Initiale Befüllung der FIFO:

```
fifo_laenge := 0;
for i := 1 to MAX_PUMPEN DO
  IF verfuegbar[i] THEN
    fifo_laenge := fifo_laenge+1;
    fifo[fifo_laenge]:=i;
  END_IF
END_FOR
IF fifo_laenge = 0 THEN (* FEHLER: keine Pumpen verfügbar *)
...
END_IF
```

dann setzt du bei jedem Start einer Pumpe aktiv[fifo[1]], verschiebst fifo[1] in fifo[fifo_laenge] und alle anderen verschiebst du um -1 nach vorne
(code überlasse ich als "leichte Übung")

beim Ausschalten gehst du durch die FIFO, ohne sie zu ändern, und schaltest die erste Pumpe aus, die aktiv ist.

```
FOR I := 1 to fifo_laenge DO
  IF aktiv[fifo[I]] THEN
    aktiv[fifo[I]] := FALSE;
    BREAK;
  END_IF
END_FOR
```

bei Änderung von verfuegbar kannst du entweder die FIFO leeren, oder die jeweils hinzugekommenen/weggefallenen ergänzen.


Es gibt natürlich noch unendlich viele andere Varianten, eine FIFO umzusetzen


----------

