|
|
Entprellung
[Bearbeiten] ProblembeschreibungMechanische Schalter wie Drehgeber neigen beim Ein- und Ausschalten zum sogenannten Prellen, d.h sie schalten schnell mehrfach aus und ein, verursacht durch mechanische Vibrationen des Schaltkontaktes, sofern sie nicht dagegen geschützt sind. Vereinfacht dargestellt, sieht eine von einem Schalter oder Taster geschaltete Spannung beim Schalten wie folgt aus: Für die Vermeidung bzw. Auswertung dieses unsauberen Signals gibt es verschiedene Ansätze: [Bearbeiten] Hardwareentprellung[Bearbeiten] Prellfreie SchalterFür Spezialanwendungen hält die elektromechanische Industrie verschiedene Sonderkonstruktionen bereit, die saubere Schaltzustände nach Aussen generieren, indem sie entweder eine mechanische Dämpfung in Form eines selbsthemmenden Federmechanismus oder eine integrierte elektronische Signalverzögerung benutzen. Solche Systeme sind jedoch teuer und werden meist nur im Leistungsbereich eingesetzt. [Bearbeiten] WechselschalterFür die Entprellung von Wechselschaltern (engl. Double Throw Switch) kann ein klassisches RS-Flipflop genutzt werden. Bei dieser Variante werden neben zwei NAND-Gattern nur noch zwei Pull-Up Widerstände benötigt.
In der gezeigten Schalterstellung liegt an der Position /S der Pegel 0 an. Damit ist das Flipflop gesetzt und der Ausgang auf dem Pegel 1. Schließt der Schalter zwischen den Kontakten 2 und 3, liegt an der Postion /R der Pegel 0 an. Dies bedeutet, dass der Ausgang des Flipflops auf den Pegel 0 geht. Sobald der Schalter von einem zum anderen Kontakt wechselt, beginnt er in der Regel zu prellen. Während des Prellens wechselt der Schalter zwischen den beiden Zuständen "Schalter berührt Kontakt" und "Schalter ist frei in der Luft". Der Ausgang des Flipflops bleibt in dieser Prellzeit aber stabil, da der Schalter während des Prellens nie den gegenüberliegenden Kontakt berührt und das RS-Flipflop seinen Zustand allein halten kann. Die Prellzeit ist stark vom Schaltertyp abhängig und liegt zwischen 0,1 und 10ms. Die Dimensionierung der Widerstände ist relativ unkritisch. Als Richtwert können hier 100kOhm verwendet werden. [Bearbeiten] Wechselschalter ohne Flip-FlopWenn man mal gerade kein Flip-Flop zur Hand hat, kann man sich auch mit dieser Schaltung behelfen.
Zur Funktionsweise: Beim Umschalten wird der Kondensator immer sofort umgeladen. Während der Kontakt prellt, befindet er sich in der Luft und hat keinerlei Verbindung. Während dieser Zeit übernimmt der Kondensator das halten des Pegels. Dimensionierung: Ist der entprellte Taster an ein IC Angeschlossen, ist der Input Leakage Current der ausschlaggebende Strom. Falls weitere Ströme fließen sind diese mit zu berücksichtigen. Bei einem Mikrocontroller von Atmel sind 1µA typisch. Es gilt: Da eine Prellung ca. 10ms dauert und die Spannung in dieser Zeit beispielsweise um maximal 0,5V fallen soll kommt man auf folgende Kapazität: Um Stromspitzen zu verringern kann ein Widerstand mit eingefügt werden. Eine Zeitkonstante von 1µs bis 1ms scheint sinnvoll. Also 500 Ohm bis 500kOhm sind nutzbar, wobei bei niedrigem Widerstand die Stromspitzen höher sind, und bei 500kOhm der Pinstrom störend wird. [Bearbeiten] Einfacher TasterAuch wenn das RS-Flipflop sehr effektiv ist, wird diese Variante der Entprellung nur selten angewendet. Grund dafür ist, dass in Schaltungen häufiger einfache Taster eingesetzt werden. Diese sind oft kleiner und preisgünstiger. Um einfache Taster (engl. Single Throw Switch) zu entprellen, kann ein einfacher RC-Tiefpass eingesetzt werden. Hierbei wird ein Kondensator über einen Widerstand je nach Schalterstellung auf- oder entladen. Das RC-Glied bildet einen Tiefpass, sodass die Spannung über den Kondensator nicht von einen Pegel auf den anderen springen kann. Wenn der Schalter geöffnet ist, lädt sich der Kondensator langsam über die beiden Widerstände R1 und R2 auf Vcc auf. Beim Erreichen der Umschaltschwelle springt der Ausgang auf den Pegel 0. Wird der Schalter geschlossen, entlädt sich der Kondensator langsam über den Widerstand R2. Demnach ändert sich der Ausgang des Inverters auf den Pegel 1. Während der Taster prellt, kann sich die Spannung über dem Kondensator nicht sprunghaft ändern, da das Auf- und Entladen eher langsam über die Widerstände erfolgt. Außerdem sind die Schaltschwellen für den Übergang LOW->HIGH und HIGH->LOW stark verschieden (Hysterese, siehe Artikel Schmitt-Trigger). Bei richtiger Dimensionierung der Bauelemente wird somit der Ausgang des Inverters prellfrei. Zu beachten ist, dass der Inverter unbedingt einer mit Schmitt-Trigger Eingängen sein muss, weil bei Standard-Logikeingängen im Bereich von üblicherweise 0,8V - 2,0V der Ausgang nicht definiert ist. Als Inverter kann zum Beispiel der 74HC14 oder der CD40106 (pinkompatibel) eingesetzt werden. Alternativ kann auch ein CD4093 eingesetzt werden. Bei dem CD4093 handelt es sich um NAND-Gatter mit Schmitt-Trigger-Eingängen. Um aus einem NAND-Gatter einen Inverter zu machen, müssen einfach nur die beiden Eingänge verbunden werden oder ein Eingang fest auf HIGH gelegt werden. Für eine geeignete Dimensionierung muss man etwas mit den Standardformeln für einen Kondensator jonglieren. Die Spannung über den Kondensator beim Entladen berechnet sich nach: Damit der Ausgang des Inverters stabil ist, muss die Spannung über den Kondensator und damit die Spannung am Eingang des Inverters über der Spannung bleiben, bei welcher der Inverter umschaltet. Diese Schwellwertspannung ist genau die zeitabhängige Spannung über den Kondensator. Durch Umstellen der Formel ergibt sich nun: Ein Taster prellt üblicherweise etwa 10ms. Zur Sicherheit kann bei der Berechnung des Widerstandes eine Prellzeit von 20ms angenommen werden. U_0 ist die Betriebsspannung also Vcc. Die Schwellwertspannung muss aus dem Datenblatt des eingesetzten Schmitt-Triggers abgelesen werden. Beim 74HC14 beträgt der gesuchte Wert 2,0V. Nimmt man für den Kondensator 1µF und beträgt die Betriebsspannung 5V, ergibt sich für den Widerstand ein Wert von etwa 22kOhm. Wird der Schalter geöffnet, lädt sich der Kondensator nach folgender Formel auf: Mit U_th=U_C ergibt das Umstellen nach (R_1+R_2): Für die Schwellspannung lässt sich aus dem Datenblatt ein Wert von 2,3V ablesen. Mit diesem Wert und den Annahmen von oben ergibt sich für R_1+R_2 ein Wert von 32kOhm. Somit ergibt sich für R_1 ein Wert von etwa 10kOhm. Anmerkung: Beim 74LS14 von Hitachi z. B. sind die oberen und unteren Schaltschwellwerte unterschiedlich. Es muss darauf geachtet werden, dass U_{th} beim Entladen die untere Schwelle und U_{th} beim Laden die obere Schwelle einnimmt. [Bearbeiten] SoftwareentprellungIn den Zeiten der elektronischen Auswertung von Tastern und Schaltern ist das softwaretechnische Entprellen oft billiger, als die Benutzung eines teuren Schalters. Daher werden heute z.B. auch Computertastaturen nicht mehr mit prellarmen Tasten oder Entprellkondensatoren ausgestattet. Bei Verwendung des in den meisten Geräten ohnehin vorhandenen Mikrocontrollers z.B., kann man sich die zusätzliche Hardware sparen, da die Entprellung in Software praktisch genauso so funktioniert. Dabei ist nur zu beachten, dass zusätzliche Rechenleistung und je nach Umsetzung auch einige Hardwareressourcen (z.B. Timer) benötigt werden. [Bearbeiten] FlankenerkennungBei einem Taster gibt es insgesamt 4 theoretische Zustände:
Diese einzelnen Zustände lassen sich jetzt bequem abfragen/durchlaufen. Die Entprellung geschieht dabei durch die ganze Laufzeit des Programms. Die Taster werden hierbei als Active-Low angeschlossen, um die internen Pull-Ups zu nutzen. Diese Routine gibt für den Zustand "steigende Flanke" den Wert "1" zurück, sonst "0"
[Bearbeiten] Warteschleifen-VerfahrenSoll nun mit einem Mikrocontroller gezählt werden, wie oft ein Kontakt oder ein Relais geschaltet wird, muss das Prellen des Kontaktes exakt berücksichtigt - und von einem gewollten Mehrfachschalten abgerenzt werden, da sonst möglicherweise Fehlimpulse gezählt- oder andererseits echte Schaltvorgänge übersprungen werden. Dies muss beim Schreiben des Programms hinsichtlich des Abtastens des Kontaktes unbedingt Rechnung getragen werden. Beim folgenden einfachen Beispiel für eine Entprellung ist zu beachten, dass der AVR im Falle eines Tastendrucks 200ms wartet, also brach liegt. Bei zeitkritische Anwendungen sollte man ein anderes Verfahren nutzen (z. B. Abfrage der Tastenzustände in einer Timer-Interrupt-Service-Routine).
Die obige Routine hat leider mehrere Nachteile:
Eine ähnlich einfach zu benutzende Routine, aber ohne all diese Nachteile findet sich im Forenthread Entprellung für Anfänger Der DEBOUNCE Befehl in dem BASIC-Dialekt BASCOM für AVR ist ebenfalls nach dem Warteschleifen-Verfahren programmiert. Die Wartezeit beträgt standardmäßig 25 ms, kann aber vom Anwender überschrieben werden. Vgl. BASCOM Online-Manual zu DEBOUNCE. Eine C-Implementierung für eine Tastenabfrage mit Warteschleife ist im Artikel AVR-GCC-Tutorial: IO-Register als Parameter und Variablen angeben. Der Nachteil dieses Verfahrens ist, dass der Controller durch die Warteschleife blockiert wird. Günstiger ist die Implementierung mit einem Timer-Interrupt. [Bearbeiten] Warteschleifenvariante mit Maske und Pointer (nach Christian Riggenbach)Hier eine weitere Funktion, um Taster zu entprellen: Durch den zusätzlichen Code kann eine Entprellzeit von durchschnittlich 1-3ms (mindestens 8*150µs = 1ms) erreicht werden. Grundsätzlich prüft die Funktion den Pegel der Pins auf einem bestimmten Port. Wenn die/der Pegel 8 Mal konstant war, wird die Schleife verlassen. Diese Funktion kann sehr gut eingesetzt werden, um in einer Endlosschleife Taster anzufragen, da sie, wie erwähnt, eine kurze Wartezeit hat.
Die Funktion wird wie folgt aufgerufen:
Als Maske kann ein beliebiger Wert übergeben werden. Sie verhindert, dass nichtverwendete Taster die Entprellzeit negativ beeinflussen. [Bearbeiten] Debounce-Makro von Peter DanneggerPeter Dannegger hat in "Entprellen für Anfänger" folgende vereinfachtes Entprellverfahren beschrieben. Das Makro arbeitet in der Originalversion mit active low geschalteten Tastern, kann aber einfach für active high geschaltete Taster angepasst werden (Tasty Reloaded).
Wenn das Makro für die gleiche Taste (Pin) an mehreren Stellen aufgerufen werden soll, muss eine Funktion angelegt werden, damit beide Aufrufe an die gleiche Zustandsvariable flag auswerten [1]:
[Bearbeiten] Timer-Verfahren (nach Peter Dannegger)[Bearbeiten] Grundroutine (AVR Assembler)Siehe dazu: Forum Vorteile
Außerdem können 8 Tasten (aktiv low) gleichzeitig bearbeitet werden, es dürfen also alle exakt zur selben Zeit gedrückt werden. Andere Routinen können z. B. nur eine Taste verarbeiten, d.h. die zuerst oder zuletzt gedrückte gewinnt, oder es kommt Unsinn heraus. Die eigentliche Einlese- und Entprellroutine ist nur 8 Instruktionen kurz. Der entprellte Tastenzustand ist im Register key_state. Mit nur 2 weiteren Instruktionen wird dann der Wechsel von Taste offen zu Taste gedrückt erkannt und im Register key_press abgelegt. Im Beispielcode werden dann damit 8 LEDs ein- und ausgeschaltet. Jede Taste entspricht einem Bit in den Registern, d.h. die Verarbeitung erfolgt bitweise mit logischen Operationen. Zum Verständnis empfiehlt es sich daher, die Logikgleichungen mit Gattern für ein Bit = eine Taste aufzumalen. Die Register kann man sich als Flipflops denken, die mit der Entprellzeit als Takt arbeiten. D.h. man kann das auch so z. B. in einem GAL22V10 realisieren. Als Kommentar sind neben den einzelnen Instruktionen alle 8 möglichen Kombinationen der 3 Signale dargestellt. Beispielcode für AVR (Assembler):
[Bearbeiten] Komfortroutine (C für AVR)Siehe dazu: Forum Anmerkung Wenn statt active-low (Ruhezustand High) active-high (Ruhezustand Low) verwendet wird muss eine Zeile geändert werden siehe: gesamter Beitrag im Forum, Stelle 1 im Beitrag, (Stelle 2 im Beitrag muss *nicht* geändert werden, da hier die Polarität gar keinen Einfluß hat). Funktionsprinzip wie oben plus zusätzliche Features:
Das Programm ist für avr-gcc/avr-libc geschrieben, kann aber mit ein paar Anpassungen auch mit anderen Compilern und Mikrocontrollern verwendet werden. Eine Portierung für den AT91SAM7 findet man hier (aus dem Projekt ARM MP3/AAC Player).
Das single-press-und-repeat-Beispiel geht nicht in jeder Beschaltung; folgendes Beispiel sollte universeller sein (einzelne LED an/aus):
[Bearbeiten] FunktionsweiseDer Code basiert auf 8 parallelen vertikalen Zählern, die über die Variablen ct0 und ct1 aufgebaut werden wobei jeweils ein Bit in ct0 mit dem gleichwertigen Bit in ct1 zusammengenommen einen 2-Bit-Zähler bildet. Der Code der sich um die 8 Zähler kümmert, ist so geschrieben, daß er alle 8 Zähler gemeinsam parallel behandelt.
i enthält an dieser Stelle für jede Taste, die sich im Vergleich mit dem vorhergehenden entprellten Zustand (keystate) verändert hat, ein 1 Bit.
Diese beiden Anweisungen erniedrigen den 2-Bit Zähler ct0/ct1 für jedes Bit um 1, welches in i gesetzt ist. Liegt an der entsprechenden Stelle in i ein 0 Bit vor (keine Änderung des Zustands), so wird der Zähler ct0/ct1 für dieses Bit auf 1 gesetzt. Der Grundzustand des Zählers ist als ct0 == 1 und ct1 == 1 (Wert 3). Der Zähler zählt daher mit jedem ISR Aufruf, bei dem die Taste im Vergleich zu keystate als verändert erkannt wurde ct1 ct0
1 1 // 3
1 0 // 2
0 1 // 1
0 0 // 0
1 1 // 3
in i bleibt nur dort ein 1-Bit erhalten, wo sowohl in ct1 als auch in ct0 ein 1 Bit vorgefunden wird, der betreffenede Zähler also bis 3 zählen konnte. Durch die zusätzliche Verundung mit i wird der Fall abgefangen, dass ein konstanter Zählerwert von 3 in i ein 1 Bit hinterlässt. Im Endergebnis bedeutet dass, dass nur ein Zählerwechsel von 0 auf 3 zu einem 1 Bit an der betreffenden Stelle in i führt, aber auch nur dann, wenn in i an dieser Bitposition ebenfalls ein 1 Bit war (welches wiederrum deswegen auf 1 war, weil an diesem Eingabeport eine Veränderung zum letzten bekannten entprellten Zustand festgestellt wurde). alles zusammengenommen heißt das, dass ein Tastendruck dann erkannt wird, wenn die Taste 4 mal hintereinander in einem anderen Zustand vorgefunden wurde als dem zuletzt bekannten entprellten Tastenzustand. An dieser Stelle ist i daher ein Vektor von 8 Bits, von denen jedes einzelne der Bits darüber Auskunft gibt, ob die entsprechende Taste mehrmals hintereinander im selben Zustand angetroffen wurde, der nicht mit dem zuletzt bekannten Tastenzustand übereinstimmt. Ist das der Fall, dann wird eine entsprechende Veränderung des Tastenzustands in key_state registriert
und wenn sich in key_state das entsprechende Bit von 0 auf 1 verändert hat, wird dieses Ereignis als 'Taste wurde niedergedrückt' gewertet.
Damit ist der Tasteneingang entprellt. Und zwar sowohl beim Drücken einer Taste als auch beim Loslassen (damit Tastenpreller beim Loslassen nicht mit dem Niederdrücken einer Taste verwechselt werden). Der weitere Code beschäftigt sich dann nur noch damit, diesen entprellten Tastenzustand weiter zu verarbeiten. Der Codeteil sieht durch die Verwendung der vielen bitweisen Operationen relativ komplex aus. Behält man aber im Hinterkopf, dass einige der bitweisen wie ein 'paralles If' gleichzeitig auf allen 8 Bits eingesetzt werden, dann vereinfacht sich vieles. Ein
ist nichts anderes als ein
nur als wesentlich kompaktere Operation ausgeführt und für alle 8 Bits gleichzeitig. Die Kürze und Effizienz dieser paar Codezeilen ergibt sich aus dem Umstand, dass jedes Bit in den Variablen für eine Taste steht und alle 8 (maximal möglichen) Tasten gleichzeitig die Operationen durchlaufen. [Bearbeiten] Reduziert auf lediglich 1 TasteDiskussionen im Forum zeigen immer wieder, dass viele eine Abneigung gegen diesen Code haben, weil er ihnen sehr kompliziert vorkommt. Der Code ist nicht leicht zu analysieren und er zieht alle Register dessen, was möglich ist, um sowohl Laufzeit als auch Speicherverbrauch einzusparen. Oft hört man auch das Argument: Ich benötige ja nur eine Entprellung für 1 Taste, gibt es da nichts Einfacheres? Hier ist die 'Langform' des Codes, so wie man das für lediglich 1 Taste schreiben würde, wenn man exakt dasselbe Entprellverfahren einsetzen würde. Man sieht: Da ist keine Hexerei dabei: In key_state wird der letzte bekannte entprellte Zustand der Taste gehalten. Der Pin-Eingang wird mit diesem Zustand verglichen und wenn sich die beiden unterscheiden, dann wird ein Zähler heruntergezählt. Produziert dieses herunterzählen einen Unterlauf des Zählers, dann gilt die Taste als entprellt und wenn dann auch noch die Taste gerade gedrückt ist, dann wird dieses in key_press entsprechend vermerkt.
Der vollständige Entprellcode, wie weiter oben gelistet, besticht jetzt aber darin, dass er compiliert kleiner ist als diese anschaulichere Variante für lediglich 1 Taste. Und das bei gleichzeitig erhöhter Funktionalität. Denn zb. ein Autorepeat ist in diesem Code noch gar nicht eingebaut. Und spätestens wenn man dann eine 2.te Taste entprellen möchte, dann ist auch der SRAM-Speicherverbrauch dieser Langform höher als der des Originals für 8 Tasten. Daraus folgt: Selbst für lediglich 1 Taste ist die Originalroutine die bessere Wahl. Und wegen der Komplexität mal eine Frage: Sind Sie selbst in der Lage eine entsprechend effiziente sqrt() Funktion zu schreiben, wie die, die sie in der Standard-C-Bibliothek vorfinden? Nein? Dann dürften Sie eigentlich Ihrer Argumentation nach die Bibliotheksfunktion sqrt() nicht verwenden, sondern müssten sich statt dessen selbst eine Wurzel-Funktion schreiben. [Bearbeiten] Selbstsättigender Filter (nach Jürgen Schuhmacher)Durch die Nutzung der diskreter Signalanalyse in Software kann die Funktionalität einer einfachen Entprellung mit einem Kondensator und einem Schmitttrigger wie in Hardware nachgebildet werden, indem ein abstrakter IIR-Filter benutzt wird, der eine Kondensatorladekurve emuliert. Mit der Vorschrift Y(t) = k Y(t-1) + Input wird ein einfaches Filter erzeugt, dass dem Eingangswert träge folgt. Bei Überschreiten eines bestimmten Wertes erfolgt mit einer einfachen Abfrage das Schalten des Ausgangssignals. Für Assembler und FPGAs eignet sich aufgrund der leicht zu implementierenden binären Operationen folgende Darstellung mit einer Auflösung des Filterwertspeichers von nur 8 bit: Wert_Neu = Wert_Alt - Wert_Alt/16 + 16*(Taste = True). Der Filterwert bildet den gedämpften Verlauf des Eingangs flankenverschliffen ab und kann Prellen bis hart an den Grenzbereich zum schnellen Tasten unterdrücken. Der Ausgangswert ist dann einfach das höchstwertige Bit des Filterwertes. Dazu muss das Signal des Tasters idealerweise um den Faktor 10-20 schneller abgetastet werden, als die höchste gewünschte Tippgeschwindigkeit vorgibt. Noch schneller abzutasten ist möglich, führt aber zu mehr Bedarf an Bits beim Filter. Die Schmittriggerfunktion kann dadurch gebildet werden, dass eine 1 bei z.B. Überschreiten einer 55% Grenze und eine 0 bei Unterschreitung der 45%-Grenze ausgeben wird. Im Zwichenbereich wird der alte Wert gehalten. [Bearbeiten] Einfacher Mittelwertfilter (nach Lothar Miller)Für digitale Schaltungen oder PLDs empfiehlt sich ein FIR-Filter mit aneinandergereihten FlipFlops. Man schiebt das Eingangssignal in eine FlipFlop-Kette und schaltet oberhalb der Mitte um: SignalInput -> FF1 -> FF2 -> FF3 -> FF4 -> FF5 -> FF6 -> FF7 -> FF8 Wenn (Summe der FFs) =8 dann SignalOutput =1 Wenn (Summe der FFs) =0 dann SignalOutput =0 [Bearbeiten] Gegenüberstellung der Verfahren
[Bearbeiten] Links zum Thema |