割り込みとハードウェアボタンのサンプリングの違い?


8

割り込みに接続したハードウェアボタンがありますが、問題はボタンが少しバウンスして、ボタンを押したときに信頼性が低下することです。これらの問題の多くはメインループでサンプリングすることで解決されると思いますが、それは技術的に間違っていると感じています。

割り込みは回路内通信に適していますか、それとも割り込みはハードウェアスイッチにも適していますか?もしそうなら、どのデバウンス技術を使用できますか?

タイマー変数を保持し、現在の時間、遅延、およびその他の手法と比較してみました。バウンスが非常に速いかのようで、それは重要ではありません。


2
これを読んでください:ganssle.com/debouncing.pdf
Smith

メインループで反応すれば、メインループでのサンプリングに問題はありません。非同期に反応したい場合は、割り込みがより適切です。時々あなたはし、時にはしません。
Eugene Ryabtsev

デバウンスする最良の方法は、単純なローパスフィルターです。
lucas92 2016年

回答:


8

デバウンスはFAQです。あなたは見つけることができるはずです...トピックのほぼ無制限の数のウェブページ。Smith氏は、このトピックに関するJack Ganssleの広く読まれているPDFについてもコメントしました。そして、これらすべての答えにより、ハードウェアとソフトウェアの両方の方法を利用できます。

まだ十分にカバーされていないアイデアについて主に話すことで、この「文学」に少しだけ追加します。しかし、私がする前に、1つか2つのポイント:

  1. アナログハードウェアでのデバウンスは、ポーリングによって、またはハードウェアのピン変更イベントによってさえ、定期的にデジタルでのみ「観測」されるスイッチでは達成できない結果を達成できます。しかし、すべての意図と目的をデジタルで「十分に」行うことができます。最近では、外部アナログデバウンスソリューションを使用する人はほとんどいません。しかし、私はワンショット(74121)を使用したパルスストレッチングから、ここでジャックガンスルが言及したテクニックまで、すべてを使用しまし
  2. 組み込みプログラミングのみを行っており、電子機器の学習にまったく関心がない場合、スイッチのデバウンスは、おそらく必要な2つの基本的なスキルセットの1つです。動作しているLEDはおそらくもう1つです。これによって、これらのスキルが1つしかないという意味ではありません。さまざまな方法でそれを行うことができるということです。あなたが本当にやるジャックGanssleはスイッチに関して、より一層に関する書き込み、どのような完全に逮捕する必要があります。

74121を使用したパルスストレッチングについて説明したので、Jack Ganssleはまだ言及しておら、まだ誰もここで説明していないため、74121または555をワンショットとして使用するための追加の推奨資料として、この追加リンクを提供することもできます。スイッチをデバウンスするためのタイマー。


さて、これをマイクロコントローラで観察することから始めましょう。

通常、ステートマシンを使用してデバウンスを処理します。これはほとんど常に、私が約に設定した通常の「ハートビート」タイマーによって駆動されます8MS、 可能であれば。(私は通常、いくつかの理由でエッジトリガー割り込みイベントを使用しません。)

ステートマシンは次のようになります。

概略図

この回路のシミュレーションCircuitLabを使用して作成された回路

スイッチのDEBOUNCEDの値は、「非アクティブ」、「アクティブ」、および「不明」の値をとることができます。このようにして、初期化後にスイッチの値が落ち着くまでソフトウェアを確実に待機させることができます。しかし、通常、私はそれを気にしません。「不明な」値をデフォルト値に置き換え、代わりにバイナリ値システムを使用します。

ステートマシンに入るには、最初にデバウンス値をデフォルトに設定してから、ステートマシンの「CHANGING」状態に入ります。各時間間隔(通常は8MS私がそれを回避できる場合は)、現在のスイッチ値を読み取り、現在の状態と、場合によってはデバウンスされた値の更新を実行します。次に、終了します。高レベルのコードは、デバウンスされた状態にのみアクセスします。

それが私にとって重要な場合、私は以前のデバウンス状態を保持することもあります。これらの場合、デバウンスされた状態自体を更新するとき、最初にその状態を「以前のデバウンスされた状態」にコピーします。次に、値のペアを使用して、デバウンスされた遷移があったかどうかを判断できます。時々、私はトランジションを気にしません。時々、そうします。したがって、状況によって異なります。しかし、すべての場合において、デバウンスされた遷移についてのみ知りたいです。私はラントトランジションを気にしません。したがって、高レベルのコードは、ステートマシンが自身の作業に使用する内部状態を決して使用しません。

この方法の良い点の1つは、スイッチのポート全体を一度にデバウンスできることです。そして、割り込みコードに単一の分岐がなくてもそれを行うことができます。これは、マイクロコントローラーのポート幅(通常は8ビット幅)までの非常に高速で短いデバウンスコードを意味します。AtmelAT90の例は、Timer0割り込みイベントを使用してこれを実現する方法を示しています。

.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

ここで、この例は、以前および現在のデバウンスされたスイッチ値を含む完全な取引を示しています。また、必要なすべての状態遷移も実行します。このコードの初期化は示していません。しかし、上記は、ステートマシンの操作がいかに簡単であり、そのために必要なコードがほとんどないということを説明しています。これは非常に高速でシンプルであり、分岐を必要としません(追加のサイクルと追加のコードスペースが必要になる場合があります)。


私は使うことを好む 8MS私が過去に取り組んだ機器を使用して、さまざまな異なる人々との長い、長いテストが私をそこに導いたので、タイミング。私はより長い期間を試しました、そしてそうするとき、私は人々に「反応性」が十分に「活発」ではないことを言われるようになります。(最近、子供たちがリアルタイムの「シュート・エム・アップ」ゲームに取り組んでいるので、私はそれをさらに短くするかもしれません。彼らは、現代のデジタルTVがフレームのセットアップと表示を行うことによって引き起こされるわずかな遅延についてさえ、苦情を言うでしょう。)

一部の人々は、システムがどれほど鮮明で応答性がよいかについて非常に明確な感情を持つでしょう。鮮明で反応がよいということは、サンプルをより頻繁ではなく、より頻繁にサンプリングすることを意味します。でも個人的には20MS許容できる観測期間。(私にとっても、それより長い時間は十分とは言えません。)

前述のステートマシンは、最初にSETTLED状態に入り、DEBOUNCEDの値が更新される前に、さらに1つのサンプル時間そこにとどまる必要があることに注意してください。したがって、ボタンを押してそれを保持するには、たとえ最良の状況であっても、次のような遷移が必要になります。

  1. SETTLEDからCHANGINGに変更します
  2. CHANGINGからSETTLEDに変更します
  3. SETTLEDにとどまり、DEBOUNCEDを更新する

したがって、新しいデバウンス状態を実現するには、最低3つのサンプル期間が必要です。

プッシュボタンは、非アクティブからアクティブになり、非アクティブに戻るには、少なくとも6サンプル時間が必要です。


上記の詳細については、サンプル時間が 8MS それはどこかの間にあることを意味します 16MS<t24MS非アクティブから認識されたアクティブなデバウンス結果に移動する。そして、それは別の時間がかかります24MS状態が非アクティブに戻る前。それは最小です40MS<t48MS プッシュボタンサイクル全体を実行します。

より長いサンプル時間を使用すると、それに応じてより長い期間が生じます。を使用して20MS 私は「受け入れられる」と私はすでに言及しました 100MS<t120MSプッシュボタンサイクル全体。そして、それは人々気づきがちな領域に真っ直ぐ上っている。それより長くなると、私は確かに「感触」が好きではありません。

この方法を使用する場合は、サンプル時間を長くすることに無頓着にしないでください。必要な場合は、ユーザー/コンシューマーを使用して多くのテストも行う必要があると思います。

タイピングキーボード用のコードを開発している場合は、使用時間を短くしてください。タイピストの記録は、数十年前に217 wpmで設定されました。これにより、約1つのキーが45MS。そのようなタイピストは、制御された順序で複数のキーを押しています。水銀で濡らされたリードリレースイッチングシステムを使用している非常に速いタイピストに良いパフォーマンスを得るには、2MS うまくいきました。


バウンス時間は、水銀スイッチの0から微小触覚スイッチの「数」ms typまで、不規則なトグルスイッチの30msまでさまざまであるため、経年変化によるバウンス時間の増加を考慮すると、8msが適切な数値です。
Tony Stewart Sunnyskyguy EE75 2016年

@ TonyStewart.EEsince'75私は、ユーザーがさまざまな種類のスイッチを備えた機器を使用して広範なテストを行うことを選択しました。(スイッチの構築と作成の練習、およびその多様性により、そのデータの収集と分析は困難に思われるため、「理論」についてはあまり心配していませんでした。)可能であれば、常に8ミリ秒を使用します。機能するソフトウェアの長い経験を書いて、アフターセールスの苦情が正確にゼロになる場所(とにかく、その時点で)を考えると、スイートスポットになる
jonk

@ TonyStewart.EEsince'75ちなみに、このテストには、キーボードで使用されているキースイッチの一部としての水銀で湿ったリードリレーの使用が含まれています(おそらく、もう製造されていないようです)。 1〜2 msのサンプリングに進みます(ユニットによって異なります)
16年

先ほど触れたそのレーザーガーデンライトには、低バウンス時間の触覚メンブレンリモートコントロールスイッチがありますが、プログラマーは10Hzレートでスイッチを切り替えたので、100ms未満でリリースしなければ、電源がオン/オフになります。?。別の注記..ヤマハのピアノキーボードは非常に高速で、10キーのロールオーバーをサポートしていますが、元のIBM PCキーボードのみが真の最先端のロールオーバーをサポートしていました。それ以来、すべてのキーボードは最初のストロークでリーディングエッジとトレーリングエッジのロールオーバーとなります。これは、私のタイピングスキルが不十分な場合のPITAです
Tony Stewart Sunnyskyguy EE75 '18

@ TonyStewart.EEsince'75このスイッチサンプリングの領域は痛い点です。組み込みプログラマの無知に加えて、ゼロの外部デバウンスと適用されるスイッチを知っている安価なマイクロの出現により、私は実際に、キーパッドまたはプッシュボタンを備えたほぼすべての単一の組み込み機器に問題を見つけました。それらはすべて私のオプションでひどく機能します。そして、それはプログラマーがほとんどまたはまったく経験がないためであると私は思うと思います。時々、ランダムなポーリングポイントでコードをソルトすることさえあります。ゴミです。動揺。正しく理解するのは簡単です。
16年

5

デバウンスは、バウンス時間のIRQをマスクしてソフトウェアで行うか、RC = T>スイッチのサイズに応じて1〜15msの範囲のバウンス時間で保持コンデンサを追加してハードウェアで行うことができます。

  • たとえば、スイッチ全体で100kプルアップと0.1μF= 50%Vddで10ms @ 63%または〜8ms、またはSchmitt Triggerゲート@ 1.33Vを使用する場合= 5VからのVilまたは〜73%V +〜12ms

4

SWをデバウンスするには、現在のイベントのタイムスタンプを記録し、最後の有効なイベントからの遅延を確認します。

#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:わずかな変更で、ダブルクリックを登録できます。

#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;
}

2

割り込みは、ハードウェアスイッチにも最適です。割り込みを使用することで、特にバッテリ駆動のデバイスを扱う場合は、リソースとおそらくエネルギーの大きな浪費を回避できます。

また、コードがますます大きくなるにつれて、メインループでボタンをポーリングするよりも、ボタンの割り込みを実装する方が簡単であることがわかります。

デバウンスに関しては、おそらくコーディングの問題です。私は通常、ボタンの解放を確認しながら、デバウンスに最大10msのタイマーを使用します。ボタンの割り込みをデバウンスする間は、一時的にボタンの割り込みも無効にして、割り込みルーチンが数回実行されないようにしてください。

それでも問題が解決しない場合は、こちらにコードを投稿してください。


1

これは、Tony StewartのAnswersとかなり似ていますが、いくつか拡張できると思います。

上の回路図は、ローまたは立ち下がりエッジでの割り込み用です。下の回路図は、高エッジまたは立ち上がりエッジでの割り込み用です。

概略図

この回路のシミュレーションCircuitLabを使用して作成された回路

個人的には、コンデンサのコストを考えると、ソフトウェアのデバウンスにバグがあるかどうか心配するのではなく、単にそれを使用する価値があります。

トニー・スチュワートが言ったように、この回路の時定数は10msであることに注意してください RC または 10kΩ1μF。それは3から5の時定数のどこかを取ります(ボタンがそれ自体をリセットするためのマイクロコントローラーの感度に依存するため、マイクロコントローラーが割り込み機能の繰り返しに問題がある場合、それが原因である可能性があり、割り込みが複数回発生しないようにキャップ/抵抗を調整します(つまり、割り込みがハイまたはローの信号で動作するように設定されており、立ち上がりエッジまたは立ち下がりエッジでは動作しないように設定されている場合のみ。

ハードウェアデバウンスに関連


1
特に割り込みピンにシュミットスタイルの入力特性がある場合(多くの場合)、どちらのバージョンも+ veまたは-veエッジの両方で機能します。SW1とSW2の両方が閉じるときに電流サージが発生します。一部のカーボンボタンプッシュボタンは、メタルドームプッシュボタンとは異なる結果をもたらす場合があります。
glen_geek 2016年

1

人間は遅いので、マイクロ秒の範囲にあるマイクロにすぐに注意を払う必要はありません。

これはもちろん、常にそれを行う唯一の方法でも正しい方法でもありませんが、タイマーを設定して(多くのマイクロにはsysティックがあります)、一定の間隔で割り込みを発生させてピンの状態を後で調べるコードの変数。あなたはバウンス中に灰でいっぱいの変数になってしまいます

10010110灰

しかし、特定の時点で次の4つの値が得られ ます。定常状態の
01111111立ち上がりエッジがデバウンスされたばかりの
11111111ボタン
100000立ち下がりエッジがデバウンスされたばかり
が定常状態で00000000ボタンを

ただし、ほとんどの場合、バウンス中にリセットするカウンターを使用します。高速で、テスト済みで、簡単に実行できます。
それが失敗した場合、私は他の人が提案したGanssleドキュメントからもっと賢いものを試します!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.