Hallo zusammen!
Ich habe versucht, den von Peter Dannegger vorgestellten Algorithmus zum
Entprellen für meine Anwendung zu adaptieren.
Meine Anforderungen:
Ich will ohne viel Verzögerung auf die erste Flanke einer gedrückten
Taste reagieren können. Das danach folgende Prellen soll unterdrückt
werden. Ich muss auch wissen, wann eine Taste losgelassen wurde (Das ist
nicht zeitkritisch).
Nun haben aber fast alle Formen des Entprellens zur Folge, dass die
Taste erst als stabil erkannt wird, wenn sie eine Zeit lang ihren
Zustand behält. Das ist ja auch gut so, wenn man mit Störungen auf der
Leitung rechnen muss. In meinem Fall kann ich annehmen, dass ich solche
Störungen nicht habe (und wenn, dann kann ich damit leben).
Lässt man den Algorithmus im Simulator laufen fällt auf, dass der erste
Tastendruck so behandelt wird wie ich mir das vorstelle. Die beiden
Zähler sind nämlich noch mit 0 initialisiert. In allen folgenden
Aufrufen stehen sie beide auf 1 für eine Taste. Das bewirkt, dass erst
die 4 Zyklen durchlaufen werden bis die Taste als gültig erkannt wird.
Wie kann man das Verhalten ändern ohne dem Algorithmus seine Eleganz und
Kompaktheit zu nehmen?
Wie erkennt man dass eine Taste losgelassen wurde?
Ich habe folgende Zeile am Ende der Tastenauswertung eingefügt:
1
key_release=key_press^i;
Die gesetzten Bits repräsentieren die Tasten, die losgelassen wurden.
Danke schon mal für eure Ideen,
Helge ;-)=)
Was stören Dich an 30ms?
Der Mensch reagiert typisch erst nach 200ms auf ein erwartetes Ereignis:
http://wdw.prosieben.de/lifestyle_magazine/galileo/themenarchiv/25791/
Du kannst auch das Abfrageintervall verkleinern.
2ms sollten noch ausreichen bei nicht allzu großen Tastern.
Das sind dann nur noch 8ms Verzögerung.
Peter
Ich habe das Vorgehen schon mal im
Beitrag "Entprellung (Hardware)" beschrieben:
Ein Problem der Entprellung kann sein, daß durch Alterung der
Tasterkontakte die Prellzeit größer wird.
Ich hatte das mal bei Telefonen (ISDN) beim Gabelschalter, weil dann
beim Abheben durch prellen gleich wieder aufgelegt wird...
Ältere Schalter konnten da durchaus mehrere 10ms nachprellen, so daß ein
Entprellen von mind. 100ms notwendig war, allerdings musste aufgrund der
max. Verzögerung nach 10ms reagiert werden.
Hardwareentprellung kommt bei Massenproduktion nicht in Frage (zu
teuer), also musste in Software dynamisch entprellt werden:
1) nach einer Tastenänderung Tastenzustand merken und 10ms warten,
2) ist der Tastenzustand nach 10ms UNgleich dem gemerkten ->
Tastenänderung ignorieren und auf nächste Änderung warten (dann weiter
bei 1))
3) ist der Tastenzustand nach 10ms gleich dem gemerkten ->
Tastenänderung dem System mitteilen und die nächsten 100ms (ich hatte
dmals sogar 1sec.) NICHT mehr auf Tastenänderungen reagiren.
4) ist nach Ablauf dieser Zeit der Tastenzustand ungleich dem dem Zustan
von 3) dann das ganze weiter bei 1)
5) ansonsten warten auf die naächste Tastenänderung.
Klingt jetzt komplizierter als es ist...ich habe das vor ~15 Jahren auf
8051 und später auf 6811 implementiert...
Drücken und loslassen behandelt man auch nicht separat, deshalb wird
oben auch immer von "Zustand" gesprochen, dieser Zustand wird nach dem
Entprellen auch weitergegeben...
Mit dem Algorithmus kannst Du in sehr kurzer Zeit reagieren...allerdings
gibt es die lange Wartezeit als "Totzeit" zwischen zwei Ereigneissen...
Hallo zusammen!
Ich habe meine eigene Routine gebastelt (konnte nicht zwei Jahre auf
Peters Programm warten) und habe folgenden Algorithmus genommen:
Interrupt auf negative Flanke -> Interruptroutine schaltet eine
Verzögerung von 30 msec ein (Timer der alle 1 msec einen Interrupt
erzeugt) und den Interrupt aus -> nach Ablauf der Verzögerungszeit wird
der momentane Tastenzustand übernommen und wenn Sie gedrückt ist, wird
der Interrupt auf positive Flanke wieder eingeschaltet. Sollte nun der
Interrupt erneut generiert werden, kann man davon ausgehen, das die
Taste released wurde. Funktioniert auch mit älteren Tastern und bisher
ohne Probleme.
Leider muss dafür nicht nur der I/O Interrupt sondern auch ein Timer
Interrupt programmiert werden. In meinem Fall nutze ich solch einen
Timer Interrupt für alle möglichen Verzögerungen die man so überwachen
muss. Der Vorteil ist, das ein Programm weiterlaufen kann und nur die
Status-Flags von Tasten oder ähnlichem im "main" abgefragt werden
müssen. Setze ich im übrigen auch erfolgreich im ARM Umfeld ein.
Nur so als Anregung!
Bernhard M. wrote:
> Ich hatte das mal bei Telefonen (ISDN) beim Gabelschalter, weil dann> beim Abheben durch prellen gleich wieder aufgelegt wird...> Ältere Schalter konnten da durchaus mehrere 10ms nachprellen, so daß ein> Entprellen von mind. 100ms notwendig war, allerdings musste aufgrund der> max. Verzögerung nach 10ms reagiert werden.
Wozu das?
Ich kenne keinen, der innerhalb 10ms den Hörer abnehmen und zum Ohr
führen kann.
Auch kenne ich keinen Anbieter, der die Gebühren 10ms genau abrechnet.
> Klingt jetzt komplizierter als es ist...ich habe das vor ~15 Jahren auf> 8051 und später auf 6811 implementiert...
Ja, man kann es eben auch kompliziert machen.
Ich mags aber lieber einfach:
Ich taste 4* auf Gleichheit ab und das für 8 Tasten gleichzeitig.
D.h. ob eine Taste oder 8 ist in CPU-Zeit und Codebedarf kein
Unterschied.
Und auf nem 32Bit ARM wärs dann für 1..32 Tasten gleich.
Die logischen Operationen haben nicht nur den Vorteil der gleichzeitigen
Bearbeitung entsprechend der Bitbreite, sondern erzeugen auch sehr
effizienten und kleinen Code. Es sind ja in der Entprellroutine
keinerlei Tests und Sprünge nötig.
Peter
Das ist ja wohl nicht allzu schwierig: Reagiere auf die erste Flanke des
Signals und füge dann eine Totzeit ein, in der kein weiteres Signal
akzeptiert ist.
@Peter:
ja, es gibt keinen Anbieter, der das so genau berechnet. Aber das war
damals für die Post (jetzt Telekom), das Hauptproblem war / ist, das im
ISDN die Verbindung nicht (wie im analogen Telefon) vom abnehmenden
Telefon hergestellt (bzw. der Audiokanal durchgeschaltet) wird, sondern
von den beteiligten Anlagen. Anforderung war, daß in 100ms die
Verbindung stehen muß, da wurde an jeder Stelle optimiert.
Unabhängig davon war eine maximale Verzögerung durch Entprellen
vorgegeben, die lag glaube ich bei 20ms.
Und "den Hörer zum Ohr führen"... nun in Call Centern, die zumindest
damals diese Telefone benutzten, wurde Headset und externer
Gabelschalter (oft als Fußschalter) benutzt.
Ich weiß, für Hobbyanfoderungen ist das übertrieben kompliziert...
@mr.chirp:
Reagieren auf die erste Flanke geht nur, wenn Dir keine Störungen eine
Flanke auslösen können.
Hallo zusammen!
Danke für die Anregungen. Ich steuere einen Auslöser einer Kamera. Dazu
habe ich einen Mikrotaster in einem Griff. Der Griff ist von der Kamera
selbst hermetisch getrennt. Daher sende ich die Ereignisse aus dem Griff
optisch in das Gehäues in dem die Kamera eingebaut ist.
Entprellung in Hardware habe ich mir auch angesehen. Das kostet locker
um die 40-60ms und ist wenig flexibel. Ausserdem braucht es Platz und
Strom.
Durch meine signal-Strecke habe ich einige Verzögerungen:
Taste entprellen
Signalübertragung
Signal in Schaltzustand an der Kamera wandeln
Ich möchte nur nicht, dass dadurch eine teure Kamera eine
Auslöseverzögerung eine billigen Kompaktknipse bekommt.
Ich habe insgesamt 7 Tastenzustände. Die übertrage ich gemeinsam als 1
byte seriell. Das passiert ohne viel zusätliche Absicherung weil ich
praktisch nur einen Optokoppler mit etwas mehr Abstand habe (max. 30mm
in einem Rohr durch 2 Glasfenster). Ob die Übertragung so funktioniert
und welche Geschwindigkeit ich maximal erreiche muss ich noch austesten.
Etwas komplexer macht die Tatsache, dass es 4 Taster gibt die jeweils
paarweise einen Drehimpulsgeber simulieren (immer eine Taste für links
drehen, eine für rechts).
Das bedeutet, dass ich die Tastenzustände dafür in zwei versetzte
Schaltzustände umsetzen muss (je nach Richtung versetzt). Da bin ich
noch am Überlegen wie ich das elegant löse. Momentan überlege ich mir
gerade eieen Ringpuffer, der die Zustände speichert und über einen Timer
abgearbeitet wird damit ich die Schaltverzögerung des Drehgebers
erreiche. Die anderen Tasten kann ich direkt ohne weitere Verzögerung
zum Schalten verwenden.
Ein weiterer Punkt ist dann auch noch der Strombedarf des Senders. Der
soll es mit einer Knopfzelle (CR2032) lange aushalten. Besonders, wenn
länger nichts passiert. Da habe ih mir auch schon ein Stromsparkonzept
überlegt.
Helge ;-)=)
Hallo,
@Helge
warum eigendlich zum Entprellen immer ERST warten und DANN die
zugehörige Anwendung ausführen?
Wenn man diese nach dem ersten Tastenpegelwechsel sofort ausführt, aber
anschließend dafür sorgt, daß die zugehörige Anwendung aufgrund des
Prellens (= anschließende "wilde" Pegelwechsel) nicht noch einmal, also
nicht mehrmals ausgelöst wird, mußte das doch auch gehen, oder?
Vielleicht könnte man beim ersten Pegelwechsel, wenn die Anwendung
ausgelöst wird, einen Timer starten, der bis zu dessen Ablauf ein
weiteres Auslösen verhindert (ZB in dieser Zeit das Tasten-polling
überspringen).
Allerdings müßte hierzu sichergegengen werden, daß kein Pegelwechsel
durch (EM-) Störungen auftritt, d.h. aufgrund irgendeiner anderen
Ursache als die des Tastendrucks.
Sebastian ;-)
>warum eigendlich zum Entprellen immer ERST warten und DANN die>zugehörige Anwendung ausführen?
Keine schlechte Idee: eigentlich :-)
Eine andere Möglichkeit wären Hall-Schalter, der per Magnet aktiviert
werden. Magnetfelder prellen nicht - behaupte ich mal. Zudem haben die
Hallsensoren meistens eine Hysterese.
>Eine andere Möglichkeit wären Hall-Schalter, der per Magnet aktiviert>werden. Magnetfelder prellen nicht - behaupte ich mal. Zudem haben die>Hallsensoren meistens eine Hysterese
Wenn die mechanische Konstruktion gut genug ist, um den Hall-Schalter
präzise auszulösen, sollte das auch gehen. Ist natürlich etwas
aufwändiger.
Nochmal zum Tastenentprellen:
Man muß berücksichtigen, daß eine menschlich bediente Taste 2 mal
prellt:
1. Beim Drücken und 2. beim Wieder-Loslassen. Meine o.g. Idee hatte ich
mal verwirklicht; aber beim Wieder-Loslassen (=fallende Flanke, wenn
Taste im high-active-style verdrahtet), hat gut funktioniert. Will man
sofort beim Tastendruck die Applikation starten (das habe ich aber noch
nicht praktisch getestet), muss natürlich dafür gesorgt werden, daß
diese beim Wieder-Laslassen nicht nochmal ungewollt ausgelöst wird. Zum
Beispiel (high-active-style-Taste):
1. An steigender Flanke: Applikation auslösen, Timer auf ca 30-100ms
starten
2. Während Timer läuft, Tasten-polling weglassen (=Tastenpegel
ignorieren)
3. Wenn Timer abgelaufen: bei erster fallenden Flanke Timer nochmal
starten
4. Wie 2.
Sebastian
Ihr wisst aber schon, dass das Prellen beim Drücken/Loslassen (nahezu)
identisch ist. Auch beim Loslassen hat man eine steigende Flanke.
Und das erklärt auch warum man erst wartet und dann die Anwendung
ausführt: Weil erst nach einer bestimmten Zeit der Status des
Schalters/Tasters bekannt ist.
Das lässt sich aber lösen.
Erkennt man eine steigende Flanke (Taster high aktiv),
so gilt das als Tastendruck.
Anschliessend wird die Prellzeit abgewartet in der Flankenwechsel
ignoriert werden
Erkennt man eine fallende Flanke (High aktiver Taster losgelassen)
so gilt das als Loslassen und danach wird wieder die Prellzeit
abgewartet und Flankenwechsel ignoriert.
Der springende Punkt ist ganz einfach der, dass nach dem Erkennen
eines Flankenwechsels erst mal eine Zeitlang alles ignoriert wird,
was denn so am Eingang passiert.
Der Nachteil: Jeglicher kleiner Spike führt zum Auslösen des
Mechanismus. Und wenn man dann auch noch Buch darüber führt,
ob die Taste jetzt gedrückt oder losgelassen ist, dann bringt
ein Spike in dieser Einfachvariante diese Buchführung
durcheinander. Aber auch das ist lösbar: Nach dem Ablaufen
der Prellzeit nachsehen in welchen Zustand der Eingang jetzt
ist und mit dem Zustand vergleichen in dem er sein sollte.
@Simon
>Ihr wisst aber schon, dass das Prellen beim Drücken/Loslassen (nahezu)>identisch ist. Auch beim Loslassen hat man eine steigende Flanke.
Klar. Siehe oben.
>Und das erklärt auch warum man erst wartet und dann die Anwendung>ausführt: Weil erst nach einer bestimmten Zeit der Status des>Schalters/Tasters bekannt ist.
Das verstehe ich nicht ganz. Wenn man weiß, daß die Taste vor dem
Drücken in Ruhe war (=Ruhepegel) und dann eine aktive Flanke auftritt,
ist doch klar, daß die Taste gedrückt wurde (außer natürlich beim
Auftritt von Leitungsstörungen o.ä., die wir ja ausschliessen wollten,
s.o.). Wenn man das anschließende Prellen ignoriert, passiert doch nix.
Beim WIederloslassen ist es ganz ähnlich, außer, daß jetz während des
Aktivpegels (=während die Taste gerdrückt bleibt) auf die Flanke in
Richtung Ruhepegel gewartet und das anschließende Prellen wieder
ignoriert werden muß .