Step 7 Frage zu Flankenauswertung von Tastern

Neurorancer

Level-2
Beiträge
572
Reaktionspunkte
4
Zuviel Werbung?
-> Hier kostenlos registrieren
Guten Tag,

ich erstelle gerade ein kleines Programm in SCL.

Das Programm soll das Drücken eines Tasters erkennen.

Ich habe bereits die Softwäremäßige-Lösung des Problems gesehen,
bei der der "Peglel" des Einganges, an dem der Taster angeschlossen wird
mittels einer IF-Abfrage überwacht und ausgewertet wird.

Dies ist aber keine saubere Lösung, da der Zustand durch "Polling" abgefragt wird.
Und es kann theoretisch passieren, dass der Taster gedrückt wird, bevor die IF-Bedingung greift.

In FUB verwendet man einen Flip-Flop für diese Aufgabe aber auch hier ist es ja so, dass die Funktionen zyklisch abgearbeitet werden.
Und auch hier kann es theoretisch passieren, dass man eine Flanke verpasst.

Andererseits ist die Zykluszeit sehr kurz (ms), sodass man die Flanke schon abfangen kann.

Bei der µController Programmierung habe ich Interrupts verwendet,
eie macht ihr das bei der SPS?
 
Du kannst ja wenn du einen Eingang hast der einen Prozessalarm auslösen kann damit die Flankenauswertung machen. Aber üblicherweise ist die normale Flankenauswertung im OB1 Zyklus mehr als ausreichend um eine von einem Menschen gedrückte Taste erkennen zu können.

Damit die If Abfrage nicht zuschlägt, müsste der Tastenimpuls kürzer als die Zykluszeit sein und dazu noch ausserhalb eines Zykluswechsels passieren.

mfG René
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Dies ist aber keine saubere Lösung, da der Zustand durch "Polling" abgefragt wird.
Polling heißt nicht automatisch dass es unsauber ist.

Und es kann theoretisch passieren, dass der Taster gedrückt wird, bevor die IF-Bedingung greift.

In FUB verwendet man einen Flip-Flop für diese Aufgabe aber auch hier ist es ja so, dass die Funktionen zyklisch abgearbeitet werden.
Und auch hier kann es theoretisch passieren, dass man eine Flanke verpasst.
Nur wenn das Ereignis (also der Tastendruck) kürzer dauert als 1 Zyklus oder der Eingangs-Filterzeit.
Was für die 90% (sicher nicht für einen manuellen Taster) der Signale nicht eintritt.

Grundsätzlich ist dir aber schon klar wir die SPS arbeitet, oder?
Stichwort "Prozessabbild der Ein/Ausgänge" bzw. "Zustände der Ein/Ausgänge ändern sich während dem Zyklus nicht"

Bei der µController Programmierung habe ich Interrupts verwendet,
Nun, man könnte. Aber wozu?

Der Vorteil am Polling und am zyklischem Programmablauf ist ja dass es einfacher und besser nachvollziehbar arbeitet.
Wenn du >1000E/As hast, dann hättest du auch hunderte Interrupts die gleichzeitig feuern...
 
Zuletzt bearbeitet:
Ich habe jetzt versucht ein Programm zur Flankenauswertung zu erstellen,
leider hackt es hier noch. Ich glaube es liegt daran, dass ich den Umgang mit den Variablen in Step7 nicht ganz verstanden habe.

Könnt Ihr bitte schauen was ich verkehrt mache?

Ich habe drei Variablen:
"taster_1" ist der Eingang der SPS %I136.0 Typ: bool
"status_taster_1" ist %MB1
"taster_1_gedr" ist %MB2

Zum Ablauf: Wenn "taster_1" gedrückt wird, wird die Variable "status_taster_1" gesetzt.
Beim nächsten Zyklus wird geprüft ob "taster_1" rückgesetzt ist und "status_taster_1" gesetzt ist.
Dann wird eine weitere Variable aktiv: "taster_1_gedr"=1 und "status_taster_1" wrd zurückgesetzt.

Somit kann ich anhand der Variablen "status_taster_1" erkennen ob die Taster gedrückt wurden ist.

Code:
//Tastendruck erkennen
IF "taster_1" = TRUE THEN
    "status_taster_1" := 1;
ELSIF "taster_1" = FALSE AND "status_taster_1" = 1 THEN
    "status_taster_1" := 0;
    "taster_1_gedr" := 1;
END_IF;


Code:
IF "taster_1_gedr" = 1 THEN
    "out_1" := 1;
    //#umdrehungszahl := #umdrehungszahl + 1000;
    "var_umdrehungszahl" :=  "var_umdrehungszahl" + INT#2000;
    "taster_1_gedr" := 0;
END_IF;

Das funktioniert nur ein mal. Beim nächsten Klicken wird die Geschwindigkeit nicht erhöht.
Mir ist aufgefallen, dass beim drücken und halten des Tasters die Geschwindigkeit auf 255 von 2000
zurückgeht beim loslassen aber wieder 2000 wird.

Das ist komisch.

Ich vermute es liegt an der Art wie ich die Variablen verwende. Ich würde gerne temporäre Variablen verwenden,
das Problem ist, dass diese beim jedem Zyklus mit dem Anfangswert überschrieben werden.
Übrigens: Die Startwerte der von mir verwendeter Variablen habe ich in OB100 festgelegt.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das liegt an den Variablen.

Habe "taster_1_gedr" auf %MB5 umgestellt und bei jedem Drücken ändert sich die Umdrehungszahl. Erstmal kleines Stückchen schneller und dann zweimal langsamer.
Und das wiederholt sich. Das sieht nach einem Überlauf aus.
Ich muss temporäre Variablen verwenden, aber wie stelle ich deren Wert ein, ohne dass sie jedes mal auf den Anfangswert zurückgehen?
Siehe #umdrehungszahl im Code

Code:
//Senden eines Wertes an SDS5000


//#umdrehungszahl := 1000;


//Tastendruck erkennen
IF "taster_1" = TRUE THEN
    "status_taster_1" := 1;
ELSIF "taster_1" = FALSE AND "status_taster_1" = 1 THEN
    "status_taster_1" := 0;
    "taster_1_gedr" := 1;
END_IF;




IF "taster_1_gedr" = 1 THEN
    "out_1" := 1;
    //#umdrehungszahl := #umdrehungszahl + 1000;
    "var_umdrehungszahl" :=  "var_umdrehungszahl" + INT#2000;
    "taster_1_gedr" := 0;
END_IF;


//"n_soll" := #umdrehungszahl;
"n_soll" := "var_umdrehungszahl";
"n_ist" := "n_ist_holen_aus_sdsd5000";
 
Sicher nicht temp. Und der Rest ist ebenfalls etwas krude. Würde es dir was ausmachen schnell im forum nach Flanke scl zu suchen?


Sent from my iPhone using Tapatalk
 
Ich habe jetzt versucht ein Programm zur Flankenauswertung zu erstellen,
leider hackt es hier noch. Ich glaube es liegt daran, dass ich den Umgang mit den Variablen in Step7 nicht ganz verstanden habe.

Könnt Ihr bitte schauen was ich verkehrt mache?

Ich habe drei Variablen:
"taster_1" ist der Eingang der SPS %I136.0 Typ: bool
"status_taster_1" ist %MB1
"taster_1_gedr" ist %MB2

Zum Ablauf: Wenn "taster_1" gedrückt wird, wird die Variable "status_taster_1" gesetzt.
Beim nächsten Zyklus wird geprüft ob "taster_1" rückgesetzt ist und "status_taster_1" gesetzt ist.
Dann wird eine weitere Variable aktiv: "taster_1_gedr"=1 und "status_taster_1" wrd zurückgesetzt.

Somit kann ich anhand der Variablen "status_taster_1" erkennen ob die Taster gedrückt wurden ist.
...
Warum muss man das Fahrrad unbedingt neu erfinden?
;)

Flanken ermittelt man normalerweise dadurch, dass man den Zustand des aktuellen mit dem Zustand im letzten Zyklus vergleicht.
Bei boolschen Signalen (z.B. Taster):
Letzter Zyklus 0 UND dieser 1 = positive Flanke = Taster wurde gedrückt
Letzter Zyklus 1 UND dieser 0 = negative Flanke = Taster wurde losgelassen
(Beides 0 oder beides 1 = Zustand hat sich gegenüber letztem Zyklus nicht verändert)
Nach diesem Vergleich wird der aktuelle Zustand als Zustand letzter Zyklus (#TasterOld = statisch) gespeichert. Die detektierte Flanke selbst (#TasterFP und/oder #TasterFN) kann temporär sein, da sie in jedem Zyklus neu bestimmt wird.

Als Code:
Code:
#TasterFP  := #Taster    AND Not #TasterOld        // Taster (neu) gedrückt
#TasterFN  := #TasterOld AND Not #Taster           // Taster (neu) losgelassen
#TasterOld := #Taster;                             // Zustand für Vergleich im nächsten Zyklus speichern

IF #TasterFP THEN
   ...;
END_IF;
#TasterOld, #TasterFP bzw. #TasterFN sind dann logischerweise auch als Bool deklariert und nicht als Byte.


Hier gibt's noch 'ne schöne FAQ zu dem Thema Flankenauswertung, wenn auch (@Harald, noch?) ohne SCL.



PS: Boolsche Variablen müssen für eine Bedingung nicht mit einem Vergleich geprüft werden, der als Ergebnis TRUE oder FALSE ausgibt, da diese Variablen selber schon TRUE oder FALSE als Ergebnis enthalten. ;)
 
Ich bleibe lieber bei meinem Programm,
das funktioniert mittlerweile.
Das Problem war die Variable "var_umdrehungszahl"
habe diese temporär gemacht mit einem Vordefinierten Wert und
jetzt klappt alles.

Ich muss mich mehr mit den Variablen auseinander setzen.
 
Die Variable hast Du temporär gemacht? Poste mal Deinen Code, ich fürchte, Du machst gerade einen großen Fehler und hast Glück, dass es läuft.
 
Code:
//Tastendruck erkennen
IF "taster_1" = TRUE THEN
    "status_taster_1" := 1;
ELSIF "taster_1" = FALSE AND "status_taster_1" = 1 THEN
    "status_taster_1" := 0;
    "taster_1_gedr" := 1;
END_IF;

IF "taster_1_gedr" = 1 THEN
    "out_1" := 1;
    //#umdrehungszahl := #umdrehungszahl + 1000;
    "var_umdrehungszahl" :=  "var_umdrehungszahl" + INT#2000;
    "taster_1_gedr" := 0;
END_IF;
Das Zuweisen/Setzen/Rücksetzen von Variablen an verschiedenen verteilten Stellen bei verschieden formulierten IF..THEN macht den Code extrem unübersichtlich und unverständlich.
Mache doch besser einfache Logik und IF..THEN nur da wo es unbedingt notwendig ist:
Code:
"taster_1_gedr" := "taster_1" AND NOT "status_taster_1"; //"gedrückt" nur bei steigender Flanke
"status_taster_1" := "taster_1";                         //Zustand "taster_1" merken

IF "taster_1_gedr" THEN                                  //wenn steigende Flanke taster_1
  "var_umdrehungszahl" := "var_umdrehungszahl" + 2000;   //dann Solldrehzahl erhöhen
END_IF;

Harald
 
Zurück
Oben