Anlage und Simulation sind nicht einig.

der_NooB

Level-2
Beiträge
254
Reaktionspunkte
7
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo, guten Morgen,

ich habe Änderungen an meinem Programm vorgenommen, und mir sind dabei Fehler aufgefallen, die zuvor nie aufgetreten sind!

Zum Beispiel habe ich eine Ausschaltverfahrenskette, bei der ein Motor immer ein Signal erhalten hat, bis er in Störung ging. In der Simulation hat er jedoch ordnungsgemäß abgeschaltet, wie es sein soll.

Außerdem habe ich einen Funktionsbaustein (FB) für drei identische Baugruppen erstellt. Bei einer davon bleibt immer ein Signal hängen, wodurch die Schrittkette blockiert wird – aber nur bei dieser einen Baugruppe!

In der Simulation tritt dieses Problem jedoch gar nicht auf.

Woran könnte das liegen?

danke euch
 
Naja ... und pauschale Aussagen zu machen ist ohnehin sehr schwierig ... so ganz ohne Fakten.Es gibt aber ja die Möglichkeit, sich im Status anzuschauen was passiert oder eben nicht passiert (obwohl es schön wäre wenn es passiert) - nennt sich debuggen - wäre vielleicht ein Ansatz ...
Ansonsten (und das solltest du mittlerweile wissen) solltest du Code liefern wenn du Hilfe erwartest ...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Naja ... und pauschale Aussagen zu machen ist ohnehin sehr schwierig ... so ganz ohne Fakten.Es gibt aber ja die Möglichkeit, sich im Status anzuschauen was passiert oder eben nicht passiert (obwohl es schön wäre wenn es passiert) - nennt sich debuggen - wäre vielleicht ein Ansatz ...
Ansonsten (und das solltest du mittlerweile wissen)
Debuggen gleich an der Anlage, also ich habe es nur mit Simulation bisher gemacht.
solltest du Code liefern wenn du Hilfe erwartest ...
Code:
Motor_EVG_AVG();

// Um zu wissen, bei welchem Schritt mein Automatikmodus ist
Anzeige_iSchrittnummer := Automatik_iSchrittnummer;

// Flanken deklarieren
fStopp(CLK := GVL.tStop);
fStart(CLK := GVL.tStart);
fRueckgabe (CLK:= GVL.xRueckgabeWert_AN_Fertig);

// Anlaufprogramm Var
mAn_Fertig := GVL.xRueckgabeWert_AN_Fertig;

// Wenn Stopp, dann muss gestoppt werden, bis wieder Start gedrückt wird
IF fStopp.Q OR NOT mAn_Fertig OR GVL.xP_allgemein THEN
    mStopp := TRUE; 
END_IF



(* Wenn Voll dann eingestelltezeit um Anlage komplett auszuschalten, wenn aus dann müssen alle Motoren ausgehen
dann Quitieren durch Stop und wieder Starten mit Start*)

fbTon_Stoermeldung ( PT := DWORD_TO_TIME (dwStoermeldung *1000));

IF (fbTonxS1.Q AND fbTonxS3.Q) OR (fbTonxS3.Q AND fbTonxS4.Q) THEN
    fbTon_Stoermeldung.IN := TRUE;
  
ELSE
      fbTon_Stoermeldung.IN := FALSE;   
END_IF

IF fbTon_Stoermeldung.Q THEN
    xStoermeldung_Sieb_Voll:= TRUE;
END_IF

IF xStoermeldung_Sieb_Voll AND fStopp.Q
    AND M1_SiebRL = FALSE
    AND M2_SiebRL = FALSE
    AND M3_SiebRL = FALSE
    AND MV1_Sieb  = FALSE THEN
      xStoermeldung_Sieb_Voll := FALSE;
END_IF

// Alles stoppen, wenn alle Motoren aus sind, dann darf wieder gestartet werden
IF mStopp and NOT GVL.xP_allgemein AND (NOT M1_SiebRL) AND (NOT M2_SiebRL) AND (NOT M3_SiebRL) AND (NOT MV1_Sieb) AND mAn_Fertig THEN
    mStopp := FALSE;
END_IF

// Start merker damit bei starten nicht nach S1 was hat nochmal Start gedrückt werden muss
IF fStart.Q or fRueckgabe.Q THEN
    mStart:= TRUE;
  
ELSIF mStopp OR mNot_Aus THEN
    mStart:= FALSE;
END_IF
// Not-Aus wurde gedrückt, dann muss zuerst mit Stopp quittiert werden
IF NOT GVL.tNot_Aus THEN
    mNot_Aus := TRUE;
ELSIF fStopp.Q AND GVL.tNot_Aus THEN
    mNot_Aus := FALSE; 
END_IF

// Not-Aus ist gedrückt oder Wahlschalter nicht mehr auf Automatik
IF mNot_Aus OR NOT mAutomatik THEN
    M1_SiebRL := FALSE;
    M2_SiebRL := FALSE;
    M3_SiebRL := FALSE;
    MV1_Sieb := FALSE;
    mAutomatik := FALSE;
    Automatik_iSchrittnummer := 40;
    Automatik_iNachvortrag := 0;
END_IF

// Hand- oder Automatikbetrieb wählen
IF GVL.mAutomatik_AP1 AND mStart THEN
    mAutomatik := TRUE;
ELSIF NOT GVL.xWahlschalter_Automatik THEN
    mAutomatik := FALSE;   
END_IF

// Automatische Schrittkette
CASE Automatik_iSchrittnummer OF
    0: // Schrittkette starten nach Bedingungen
        IF mStart AND mAutomatik AND NOT mStopp AND NOT xStoermeldung_Sieb_Voll  THEN
            Automatik_iSchrittnummer := 5;
        END_IF

    5: // hat S1 was dann Startet
        IF mStopp OR xStoermeldung_Sieb_Voll  THEN
            Automatik_iSchrittnummer := 30;   
        ELSIF fbTonxS1.Q THEN
            Automatik_iSchrittnummer := 10;
        END_IF

    10: // Zweite Schnecke an, dann Erste, also Auffüllbehälter leer
        IF mStopp OR xStoermeldung_Sieb_Voll THEN
            Automatik_iSchrittnummer := 30;   
        ELSIF fbTonS1_AVG.Q THEN 
            Automatik_iSchrittnummer := 5;
        ELSIF fbTonxS1.Q AND (fbTonS2_AVG.Q AND fbTonS3_AVG.Q) OR (fbTonS3_AVG.Q AND fbTonxS2.Q) THEN
            M2_SiebRL := TRUE;
        END_IF

        // 1 Sekunde Verzögerung, um M1 anzuschalten
        IF mStopp OR xStoermeldung_Sieb_Voll THEN
            Automatik_iSchrittnummer := 30;
        ELSIF fbTonS1_AVG.Q THEN
            Automatik_iSchrittnummer := 25;
        ELSE
            Automatik_iSchrittnummer := 15;
        END_IF

    15: // wenn beide Schnecken an sind dann warten bis irgendwas passiert
        IF mStopp OR xStoermeldung_Sieb_Voll THEN
            Automatik_iSchrittnummer := 30;
        ELSIF fbTonS1_AVG.Q OR fbTonxS3.Q THEN
            Automatik_iSchrittnummer := 25;
        ELSIF M1_SiebRL AND M2_SiebRL THEN
            Automatik_iSchrittnummer := 20; 
        END_IF

    20: // Beide Schnecken laufen, bis der Behälter voll wird oder tStop wurde gedrückt
        IF mStopp OR xStoermeldung_Sieb_Voll THEN
            Automatik_iSchrittnummer := 30;
        ELSIF fbTonS1_AVG.Q OR fbTonxS3.Q THEN
            Automatik_iSchrittnummer := 25;
        END_IF

    25: // Behälter voll oder keine Kohle da Fall.....
        M1_SiebRL := FALSE;
        IF M1_SiebRL = FALSE THEN
            fbTonM2_Aus_Verzogerung.IN := TRUE;
        END_IF
        IF fbTonM2_Aus_Verzogerung.Q THEN
            M2_SiebRL := FALSE;
            Automatik_iSchrittnummer := 27;
        END_IF

    27: // Timern zurücksetzen in Behältervoll-Fall
        IF NOT M2_SiebRL AND NOT M1_SiebRL THEN
            fbTonM1_Ein_Verzogerung.IN := FALSE;
            fbTonM2_Aus_Verzogerung.IN := FALSE;
            Automatik_iSchrittnummer := 5;
        END_IF
  
    30: // (Stopp-Fall) Schnecken nacheinander ausschalten, Timer zurücksetzen
        M1_SiebRL := FALSE;
        IF M1_SiebRL = FALSE THEN
            fbTonM2_Aus_Verzogerung.IN := TRUE;
        END_IF
        IF fbTonM2_Aus_Verzogerung.Q THEN
            M2_SiebRL := FALSE;
            Automatik_iSchrittnummer := 40;
        END_IF

    40: // Timer zurücksetzen und zum Anfang springen beim tStop
        IF NOT M2_SiebRL AND NOT M1_SiebRL THEN
            fbTonM1_Ein_Verzogerung.IN := FALSE;
            fbTonM2_Aus_Verzogerung.IN := FALSE;
            Automatik_iSchrittnummer := 0;
        END_IF
END_CASE

// Zweite Schrittkette (Nachvortrag)
CASE Automatik_iNachvortrag OF
    // Läuft in Abhängigkeit vom Vortagesbehälter
    0: // Startbedingungen
        IF mAutomatik AND mStart THEN
            Automatik_iNachvortrag := 10;
        END_IF

    10: // Behälter hat Inhalt, dann M3 und MV1 anschalten
        IF mStopp OR xStoermeldung_Sieb_Voll THEN
            Automatik_iNachvortrag := 20;
        ELSIF (fbTonxS3.Q AND fbTonxS2.Q) AND (fbTonS4_AVG.Q) THEN                           
            M3_SiebRL := TRUE;
            MV1_Sieb := TRUE;
        Automatik_iNachvortrag := 20;
        END_IF

    20: // Stopp alles und zurück zur Anfang
        IF mStopp OR xStoermeldung_Sieb_Voll THEN
            M3_SiebRL := FALSE;
            MV1_Sieb := FALSE;
            Automatik_iNachvortrag := 0;
        ELSIF fbTonS2_AVG.Q OR fbTonxS4.Q THEN
            M3_SiebRL := FALSE;
            MV1_Sieb := FALSE;
            Automatik_iNachvortrag := 10;
        END_IF
END_CASE
so sieht mein FB aus

Edit:
Ich habe in meinem Code viele sinnlose Dinge entdeckt. Ich werde diese beheben und mich dann wieder melden.

Danke euch allen!
 
Zuletzt bearbeitet:
Also generell würde ich Schrittketten nie in SCL programmieren.Ist aber Geschmackssache.
Gerade wenn jetzt weiterschaltbedingungen nicht kommen, kann man mit Max-Zeiten den Schritt auch gut überwachen und pro Schritt eine
Zeitüberwachung programmieren.Zum Thema Flanken in Schrittketten.
Wenn Flanken 1 Zyklus anstehen und die Weiterschaltbedingungen stimmen, springen sie in einem Zyklus in mehrere Schritte, was sicher nicht im
Sinne des Anwenders ist.Da muss man ziemlich aufpassen.Zeiten und Zähler,Flanken ausserhalb der Schrittkette programmieren.
Wenn man probleme umgehen will, erst mal eine Mindestlaufzeit(Wartezeit) einführen.
Ich schreibe das sowieso immer mit R/S Befehlen in FUP.
Um ehrlich zu sein, halte ich von diesen if,else Konstrukten nicht soviel in SK.
Dafür ist SCL nicht ideal.
 
Für mich sind in dem SCL-Code zu viele Zuweisungen nur bei IF...THEN. Fast eine Orgie ... Da hätte ich keine Lust zu suchen, ob die Logik komplett ist, unter welchen Bedingungen unerwartet gar keine Zuweisung stattfindet und ob auch immer zu einem Set auch ein Reset vorhanden ist ...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Erstens das und zweitens ist es nicht anschaulich.Wenn ich eine Schrittkette zu Fuß programmiere sehe ich wo ich bin.
Ideal ist natürlich Graph 7 da ist aber der Overhead sehr gross.
Trotzdem würrde ich sagen wenn man das regelmässig macht und groessere Ketten hat und Schrittanwahl und Schrittweiterschalten
Automatik und Hand braucht, würde ich mir hier mal ein Vorlagekonstrukt schaffen.
Das lohnt sich dann schon.Auch die Übergangsmerker kann man schon einfügen und hat so ein Vorlageprojekt.
Außerdem kann man wartezeiten und überwachungseiten parametrieren.Wo ich abrate ist von den vielen Konstrukten wo es da gibt.
Ich würde wirklich nur die Schrittmerker auf die Ausgänge zuweisen.(nicht setzen)
 
@sps_klassik : CASE ist eigentlich ein guter Weg um in SCL Schrittketten umzusetzen ... und läßt sich auch sehr schön debuggen ... wenn man es denn richtig macht. Aber natürlich, wie du schon schreibst, ist das Geschmackssache. Ich mag z.B. GRAPH7 nicht (oder in CodeSys heißt es, so glaube ich, AS )

@der_NooB : Ich muss Harald hier Recht geben - so einen Baustein würde ich auch nicht haben wollen und auch keine Fehler drin suchen wollen. Mit einer (? vernünftigen ?) Schrittketten-Umsetzung hat das wenig zu tun. Ich würde dir mal folgenden Vorschlag machen - das bringt dich wahrscheinlich gleich 3 Schritte weiter : Mal dir den Ablauf deiner Schrittkette mal grafisch auf und schreib dann auch an jeden deiner Schritte was da passieren so und wie. Wenn du bei deinem Konstrukt das noch hingemalt bekommst UND da selber dann noch durchsteigst dann "Hut ab".

Vielleicht mal konstuktiv/destruktiv : was du innerhalb einer Schrittkette machen solltest (mit IF !!!) ist auf den nächsten Schritt, der kommen soll, umzuschalten. Was du nicht machen solltest ist dann innerhalb des Schrittes noch Verknüpfungen einzubauen, die dann vielleicht oder vielleicht auch nicht, irgebdwelche Aktionen auslösen. Ich denke mal, dass das dein Haupt-Problem überhaupt sein wird ... und möglicherweise ist das dann auch gleich der Unterschied zwischen Simulation und realem Lauf.
Und nochmals zur Simulation : die würde ich nur verwenden um syntaktische Fehler im Code zu finden.
 
Ich bin generell kein Fan von SCL sofern es Logik betrifft.Und auch in Schrittketten braucht man Logik und Zeiten.
Du schreibst es ja selbst, mal dir den Verlauf auf.
Wenn das die anschaulichste Art ist, macht es eigentlich keinen Sinn, es in SCL wieder neu umzusetzen.
Für Formeln und Arrays und Berechnungen nutze ich SCL, für alles andere nicht.Aber wie gesagt jeder wie er mag.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@der_NooB : Ich muss Harald hier Recht geben - so einen Baustein würde ich auch nicht haben wollen und auch keine Fehler drin suchen wollen. Mit einer (? vernünftigen ?) Schrittketten-Umsetzung hat das wenig zu tun. Ich würde dir mal folgenden Vorschlag machen - das bringt dich wahrscheinlich gleich 3 Schritte weiter : Mal dir den Ablauf deiner Schrittkette mal grafisch auf und schreib dann auch an jeden deiner Schritte was da passieren so und wie. Wenn du bei deinem Konstrukt das noch hingemalt bekommst UND da selber dann noch durchsteigst dann "Hut ab".

Vielleicht mal konstuktiv/destruktiv : was du innerhalb einer Schrittkette machen solltest (mit IF !!!) ist auf den nächsten Schritt, der kommen soll, umzuschalten. Was du nicht machen solltest ist dann innerhalb des Schrittes noch Verknüpfungen einzubauen, die dann vielleicht oder vielleicht auch nicht, irgebdwelche Aktionen auslösen. Ich denke mal, dass das dein Haupt-Problem überhaupt sein wird ... und möglicherweise ist das dann auch gleich der Unterschied zwischen Simulation und realem Lauf.
Und nochmals zur Simulation : die würde ich nur verwenden um syntaktische Fehler im Code zu finden.
Moin, du hast Recht ich hatte mehrere IF Anweisung in einem Schritt was zu Konflikte führen kann!
Also so sieht jzt mein Programm aus falls Interesse besteht ^_^

Code:
// Automatische Schrittkette
CASE Automatik_iSchrittnummer OF
    0: // Schrittkette starten nach Bedingungen
        IF mStart AND mAutomatik AND NOT mStopp AND NOT xStoermeldung_Sieb_Voll  THEN
            Automatik_iSchrittnummer := 5; 
        END_IF

    5: // hat S1 was dann Startet
        IF mStopp OR xStoermeldung_Sieb_Voll  THEN
            Automatik_iSchrittnummer := 25;     
        ELSIF fbTonxS1.Q THEN
            Automatik_iSchrittnummer := 10;
        END_IF

    10: // Zweite Schnecke an, dann Erste, also Auffüllbehälter leer
        IF mStopp OR xStoermeldung_Sieb_Voll THEN
            Automatik_iSchrittnummer := 25;     
        ELSIF fbTonS1_AVG.Q THEN   
            Automatik_iSchrittnummer := 5;
        ELSIF fbTonxS1.Q AND fbTonS3_AVG.Q THEN
            M2_SiebRL := TRUE;
        Automatik_iSchrittnummer := 15;
        END_IF     
  
    15: // wenn beide Schnecken an sind dann warten bis irgendwas passiert
        IF mStopp OR xStoermeldung_Sieb_Voll THEN
            Automatik_iSchrittnummer := 25;
        ELSIF fbTonS1_AVG.Q OR fbTonxS3.Q THEN
            Automatik_iSchrittnummer := 25;
        ELSIF M1_SiebRL AND M2_SiebRL THEN
            Automatik_iSchrittnummer := 20;   
        END_IF

    20: // Beide Schnecken laufen, bis der Behälter voll wird oder tStop wurde gedrückt
        IF mStopp OR xStoermeldung_Sieb_Voll OR
         fbTonS1_AVG.Q OR fbTonxS3.Q THEN
            Automatik_iSchrittnummer := 25;
        END_IF
      
                             (*************** Hier fängt Ausschaltverfaheren***********)
                    
    25: // Behälter voll oder keine Kohle da Fall.....
      
     IF NOT M1_SiebRL THEN
            Automatik_iSchrittnummer := 27;
        END_IF

    27: // Timern zurücksetzen in Behältervoll-Fall
        IF NOT M2_SiebRL AND NOT M1_SiebRL THEN
            Automatik_iSchrittnummer := 30;
        END_IF
    
    30: // (Stopp-Fall) Schnecken nacheinander ausschalten, Timer zurücksetzen
        IF mStopp OR xStoermeldung_Sieb_Voll THEN
            Automatik_iSchrittnummer := 0;
        ELSE
         Automatik_iSchrittnummer := 5;
        END_IF

END_CASE

// Zweite Schrittkette (Nachvortrag)
CASE Automatik_iNachvortrag OF
    // Läuft in Abhängigkeit vom Vortagesbehälter
    0: // Startbedingungen
        IF mAutomatik AND mStart THEN
            Automatik_iNachvortrag := 10;
        END_IF

    10: // Behälter hat Inhalt, dann M3 und MV1 anschalten
        IF mStopp OR xStoermeldung_Sieb_Voll THEN
            Automatik_iNachvortrag := 20;
        ELSIF (fbTonxS3.Q AND fbTonxS2.Q) AND (fbTonS4_AVG.Q) THEN                             
            M3_SiebRL := TRUE;
            MV1_Sieb := TRUE;
        Automatik_iNachvortrag := 20;
        END_IF

    20: // Stopp alles und zurück zur Anfang
        IF mStopp OR xStoermeldung_Sieb_Voll THEN
            M3_SiebRL := FALSE;
            MV1_Sieb := FALSE;
            Automatik_iNachvortrag := 0;
        ELSIF fbTonS2_AVG.Q OR fbTonxS4.Q THEN
            M3_SiebRL := FALSE;
            MV1_Sieb := FALSE;
            Automatik_iNachvortrag := 10; 
        END_IF
END_CASE
 
Wichtig ist eigentlich, dass du innerhalb der Schrittkette, also der CASE-Abfrage, nicht noch irgendwelche bedingten Aktionen drin hast sondern dass du hier nur die Bedingungen abfragst, die dich zum jeweils nächsten Schritt bringen. Das, was der Schritt letztlich bewirken soll, sollte im Nachgang, also außerhalb der Schrittkette passieren. So kannst es dir dann eigentlich nicht passieren, dass es die von dir genannten Diskrepanzen gibt ...
 
Zurück
Oben