Flankenauswertung

  • Hallo,


    ich hab schon wieder Fragen. Und immer noch zu der IRC5.
    wie kann man am einfachsten eine Flankenauswertung machen, bei mir sieht es einwenig unübersichtlich aus, Funktion ist zwar da nur hätte ich es gerne einwenig komfortabler.


    VAR num nFP:=0;
    VAR num nM1:=0;


    PROC main()
    !Flanke Positiv
    IF diS10=1 AND nM1=0 THEN
    nFP:=1;
    nM1:=1;
    ELSEIF diS10=1 AND nM1=1 THEN
    nFP:=0;
    ELSEIF diS10=0 THEN
    nM1:=0;
    ENDIF
    ENDPROC



    Macht ihr das villeicht mit einem Systemmodul? :kopfkratz:


    MfG heini

  • ANZEIGE
  • Hallo heini0707,


    also ich würde versuchen so etwas über einen Interrupt zu lösen. Die sind nämlich genau für solche Anwendungen gedacht (u.a.)...


    Lies Dir doch mal zu diesem Thema die Doku durch, ansonsten (bei Problemen) melde Dich nochmal.
    Habe im Augenblick aber nur wenig Zeit zum Schreiben :(


    Gruß
    Rainer

  • Hallo heini0707,


    hier mal einige Gedanken/Hinweise zu der o.g. Problematik (in Kurzfassung ;)):



    1. Prinzipiell solltest Du für die o.g. Variablen (nFP, nM1) boolsche(=logische=True/False) Datentypen wählen und nicht NUM. Ist erstens nicht im Sinne des Erfinders und zweitens brauchst Du dann nicht ständig auf =0 oder =1 abfragen...


    2. Du willst eine Flanke erkennen, in Deinem Beispiel eine Positive, d.h. einen Übergang(!) von 0 auf 1 (LOW auf HIGH). Wenn ich mal unterstelle, dass die Variable nFP (FP=Flanke Positiv ?) diesen Zustandsübergang(!) speichern soll, wird das aber nicht funzen wenn der Signaleingang diS10 beim Start von Main() bereits HIGH ist. Dann wird nämlich nFP:=1 d.h. eine positive Flanke signalisiert, obwohl ein Übergang LOW auf HIGH nie(!!!) stattgefunden hat (diS10 war ja möglicherweise vorher nie 0 bzw. LOW).
    :ks:


    3. Wenn es denn unbedingt sein müsste, könnte man das auch etwa so programmieren (ungetestet, ohne Gewähr!)


    Wenn nur eine Flankenart gebraucht wird kann natürlich der andere Teil entfallen.
    Der Nachteil dieser Methode bleibt allerdings gleich: kurze Impulse werden u.U. nicht oder nur unzuverlässig erkannt!


    4. Wie bereits gesagt, die beste Methode bleibt der Interrupt. Flanken werden hierbei deutlich schneller und zuverlässiger per Hardware erkannt, der Aufwand geht allerdings auch über einen simplen Dreizeiler hinaus...


    Gruß
    Rainer

  • Hallo,


    wau :danke:, das es so kurz wird hätte ich auch nicht gedacht :danke:.


    Das mit numerischen Variablen ist meine Art zu programmieren, bei Fanuc oder normale CNC gibt es nur numerische Var., deswegen bin ich gewonnt die auch zu nutzen, hat auch Vorteile ich kann die Var. auch auf 2 setzen, bei mir würde das heißen die Funktion überspringen, brauch nicht noch extra Variable dazu, ist bei einigen Steuerungen die Anzahl zu mager 32 oder 100, aufmotzen kostet Geld, Kunde ist nicht immer bereit dafür zu zahlen.


    Das mit dem Signalzustand davor habe ich einfach verschlampert, danke für den Hinweis.


    So jetzt zum XOR, ich hab die Funktion noch nie kapiert, na ja mir hat es noch keiner richtig sagen können wie ich die Funktion gescheid nutzen kann, ich weß zwar wörtlich was es bedeutet aber nutzen kann ich die noch nicht.


    XOR - Exklusive oder


    bPosEdge:=(TestDI(diS10) XOR bPrevS10) AND (NOT bPrevS10);


    heißt das etwa wenn diS10=1 dann ist es egal welchen Wert bPrevS10 hat :kopfkratz: ?


    MfG heini

  • Hallo,


    fast vergessen.


    das mit der Ansprechzeit ist nicht so wichtig (in dem Fall), es werden nur Tasten abgefragt, es ist dann egal ob der Kunde viertel Sekunde mehr oder weniger drücken muss. :ylsuper:


    MfG heini

  • Hallo heini0707,


    [...]
    heißt das etwa wenn diS10=1 dann ist es egal welchen Wert bPrevS10 hat :kopfkratz: ?
    [...]


    Das XOR liefert dann TRUE wenn diS10 und bPrevS10 unterschiedliche(!) Werte/Zustände haben, also
    diS10=0 und bPrevS10=1 oder diS10=1 und bPrevS10=0.
    Damit kriegt man raus ob der Signalzustand zwischen der ersten und zweiten Zeile in Main() gewechselt hat, weiß aber noch nicht in welche Richtung (pos/nach oben oder neg/nach unten).
    Wenn der vorherige Zustand (bPrevS10) LOW war und der Zustand gewechselt hat, dann muß die Flanke logischerweise aufsteigend gewesen sein, deswegen das

    Code
    AND (NOT bPrevS10);


    um herauszufinden ob der vorherige Zustand 0/LOW war.


    Wie oben schon gesagt: mit dem XOR kriegst du raus, ob der Zustand zwischen den Zeilen
    bPrevS10 := TestDI(diS10);
    und
    bPosEdge:=(TestDI(diS10) XOR bPrevS10) AND (NOT bPrevS10);
    gewechselt hat.
    Ob das alles so funzt wie gewünscht, hängt natürlich auch stark davon ab ob und was du zwischen diesen Zeilen noch programmierst, bzw. was überhaupt noch im Rest von Main() passiert, deswegen immer noch meine Empfehlung: nimm Interrupt :supi:


    Gruß
    Rainer

    Einmal editiert, zuletzt von rmac ()

  • Hallo rmac,


    d.h. wenn ich
    bPrevS10 := TestDI(diS10);
    hinter
    bPosEdge:=(TestDI(diS10) XOR bPrevS10) AND (NOT bPrevS10);
    packe, habe die Zustandsänderung vom ganzen Zyklus?


    Ich habe vergessen zu sagen, fällt mir gerade ein, dass es ein Semistatischer Task ist, soll SPS änlich ablaufen. Hoffe das die Zykluszeit unter 0,2s liegen wird, die Programme sind schon verdammt groß geworden und werden noch größer.


    MfG heini

  • Hallo heini07070,


    Wenn du
    bPrevS10 := TestDI(diS10);
    hinter
    bPosEdge:=(TestDI(diS10) XOR bPrevS10) AND (NOT bPrevS10);
    packst, hast du erstmal wieder das gleiche Problem wie bei deiner Lösung:
    bPrevS10 ist bei der ersten Auswertung (bPosEdge:=...) nicht definiert. :???:
    Eine "echte" und verlässliche Zustandsänderung innerhalb bzw. während eines Zyklus kriegst du mit dieser Methode u.U. nicht hin, deswegen ja der Interrupt 8)


    Lass es mich mal mit anderen Worten sagen was die zwei Zeilen da machen:
    um den Tastendruck eines Bedieners damit ermitteln zu können, dürfte der Bediener
    1. die Taste zum Zeitpunkt der Ausführung von bPrevS10 := TestDI(diS10); NICHT drücken und
    2. bei der Ausführung von bPosEdge:=(TestDI(diS10) XOR bPrevS10) AND (NOT bPrevS10); die Taste gedrückt halten, nicht mehr und nicht weniger !!!


    Angenommen die Bedingung 1 ist erfüllt und zwischen der Ausführung dieser beiden Zeilen liegen 10 Sekunden, dann kann dein Anwender in dieser Zeit auf der Taste ein Schlagzeugsolo spielen, solange Bedingung 2 zu diesem Zeitpunkt nicht erfüllt ist, ist es dem Programm völlig wurscht.


    Ich weiß ja nicht genau was mit dem Tastendruck ausgelöst oder unterbrochen werden soll. Da gibt es je nach Anwendungsfall vielleicht auch alternative Programmideen.
    Wenn die Taste z.B. zum Starten/Freigabe eines weiteren Ablaufs verwendet werden soll könnte man das auch so (oder ähnlich) machen:


    WaitDI diS10,0; ! Signal muß erst LOW werden, darf also nicht gedrückt gehalten werden
    WaitDI diS10,1; ! Wenn gedrückt geht's los ...


    Zur Unterbrechung würde ich aber wahrscheinlich wieder einen Interrupt 8) nehmen, aus Sicherheitsgründen...


    Gruß
    Rainer

  • Hallo rmac,


    versteh mich nicht falsch, Inrerrupt hin oder her, ist gut, dass es die gibt.
    Nur will ich einen SPS änlichen Aufbau machen und es ist sicherlich möglich (meine ich) :wallbash:.


    Was ist wenn ich einen virtuellen Ausgang nehme (ist halt besser als Variable da bei Restart auf Null desetzt wird) und so Programmiere:


    Code
    bPosEdge:=(TestDI(diS10) XOR bPrevS10) AND (NOT bPrevS10);
    dovS10:= TestDI(diS10);


    Ab jetzt ist es doch definiert, oder :kopfkratz: ?


    MfG heini

  • Hallo heini0707,

    Code
    bPosEdge:=(TestDI(diS10) XOR bPrevS10) AND (NOT bPrevS10);
    dovS10:= TestDI(diS10);


    Ab jetzt ist es doch definiert, oder :kopfkratz: ?


    Hmmm, bPrevS10 wird doch dadurch auch nicht definiert , oder ?



    Was ist wenn ich einen virtuellen Ausgang nehme (ist halt besser als Variable da bei Restart auf Null desetzt wird)


    Abhängig von der Startart werden Daten (Variablen etc.) auch auf ihren Initialisierungswert zurückgesetzt (siehe Doku), dafür muß man nicht unbedingt einen (virt.) Ausgang nehmen.



    Nur will ich einen SPS änlichen Aufbau machen und es ist sicherlich möglich (meine ich) :wallbash:.


    jo, das ist es bestimmt.
    Es gibt aber immer (fast) unendlich viele Möglichkeiten ein Programm zu schreiben, jeweils mit jeder Menge kleiner und großer Vor- und Nachteile. Insofern möchte ich es gerne vermeiden, ohne sachgerechte Kenntnis der Anwendung, dir einen Tipp in die falsche Richtung zu geben. Du hast nachher ein Problem und bist sauer weil der Ansatz falsch war...


    Gruß
    Rainer

  • Hallo rmac,


    ich habe es so gemeint:

    Code
    bPosEdge:=(TestDI(diS10) XOR dovS10) AND (NOT dovS10);
    dovS10:= TestDI(diS10);


    aber nicht umgesetzt. :oops:


    Jetzt müsste es aber tun :huh:


    MfG heini

  • Probier doch aus ob es für deine Zwecke/Belange ausreicht und funzt...
    (unter Beachtung aller Dinge die ich schon in den vorherigen Postings geschrieben habe)


    Wenn du Main() als Endlos-Schleife betreibst und diese lediglich aus den zwei Zeilen besteht, spielt es (fast) keine Rolle welcher Befehl zuerst kommt, es sind dann eigentlich zwei Zeilen die wechselseitig aufgerufen werden, wobei das Problem bleibt, dass eine gedrückte Taste zu Beginn des Programmstarts als steigende Flanke gewertet werden würde, wie in deinem ursprünglichen Ansatz...


    Probieren geht über Studieren (solange du keinen Schrott produzierst...) ;)


    Gruß
    Rainer

  • Hallo,


    rmac, :danke: für deine Hilfe :danke: , funktioniert herforagend.



    Durch die Vorbelegung, die beim Restart geschieht, sind die Variablen schon vorbelegt.
    => Funktion erfüllt. (was will man eigentlich mehr)


    :danke: :ylsuper: :ylsuper: :ylsuper: :ylsuper: :danke:


    MfG heini

  • Hallo,


    das kann ich selbst kaum glauben, aber ich habe schon wieder ein Problem (ich meine dass ich die Probbleme irgend wie magisch anziehe :().


    Wie kann ich einem boolschen Operanden den Wert vom Ausgang zuweisen :huh: ,die beiden Varianten habe ich ausprobiert, funktioniert nicht.

    Code
    bTest:=DOutput(do12);
    bTest:=do12;


    Dann kommt der Fehler 101 Typenkonflikt bei erwartetem Typ bool und gefundenem Typ dionum.


    Mit Eingängen funktioniert das aber

    Code
    bTest:=Test(diS10);


    Ich finde auch nichts in den Büchern. :hilfe:


    MfG heini

  • Hallo heini0707,


    also eine Funktion dafür kenne ich auch nicht, aber in deiner ursprünglichen Flankenerkennungsmethode hast du was Brauchbares schon (in ähnlicher Form) verwendet. Kann man z.B. so machen:

    Code
    bTest:=(diS10=1);


    D.h. du weist der Variablen bTest den Wert des boolschen/logischen Ausdrucks diS10=1 zu. Ist das Gleiche wie im IF-Befehl...
    Zur besseren Lesbarkeit solltest du aber die vordefinierten Konstanten LOW/HIGH verwenden:

    Code
    bTest:=(diS10=HIGH);


    dann ist das schon auf den ersten Blick erkennbar :zwink:


    Dann habe ich (wiedermal) was zum Klugscheissen :ks: :

    Zitat

    [...]Wie kann ich einem boolschen Operanden den Wert [...] zuweisen [...]


    Operanden nennt man die Beteiligten(!) an einer Operation, in unserem Beispiel wären diS10 und die Konstante HIGH die Operanden bei der Vergleichsoperation mit = als Operator.
    bTest ist aber (nur) eine Variable der ein Wert zugewiesen wird. Würde man also nicht als Operand bezeichnen... :zwink:


    Gruß
    Rainer

    Einmal editiert, zuletzt von rmac ()

Hilfe und Support für ABB Roboter Programmierung, Konfiguration, Inbetriebnahme finden Sie hier im ABB Roboter Forum. ABB Rapid Programmierung ist einfach, die Roboterforum Community hilft sehr gerne.

Erstelle ein Benutzerkonto oder melde dich an um zu kommentieren

Du musst ein Benutzerkonto haben um einen Kommentar hinterlassen zu können

Benutzerkonto erstellen
Neues Benutzerkonto für unsere Community erstellen. Geht einfach!
Neues Benutzerkonto erstellen
Anmelden
Du hast bereits ein Benutzerkonto? Melde dich hier an.
Jetzt anmelden