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

Ergebnis 1 bis 8 von 8

Thema: Programmierwettbewerb, 3. Aufgabe

  1. #1
    Registriert seit
    19.05.2008
    Beiträge
    648
    Danke
    117
    Erhielt 136 Danke für 105 Beiträge

    Frage


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Hallo Ihr,

    Ist das wirklich erst die 3. Aufgabe?
    Die Suchfunktion brachte folgende Fehlermeldung:
    Die folgenden Wörter sind sehr allgemein, zu kurz oder zu lang und wurden daher in der Suchanfrage ignoriert: Programmierwettbewerb“

    Egal – aus aktuellem Anlass habe ich eine schöne Aufgabe, die mit Sicherheit ein Vielzahl an unterschiedlichen Lösungen hervorbringt.

    Bestimmt kennen einige die Variante „Automatik Stopp bei x Fehlerteile in Folge“. Das lässt sich auch recht einfach mit wenigen Programmzeilen realisieren:
    Ein Zähler für Schlecht-Teile wird mit dem Grenzwert X verglichen. Bei Überschreitung wird der Stopp ausgelöst. Kommt ein gutes Teil, wird der Zähler zurückgesetzt.

    Jetzt kann es aber sein, dass zum Beispiel für x=10 Teile eingestellt sind und die Maschine immer wieder ein „Gutes“ Werkstück zwischen den „Schlechten“ produziert. Im Extremfall könnte 90% Ausschuss produziert werden und es würde kein „Automatik Stopp“ statt finden.

    Daher die Aufgabe: X aus Y ermitteln
    Anstatt der festen Folge von Schlecht-Teilen, soll eine parametrierbare Anzahl X überwacht werden. Wird die maximal zulässige Menge Y (ebenfalls einstellbar) überschritten, soll der „Automatik Stopp“ erfolgen.
    X und Y soll im Bereich von 0-100 einstellbar sein. Y muss <=X sein.
    Wird X während dem Betrieb verändert, soll die Funktion mit einer frischen Bewertung beginnen.

    Code:
    FUNCTION_BLOCK  X_aus_Y 
    TITLE = VERSION : 0.1 
    VAR_INPUT   
      bWS_IO  : BOOL ;      // Werkstück in Ordnung   
      bWS_NIO : BOOL ;      // Werkstück nicht in Ordnung   
      bReset  : BOOL ;      // Initialisierung   
      iX      : INT ;       // Größe des Bereichs der Auswertung   
      iY      : INT ;       // Grenzwert für die Summe 
    END_VAR 
    VAR_OUTPUT   
      bZ     : BOOL ;       // Grenzwert für die Summe überschritten   
      iZ     : INT ;        // Summe   
      Fehler : BOOL ;       // Fehler, Ungültige Eingangswerte 
    END_VAR 
    BEGIN 
    NETWORK TITLE =  
    
    END_FUNCTION_BLOCK
    Viel Vergnügen
    Chräshe
    Zitieren Zitieren Programmierwettbewerb, 3. Aufgabe  

  2. #2
    Registriert seit
    06.10.2003
    Beiträge
    3.412
    Danke
    451
    Erhielt 506 Danke für 408 Beiträge

    Standard

    Na dann will ich doch mal was zum Besten geben.

    Code:
    FUNCTION_BLOCK  "X_aus_Y" 
    TITLE = 'VERSION : 0.1' 
    
    VAR_INPUT   
      bWS_IO            : BOOL;                   // Werkstück in Ordnung   
      bWS_NIO           : BOOL;                   // Werkstück nicht in Ordnung   
      bReset            : BOOL;                   // Initialisierung   
      iX                : INT;                    // Größe des Bereichs der Auswertung   
      iY                : INT;                    // Grenzwert für die Summe 
    END_VAR 
    
    VAR_OUTPUT   
      bZ                : BOOL;                   // Grenzwert für die Summe überschritten   
      iZ                : INT;                    // Summe   
      Fehler            : BOOL;                   // Fehler, Ungültige Eingangswerte 
    END_VAR 
    
    VAR_TEMP
      PIM_bWS_IO        : BOOL;                   // pos. Impuls
      PIM_bWS_NIO       : BOOL;                   // pos. Impuls
      PIM               : BOOL;                   // pos. Impuls
    END_VAR
    
    VAR
      REGISTER          : ARRAY[1..100] OF BOOL;  // Umlaufregister
      X_ALT, Y_ALT      : INT;                    // Altwerte Eingangsparameter
      IO, NIO           : INT;                    // Zähler nio/io
      FUELLSTAND        : INT;                    // Füllstand des Registers
      FLM_bWS_IO        : BOOL;                   // Flankenmerker
      FLM_bWS_NIO       : BOOL;                   // Flankenmerker
      VOLL              : BOOL;                   // Register ist bis zum Wert iY gefüllt
      P_EIN, P_AUS      : INT;                    // Eintrags- und Austragszeiger
    END_VAR
    
    
    BEGIN 
    
    //*** Initialisierung & Eingangswerte überprüfen
    IF bReset OR iX<>X_ALT OR iY<>Y_ALT THEN
        X_ALT      := iX;
        Y_ALT      := iY;
        Fehler     := iX<1 OR iX>100 OR iY>iX OR iY=iX;
        P_EIN      := 0;
        P_AUS      := 0;
        IO         := 0;
        NIO        := 0;
        VOLL       := false;
        FUELLSTAND := 0;
    END_IF;
    
    //*** Flankenauswertung
    PIM_bWS_IO  := bWS_IO AND NOT FLM_bWS_IO;
    FLM_bWS_IO  := bWS_IO;
    PIM_bWS_NIO := bWS_NIO AND NOT FLM_bWS_NIO;
    FLM_bWS_NIO := bWS_NIO;
    PIM         := PIM_bWS_IO OR PIM_bWS_NIO;
    
    //*** Austragen
    IF PIM AND VOLL THEN
        P_AUS := P_AUS MOD iX; 
        P_AUS := P_AUS + 1;                       // Umlaufzähler Austrag
        IF REGISTER[P_AUS]
            THEN  IO :=  IO - 1;
            ELSE NIO := NIO - 1;
        END_IF;
    END_IF;        
    
    //*** Eintragen
    IF PIM THEN
        P_EIN := P_EIN MOD iX; 
        P_EIN := P_EIN + 1;                       // Umlaufzeiger Eintrag
        IF PIM_bWS_IO
            THEN REGISTER[P_EIN] := true;
                 IO := IO + 1;
            ELSE REGISTER[P_EIN] := false;
                 NIO := NIO + 1;
        END_IF;
    END_IF;        
    
    //*** Füllstand Register
    IF PIM AND NOT VOLL THEN
        FUELLSTAND := FUELLSTAND+1;
        IF FUELLSTAND = iX THEN
            VOLL := true;
        END_IF;
    END_IF;
    
    //*** NIO ausgeben
    bZ := NIO > iY OR Fehler;
    
    //*** Zähler Schlechtteile ausgeben
    iZ := NIO;
    
    END_FUNCTION_BLOCK

    Gruß, Onkel

    Prg_we_1.zip
    Es gibt viel mehr Leute, die freiwillig aufgeben, als solche, die echt scheitern.
    Henry Ford

  3. #3
    Registriert seit
    07.09.2011
    Beiträge
    101
    Danke
    17
    Erhielt 16 Danke für 12 Beiträge

    Beitrag

    Nicht schlecht Onkel!

    Ich muss zugeben, den MOD hab ich abgeguckt.


    Hier mein Versuch:

    Code:
     FUNCTION_BLOCK X_aus_Y
     VAR_INPUT
       bWS_IO    : BOOL;      (*// Werkstück in Ordnung *)
       bWS_NIO   : BOOL;      (*// Werkstück nicht in Ordnung    *)
       bReset    : BOOL;      (*// Initialisierung *)
       iX        : INT;       (*// Größe des Bereichs der Auswertung    *)
       iY        : INT;       (*// Grenzwert für die Summe  *)
     END_VAR
     VAR_OUTPUT
       bZ        : BOOL;      (*// Grenzwert für die Summe überschritten    *)
       iZ        : INT;       (*// Summe    *)
       bFehler   : BOOL;      (*// Fehler, Ungültige Eingangswerte  *)
     END_VAR
     VAR
       FP_IO     : R_TRIG;    (*// Flanke IO *)
       FP_NIO    : R_TRIG;    (*// Flanke NIO *)
       REGISTER  : ARRAY[1..100] OF BYTE;  (*// Umlaufregister 0=leer, 1=NIO, 2=IO *)
       REG_Leer  : ARRAY[1..100] OF BYTE;  (*// für INIT *)
       iX_ALT    : INT;       (*// Alter Eingangsparameter *)
       iIO       : INT;       (*// Zähler io - nicht notwendig aber vielleicht zur Kontrolle... *)
       iNIO      : INT;       (*// Zähler nio *)
       iZeiger   : INT;       (*// Aktuelles Register  *)
     END_VAR
      
     (*// *** Initialisierung & Eingangswerte überprüfen *)
         IF bReset OR iX<>iX_ALT THEN
             REGISTER    := REG_Leer;
                 iX_ALT  := iX;
                 iZeiger := 0;
                 iIO     := 0;
                 iNIO    := 0;
                 bFehler := FALSE;
         END_IF;
      
     (*// *** Flankenauswertung  *)
         FP_IO  (CLK:=bWS_IO , Q=> );
         FP_NIO (CLK:=bWS_NIO , Q=> );
      
     (*// *** Austragen / Eintragen  *)
         IF FP_IO.Q OR FP_NIO.Q THEN
             iZeiger := iZeiger MOD iX;
             iZeiger := iZeiger + 1;
             (*// Austragen alter Werte *)
               IF REGISTER[iZeiger] = 2 THEN
                 iIO := iIO - 1;
             ELSIF REGISTER[iZeiger] = 1 THEN
                 iNIO := iNIO - 1;
             END_IF;
    
             (*// Eintragen neuer Werte *)
             IF FP_IO.Q  THEN
                REGISTER[iZeiger] := 2;
                iIO := iIO + 1;
             ELSE REGISTER[iZeiger] := 1;
                iNIO := iNIO + 1;
             END_IF;
         END_IF;
      
     (*// *** Fehler speichern und Ausgeben  *)
         IF iX=0 OR iX>100 OR iY>=iX OR (FP_IO.Q AND FP_NIO.Q) THEN
             bFehler  :=  TRUE;
         END_IF;
      
     (*// *** NIO ausgeben  *)
         bZ := iNIO > iY OR bFehler;
      
     (*// *** Zähler Schlechtteile ausgeben  *)
         iZ := iNIO;
    Mein Anhang ist für TwinCAT gedacht. Die Siemens-Jünger müssen halt die „(*“ gegen Leerzeichen ersetzen.
    So – dann warte ich mal gespannt auf eine Variante in AWL...

    Der Wutbürger
    Angehängte Dateien Angehängte Dateien

  4. #4
    Registriert seit
    25.11.2010
    Ort
    OWL
    Beiträge
    750
    Danke
    27
    Erhielt 165 Danke für 143 Beiträge

    Standard

    Hm, viel kann man da ja nicht mehr anders machen. Reiche trotzdem mal einen Vorschlag ein.
    Die Variablendeklaration
    Code:
    FUNCTION_BLOCK X_aus_Y
    VAR_INPUT
      bWS_IO  : BOOL ;      (* Werkstück in Ordnung *)
      bWS_NIO : BOOL ;      (* Werkstuck nicht in Ordnung *)
      bReset  : BOOL ;      (* Initialisierung *)
      iX      : INT ;       (* Grösse des Bereichs der Auswertung *)
      iY      : INT ;       (* Grenzwert fuer die Summe *)
    END_VAR
    VAR_OUTPUT
      bZ     : BOOL ;       (* Grenzwert fuer die Summe überschritten *)
      iZ     : INT ;        (* Summe *)
      Fehler : BOOL ;       (* Fehler, Ungültige Eingangswerte *)
    END_VAR
    VAR
        Buffer:ARRAY[0..99] OF BYTE;    (* Ringpuffer für 100 IOs/NIOs *)
        Index:INT;                            (* Lese-Schreibzeiger auf Puffer *)
        ReadEnable:BOOL;                    (* Freigabe zum Auslesen (erst nach einem Pufferumlauf) *)
        IOTrig:R_TRIG;                        (* IO-Flankenerkennung *)
        NIOTrig:R_TRIG;                    (* NIO-Flankenerkennung *)
        LocalX:INT;                            (* Lokale Variable für iX *)
    END_VAR
    und der Code dazu
    Code:
    (* IO/NIO-Trigger *)
    IOTrig(Clk:=bWS_IO);
    NIOTrig(Clk:=bWS_NIO);
    
    (*Fehler ausgeben bei gleichzeitigen IO/NIO-Flanken oder ungültigen iX/iY-Werten *)
    Fehler:=(IOTrig.Q AND NIOTrig.Q)
              OR (iY>iX)
              OR (ix>100)
              OR (iY>100);
    
    IF NOT Fehler
    THEN
        (* Reset *)
        IF bReset OR (iX<>LocalX)    (* Bei Reset oder geändertem iX *)
        THEN
            LocalX:=iX;                    (* iX in lokale Variable übernehmen *)
            iZ:=0;                        (* Fehlersumme auf 0 setzen *)
            Index:=0;                    (* Puffer-Index auf 0 setzen *)
            ReadEnable:=FALSE;        (* Auslesefreigabe rücksetzen *)
        END_IF;
    
        (* IO/NIO-Signale auswerten *)
        IF IOTrig.Q XOR NIOTrig.Q    (* Bei IO/NIO-Flanke *)
        THEN
            Index:=(Index+1) MOD LocalX;                (* Pufferzeiger um 1 erhöhen *)
            IF ReadEnable                                    (* Wenn Lesefreigabe *)
            THEN
                iZ:=iZ-Buffer[Index];                    (* Ältestes IO=0/NIO=1 von iZ subtrahieren *)
            END_IF;
            iZ:=iZ+BOOL_TO_BYTE(bWS_NIO);                (* Neues IO=0/NIO=1 zu iZ addieren *)
            Buffer[Index]:=BOOL_TO_BYTE(bWS_NIO);    (* und in Puffer eintragen *)
            IF Index=0                (* Wenn iX Werte eingetragen sind, d. h. nach dem ersten Pufferumlauf *)
            THEN
                ReadEnable:=TRUE;    (* Lesefreigabe setzen *)
            END_IF;
        END_IF;
    END_IF;
    
    (* Ausgabe zulässige NIOs überschritten *)
    bZ:=iZ>iY;
    Noch eine Anmerkung: Statt der getrennten IO/NIO-Eingänge würde ich einen EIngang für IO=False/NIO=True und einen Takteingang zum Triggern vorziehen.
    Geändert von StructuredTrash (21.11.2011 um 21:32 Uhr) Grund: Anmerkung hinzugefügt

  5. #5
    Avatar von Chräshe
    Chräshe ist offline Erfahrener Benutzer
    Themenstarter
    Registriert seit
    19.05.2008
    Beiträge
    648
    Danke
    117
    Erhielt 136 Danke für 105 Beiträge

    Daumen hoch

    Hallo Ihr,

    Ein GROSSES Dankeschön an alle die mitgemacht haben.

    So wie es aussieht, kommen keine weiteren Beiträge. In AWL wäre die Lösung natürlich auch möglich gewesen, aber mit Sicherheit nicht so kurz und übersichtlich.

    Ich schlage vor, wir kommen zur Abstimmung. Setzt bei eurem Favoriten einfach ein „Danke“ darunter.

    Gruß
    Chräshe

    --
    @Wutbürger
    Kuck dir die Flanken-Erkennung auch beim Onkel ab. Das mit R_TRIG geht bei Siemens, wenn überhaupt, nicht so einfach...

  6. #6
    Registriert seit
    19.01.2010
    Ort
    Graz / Austria
    Beiträge
    100
    Danke
    6
    Erhielt 10 Danke für 8 Beiträge

    Standard

    Ich habe hier eine etwas andere Lösung gefunden, welche nur die schlechten Teile zählt. Dadurch brauche ich nicht Speicher für gute Stücke reservieren, was sich z.B. bei einer Auswertung von 5 aus 10.000 bemerkbar machen würde.
    Das Programm ist im Moment für bis zu 10 schlechte und 65535 gute Teile ausgelegt.

    Code:
    VAR
        bWS_IO : BOOL; (* Werkstück in Ordnung *)
        bWS_NIO : BOOL; (* Werkstück nicht in Ordnung *)
        bReset : BOOL; (* Initialisierung *)
        iX : UINT; (* Größe des Bereichs der Auswertung *)
        iY : INT; (* Grenzwert für die Summe *)
        bZ : BOOL; (* Grenzwert für die Summe überschritten *)
        iZ : INT; (* Summe *)
        Fehler : BOOL; (* Fehler, Ungültige Eingangswerte *)
        iarrSchlechtCoun : ARRAY[0..9] OF UINT; (*Position der schlechten Teile zwischen den Guten*)
        rtWS_IO : R_TRIG := (0); (*Steigende Flanken Erkennung*)
        rtWS_NIO : R_TRIG := (0); (*Steigende Flanken Erkennung*)
        i : UINT := 0; (*Schleifenzähler*)
    END_VAR
    Code:
    PROGRAM _CYCLIC
        
        (* Schlechtes Teil *)
        rtWS_NIO (CLK:=bWS_NIO);
        IF rtWS_NIO.Q THEN
            (* Suche freien Stückzähler *)
            i := 0;
            WHILE (i < 9 AND iarrSchlechtCoun[i] > 0) DO
                i := i + 1;
            END_WHILE
            
            (* Falls frei, setze Zähler auf maximum *)
            IF iarrSchlechtCoun[i] = 0 THEN
                iarrSchlechtCoun[i] := iX;
            END_IF
            
            (* Zähle schlechte Teile *)
            iZ := 0;
            FOR i:=0 TO 9 BY 1 DO
                IF iarrSchlechtCoun[i] > 0 THEN
                    iZ := iZ + 1;
                END_IF
            END_FOR
        END_IF
        
        
        (* Gutes Teil *)
        rtWS_IO (CLK:=bWS_IO);
        IF rtWS_IO.Q THEN
            (* Alle Positionszähler für schlechte Teile verringern *)
            FOR i:=0 TO 9 BY 1 DO
                IF iarrSchlechtCoun[i] > 0 THEN
                    iarrSchlechtCoun[i] := iarrSchlechtCoun[i] - 1;
                END_IF
            END_FOR
            
            (* Zähle schlechte Teile *)
            iZ := 0;
            FOR i:=0 TO 9 BY 1 DO
                IF iarrSchlechtCoun[i] > 0 THEN
                    iZ := iZ + 1;
                END_IF
            END_FOR
        END_IF
    
        
        (* Reset *)
        IF bReset THEN
            FOR i:=0 TO 9 BY 1 DO
                IF iarrSchlechtCoun[i] > 0 THEN
                    iarrSchlechtCoun[i] := 0;
                END_IF
            END_FOR
            iZ := 0;
        END_IF
        
        
        (* Grenzwert überschritten *)
        bZ := iZ >= iY;
    
        (* Fehler bei falschen Eingängen *)
        Fehler:= (bWS_IO AND bWS_NIO)
        OR (iY>iX)
        OR (iX>100)
        OR (iY>100);
        
    END_PROGRAM

  7. #7
    Avatar von Chräshe
    Chräshe ist offline Erfahrener Benutzer
    Themenstarter
    Registriert seit
    19.05.2008
    Beiträge
    648
    Danke
    117
    Erhielt 136 Danke für 105 Beiträge

    Standard

    Hallo Ihr,

    kommen wir zur Siegerehrung - Folgende Teilnehmer haben die meisten Danke erhalten:
    (Die Reihenfolge ist sortiert nach dem Abgabetermin)

    Onkel Dagobert _000000
    Wutbürger
    ______000000
    StructuredTrash 000000
    MichaelUray ____000000

    Einen zweiten und dritten Platz hat es leider nicht gegeben...



    Als Anregung, falls mal jemand so eine Funktion braucht: Der Fehler bei falschen Eingabewerten wird bei allen 4 Lösungen ausgewertet. Es ist dann natürlich auch sinnvoll, die Bearbeitung vom restlichen Programm zu unterbinden. Das war bei StructuredTrash schön umgesetzt.

    Ich schlage vor, wer eine schöne Aufgabe hat, stellt die „4. Aufgabe“.

    Gruß
    Chräshe
    Zitieren Zitieren Siegerehrung  

  8. #8
    Registriert seit
    06.10.2003
    Beiträge
    3.412
    Danke
    451
    Erhielt 506 Danke für 408 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Ok, die Abende werden wieder länger .

    Ich habe eine kleine Aufgabe, die jeden interessieren dürfte und die viele unter uns auch lösen können. Ich mach dann mal einen neuen Thread auf.

    http://www.sps-forum.de/showthread.p...916#post365916


    Gruß, Onkel
    Geändert von Onkel Dagobert (05.12.2011 um 20:56 Uhr)
    Es gibt viel mehr Leute, die freiwillig aufgeben, als solche, die echt scheitern.
    Henry Ford

  9. Folgender Benutzer sagt Danke zu Onkel Dagobert für den nützlichen Beitrag:

    Chräshe (08.12.2011)

Ähnliche Themen

  1. Programmierwettbewerb, 2. Aufgabe
    Von LargoD im Forum Stammtisch
    Antworten: 14
    Letzter Beitrag: 02.08.2011, 22:27
  2. Programmierwettbewerb
    Von M-Ott im Forum Stammtisch
    Antworten: 49
    Letzter Beitrag: 22.06.2011, 14:00
  3. Programmierwettbewerb: Diskussion
    Von Kai im Forum Stammtisch
    Antworten: 51
    Letzter Beitrag: 20.06.2011, 10:05
  4. Programmierwettbewerb: Interesse? Regeln!
    Von M-Ott im Forum Stammtisch
    Antworten: 67
    Letzter Beitrag: 18.06.2011, 08:28
  5. ##Aufgabe##
    Von Dr.Know? im Forum Simatic
    Antworten: 14
    Letzter Beitrag: 02.12.2006, 21:07

Stichworte

Lesezeichen

Berechtigungen

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