Unterschiede zwischen Interrupts und Sampling für Hardware-Button?

8

Ich habe eine Hardware-Taste, die ich mit einem Interrupt verbunden habe, aber mein Problem ist, dass sie ein wenig abprallt und das Drücken der Taste unzuverlässig macht. Ich denke, ein Großteil dieser Probleme würde durch Sampling in der Hauptschleife gelöst, aber das fühlt sich technisch einfach falsch an.

Sind Interrupts besser für die Intra-Circuit-Kommunikation geeignet oder sind Interrupts auch für Hardware-Switches geeignet? Wenn ja, welche Entprellungstechniken kann ich verwenden?

Ich habe versucht, eine Timer-Variable beizubehalten und sie mit der aktuellen Zeit, Verzögerungen und anderen Techniken zu vergleichen. Es scheint, als ob die Sprünge so schnell sind, dass es keine Rolle spielt.

OneChillDude
quelle
2
Lesen Sie dies: ganssle.com/debouncing.pdf
Smith
Es ist nichts Falsches an der Abtastung in der Hauptschleife, wenn Sie in der Hauptschleife reagieren. Interrupts sind besser geeignet, wenn Sie asynchron reagieren möchten. Manchmal tust du das und manchmal nicht.
Eugene Ryabtsev
Der beste Weg zum Entprellen ist ein einfacher Tiefpassfilter.
Lucas92

Antworten:

8

Das Entprellen ist eine FAQ. Sie sollten in der Lage sein, ... nahezu unbegrenzt viele Webseiten zum Thema zu finden. Smith kommentierte auch Jack Ganssles vielgelesenes PDF zu diesem Thema. Und mit all diesen Antworten haben Sie sowohl Hardware- als auch Softwaremethoden.

Ich werde diese "Literatur" nur ein wenig ergänzen, indem ich hauptsächlich über Ideen spreche, die noch nicht gut behandelt wurden. Aber bevor ich es tue, ein oder zwei Punkte:

  1. Das Entprellen in analoger Hardware kann zu Ergebnissen führen, die Sie nicht mit einem Schalter erzielen können, der nur digital in regelmäßigen Abständen durch Abfragen oder sogar durch Hardware-Pin-Change-Ereignisse "beobachtet" wird. Aber Sie können in jeder Hinsicht "gut genug" digital arbeiten. Fast niemand verwendet heutzutage externe analoge Entprellungslösungen. Aber ich habe alles verwendet, von Pulsdehnung mit One-Shots (74121) bis zu Techniken, die Jack Ganssle hier erwähnt hat .
  2. Für diejenigen, die nur Embedded-Programmierung betreiben und überhaupt nicht daran interessiert sind, etwas über Elektronik zu lernen, ist das Entprellen von Schaltern wahrscheinlich eine der beiden grundlegenden Fähigkeiten, die benötigt werden. Betriebs-LEDs ist wahrscheinlich die andere. Und damit meine ich nicht, nur eine Fähigkeit zu haben. Ich meine, es auf verschiedene Arten tun zu können. So dass Sie wirklich tun müssen , um voll apprehend was Jack Ganssle schreibt über, und mehr noch, in Bezug auf Schalter.

Da ich die Pulsdehnung mit einer 74121 erwähnt habe und Jack Ganssle sie noch nicht erwähnt hat und noch niemand hier, kann ich diesen zusätzlichen Link auch als zusätzlichen Lesevorschlag zur Verwendung der 74121 oder 555 als One-Shot bereitstellen Timer zum Entprellen von Schaltern.


Nun dazu durch Beobachtung mit einem Mikrocontroller.

Normalerweise benutze ich eine Zustandsmaschine, um das Entprellen zu handhaben. Dies wird fast immer von einem regulären "Herzschlag" -Timer gesteuert, den ich auf ungefähr , wo möglich. (Ich verwende im Allgemeinen aus mehreren Gründen KEINE flankengetriggerten Interrupt-Ereignisse.)8Frau

Die Zustandsmaschine sieht folgendermaßen aus:

schematisch

simulieren Sie diese Schaltung - Schema erstellt mit CircuitLab

Der Wert von DEBOUNCED für den Switch kann die Werte "inaktiv", "aktiv" und "unbekannt" annehmen. Auf diese Weise können Sie sicherstellen, dass Ihre Software wartet, bis sich der Schaltwert nach der Initialisierung einstellt. Aber normalerweise kümmere ich mich nicht darum. Ich ersetze den "unbekannten" Wert durch einen Standardwert und verwende stattdessen nur ein Binärwertsystem.

Die Zustandsmaschine wird aufgerufen, indem zuerst der entprellte Wert auf den Standardwert gesetzt und dann der Zustand "ÄNDERN" der Zustandsmaschine aufgerufen wird. In jedem Zeitintervall (normalerweise wenn ich damit durchkommen kann), lese ich den aktuellen Schaltwert und führe eine Aktualisierung des aktuellen Status und möglicherweise des entprellen Wertes durch. Dann gehe ich einfach. Der High-Level-Code greift dann nur auf den entprellen Zustand zu.8Frau

Wenn es mir wichtig ist, kann ich auch einen zuvor entwerteten Zustand beibehalten. In diesen Fällen kopiere ich beim Aktualisieren des entprellten Zustands selbst diesen Zustand zuerst in einen "vorherigen entprellen Zustand". Ich kann dann das Wertepaar verwenden, um festzustellen, ob ein entprellter Übergang stattgefunden hat. Manchmal interessieren mich Übergänge nicht. Manchmal mache ich. Es kommt also darauf an. Aber in jedem Fall möchte ich nur über entprellte Übergänge wissen. Ich kümmere mich nie um kleine Übergänge. High-Level-Code verwendet also niemals den internen Status, den die Zustandsmaschine für ihre eigene Arbeit verwendet.

Eines der schönen Dinge an dieser Methode ist, dass ich einen ganzen Port von Switches gleichzeitig entprellen kann. Und ich kann es auch ohne einen einzigen Zweig im Interrupt-Code tun. Dies bedeutet einen sehr schnellen und kurzen Entprellungscode für bis zur Portbreite des Mikrocontrollers (normalerweise 8 Bit breit). Ein Beispiel aus dem Atmel AT90 zeigt, wie dies mit einem Timer0-Interrupt-Ereignis erreicht wird:

.equ    SWPORTPINS  =   PINB
.def    SwRawCurr   =   r4
.def    SwRawPrev   =   r5
.def    SwState     =   r6
.def    SwDebCurr   =   r7
.def    SwDebPrev   =   r8

            ; Debounce the input switches.

                mov     SwRawPrev, SwRawCurr
                in      SwRawCurr, SWPORTPINS
                mov     Timer0Tmp1, SwRawCurr
                eor     Timer0Tmp1, SwRawPrev
                mov     Timer0Tmp0, Timer0Tmp1
                or      Timer0Tmp1, SwState
                mov     SwState, Timer0Tmp0
                mov     Timer0Tmp0, Timer0Tmp1
                com     Timer0Tmp0
                and     Timer0Tmp1, SwDebCurr
                and     Timer0Tmp0, SwRawCurr
                or      Timer0Tmp1, Timer0Tmp0
                mov     SwDebPrev, SwDebCurr
                mov     SwDebCurr, Timer0Tmp1

Dieses Beispiel zeigt nun den vollständigen Deal, einschließlich der vorherigen und aktuellen entprellten Switch-Werte. Und es führt auch alle notwendigen Zustandsübergänge durch. Ich zeige die Initialisierung dieses Codes nicht. Aber das Obige verdeutlicht, wie einfach die Zustandsmaschine zu bedienen ist und wie wenig Code dafür erforderlich ist. Es ist recht schnell und einfach und erfordert keine Verzweigung (was manchmal zusätzliche Zyklen sowie zusätzlichen Code-Speicherplatz erfordert).


8Frau

20Frau

Bitte beachten Sie, dass die von mir erwähnte Zustandsmaschine zuerst in den Zustand SETTLED wechseln und dann eine weitere Beispielzeit dort bleiben muss, bevor der Wert für DEBOUNCED aktualisiert wird. Wenn Sie also einen Knopf drücken und ihn auch unter den besten Umständen gedrückt halten, sind folgende Übergänge erforderlich:

  1. Wechseln Sie von SETTLED zu CHANGING
  2. Wechseln Sie von ÄNDERN zu EINSTELLEN
  3. Bleiben Sie in SETTLED und aktualisieren Sie DEBOUNCED

Für einen neuen entprellten Zustand sind mindestens 3 Abtastzeiträume erforderlich.

Ein Druckknopf benötigt mindestens 6 Abtastzeiten, um von inaktiv zu aktiv und dann zurück zu inaktiv zu wechseln.


8Frau16Frau<t24Frau24Frau40Frau<t48Frau

20Frau100Frau<t120Frau

Wenn Sie diesen Weg gehen, sollten Sie keine unbekümmerten Probenzeiten verwenden. Wenn Sie müssen, dann müssen Sie meiner Meinung nach auch viele Tests mit Benutzern / Verbrauchern durchführen.

45Frau2Frau

Jonk
quelle
Die Sprungzeiten variieren von 0 für Quecksilberschalter bis zu "wenigen" ms für mikrotaktile Schalter bis 30 ms für klobige Kippschalter. 8 ms sind daher eine gute Zahl, wenn man bedenkt, dass die Sprungzeit mit zunehmendem Alter zunimmt.
Tony Stewart Sunnyskyguy EE75
@ TonyStewart.EEsince'75 Ich habe mich entschieden, umfangreiche Tests mit Benutzern durchzuführen, die Geräte mit einer Vielzahl verschiedener Arten von Schaltern verwenden, und die 8-ms-Zahl stammt aus einer Destillation all dieser Arbeiten. (Ich habe mich nicht so sehr um "Theorie" gekümmert, da die Praxis des Bauens und Herstellens von Schaltern und ihre schiere Vielfalt die Erfassung und Analyse dieser Daten entmutigend erscheinen ließen.) Ich verwende immer 8 ms, wenn möglich, da es so scheint Angesichts der langjährigen Erfahrung mit dem Schreiben von Software, die einfach funktioniert und bei der Beschwerden nach dem Verkauf auf eine exakte Null gehen (jedenfalls in diesem Punkt), der Sweet Spot zu sein
jonk
@ TonyStewart.EEsince'75 Übrigens beinhaltet dieser Test die Verwendung von mit Quecksilber benetzten Reed-Relais als Teil von Schlüsselschaltern, die in Tastaturen verwendet werden (die meiner Meinung nach nicht mehr hergestellt werden). In diesen Fällen jedoch Ich gehe zu 1-2 ms Abtastung (abhängig von der Einheit.)
Jonk
Das Laser-Gartenlicht, das ich vor einiger Zeit erwähnt habe, hat taktile Membran-Fernbedienungsschalter mit geringer Sprungzeit, aber der Programmierer hat sie mit einer 10-Hz-Rate umschalten lassen, sodass man sie in <100 ms loslassen muss, sonst geht die Stromversorgung aus und wieder aus. ? .auf eine andere Anmerkung .. Yamaha-Klaviertastatur ist extrem schnell und unterstützt 10-Tasten-Rollover, während nur die ursprüngliche IBM PC-Tastatur einen echten Vorderkanten-Rollover unterstützt. Seitdem sind alle Tastaturen 1. Striche sind Vorderkante und dann Hinterkante Rollover, was eine PITA für schlechte Schreibfähigkeiten wie meine ist
Tony Stewart Sunnyskyguy EE75
@ TonyStewart.EEsince'75 Dieser Bereich der Switch-Abtastung ist ein wunder Punkt. Das Aufkommen billiger Mikros ohne externes Entprellen und wer-weiß-was-Schalter hat dazu geführt, dass ich Probleme mit fast JEDEM EINZELNEN eingebetteten Instrument mit Tastatur oder Druckknopf habe. Sie alle funktionieren schrecklich, nach meiner Wahl. Und ich denke, das liegt hauptsächlich daran, dass die Programmierer wenig bis gar keine Erfahrung haben. Gehen Sie einfach ohne nachzudenken auf Google und wenden Sie es an. Manchmal wird sogar der Code mit zufälligen Abrufpunkten gesalzen. Es ist Müll. Aufregen. Es ist einfach, richtig zu machen.
Jonk
5

Das Entprellen kann in der Software durch Maskieren der IRQs für die Absprungzeit oder in der Hardware durch Hinzufügen eines Haltekondensators mit einer Absprungzeit von RC = T> im Bereich von 1 bis 15 ms erfolgen, abhängig von der Größe des Schalters.

  • zB 100k Pullup und 0,1μF über Schalter = 10 ms bei 63% oder ~ 8 ms bei 50% Vdd oder bei Verwendung eines Schmitt-Trigger-Gates bei 1,33 V = Vil von 5 V oder ~ 73% V + ~ 12 ms
Tony Stewart Sunnyskyguy EE75
quelle
4

Um ein SW-De-Bounce durchzuführen, zeichnen Sie den Zeitstempel des aktuellen Ereignisses auf und prüfen Sie, ob sich das letzte gültige Ereignis verzögert hat:

#define DELAY_DEBOUNCE       150

uint32_t    __ts_lastpress = 0;

ISR(some_vector)
{
    uint32_t    now = millis(); // some timer tick counter

    if ( now - __ts_lastpress < DELAY_DEBOUNCE )
        return; // ignore it

    __ts_lastpress = now;
    // do the job here
}

UPD: Mit wenigen Änderungen können Sie Doppelklicks registrieren:

#define DELAY_DEBOUNCE       150
#define DELAY_DOUBLE_CLICK   600

uint32_t    __ts_lastpress = 0;

ISR(some_vector)
{
    uint32_t    now = millis(); // some timer tick counter

    if ( now - __ts_lastpress < DELAY_DEBOUNCE )
        return; // ignore it

    // do the job here
    if ( now - __ts_lastpress < DELAY_DOUBLE_CLICK )
    {
        // it is double click
    }
    else
    {
        // it is single click
    }

    __ts_lastpress = now;
}
Flanker
quelle
2

Interrupts eignen sich definitiv auch hervorragend für Hardware-Switches. Durch die Verwendung von Interrupts vermeiden Sie eine große Verschwendung von Ressourcen und möglicherweise Energie, insbesondere wenn Sie mit batteriebetriebenen Geräten arbeiten.

Wenn Ihr Code immer größer wird, werden Sie feststellen, dass es noch einfacher ist, die Interrupts für Schaltflächen zu implementieren, als sie in Ihrer Hauptschleife abzufragen.

Bei Ihrem Entprellen handelt es sich wahrscheinlich um ein Codierungsproblem. Ich benutze normalerweise einen ~ 10ms Timer zum Entprellen, während ich nach dem Loslassen der Taste suche. Stellen Sie sicher, dass Sie den Tasteninterrupt auch vorübergehend deaktivieren, während Sie ihn entprellen, damit die Interruptroutine nicht mehrmals ausgeführt wird.

Wenn Sie immer noch Probleme haben, geben Sie den Code hier ein, damit wir Ihnen helfen können.

Pedro Mantovani
quelle
1

Dies ist Tony Stewarts Antwort ziemlich ähnlich, aber ich denke, es könnte etwas erweitert werden.

Das obere Schema ist entweder für einen Interrupt bei niedriger oder bei fallender Flanke. Das untere Schema ist für einen Interrupt bei hoher oder steigender Flanke.

schematisch

simulieren Sie diese Schaltung - Schema erstellt mit CircuitLab

Angesichts der Kosten eines Kondensators lohnt es sich für mich, ihn einfach zu verwenden, anstatt mir Sorgen zu machen, ob mein Software-Debounce fehlerhaft ist.

(R.C.10kΩ1μF.)

Bezogen auf Hardware-Debouncing

ambitiose_sed_ineptum
quelle
1
Jede Version funktioniert sowohl für + ve als auch für -ve Flanke, insbesondere wenn der Interrupt-Pin eine Eingabekennlinie im Schmitt-Stil hat (viele tun dies). Sowohl SW1 als auch SW2 erfahren beim Schließen einen Stromstoß. Einige Carbon-Knopf-Drucktasten können andere Ergebnisse liefern als Metall-Kuppel-Drucktasten.
glen_geek
1

Menschen sind langsam, wir brauchen nicht die sofortige Aufmerksamkeit eines Mikros, das im Mikrosekundenbereich liegt.

Dies ist natürlich nicht der einzige und auch nicht der richtige Weg, dies immer zu tun, aber ich finde es im Allgemeinen sinnvoller, einen Timer einzurichten (viele Mikros haben System-Ticks), um einen Interrupt in festgelegten Intervallen auszulösen und den Zustand des Pins in einen zu verschieben Variable, die der Code später untersuchen soll. Sie erhalten eine Var, die beim Hüpfen voller Asche ist

10010110 Asche

Aber zu bestimmten Zeitpunkten erhalten Sie diese 4 Werte:
01111111 steigende Flanke gerade entprellt
11111111 Taste im eingeschwungenen Zustand nach oben
10000000 fallende Flanke gerade entprellt
00000000 Taste im eingeschwungenen Zustand nach unten

Meistens verwende ich jedoch nur einen Zähler, der beim Abprallen zurückgesetzt wird. Es ist schnell, getestet und einfach zu machen.
Wenn es fehlschlägt, versuche ich etwas Klügeres aus dem von anderen vorgeschlagenen Ganssle-Dokument!

zakkos
quelle