Forum: Mikrocontroller und Digitale Elektronik Schalter entprellen


von Jan (Gast)


Lesenswert?

Hallo,

ich benutze aus https://www.mikrocontroller.net/articles/Entprellung die 
Komfortroutine in c von Peter. Ich habe sie auf meinen µC portiert und 
sie funktioniert erst mal sehr gut. Im Moment habe ich vier Taster und 
einen Schalter angeschlossen. Dieser muss ja auch Entprellt werden.

Kann ich die Routine auch hierzu nutzen? Wenn ja... ich bekomme es 
gerade nicht hin...


Wenn ich es richtig verstanden habe, geht die Repeatfunktion immer nur 
für eine Taste gleichzeitig oder? Den Schalter habe ich aus dem Repeat 
rausgenommen (sonst geht nichts mehr).

Dank und Gruß
Jan

von Schwarzfunker (Gast)


Lesenswert?

Es werden immer 8 Eingänge gleichzeitig entstellt.

von Schwarzfunker (Gast)


Lesenswert?

Entprellt. Blöde Autovervollständigung.

von Roth (Gast)


Lesenswert?

Wenn ich Peters Sourcen nur früher gekannt hätte...hab selbst 
rumprobiert und mich gequält.

Habe mir eine Bitqueue überlegt, wo der Pin-Status 8x reingeschoben 
wird. Nur wenn alle Bits gesetzt sind oder gar keins, wir der Status 1 
oder 0 übernommen. Alle anderen Werte ändern den entprellten Pin-Status 
nicht.

Die Routine stammt aus einem Timer-Event. Bei einer Pin-Abtastrate von 
160x pro Sekunde lassen sich 20 entprellte Zustände pro Sekunde 
einlesen. Das reicht, um sogar schnelles "DoubleClick", also Taster 2x 
kurz hintereinander gedrückt (sozusagen DoublePress) sicher zu 
identifizieren.
1
       // Pin einlesen und entprellen. 
2
       // Das '& 1' ist nur symbolisch
3
4
       byte iBit0 = digitalRead(iPin) & 1;  // Status des digitalen Pin als Bit einlesen
5
       iPuffer <<= 1;                       // Platz in der Queue schaffen
6
       iPuffer |= iBit0;                    // Pin als Bit 0 übernehmen
7
8
       // Nur wenn die Queue ganz voll (255) oder ganz leer (0) ist, 
9
       // wird der Status '1' oder '0' als 'iEntprellterPinStatus' übernommen
10
11
       if (iPuffer == 0b11111111)           // 0b11111111 = Taster gedrückt
12
          {iEntprellterPinStatus = 1;}      // dann nur Taster-Gedrückt-Bit setzen, fertig
13
       else if (iPuffer == 0b00000000)      // 0b00000000 = Taster nicht gedrückt
14
          {iEntprellterPinStatus = 0;}      // nur Taster-Gedrückt-Bits löschen, fertig

Die Routine entprellt sogar eine rostige Büroklammer. Einen ISR-Rumpf 
(Timer-Interrupt) habe ich hier gerade gepostet: 
Beitrag "Re: delay() in Timer-Event ISR (Arduino)" In den 
Rumpf kannst du, statt der LED-Ansteuerung, die Pin-Abfrage mit 
Entprellung einbauen. Ist ganz easy und funzt sofort.

Wenn du mehr als nur entprellen willst, z.B. 'Doppelter Tasterdruck' 
oder 'Taster gedrückt gehalten' erkennen willst, musst du sehr viel 
tiefer in die Materie gehen. Meine Sourcen, nach viel rumprobieren (und 
überlegen, wie ich doppelten und einfachen Tastendruck auseinander 
halten kann), sind seit gestern so weit, dass bei 6 Taster-Ereignissen 
verschiedene Eventfunktionen angesprungen werden können. Alles 
"unsichtbar" per Timer-OInterrupt organisiert. Macht Spaß und das 
Erstellen eines Programms wird zum Kinderspiel. Wenn du noch was wissen 
willst, frag einfach. Ich bin zwar C-einsteiger, stecke in dieser 
Materie Entprellen, Meßwertglättung und Dämpfung gerade mittendrin.

von jemand (Gast)


Lesenswert?

Warum eine Entprellroutine?
Polling im 20ms-Raster behebt das Problem viel einfacher. Und die 
Timer-ISR braucht der Code ja auch.

20ms reichen für jeden Taster locker aus, und sind mehr als schnell 
genug, um manuelle Eingaben flüssig zu verarbeiten.

Die Entprellroutine sollte man höchstens bei einem Drehencoder 
benötigen, wenn überhaupt.

von Stefan F. (Gast)


Lesenswert?

Schwarzfunker schrieb:
> Entprellt. Blöde Autovervollständigung.

Warum benutzt ihr dieses Feature überhaupt? Diese Funktion gibt es seit 
mindestens 25 Jahren und sie ist immer noch Kacke! Hofft Ihr irgendwie 
auf einen heimlichen Durchbruch der KI?

von Stefan F. (Gast)


Lesenswert?

jemand schrieb:
> Polling im 20ms-Raster behebt das Problem viel einfacher.

Meinst du das so?:
1
                   __________
2
Tastendruck ______|          |_______________
3
                     ________
4
Signal      ______|||        |||_____________
5
6
Polling      ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^ 
7
                    ______________
8
Resultat    _______|              |__________
9
                       ________
10
oder:       __________|        |_____________
11
                    ___________
12
oder:       _______|           |_____________
13
                       ___________
14
oder:       __________|           |__________

Könnte klappen, wenn man mit den damit verbundenen bis zu 40ms langen 
Verzögerungen leben kann. Ich bin nicht sicher, ob das bei up/down 
Tasten (zum Beispiel zum Stellen einer Uhr) zufriedenstellend 
funktioniert. Müsste man mal ausprobieren.

von Peter D. (peda)


Lesenswert?

Jan schrieb:
> Kann ich die Routine auch hierzu nutzen?

Ja. Kostet ja keinen zusätzlichen Code.
Ich benutze das z.B. für einen Interlockkreis. Es soll ja nicht bei 
jedem Störimpuls abgeschaltet werden, sondern nur bei einem echten 
Schalten.

Jan schrieb:
> Wenn ich es richtig verstanden habe, geht die Repeatfunktion immer nur
> für eine Taste gleichzeitig oder?

Ja. Etwas anderes erschien mir unnötig.

Jan schrieb:
> Den Schalter habe ich aus dem Repeat
> rausgenommen (sonst geht nichts mehr).

Nur die Tasten dürfen in der Repeatmaske sein, die auch repeatet werden 
sollen.

von A. S. (Gast)


Lesenswert?

Stefanus F. schrieb:
> Könnte klappen, wenn man mit den damit verbundenen bis zu 40ms langen
> Verzögerungen leben kann. Ich bin nicht sicher, ob das bei up/down
> Tasten (zum Beispiel zum Stellen einer Uhr) zufriedenstellend
> funktioniert. Müsste man mal ausprobieren.

Doch funktioniert für normales Drücken! Es sind jedoch Randbedingungen 
zu beachten:

Aus dem Alter der Digitaluhren mit Stoppfunktion ist bekannt, dass zwei 
Tastendrücke mindestens 100ms auseinander liegen. Oder anders: Du kannst 
eine Taste maximal 10/s drücken.

Für 20ms Abtastrate musst Du sicherstellen (garantieren), dass
 * der Kontakt maximal 19.9ms prellt (je beim Drücken und beim 
Loslassen)
 * der Kontakt dazwischen mindestens 20.1ms durchgehend gedrückt bleibt

Die Verzögerung von 1..20ms ist dabei in jedem Fall zu vernachlässigen, 
sie würde durch übliche Entprellungen im gleichen Rahmen liegen.

Wenn man dass mit schnell kombinieren will, dann kann man bei stabilem 
Signal (>100ms gleicher Pegel) den ersten Peak in die anderen Richtung 
(im 1ms-Raster oder als Interrupt) als Tasten-Event verarbeiten und 
dann, ganz wichtig, das nächste 20ms-Signal ignorieren.

von jemand (Gast)


Lesenswert?

Stefanus F. schrieb:
> Könnte klappen, wenn man mit den damit verbundenen bis zu 40ms langen
> Verzögerungen leben kann. Ich bin nicht sicher, ob das bei up/down
> Tasten (zum Beispiel zum Stellen einer Uhr) zufriedenstellend
> funktioniert. Müsste man mal ausprobieren.

Tut es im Normalfall. Man merkt es kaum.

Außerdem prellen die wenigsten Taster 20ms, d.h. fallweise kann man also 
schneller pollen. Dazu kann man sich das mit dem Oszi ansehen. Ich 
stelle das Scope dazu einfach auf "persist", und malträtiere den Taster 
ein paar Minuten auf verschiedene Art und Weise. Dann schlage ich eine 
gute "Alterungsreserve" oben drauf.

Natürlich gibt es Fälle, wo das zu langsam ist. Ein Encoder wäre da zum 
Beipsiel zu nennen.
In solchen Fällen nehme ich Hardware. Ein RC-Glied+Schmitt-Trigger 
machen einen schönen Rechteck, wenn man die Zeitkonstante hoch genug 
wählt.

von Stefan F. (Gast)


Lesenswert?

Der Ansatz mit dem 20ms Polling gefällt mir. ist viel simpler, als wie 
ich es bisher gemacht habe: Ich hatte die Abfrage des Tasters so lange 
wiederholt, bis ich mindestens 20ms lang ein stabiles Signal hatte (also 
ohne Wechsel).

Das harmonierte aber schlecht mit parallel laufenden Threads. Das 
Polling in regelmäßigen Intervallen lässt sich hingegen sehr einfach in 
einer Timer ISR unterbringen und kostet fast nichts.

Meine alte Methode wäre bei Tastern sinnvoll, die sehr lange prellen. 
Aber solche Taster meide ich ohnehin an den Stellen, wo die Anzahl der 
Tastendrücke innerhalb kurzer Zeit) eine Rolle spielt.

von A. S. (Gast)


Lesenswert?

Jetzt wertet hier jemand jemandes Alternative konsequent ab! Hat wohl 
nach langer Zeit endlich Peters Routinen verstanden und ist pissed, dass 
er sich das auch hätte sparen können.


Leute gibt's... Naja, einen kann ich neutralisieren!

von Teo D. (teoderix)


Lesenswert?

Wiesjemand schrieb:
> Stefanus F. schrieb:
>> Könnte klappen, wenn man mit den damit verbundenen bis zu 40ms langen
>> Verzögerungen leben kann. Ich bin nicht sicher, ob das bei up/down
>> Tasten (zum Beispiel zum Stellen einer Uhr) zufriedenstellend
>> funktioniert. Müsste man mal ausprobieren.
>
> Tut es im Normalfall. Man merkt es kaum.
>
> Außerdem prellen die wenigsten Taster 20ms, d.h. fallweise kann man also
> schneller pollen.

Wieso Verzögerung?
Wenn man von Störungen absehen kann, kann man doch sofort reagieren, 
bzw. die Tasten als gedrückt annehmen. Nur was dann in den nächsten 
10-20ms passiert, sollte man ignorieren. Nur "Sofort", will man sicher 
eher selten haben. Ein-Zwei Bestätigungen, sind da selbst bei ~50ms 
drin.
Einen Drehenkoder pollt man so schnell, das wiederum einige 
Bestätigungen reinkommen (~1kHz). Durch die Codierung, kann ja nur 
zwischen zwei Zuständen gesprungen werden, fällt also nicht auf.

von Stefan F. (Gast)


Lesenswert?

Teo D. schrieb:
> Wieso Verzögerung?

Schau Dir meine obigen ASCII Diagramme an und vergleiche die Resultate 
mit dem "Tastendruck". Die Verschiebungen auf der Zeitachse meinte ich.

von Jan (Gast)


Lesenswert?

Peter D. schrieb:
> Ja. Kostet ja keinen zusätzlichen Code.
> Ich benutze das z.B. für einen Interlockkreis. Es soll ja nicht bei
> jedem Störimpuls abgeschaltet werden, sondern nur bei einem echten
> Schalten.

Hallo Peter,

frage ist mit welcher Funktion frage ich das ab. Wenn ich KeyPressed 
nehme dann bekomme ich das Einschalten des Schalters. Aber woher weiß 
ich ob er noch an ist, bzw. wann er wieder ausgeschaltet wurde?

Viele Grüße
Jan

von Teo D. (teoderix)


Lesenswert?

Stefanus F. schrieb:
> Schau Dir meine obigen ASCII Diagramme an und vergleiche die Resultate
> mit dem "Tastendruck". Die Verschiebungen auf der Zeitachse meinte ich.

Bau da mal reale Zeiten ein und zeichne auch mal den kürzesten zu 
erwartenden Tastendruck ein.

Das Abfragen der Tasten kann ja ruhig so schnell wie möglich erfolgen, 
nur wenn ein Ereignis eintritt, muss gewartet werden bis das Nächste als 
gültig angesehen werden kann. Oder anders, Polling heißt nicht unbedingt 
mit exakten Zeitabständen und ständig die Ports abzufragen.
Das Ganze lässt sich auch gut mit einem Interrupt starten. Wenns den 
sein muss....

von Stefan F. (Gast)


Lesenswert?

Wird sind uns aber einig, dass die Routine von Peter D. schon alleine 
deswegen besser ist, weil sie kurze Störimpulse heraus filtern kann?

von Teo D. (teoderix)


Lesenswert?

Stefanus F. schrieb:
> Wird sind uns aber einig, dass die Routine von Peter D. schon alleine
> deswegen besser ist, weil sie kurze Störimpulse heraus filtern kann?

Besser als was? :)
Das ist eine EierlegendeWollMilchSau! Das ist nicht mit individuellen 
Lösungen zu vergleichen.

Ich war auch noch nie genötigt, eine Tasten-Matrix abfragen zu müssen. 
Bei 1-2 Tasten lohnt der Einsatz nich wirklich, ist ja nur ne Handvoll 
Code.
Ich plag mich auch lieber mit ner Zeitgesteuerten Mehrfachbelegung 
einer Taste rum, als das ich da in Erwägung ziehe, eine Zweite 
einzubauen. :D

von Peter D. (peda)


Lesenswert?

Jan schrieb:
> frage ist mit welcher Funktion frage ich das ab.

Die entprellten Zustände stehen in key_state. Ein Eingang wird 
übernommen, wenn er 4-mal hintereinander den gleichen Zustand hatte.
1
uint8_t get_key_state(uint8_t key_mask)
2
{
3
  return key_state & key_mask;
4
}

von Stefan F. (Gast)


Lesenswert?

Teo D. schrieb:
> Stefanus F. schrieb:
>> Wird sind uns aber einig, dass die Routine von Peter D. schon alleine
>> deswegen besser ist, weil sie kurze Störimpulse heraus filtern kann?
> Besser als was? :)

Besser als das oben skizzierte einfache Polling im 20ms Intervall.

von A. S. (Gast)


Lesenswert?

Stefanus F. schrieb:
> Wird sind uns aber einig, dass die Routine von Peter D. schon alleine
> deswegen besser ist, weil sie kurze Störimpulse heraus filtern kann?

Sehr allgemein gehaltene Aussage. Ein Engländer ist nicht deshalb der 
bessere 13er Schlüssel, weil er auch 14er kann.

von Teo D. (teoderix)


Lesenswert?

Stefanus F. schrieb:
> Wird sind uns aber einig, dass die Routine von Peter D. schon alleine
> deswegen besser ist, weil sie kurze Störimpulse heraus filtern kann?

Peter D. schrieb:
> Ein Eingang wird
> übernommen, wenn er 4-mal hintereinander den gleichen Zustand hatte.

Und schon ist das große Geheimnis der Entstörung gelüftet. :)

Mir reicht schon eine Bestätigung, ob die Taste immer noch gedrückt ist. 
Da ja meist der Mensch der Störfaktor ist.... Oft will man ja garnicht 
sofort reagieren.
Passt sich so natürlich auch nicht auf Alte-Taste an, die länger 
prellen könnten. Stört mich aber nicht, da die in kürze eh total 
ausfallen.


PS: Das soll hier kein "Ich kanns besser" werden! Nur ein weiterer 
Versuch, das Thema zu entmystifizieren. :)

von m.n. (Gast)


Lesenswert?

Zwei Sachen sind dann doch zu bemerken:

1.
Stefanus F. schrieb:
> Schau Dir meine obigen ASCII Diagramme an und vergleiche die Resultate
> mit dem "Tastendruck". Die Verschiebungen auf der Zeitachse meinte ich.

Was hat denn das Diagramm mit realen Prellvorgängen zu tun?

2.
Teo D. schrieb:
> Mir reicht schon eine Bestätigung, ob die Taste immer noch gedrückt ist.

Dann hast Du noch keine Erfahrung mit schlechten Tastern gemacht. Wenn 
es richtig dumm läuft, bekommt man nämlich mehrere Tastendrücke obwohl 
man permanent gedrückt hält.

von Stefan F. (Gast)


Lesenswert?

m.n. schrieb:
>> Schau Dir meine obigen ASCII Diagramme an und vergleiche die Resultate
>> mit dem "Tastendruck". Die Verschiebungen auf der Zeitachse meinte
>> ich.

> Was hat denn das Diagramm mit realen Prellvorgängen zu tun?

Lies nochmal zusammenhängend, worauf du dich beziehst. Das Diagramm 
stellt die Verschiebungen auf der Zeitachse dar, die durch das Polling 
in regelmäßigen Intervallen entsteht, wenn man es so einfach macht, wie 
der Benutzer "jemand" zuvor empfohlen hat.

Das Polling wiederum hatte er als Lösungsansatz zum Entprellen genannt. 
Da ist der Zusammenhang zu Prellvorgängen.

von Jan (Gast)


Lesenswert?

Peter D. schrieb:
> Die entprellten Zustände stehen in key_state. Ein Eingang wird
> übernommen, wenn er 4-mal hintereinander den gleichen Zustand
> hatte.uint8_t get_key_state(uint8_t key_mask)
> {
>   return key_state & key_mask;
> }

Danke Peter, jetzt habe ich es verstanden. Danke für das Teilen von dem 
Code.

@all: bitte weiter streiten :-) haha

von Teo D. (teoderix)


Lesenswert?

m.n. schrieb:
> Dann hast Du noch keine Erfahrung mit schlechten Tastern gemacht. Wenn
> es richtig dumm läuft, bekommt man nämlich mehrere Tastendrücke obwohl
> man permanent gedrückt hält.

Wenn er wackelt is er hin!
Wackeln (weniger, statt zu viel) die oft bei dir? Dann gug mal ob du 
auch den min. Schaltstrom einhältst!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.