TIA Unwichtig/Diskussion: Schrittkette verbessern

Zuviel Werbung?
-> Hier kostenlos registrieren
Ich versuche das Bestehende zu verbessern, hauptsächlich um etwas zu lernen und weil das Programm dank des Umbauversuchs mit zwei verschiedenartigen Schrittketten läuft. Vor dem Hochrüsten auf V17 möchte ich etwas aufräumen. Und wenn man mal eine schöne Schrittkette hat kann man die ja wiederverwenden.
Dann solltest du das eingangs gepostete Beispiel entsprechend der hier schon gemachten Anregungen komplett überdenken. Für mich hatte sich auf den ersten und zweiten Blick der Sinn der da gemachten Konstruktion schon nicht erschlossen - und das ging ja anscheinend nicht nur mir so.
Wer programmiert denn in deiner Firma alles ? Wichtig wäre/ist hier einen gemeinsamen Konsens zu finden - sonst ändert sich am Ende nämlich gar nichts ...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Leider gehen bei der 1200er keine AWL-Schrittketten mit Sprungverteilern, was eine recht effektive Methode ist.

In Hochsprachen am PC macht man StateMachines (Schrittketten) üblicher weise mit CASE Anweisungen.
Das geht auch bei der 1200er Serie! Hab leider kein fertiges Beispiel, da ich sowas normal nicht mache!


CASE SNR OF
1:
IF condition THEN
// Aktions Anweisung
// oder Aufruf von Schritt-FC
SNR : = SNR +1
END_IF;

2 :
// Anweisungen_8
;
ELSE:
// Anweisungen_ELSE
;
END_CASE;
 
Ehrlich gesagt sind doch Sprungverteiler in AWL oder Case in SCL recht unflexibel.
Schönes Beispiel sind Parallelverzweigungen. Dafür brauchst du quasi ne eigene Unterkette.
Alternativverzweigungen funktionieren, machen die Sache aber unübersichtlich.
Da ist ne simple annehmende Merkerschrittkette deutlich übersichtlicher 😀
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich steh gerade ein bisschen auf dem Schlauch. Was verstehst du darunter? Ich meine das annehmende.

Die annehmende Merkerschrittkette stammt im Prinzip aus der Schütztechnik.
Im Gegensatz zur „normalen“ Merkerschrittkette bleiben bei der annehmenden Schrittkette alle Schritte gesetzt.
Lässt sich sehr einfach in Kop programmieren, da ein Schritt einfach eine Spule mit Selbsthaltung ist.
Kennt heute kaum einer noch, ist aber gar nicht schlecht.
Ich hab sie früher bei Logo-Steuerungen verwendet. Da war die Anzahl der der SR-Bausteine stark begrenzt.
 
Hallo Saufautomat,
Hallo Zusammen,

vielleicht könnte das was sein... ein Schrittkettenbaustein für 0...255 Schritte

- Schrittbits können im Programm dann über "idbxyz".sSk.sxAktivS.S[1] bzw. "idbxyz".sSk.sxPermS.S[1] aufegrufen werden.
- PermS-Bits werden immer ausgegeben, AktivS-Bits nur dann wenn die Sk in Automatik ist -> ixBA_Auto=true
- mit ixInitS= wird die Schrittkette zurück auf S0 gesetzt
- es gibt eine Laufzeitüberwachung für die Schritte -> ioxAlarm, wird dann gesetzt
- es gibt eine Mindestlaufzeit in der Schritt verharrt , auch wenn die Weiterschaltbedingung erfüllt ist
- es kann im Schritt nach 0..7 Zielen gesprungen werden, wo bei die Prio von 0...7 steigt, sind zwei Weiterschaltbedingungen erfüllt wird zum höherem Sprungziel gesprungen

der Aufruf als Beispiel...

Code:
// Baustein Sk-Verwaltung
#sSk(ixInitS0       := #sxInitSk,
     ixBA_Auto      := "db KopplungHMI".BA_VTW1.Status.BA_Automatik,
     ixBA_Einzel    := false,
     ixCMD_Einzel   := false,
     ixImp100ms     := "Imp10Hz",
     ixResetAlarm   := "xAllgImpStörReset");
;
#sxInitSk           := FALSE; // Hilfsbit Schrittkette zurücksetzten
;
// Vorbelegen der Werte, sonst in den Schritten erneut zuweisen, wenn gewünscht
#sSk.siA_SollZeit   := 999; // Überwachungszeit in 1/10sec
#sSk.sxHaltAZeit    := true; // Überwachung angehalten
#sSk.siS_SollZeit   := 0; // Sollschrittschrittzeit in 1/10sec, Zeit in dem der Schritt bleibt, trotz erfüllter Weiterschaltbedingung
#sSk.sxHaltSZeit    := FALSE; // Schrittzeit anhalten
;
;
REGION // Schrittkette
    // # SO ###################################################################
    REGION Init_SK
        // S0 Init
        //Abfrage VTW belegt?
            // Ja -> Fahrauftrag vorhanden? -> BringZiel anfahren S51
            // Ja -> kein FahrAuftrag vorhanden?
            // Meldung am HMI, Fahrauftrag von Hand am HMI manipulieren(vorgeben) und Quittieren -> BringZiel anfahren S51
            // oder VTW leer räumen, oder von Hand verfahren
            //
            // nein-> S21, wenn kein Fahrauftrag aktiv
            // nein-> S25, wenn Fahrauftrag aktiv
            //
        // S0 Init   
        IF 0 = #sSk.siS_No THEN
            IF NOT("VTW1 FahrJobs".sActJob.error) THEN
                #sSk.sxSprungZielK[0] := "dbRollenbahn".RB_VTW1.xPlatzFrei AND NOT ("VTW1 FahrJobs".sActJob.aktiv);
                #sSk.sxSprungZielK[1] := "dbRollenbahn".RB_VTW1.xPlatzFrei AND "VTW1 FahrJobs".sActJob.geladen AND "VTW1 FahrJobs".sActJob.aktiv;
                #sSk.sxSprungZielK[2] := "dbRollenbahn".RB_VTW1.xPlatzInPos AND "VTW1 FahrJobs".sActJob.geladen AND "VTW1 FahrJobs".sActJob.aktiv;
                #sSk.sxSprungZielK[3] := "dbRollenbahn".RB_VTW1.xTrJobRecvAct AND "VTW1 FahrJobs".sActJob.aktiv;
                #sSk.sxSprungZielK[4] := "dbRollenbahn".RB_VTW1.xTrJobSendAct AND "VTW1 FahrJobs".sActJob.aktiv;
                ;               
            END_IF;
            ;
            #sSk.siZielK[0] := 21;
            #sSk.siZielK[1] := 25;
            #sSk.siZielK[2] := 51;
            #sSk.siZielK[3] := 47;
            #sSk.siZielK[4] := 67; // Sind mehere Weiterschaltbedinungen erfüllt, wird das höchste Ziel angesprungen, hier Ziel[4]
;         
        END_IF;


    END_REGION
END_REGION

######################################################

und der Baustein dazu...

Code:
TYPE "udt_Schritte"
VERSION : 0.1
   STRUCT
      S : Array[0..255] of Bool;
   END_STRUCT;

END_TYPE

FUNCTION_BLOCK "fbAllg_SchrittVerwaltung_2"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT
      ixInitS0 : Bool;
      ixBA_Auto : Bool;
      ixBA_Einzel : Bool;
      ixCMD_Einzel : Bool;
      ixImp100ms : Bool;
      ixResetAlarm : Bool;
   END_VAR

   VAR_IN_OUT
      ioxAlarm : Bool;
   END_VAR

   VAR RETAIN
      sxImpS0 : Bool;
      sxhmImpS0 : Bool;
      sxImpNextS : Bool;
      sxhmImpNextS : Bool;
      siS_No : Int;   // aktueller Schritt
      siS_Before1Cycle : Int;
      siS_Before : Int;
      siS_Next : Int;
      siS_IstZeit : Int;   // Ist Schrittzeit [0,1sec]
      siS_SollZeit : Int := 0;   // Soll Schrittzeit [0,1sec]
      siA_IstZeit : Int;   // Ist AlarmSchrittzeit [0,1sec]
      siA_SollZeit : Int := 0;   // Soll AlarmSchrittzeit [0,1sec]
      siZielK : Array[0..7] of Int;
      sxSprungZielK : Array[0..7] of Bool;
      sxImpSWechsel : Bool;
      sxhmImpSWechsel : Bool;
      sxHaltSZeit : Bool;
      sxHaltAZeit : Bool;
      sxAktivS : "udt_Schritte";
      sxPermS : "udt_Schritte";
   END_VAR
   VAR
      sxLoeschS : "udt_Schritte";
   END_VAR
   VAR RETAIN
      siHist : Array[0..15] of Int;
      siIdx : Int;
   END_VAR

   VAR_TEMP
      txNextS : Bool;
      txStepTimeOn : Bool;
      txAlarmTimeOn : Bool;
   END_VAR


BEGIN
    (*
    #############################
    2019-05-24 S.Lüth
    Baustein entstand aus dem Sk-Verwaltunsbaustein mit der Sprungliste
    Der original Baustein war in AWL geschrieben
    dieser wurde um die Funktion der History erweitert, ebenso die max Schrittzahl von 159 auf 255
    damit lassen sich in einer Schrittkette gegebenfalls besser Gruppen bilden
  
    ********************
    Der Aufruf der SPL
    L  xxx.siS_No
          SPL   ESPL
          SPA   S0
          SPA   S1
          SPA   S2
          SPA   S3
          SPA   NC
          SPA   S5
          SPA   S6
          SPA   NC
          SPA   NC
          SPA   NC
  
    ESPL: NOP 0
    NC:   SPA   AUSG
  
    S0:   NOP 0
          U     "AlwaysTRUE"
          S     "fbAllg_SchrittVerwaltung_2_DB".sxSprungZielK[0]
          L     1
          T     "fbAllg_SchrittVerwaltung_2_DB".siZielK[0]
          SPA   AUSG
        
    ********************
    lässt sich in SCl in
    IF xxx.siS_No Then
        xxx.sxSprungZielK[0]:=True;
        xxx.siZielK[0]      :=1;
    end_if;
  
    darstellen
    ********************
  
  
  
    #############################
  
    #############################
  
    *)
  
  
  
  
  
    #sxImpS0:= #ixInitS0 AND NOT #sxhmImpS0;
    #sxImpNextS := #ixCMD_Einzel AND #sxhmImpNextS;
  
    IF #sxImpS0 THEN
        #siS_No := 0;
        #siS_IstZeit := 0;
        #siA_IstZeit := 0;
    END_IF;
  
    IF ((#ixBA_Auto AND NOT (#ixBA_Einzel)) OR (NOT (#ixBA_Auto) AND #ixBA_Einzel AND #ixCMD_Einzel))
        AND ((#sxSprungZielK[0] OR #sxSprungZielK[1] OR #sxSprungZielK[2] OR #sxSprungZielK[3] OR #sxSprungZielK[4]
            OR #sxSprungZielK[5] OR #sxSprungZielK[6] OR #sxSprungZielK[7]))
        AND (#siS_IstZeit >= #siS_SollZeit) THEN
        #txNextS := TRUE;
    ELSE
        #txNextS := FALSE;
    END_IF;
  
    #txStepTimeOn   := NOT(#sxHaltSZeit);
    #txAlarmTimeOn  := NOT(#sxHaltAZeit);
    REGION Ziele verwalten
        IF #sxSprungZielK[0] THEN
            #siS_Next := #siZielK[0];
        END_IF;
        IF #sxSprungZielK[1] THEN
            #siS_Next := #siZielK[1];
        END_IF;
        IF #sxSprungZielK[2] THEN
            #siS_Next := #siZielK[2];
        END_IF;
        IF #sxSprungZielK[3] THEN
            #siS_Next := #siZielK[3];
        END_IF;
        IF #sxSprungZielK[4] THEN
            #siS_Next := #siZielK[4];
        END_IF;
        IF #sxSprungZielK[5] THEN
            #siS_Next := #siZielK[5];
        END_IF;
        IF #sxSprungZielK[6] THEN
            #siS_Next := #siZielK[6];
        END_IF;
        IF #sxSprungZielK[7] THEN
            #siS_Next := #siZielK[7];
        END_IF;
      
    END_REGION
  
    // nächster Schritt
    IF #txNextS THEN
        #siS_Before     := #siS_No;
        #siS_No         := #siS_Next;
        #siS_IstZeit    := 0;
        #siA_IstZeit    := 0;
    END_IF;
  
    //Schrittwechel makieren
    #sxImpSWechsel := #siS_No <> #siS_Before1Cycle;
    #siS_Before1Cycle := #siS_No;
    IF #sxImpSWechsel THEN
        #siS_IstZeit := 0;
        #siA_IstZeit := 0;
    END_IF;
  
    // Schrittfolge History aufzeichenen
    IF #sxImpSWechsel THEN
        #siHist[#siIdx MOD 16] := #siS_No;
        #siIdx := #siIdx + 1;
        #siIdx := #siIdx MOD 16;
        #siHist[#siIdx] := -1;
    END_IF;
    REGION Überwachung und Schrittlaufzeiten
        IF #ixImp100ms THEN
            IF (#siS_IstZeit < #siS_SollZeit) AND (#ixBA_Auto OR #ixBA_Einzel) AND #txStepTimeOn THEN
                #siS_IstZeit := #siS_IstZeit + 1;
            END_IF;
          
            IF NOT #ioxAlarm AND #ixBA_Auto AND NOT(#ixBA_Einzel) AND #txAlarmTimeOn THEN
                #siA_IstZeit := #siA_IstZeit + 1;
            END_IF;
        END_IF;
        //Setze Laufzeitalarm zurück
        IF #ioxAlarm AND #ixResetAlarm THEN
            #ioxAlarm := false;
            #siA_IstZeit := 0;
        END_IF;
      
        //Setze Laufzeitalarm
        IF (#siA_IstZeit >= #siA_SollZeit) AND #ixBA_Auto THEN
            #ioxAlarm := true;
        END_IF;
      
    END_REGION
  
    #sxSprungZielK[0] := FALSE;
    #sxSprungZielK[1] := FALSE;
    #sxSprungZielK[2] := FALSE;
    #sxSprungZielK[3] := FALSE;
    #sxSprungZielK[4] := FALSE;
    #sxSprungZielK[5] := FALSE;
    #sxSprungZielK[6] := FALSE;
    #sxSprungZielK[7] := FALSE;
    #siZielK[0] := 0;
    #siZielK[1] := 0;
    #siZielK[2] := 0;
    #siZielK[3] := 0;
    #siZielK[4] := 0;
    #siZielK[5] := 0;
    #siZielK[6] := 0;
    #siZielK[7] := 0;
    #sxHaltAZeit := FALSE;
    #sxHaltSZeit := false;
    #siS_SollZeit := 0;
    #siA_SollZeit := 0;
  
    // Bereich ablöschen
    #sxPermS := #sxLoeschS;
    #sxAktivS := #sxLoeschS;
  
    //Schrittgrenzen definieren
    IF #siS_No > 255 THEN
        #siS_No := 255;
    END_IF;
    IF #siS_No < 0 THEN
        #siS_No := 0;
    END_IF;
  
    // passendes Schrittbit setzen
    #sxPermS.S[#siS_No] := TRUE;
  
    // Wenn Schittkette aktiv Schritte kopieren
    IF #ixBA_Auto OR #ixBA_Einzel THEN
        #sxAktivS := #sxPermS;
    END_IF;
  
  
  
  
  
  
  
  
  
  
  
  
  
  
END_FUNCTION_BLOCK
 
Zuletzt bearbeitet von einem Moderator:
Zurück
Oben