ボタンデバウンスが機能しない

私はプッシュボタンとATMega16aでLEDをトグルしたいのですが、何らかの理由でトグル動作が少しランダムに見えます。

#include 
#include 

/* if true we toggle PB0 */
volatile uint8_t toggle = 0;
/* contains last value of PD2 */
volatile uint8_t newval = 0;
volatile uint8_t oldval = 0;

int main(void) {
    /* set PB0 as output and PD2 as input */
    DDRB |=  (1 << PB0);
    DDRD &= ~(1 << PD2);

    /* enable timer such that we can pool every 16ms */
    TIMSK |= (1 << TOIE0);
    TCCR0 |= (1 << CS00) | (1 << CS01);

    sei();

    for (;;) {
        if (toggle) {
            PORTB ^= (1 << PB0);
        }
    }

    return 0;
}

ISR (TIMER0_OVF_vect) {
    /* get new input value */
    newval = PIND & (1 << PD2);

    /* only handles button presses */
    if (newval && !oldval) {
        if (toggle) {
            toggle = 0;
        } else {
            toggle = 1;
        }
    }

    oldval = newval;
}

コードに問題がありますか、それともハードウェアの問題ですか?

2
nl ru de
あなたはきちんとあなたのボタンをデバウンスしましたか?
追加された 著者 Tachyons,
@ uint128_tはい( github.com/を参照) bodokaiser/avr/blob/master/03-blink-led-button /&hellip; )しかし、後の回答で述べたように、問題は内部抵抗を引き上げていないことでした。デバウンスする?
追加された 著者 M.A. Golding,

4 答え

典型的なプッシュボタンスイッチは、バウンスとなります特定のスイッチにもよりますが、これは数十ミリ秒続くことがあります。

スイッチを閉じると、ISRハンドラが制御を取得した時点で、スイッチの接点がバウンスしている可能性があります。あなたはスイッチの複数の読み込みをする必要があります。

統計的には、スイッチがバウンスしていると同時にタイマー割り込みが発生する場合があります。

2
追加された
理論はわかったと思いますが、コードはどうでしょうか。それは正しいようですか?入力ピンを複数回読み取るので、エラーを特定できません。
追加された 著者 M.A. Golding,
テストには実際には1つの読み取りしかありません。一連のnewval [2]があり、3回の連続したタイマー割り込みでそれらが同じであることを確認したら、スイッチを正しくデバウンスするでしょう。
追加された 著者 Peter Smith,

これが私がタイマー割り込みでデバウンスする方法です。以下の例では、ロータリーエンコーダも読み取り、ボタンの「押された」状態と「離された」状態も返します。


    //encoder on RA2-3, shaft button on RA1
uint8_t tmp;
static const int8_t const enc_states[] =         //encoder lookup table
    {0,ENCD_SIG,ENCI_SIG,0,ENCI_SIG,0,0,ENCD_SIG,ENCD_SIG,0,0,ENCI_SIG,0,ENCI_SIG,ENCD_SIG,0};

static uint8_t old_AB = 0;    //previous state of the encoder
static uint8_t debounce_state = 0U;
static uint8_t btn_debounced = 0U;

_T1IF = 0;                              /* clear interrupt */

tmp = PORTA;    //read encoder

//process encoder
old_AB >>= 2;                //remember previous state
old_AB |= ( tmp & 0x0c );  //add current state

if( enc_states[(old_AB & 0x0f)]) { //encoder changed state
    QACTIVE_POST_X_ISR((QActive *)&AO_Console,
        1, enc_states[(old_AB & 0x0f)], 0U);
}

/* read and debouce encoder shaft button */

tmp = EBUT_PIN;               /* read the shaft button */

switch (debounce_state) {
    case 0:
        if (tmp != btn_debounced) {
            debounce_state = 1U;        /* transition to the next state */
        }
        break;
    case 1:
        if (tmp != btn_debounced) {
            debounce_state = 2U;        /* transition to the next state */
        }
        else {
            debounce_state = 0U;          /* transition back to state 0 */
        }
        break;
    case 2:
        if (tmp != btn_debounced) {
            debounce_state = 3U;        /* transition to the next state */
        }
        else {
            debounce_state = 0U;        /* transition back to state 0 */
        }
        break;
    case 3:
        if (tmp != btn_debounced) {
            btn_debounced = tmp;        /* save the debounced button value */

            if (tmp == 0U) {            /* is the button depressed? */
                QACTIVE_POST_X_ISR((QActive*)&AO_Console, 1,
                    EBUT_PRESS_SIG, 0U);
            }
            else {
                QACTIVE_POST_X_ISR((QActive*)&AO_Console, 1,
                    EBUT_RELEASE_SIG, 0U);
            }
        }
        debounce_state = 0U;              /* transition back to state 0 */
        break;
}//switch(debounce_state...

QACTIVE_POST_X_ISR((QActive*)&AO_Console, 1,
    TICK_SIG, 0U);

QF_tickISR();                /* handle all armed time events in QF-nano */

0
追加された

I found the problem: It did not really had something to do with debouncing but with the state of the input pin. I needed to put the internal pull up resistor of the input pin up PORTD |= (1 << PD2);.

0
追加された

ハードウェアの設定方法によっては、コンデンサと抵抗回路を使用してバウンスを常に減らすことができます。下の画像のように:

Switch De-bouncing

これは時定数ですが、R/Cの関係を調整して、ニーズに合わせて立ち上がり/立ち下がり時間を減らすことができます。

0
追加された