Ein digitaler SPS-Eingang, an dem ein prellender Kontakt eines Relais angeschlossen ist, soll entprellt werden.
Die Aufgabe soll via Software realisiert werden. Zusätzlich soll die Wirkung der Entprellung veranschaulicht werden.
Eine passende Test-Schaltung für diese Aufgabe könnte dann so aussehen:
Um die Auswirkungen der Entprellung besser zu verdeutlichen wurde die Schaltung um einige Komponenten erweitert.
Neben dem prellenden Kontakt (K1 auf E0.0) kommen noch drei Schalter hinzu. Ein Reset-Schalter (S1), Start-Schalter (S3) und ein
Schalter (S2), mit dem die Software-Entprellung aktiviert bzw. deaktiviert werden kann. Zusätzlich wird noch ein Anzeige-Gerät
verwendet. Die Spule des Relais wird direkt von der SPS angesteuert.
Fertig aufgebaute Schaltung sieht dann so aus:
Testschaltung
Der prellende Kontakt ist an dem Eingang E0.0 angeschlossen. Um den Prelleffekt besser zu erkennen, wird der
Eingang als ein schneller Eingang (schneller Zähler HSC, hier 100kHz) in der SPS konfiguriert. Mit diesem Zähler werden die Prellungen
des Kontaktes gezählt und angezeigt. Der Wert wird in der Variable "Zählerstand_Eingang_1" festgehalten. Gleichzeitig werden auch
die Schaltvorgänge des Relais gezählt ("Zählerstand_Ausgang"), damit der Vergleich der Anzahl der Impulse möglich ist.
Würde an dem Schaltkontakt keine Prellung entstehen, würden die beiden Zähler bei jedem Einschalten des Relais um 1 erhöht und
stets gleich bleiben.
Auf dem kurzen Video (Teil 1) kann man beobachten, dass das Verhalten ganz anders ist. Bei jedem Schaltvorgang erhöht sich die
Zahl der Impulse, die von dem Eingang kommen, sprunghaft. Der Kontakt prellt.
Wenn man die Zähler aufmerksam beobachtet, stellt man fest, dass auch beim Ausschalten des Relais (seltener) Prell-Signale
registriert werden.
Die kurze Entprellungssequenz im Programm beinhaltet einen Timer, der gestartet wird, wenn eine positive oder negative Flanke
am Eingang E0.0 erkannt wird. Auf dem Timer stellen wir die Zeit, die der geschätzten Zeit der Prellung entspricht, ein. Für diese
Zeit wird eine weitere Abfrage des Eingangs unterbunden, keine "falschen" Signale werden berücksichtigt.
Die Prellzeit eines Kontaktes kann sehr unterschiedlich lang sein. Sie reicht von einigen bis zu mehreren hundert Millisekunden
aus.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
IF NOT #Abfrage_blockiert AND NOT "Test_Eingang" THEN "SIGNAL" := FALSE; END_IF;
"R_TRIG_DB"(CLK := "Test_Eingang", Q => #Positive_Flanke);
IF (#Positive_Flanke AND NOT #Abfrage_blockiert) THEN "SIGNAL" := TRUE; END_IF;
"IEC_Timer_0_DB_1".TP(IN :=
("Test_Eingang" AND NOT #Abfrage_blockiert) OR
(NOT "Test_Eingang" AND NOT #Abfrage_blockiert),
PT := t#50ms,
Q => "Abfrage_blockiert")
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Sobald eine positive Flanke an dem Testeingang erkannt wird, wird die Variable "SIGNAL", die unser entprelltes
Signal repräsentiert, gesetzt. Gleichzeitig wird für die voreingestellte Zeit ein Zeitimpuls gestartet. In der Zeit wird der Merker
"Abfrage blockiert" aktiviert und keine weiteren Änderungen am Eingang berücksichtigt.
Wenn nach abgelaufener Zeit das Signal am Test-Eingang immer noch ansteht, bleibt die Variable "SIGNAL" gesetzt, sonst wird
sie zurückgesetzt.
Ein ähnlicher Ablauf findet auch bei fallender Flanke statt.
Das komplette Programm für diesen Test (SCL):
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Relais Ein und Aus je 1000ms
"IEC_Timer_0_DB".TP(IN:=NOT "Relais_AUS", PT:=t#1000ms, Q=>"Relais_EIN", ET=>#Zeit_IST);
"IEC_Timer_0_DB_2".TP(IN:=NOT "Relais_EIN", PT:=t#1000ms, Q=>"Relais_AUS", ET=>#Zeit_IST);
"Relais_Ausgang" := FALSE;
IF "Start" THEN "Relais_Ausgang" := "Relais_EIN"; END_IF;
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Zähler für Relais EIN
"IEC_Counter_0_DB".CTU(CU:="Relais_Ausgang",
R:="Zähler_Reset",
PV:=10000,
CV=>#Zählerstand_Ausgang);
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Eingang Entprellung
IF NOT #Abfrage_blockiert AND NOT "Test_Eingang" THEN "SIGNAL" := FALSE; END_IF;
"R_TRIG_DB"(CLK := "Test_Eingang", Q => #Positive_Flanke);
IF (#Positive_Flanke AND NOT #Abfrage_blockiert) THEN "SIGNAL" := TRUE; END_IF;
"IEC_Timer_0_DB_1".TP(IN :=
("Test_Eingang" AND NOT #Abfrage_blockiert) OR
(NOT "Test_Eingang" AND NOT #Abfrage_blockiert),
PT := t#50ms,
Q => "Abfrage_blockiert");