Zuviel Werbung? - > Hier kostenlos beim SPS-Forum registrieren

Seite 3 von 3 ErsteErste 123
Ergebnis 21 bis 28 von 28

Thema: Frage bez. FOR-Schleife (Beckhoff CX9000-001)

  1. #21
    Registriert seit
    22.06.2009
    Ort
    Sassnitz
    Beiträge
    11.197
    Danke
    926
    Erhielt 3.292 Danke für 2.661 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Wenn ein Vorwärtszähler vorgeschrieben ist, dann würde ich das Programm so schreiben:
    Code:
    VAR_INPUT
        Enable            : BOOL;
        myNumber          : INT;
    END_VAR
    VAR
        En_Trig           : R_TRIG;
        Timer_Puls        : TON;
        Timer_Pause       : TON;
        Counter           : INT;
        greenLightControl : BOOL;
    END_VAR
    
    
    En_Trig (CLK := Enable);
    
    IF En_Trig.Q THEN
        Counter := 0;
    END_IF;
    
    Timer_Puls (IN := Enable AND (Counter < MyNumber) AND NOT Timer_Pause.Q, PT := T#1s);
    Timer_Pause (IN := Timer_Puls.Q, PT := T#1s);
    
    IF Timer_Pause.Q THEN
        Counter := Counter + 1;
    END_IF;
    
    greenLightControl := Enable AND (Counter < MyNumber) AND NOT Timer_Puls.Q;
    Vorwärtszählen hat die Besonderheit, daß sich der Vergleichswert myNumber über den ganzen Impulsausgabezyklus nicht ändern darf, es sei denn, man will absichtlich noch während laufendem Impulsausgabezyklus nachträglich die Impulszahl ändern. Wenn myNumber sich ungewünscht ändern kann, dann muß man beim Impulszyklus-Start myNumber in eine Kopie speichern und dann mit dieser Kopie arbeiten.


    Dieses Problem umgeht man elegant, wenn man mit einem Rückwärtszähler arbeitet, da wird myNumber im Counter gespeichert und danach nicht mehr beachtet:
    Code:
    VAR_INPUT
        Enable            : BOOL;
        myNumber          : INT;
    END_VAR
    VAR
        En_Trig           : R_TRIG;
        Timer_Puls        : TON;
        Timer_Pause       : TON;
        Counter           : INT;
        greenLightControl : BOOL;
    END_VAR
    
    
    En_Trig (CLK := Enable);
    
    IF En_Trig.Q THEN
        Counter := myNumber;
    END_IF;
    
    IF NOT Enable THEN
        Counter := 0;
    END_IF;
    
    Timer_Puls (IN := (Counter <> 0) AND NOT Timer_Pause.Q, PT := T#1s);
    Timer_Pause (IN := Timer_Puls.Q, PT := T#1s);
    
    IF Timer_Pause.Q AND (Counter <> 0) THEN
        Counter := Counter - 1;
    END_IF;
    
    greenLightControl := (Counter <> 0) AND NOT Timer_Puls.Q;
    Ein weiterer Vorteil des Rückwärtszählers ist, daß man den Zählerstand direkt zur Anzeige eines Countdowns benutzen kann.


    Wenn Pulszeit und Pausezeit gleich lang sind, dann braucht man nur 1 Timer. Mein Favorit ist in dem Fall ein Rückwärtszähler, der die Pulse und die Pausen zählt und die Pulsausgabe wird nur bei ungeraden Zählerständen TRUE:
    Code:
    VAR_INPUT
        Enable            : BOOL;
        myNumber          : INT;
    END_VAR
    VAR
        En_Trig           : R_TRIG;
        Timer             : TON;
        Counter           : INT;
        greenLightControl : BOOL;
    END_VAR
    
    
    En_Trig (CLK := Enable);
    
    IF En_Trig.Q AND (myNumber > 0) THEN
        Counter := myNumber + myNumber - 1;
    END_IF;
    
    IF NOT Enable THEN
        Counter := 0;
    END_IF;
    
    Timer (IN := (Counter <> 0) AND NOT Timer.Q, PT := T#1s);
    
    IF Timer.Q AND (Counter <> 0) THEN
        Counter := Counter - 1;
    END_IF;
    
    greenLightControl := WORD_TO_BOOL(INT_TO_WORD(Counter) AND 1);
    
    (* greenLightControl := Counter.0; darf man in ST wahrscheinlich nicht schreiben? *)
    Harald
    Es ist immer wieder überraschend, wie etwas plötzlich funktioniert, sobald man alles richtig macht.

    FAQ: Linkliste SIMATIC-Kommunikation über Ethernet
    Zitieren Zitieren Erzeugung einer vorgegebenen Pulsanzahl  

  2. #22
    Registriert seit
    08.01.2007
    Beiträge
    54
    Danke
    1
    Erhielt 10 Danke für 8 Beiträge

    Standard

    Ich würds so machen:
    FUNCTION_BLOCK _BLINK
    VAR_INPUT
    BLINK_COUNT:INT;
    BLINK_ON_TIME:TIME;
    BLINK_OFFTIME:TIME;
    END_VAR
    VAR_OUTPUT
    THE_BLINKER:BOOL;
    END_VAR
    VAR
    TIMER:TON;
    END_VAR


    IF BLINK_COUNT>0 THEN
    IF NOT TIMER.IN THEN
    IF THE_BLINKER THEN
    TIMER.PT:=BLINK_ON_TIME;
    ELSE
    TIMER.PT:=BLINK_OFFTIME;
    END_IF;
    END_IF;
    TIMER(IN:=NOT TIMER.Q);
    IF TIMER.Q THEN
    THE_BLINKER:=NOT THE_BLINKER;
    IF NOT THE_BLINKER THEN
    BLINK_COUNT:=BLINK_COUNT-1;
    END_IF;
    END_IF;
    ELSE
    TIMER(IN:=FALSE);
    THE_BLINKER:=FALSE;
    END_IF;
    Geändert von soma (04.05.2011 um 15:45 Uhr)

  3. #23
    Registriert seit
    22.06.2009
    Ort
    Sassnitz
    Beiträge
    11.197
    Danke
    926
    Erhielt 3.292 Danke für 2.661 Beiträge

    Standard

    Zitat Zitat von soma Beitrag anzeigen
    Ich würds so machen:
    Ist das in ST so üblich, daß man VAR_INPUT wie interne Variablen benutzt (Beschreiben und Werte für den nächsten Zyklus merken)?
    Da darf man ja die Inputs gar nicht beschalten und braucht 2 verschiedene Aufrufe des Bausteins oder muß zum Starten außerhalb des Aufrufs den Input-Parameter BLINK_Instanz.BLINK_COUNT beschreiben. Das finde ich gar nicht schön.

    Zusätzlich wäre es besser, wenn das Programm sofort mit der Impulsausgabe beginnen würde statt mit der Impulspause.

    Tip:
    Für bessere Lesbarkeit kann man Programmcode in eine Code-Box einfügen. Das erreicht man mit den Code-Tags [CODE] und [/CODE] bzw. im Beitragseditor mit dem #-Button. Dein Code könnte dann so aussehen:
    Code:
    FUNCTION_BLOCK _BLINK
    VAR_INPUT
        BLINK_COUNT:INT;
        BLINK_ON_TIME:TIME;
        BLINK_OFFTIME:TIME;
    END_VAR
    VAR_OUTPUT
        THE_BLINKER:BOOL;
    END_VAR
    VAR
        TIMER:TON;
    END_VAR
    
    
    IF BLINK_COUNT>0 THEN
        IF NOT TIMER.IN THEN
            IF THE_BLINKER THEN
                TIMER.PT:=BLINK_ON_TIME;
            ELSE
                TIMER.PT:=BLINK_OFFTIME;
            END_IF;
        END_IF;
        TIMER(IN:=NOT TIMER.Q);
        IF TIMER.Q THEN
            THE_BLINKER:=NOT THE_BLINKER;
            IF NOT THE_BLINKER THEN
                BLINK_COUNT:=BLINK_COUNT-1;
            END_IF;
        END_IF;
    ELSE
        TIMER(IN:=FALSE);
        THE_BLINKER:=FALSE;
    END_IF;
    Harald
    Es ist immer wieder überraschend, wie etwas plötzlich funktioniert, sobald man alles richtig macht.

    FAQ: Linkliste SIMATIC-Kommunikation über Ethernet

  4. Folgender Benutzer sagt Danke zu PN/DP für den nützlichen Beitrag:

    Tommi (04.05.2011)

  5. #24
    Registriert seit
    22.03.2007
    Ort
    Detmold (im Lipperland)
    Beiträge
    11.727
    Danke
    398
    Erhielt 2.404 Danke für 2.002 Beiträge

    Standard

    Zitat Zitat von PN/DP Beitrag anzeigen
    Ist das in ST so üblich, daß man VAR_INPUT wie interne Variablen benutzt (Beschreiben und Werte für den nächsten Zyklus merken)?
    Da darf man ja die Inputs gar nicht beschalten und braucht 2 verschiedene Aufrufe des Bausteins oder muß zum Starten außerhalb des Aufrufs den Input-Parameter BLINK_Instanz.BLINK_COUNT beschreiben. Das finde ich gar nicht schön.
    ... das sehe ich genau so - unabhängig ob ST oder SCL.
    Vor Allem auch deswegen, da ich bei solchen Bausteinen die IN-Parameter auch gerne mal mit einer Konstante (also einem Festwert) beschalte - das entspräche hier ja sogar auch dem Sinn des Bausteins ...

    Gruß
    Larry

  6. #25
    Registriert seit
    22.03.2007
    Ort
    Detmold (im Lipperland)
    Beiträge
    11.727
    Danke
    398
    Erhielt 2.404 Danke für 2.002 Beiträge

    Standard

    Zitat Zitat von PN/DP Beitrag anzeigen
    ... und weil es nur eine nette Ablenkung war muß man sich wohl auch keine Mühe geben ...

    Was mich generell an diesem ST stört:
    Es verführt unerfahrene Programmierer unheimlich zu ereignisorientierter Programmierung mit überwiegend bedingten Zuweisungen, was zu lauter solchen undurchdachten und unvollständigen Programmen mit logischen Fehlern führt, wie hier und in anderen Threads leider immer wieder zu sehen ist. Es wird ohne Plan einfach losgetippt - "nur schnell gebastelt" - der Anwender wird zum ewigen Betatester, weil diese Programme aus dem Entwurfsstadium nie herauskommen - auch wenn noch so viel nachgeflickt wird.
    Das sehe ich nicht so ...
    Natürlich sollte man sich Mühe geben - da hast du Recht. Auf der anderen Seite geht es hier aber nicht darum "dem Anderen seine Arbeit zu machen" sondern aus meiner Sicht eher "dem Anderen einen Start zu ermöglichen". Dazu ist kein 100% fehlerfreies Code-Beispiel oder am Besten schon die ganze erledigte Arbeit notwendig. Das würde im Gegenteil dem Anderen auch gar nicht helfen, da es niemanden wirklich hilft, mit etwas zu arbeiten das man nicht wirklich verstanden hat.
    Dem entsprechend sehe ich meine Tätigkeit hier (im Forum) unter der Prämisse des Helfens verstehen zu lernen.

    Gruß
    Larry

  7. Folgender Benutzer sagt Danke zu Larry Laffer für den nützlichen Beitrag:

    Schnick und Schnack (06.05.2011)

  8. #26
    Registriert seit
    19.11.2006
    Beiträge
    1.346
    Danke
    6
    Erhielt 254 Danke für 231 Beiträge

    Standard

    Zitat Zitat von Schnick und Schnack Beitrag anzeigen
    Wie kann denn der Counter einr FOR-Schleife beeinflusst werden?
    Da bin ich jetzt ehrlichgesagt überfragt. Dafür verwende ich FOR/WHILE
    zu selten, zumindest in zyklischen SPS-Programmen.
    mit "EXIT":

    Code:
    VAR
      i: INT;
      Limit : INT := 50;
    END_VAR
    
    FOR i := 0 TO 100 DO
      IF i > Limit  THEN
        EXIT;
      END_IF
    END_FOR
    Hier würde die FOR-Schleife bei i = 51 abgebrochen werden

  9. #27
    apmIng ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    03.05.2011
    Beiträge
    7
    Danke
    6
    Erhielt 0 Danke für 0 Beiträge

    Standard

    Zitat Zitat von PN/DP Beitrag anzeigen
    Es verführt unerfahrene Programmierer unheimlich zu ereignisorientierter Programmierung mit überwiegend bedingten Zuweisungen
    Klar, wenn man 19 Jahre C++ programmiert, ist es schwer, sich davon zu lösen

  10. #28
    Registriert seit
    02.02.2007
    Beiträge
    104
    Danke
    12
    Erhielt 16 Danke für 13 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Zitat Zitat von apmIng Beitrag anzeigen
    Klar, wenn man 19 Jahre C++ programmiert, ist es schwer, sich davon zu lösen
    Wenn man einmal verstanden hat wie eine SPS arbeitet, kann man mit jeder Sprache verständliche und funktionierende Programme schreiben.

    In FUP oder AWL kann man genauso schlecht oder gut programmieren.

    Dein Problem kann man auch ohne verwendung von Timern und Bedingungen programmieren.

    Code:
    counter :=(counter + 1)MOD NumberOfCycles;
    boOut:= boOut XOR (counter <= 0  );
    Gruß

    dummy
    Geändert von Dummy (05.05.2011 um 15:27 Uhr)

Ähnliche Themen

  1. Beckhoff CX9000 Profinet verwenden
    Von s.murauer im Forum CODESYS und IEC61131
    Antworten: 7
    Letzter Beitrag: 14.10.2011, 09:30
  2. Biete: Beckhoff CX9000
    Von chrischio im Forum Suche - Biete
    Antworten: 5
    Letzter Beitrag: 09.08.2011, 08:15
  3. Beckhoff CX9000-N000 target
    Von Fallon im Forum CODESYS und IEC61131
    Antworten: 18
    Letzter Beitrag: 28.07.2011, 13:27
  4. Visualisierung für Beckhoff CX9000 gesucht
    Von klaus1 im Forum CODESYS und IEC61131
    Antworten: 29
    Letzter Beitrag: 17.01.2010, 16:07
  5. Beckhoff CX9000-KBus
    Von SPS_Neuling im Forum CODESYS und IEC61131
    Antworten: 7
    Letzter Beitrag: 26.12.2007, 12:29

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •