# e cockpit Funktionsbausten / PFC100



## Ralf-Jürgen (6 Mai 2021)

Hallo SPS Fangemeinde,
ich tapse mich gerade durch die ersten Hürden..
Ich habe einen FB gebastelt:

```
FUNCTION_BLOCK ABLAUF
VAR_IN_OUT
    istep:INT;
END_VAR
VAR_INPUT
    xstart:BOOL;
    istepmax:int;
END_VAR
VAR_OUTPUT
    xready:BOOL;
    
END_VAR
VAR
    ttime:TIME;
    TON_0:TON;
    RS_0:RS;
    xm_0:BOOL;
END_VAR


IF xstart THEN
    xready:=FALSE;
    ttime:=GVL.asteps[istep].ttime;
    xm_0:=xstart;
    TON_0(IN := xm_0, PT:= ttime);
    RS_0(SET:=TRUE);
    GVL.aausgaenge[istep]:=RS_0.Q1;
    IF TON_0.Q THEN
        RS_0(set:=FALSE, RESET1:=TRUE);
        istep:=istep+1;
        xm_0:=FALSE;
    END_IF


    
END_IF
IF istep>=istepmax THEN
        xready:=TRUE;
END_IF
```

der soll bis istepmax laufen, der erste Durchlauf geht, aber danach ist Schluß
Obwohl xstart true ist, wird bereits die ttime Zuweisung nicht mehr ausgeführt
(getestet in der Simulation)
gibts eine Idee?
Danke 
Jürgen


----------



## Thruser (6 Mai 2021)

Hallo,

der TON_0 muß mindestens ein mal mit xm_0 := false aufegrufen werden, damit er weider neu getriggert wird (Flankenwechsel false->true auf IN). Das passiert hier aber nicht. xm_= wird zwar in der IF Bedingung auf false gesetzt, ist aber bereits beim nächsten Aufruf von TON_0 wieder true.

Gruß

PS: In ST benötigt man den RS Baustein nicht. Die Zuweisung := True und dann := False an einer anderen Stelle bewirkt das gleiche. So wie Du es mit xm_0 machst.


----------



## Ralf-Jürgen (6 Mai 2021)

Hallo Thruser,

vielen Dank für den schnellen Hinweis, ich glaube ich hatte diese Varianten schon alle durch.
Hauptproblem war aber die falsche Aussenbeschaltung der IN-OUT Variable. Diese wurde bei jedem Durchlauf neu mit 0 initialisiert und damit geht nix...da im FB ja nur referenziert wird
Ja ja, wie immer sitzt das Hauptproblem zwischen Bildschirm und Stuhllehne...
Der RS stammt noch aus einer funktionierenden FUP- Variante
Ich habe mal bischen aufgeräumt:

```
FUNCTION_BLOCK ABLAUFVAR_IN_OUT
    istep_in_out:INT;
END_VAR


VAR_INPUT
    xstart:BOOL;
    istepmax:int;
    
END_VAR
VAR_OUTPUT
    xready:BOOL;
        
END_VAR


VAR
    istep:INT;
    ttime:TIME;
    TON_0:TON;
    xm_0:BOOL;
END_VAR




IF xstart THEN
    xready:=FALSE;
    ttime:=GVL.asteps[istep_in_out].ttime;
    xm_0:=xstart;
    TON_0(IN := xm_0, PT:= ttime);
    GVL.aausgaenge[istep_in_out]:=TRUE;
    IF TON_0.Q THEN
        istep_in_out:=istep_in_out+1;
        xm_0:=FALSE;
        TON_0(IN:= xm_0);
        GVL.aausgaenge[istep_in_out]:=FALSE;
    END_IF
END_IF
IF istep_in_out>=istepmax THEN
        xready:=TRUE;
END_IF
```

ich würde gern noch die kruden GVL-Zugriffe aus dem FB verbannen, hab aber im Moment keinen Nerv dafür...


----------



## KLM (6 Mai 2021)

Moin, Du kannst TON und TOF auch mit sich selbst triggern, z.B. fbTON(IN:=NOT fbTON.Q, ..), dann hast Du immer einen Aufruf dazwischen, der den Timer neu startet.


----------



## Ralf-Jürgen (7 Mai 2021)

Hier nun der Vollständigkeit halber der komplette FB
da ich in letzter Zeit - als SPS- Gelegenheitsarbeiter- einige Male einfache Zeitabläufe machen musste hatte ich keine Lust mehr, haufenweise TONs und RS in FUP aneinanderzufummeln.



Der Klotz holt sich den aktuelle step und die dazugehörige Zeit aus einem array oder sonstwoher, hat eine maximale step- Anzahl und kann einen bool - Ausgang für die Step-Zeit auf True bringen.
Durch Manipulation des istep_aktuell kann der Start-step und mit stepmax der letzte step festgelegt werden. Alles andere ist selbsterklärend.

Man achte darauf, den istep_in_out nicht fest zu initialisieren, sondern das über SEL oder MOVE oder sowas zu machen, sonst ist die stepzählung im Fb ko

Hier noch der code; sachliche Hinweise von den Profis nehme ich gern entgegen...

```
FUNCTION_BLOCK ABLAUF
VAR_IN_OUT
    istep_in_out:INT;
END_VAR
VAR_INPUT
    xstart:BOOL;
    istepmax:INT;
    ttime:TIME;
    xbreak:BOOL;
END_VAR
VAR_OUTPUT
    xout:BOOL;
    xready:BOOL;
    trestzeit:TIME;
END_VAR
VAR
    TON_0:TON;
    xm_0:BOOL;
    xm_1:BOOL;
    TP_0:TP;
END_VAR


IF istep_in_out <= istepmax THEN
    xm_0:= NOT xm_0; //hier wird ein Zyklus übersprungen, damit das array(GVL, bool) über xout aktualisiert werden kann
    IF xstart AND xm_0 THEN
        xready:=FALSE;
        xout:=TRUE;
        TON_0(IN := xstart, PT:= ttime);
        trestzeit:=ttime-TON_0.ET;
    END_IF
    IF xbreak THEN
        TON_0(IN:=FALSE);
        xm_1:=TRUE;
    END_IF
    IF NOT xbreak AND xm_1 THEN
        TON_0(IN:=TRUE, PT:= trestzeit);
        xm_1:=FALSE;
    END_IF
    IF TON_0.Q THEN
        xout:=FALSE; // xout auf False
        IF NOT xm_0 THEN
            TON_0(IN:=xm_0); // ein Zyklus weiter step erhöhen und timer init
            istep_in_out:=istep_in_out+1;
        END_IF
    END_IF
ELSE
    istep_in_out:=istep_in_out-1;
    xout:=FALSE;
    xready:=TRUE;
END_IF
```

Vielen Dank an alle Mitdenker !
Beste Grüße und schönes Wochenende
Jürgen


----------

